2 * PowerPC CPU initialization for qemu.
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
30 const unsigned char *name;
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 */
53 static void spr_read_xer (void *opaque, int sprn)
58 static void spr_write_xer (void *opaque, int sprn)
64 static void spr_read_lr (void *opaque, int sprn)
69 static void spr_write_lr (void *opaque, int sprn)
75 static void spr_read_ctr (void *opaque, int sprn)
80 static void spr_write_ctr (void *opaque, int sprn)
85 /* User read access to SPR */
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) */
98 static void spr_read_decr (void *opaque, int sprn)
103 static void spr_write_decr (void *opaque, int sprn)
108 /* SPR common to all non-embedded PPC, except 601 */
110 static void spr_read_tbl (void *opaque, int sprn)
115 static void spr_write_tbl (void *opaque, int sprn)
120 static void spr_read_tbu (void *opaque, int sprn)
125 static void spr_write_tbu (void *opaque, int sprn)
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);
150 static void spr_write_ibatu_h (void *opaque, int sprn)
152 DisasContext *ctx = opaque;
154 gen_op_store_ibatu((sprn - SPR_IBAT4U) / 2);
158 static void spr_write_ibatl (void *opaque, int sprn)
160 DisasContext *ctx = opaque;
162 gen_op_store_ibatl((sprn - SPR_IBAT0L) / 2);
166 static void spr_write_ibatl_h (void *opaque, int sprn)
168 DisasContext *ctx = opaque;
170 gen_op_store_ibatl((sprn - SPR_IBAT4L) / 2);
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);
194 static void spr_write_dbatu_h (void *opaque, int sprn)
196 DisasContext *ctx = opaque;
198 gen_op_store_dbatu((sprn - SPR_DBAT4U) / 2);
202 static void spr_write_dbatl (void *opaque, int sprn)
204 DisasContext *ctx = opaque;
206 gen_op_store_dbatl((sprn - SPR_DBAT0L) / 2);
210 static void spr_write_dbatl_h (void *opaque, int sprn)
212 DisasContext *ctx = opaque;
214 gen_op_store_dbatl((sprn - SPR_DBAT4L) / 2);
219 static void spr_read_sdr1 (void *opaque, int sprn)
224 static void spr_write_sdr1 (void *opaque, int sprn)
226 DisasContext *ctx = opaque;
232 static void spr_write_pir (void *opaque, int sprn)
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)
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);
254 #if defined(PPC_DEBUG_SPR)
255 printf("*** register spr %d (%03x) %s val %08" PRIx64 "\n", num, num, name,
256 (unsigned long long)initial_value);
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,
275 spr_register(env, SPR_LR, "LR",
276 &spr_read_lr, &spr_write_lr,
277 &spr_read_lr, &spr_write_lr,
279 spr_register(env, SPR_CTR, "CTR",
280 &spr_read_ctr, &spr_write_ctr,
281 &spr_read_ctr, &spr_write_ctr,
283 /* Interrupt processing */
284 spr_register(env, SPR_SRR0, "SRR0",
285 SPR_NOACCESS, SPR_NOACCESS,
286 &spr_read_generic, &spr_write_generic,
288 spr_register(env, SPR_SRR1, "SRR1",
289 SPR_NOACCESS, SPR_NOACCESS,
290 &spr_read_generic, &spr_write_generic,
292 /* Processor control */
293 spr_register(env, SPR_SPRG0, "SPRG0",
294 SPR_NOACCESS, SPR_NOACCESS,
295 &spr_read_generic, &spr_write_generic,
297 spr_register(env, SPR_SPRG1, "SPRG1",
298 SPR_NOACCESS, SPR_NOACCESS,
299 &spr_read_generic, &spr_write_generic,
301 spr_register(env, SPR_SPRG2, "SPRG2",
302 SPR_NOACCESS, SPR_NOACCESS,
303 &spr_read_generic, &spr_write_generic,
305 spr_register(env, SPR_SPRG3, "SPRG3",
306 SPR_NOACCESS, SPR_NOACCESS,
307 &spr_read_generic, &spr_write_generic,
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,
319 spr_register(env, SPR_DAR, "DAR",
320 SPR_NOACCESS, SPR_NOACCESS,
321 &spr_read_generic, &spr_write_generic,
324 spr_register(env, SPR_DECR, "DECR",
325 SPR_NOACCESS, SPR_NOACCESS,
326 &spr_read_decr, &spr_write_decr,
328 /* Memory management */
329 spr_register(env, SPR_SDR1, "SDR1",
330 SPR_NOACCESS, SPR_NOACCESS,
331 &spr_read_sdr1, &spr_write_sdr1,
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,
342 spr_register(env, SPR_IBAT0L, "IBAT0L",
343 SPR_NOACCESS, SPR_NOACCESS,
344 &spr_read_ibat, &spr_write_ibatl,
346 spr_register(env, SPR_IBAT1U, "IBAT1U",
347 SPR_NOACCESS, SPR_NOACCESS,
348 &spr_read_ibat, &spr_write_ibatu,
350 spr_register(env, SPR_IBAT1L, "IBAT1L",
351 SPR_NOACCESS, SPR_NOACCESS,
352 &spr_read_ibat, &spr_write_ibatl,
354 spr_register(env, SPR_IBAT2U, "IBAT2U",
355 SPR_NOACCESS, SPR_NOACCESS,
356 &spr_read_ibat, &spr_write_ibatu,
358 spr_register(env, SPR_IBAT2L, "IBAT2L",
359 SPR_NOACCESS, SPR_NOACCESS,
360 &spr_read_ibat, &spr_write_ibatl,
362 spr_register(env, SPR_IBAT3U, "IBAT3U",
363 SPR_NOACCESS, SPR_NOACCESS,
364 &spr_read_ibat, &spr_write_ibatu,
366 spr_register(env, SPR_IBAT3L, "IBAT3L",
367 SPR_NOACCESS, SPR_NOACCESS,
368 &spr_read_ibat, &spr_write_ibatl,
370 spr_register(env, SPR_DBAT0U, "DBAT0U",
371 SPR_NOACCESS, SPR_NOACCESS,
372 &spr_read_dbat, &spr_write_dbatu,
374 spr_register(env, SPR_DBAT0L, "DBAT0L",
375 SPR_NOACCESS, SPR_NOACCESS,
376 &spr_read_dbat, &spr_write_dbatl,
378 spr_register(env, SPR_DBAT1U, "DBAT1U",
379 SPR_NOACCESS, SPR_NOACCESS,
380 &spr_read_dbat, &spr_write_dbatu,
382 spr_register(env, SPR_DBAT1L, "DBAT1L",
383 SPR_NOACCESS, SPR_NOACCESS,
384 &spr_read_dbat, &spr_write_dbatl,
386 spr_register(env, SPR_DBAT2U, "DBAT2U",
387 SPR_NOACCESS, SPR_NOACCESS,
388 &spr_read_dbat, &spr_write_dbatu,
390 spr_register(env, SPR_DBAT2L, "DBAT2L",
391 SPR_NOACCESS, SPR_NOACCESS,
392 &spr_read_dbat, &spr_write_dbatl,
394 spr_register(env, SPR_DBAT3U, "DBAT3U",
395 SPR_NOACCESS, SPR_NOACCESS,
396 &spr_read_dbat, &spr_write_dbatu,
398 spr_register(env, SPR_DBAT3L, "DBAT3L",
399 SPR_NOACCESS, SPR_NOACCESS,
400 &spr_read_dbat, &spr_write_dbatl,
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,
412 spr_register(env, SPR_IBAT4L, "IBAT4L",
413 SPR_NOACCESS, SPR_NOACCESS,
414 &spr_read_ibat_h, &spr_write_ibatl_h,
416 spr_register(env, SPR_IBAT5U, "IBAT5U",
417 SPR_NOACCESS, SPR_NOACCESS,
418 &spr_read_ibat_h, &spr_write_ibatu_h,
420 spr_register(env, SPR_IBAT5L, "IBAT5L",
421 SPR_NOACCESS, SPR_NOACCESS,
422 &spr_read_ibat_h, &spr_write_ibatl_h,
424 spr_register(env, SPR_IBAT6U, "IBAT6U",
425 SPR_NOACCESS, SPR_NOACCESS,
426 &spr_read_ibat_h, &spr_write_ibatu_h,
428 spr_register(env, SPR_IBAT6L, "IBAT6L",
429 SPR_NOACCESS, SPR_NOACCESS,
430 &spr_read_ibat_h, &spr_write_ibatl_h,
432 spr_register(env, SPR_IBAT7U, "IBAT7U",
433 SPR_NOACCESS, SPR_NOACCESS,
434 &spr_read_ibat_h, &spr_write_ibatu_h,
436 spr_register(env, SPR_IBAT7L, "IBAT7L",
437 SPR_NOACCESS, SPR_NOACCESS,
438 &spr_read_ibat_h, &spr_write_ibatl_h,
440 spr_register(env, SPR_DBAT4U, "DBAT4U",
441 SPR_NOACCESS, SPR_NOACCESS,
442 &spr_read_dbat_h, &spr_write_dbatu_h,
444 spr_register(env, SPR_DBAT4L, "DBAT4L",
445 SPR_NOACCESS, SPR_NOACCESS,
446 &spr_read_dbat_h, &spr_write_dbatl_h,
448 spr_register(env, SPR_DBAT5U, "DBAT5U",
449 SPR_NOACCESS, SPR_NOACCESS,
450 &spr_read_dbat_h, &spr_write_dbatu_h,
452 spr_register(env, SPR_DBAT5L, "DBAT5L",
453 SPR_NOACCESS, SPR_NOACCESS,
454 &spr_read_dbat_h, &spr_write_dbatl_h,
456 spr_register(env, SPR_DBAT6U, "DBAT6U",
457 SPR_NOACCESS, SPR_NOACCESS,
458 &spr_read_dbat_h, &spr_write_dbatu_h,
460 spr_register(env, SPR_DBAT6L, "DBAT6L",
461 SPR_NOACCESS, SPR_NOACCESS,
462 &spr_read_dbat_h, &spr_write_dbatl_h,
464 spr_register(env, SPR_DBAT7U, "DBAT7U",
465 SPR_NOACCESS, SPR_NOACCESS,
466 &spr_read_dbat_h, &spr_write_dbatu_h,
468 spr_register(env, SPR_DBAT7L, "DBAT7L",
469 SPR_NOACCESS, SPR_NOACCESS,
470 &spr_read_dbat_h, &spr_write_dbatl_h,
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,
482 spr_register(env, SPR_TBL, "TBL",
483 SPR_NOACCESS, SPR_NOACCESS,
484 SPR_NOACCESS, &spr_write_tbl,
486 spr_register(env, SPR_VTBU, "TBU",
487 &spr_read_tbu, SPR_NOACCESS,
488 &spr_read_tbu, SPR_NOACCESS,
490 spr_register(env, SPR_TBU, "TBU",
491 SPR_NOACCESS, SPR_NOACCESS,
492 SPR_NOACCESS, &spr_write_tbu,
496 /* SPR common to all 7xx PowerPC implementations */
497 static void gen_spr_7xx (CPUPPCState *env)
500 /* XXX : not implemented */
501 spr_register(env, SPR_DABR, "DABR",
502 SPR_NOACCESS, SPR_NOACCESS,
503 &spr_read_generic, &spr_write_generic,
505 /* XXX : not implemented */
506 spr_register(env, SPR_IABR, "IABR",
507 SPR_NOACCESS, SPR_NOACCESS,
508 &spr_read_generic, &spr_write_generic,
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,
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,
522 /* XXX : not implemented */
523 spr_register(env, SPR_MMCR1, "MMCR1",
524 SPR_NOACCESS, SPR_NOACCESS,
525 &spr_read_generic, &spr_write_generic,
527 /* XXX : not implemented */
528 spr_register(env, SPR_PMC1, "PMC1",
529 SPR_NOACCESS, SPR_NOACCESS,
530 &spr_read_generic, &spr_write_generic,
532 /* XXX : not implemented */
533 spr_register(env, SPR_PMC2, "PMC2",
534 SPR_NOACCESS, SPR_NOACCESS,
535 &spr_read_generic, &spr_write_generic,
537 /* XXX : not implemented */
538 spr_register(env, SPR_PMC3, "PMC3",
539 SPR_NOACCESS, SPR_NOACCESS,
540 &spr_read_generic, &spr_write_generic,
542 /* XXX : not implemented */
543 spr_register(env, SPR_PMC4, "PMC4",
544 SPR_NOACCESS, SPR_NOACCESS,
545 &spr_read_generic, &spr_write_generic,
547 /* XXX : not implemented */
548 spr_register(env, SPR_SIA, "SIA",
549 SPR_NOACCESS, SPR_NOACCESS,
550 &spr_read_generic, SPR_NOACCESS,
552 spr_register(env, SPR_UMMCR0, "UMMCR0",
553 &spr_read_ureg, SPR_NOACCESS,
554 &spr_read_ureg, SPR_NOACCESS,
556 spr_register(env, SPR_UMMCR1, "UMMCR1",
557 &spr_read_ureg, SPR_NOACCESS,
558 &spr_read_ureg, SPR_NOACCESS,
560 spr_register(env, SPR_UPMC1, "UPMC1",
561 &spr_read_ureg, SPR_NOACCESS,
562 &spr_read_ureg, SPR_NOACCESS,
564 spr_register(env, SPR_UPMC2, "UPMC2",
565 &spr_read_ureg, SPR_NOACCESS,
566 &spr_read_ureg, SPR_NOACCESS,
568 spr_register(env, SPR_UPMC3, "UPMC3",
569 &spr_read_ureg, SPR_NOACCESS,
570 &spr_read_ureg, SPR_NOACCESS,
572 spr_register(env, SPR_UPMC4, "UPMC4",
573 &spr_read_ureg, SPR_NOACCESS,
574 &spr_read_ureg, SPR_NOACCESS,
576 spr_register(env, SPR_USIA, "USIA",
577 &spr_read_ureg, SPR_NOACCESS,
578 &spr_read_ureg, SPR_NOACCESS,
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,
586 /* XXX : not implemented */
587 spr_register(env, SPR_THRM2, "THRM2",
588 SPR_NOACCESS, SPR_NOACCESS,
589 &spr_read_generic, &spr_write_generic,
591 /* XXX : not implemented */
592 spr_register(env, SPR_THRM3, "THRM3",
593 SPR_NOACCESS, SPR_NOACCESS,
594 &spr_read_generic, &spr_write_generic,
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,
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,
613 /* XXX : not implemented */
614 spr_register(env, SPR_IABR, "IABR",
615 SPR_NOACCESS, SPR_NOACCESS,
616 &spr_read_generic, &spr_write_generic,
618 /* XXX : not implemented */
619 spr_register(env, SPR_DABR, "DABR",
620 SPR_NOACCESS, SPR_NOACCESS,
621 &spr_read_generic, &spr_write_generic,
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,
629 /* XXX : not implemented */
630 spr_register(env, SPR_MMCR1, "MMCR1",
631 SPR_NOACCESS, SPR_NOACCESS,
632 &spr_read_generic, &spr_write_generic,
634 /* XXX : not implemented */
635 spr_register(env, SPR_PMC1, "PMC1",
636 SPR_NOACCESS, SPR_NOACCESS,
637 &spr_read_generic, &spr_write_generic,
639 /* XXX : not implemented */
640 spr_register(env, SPR_PMC2, "PMC2",
641 SPR_NOACCESS, SPR_NOACCESS,
642 &spr_read_generic, &spr_write_generic,
644 /* XXX : not implemented */
645 spr_register(env, SPR_PMC3, "PMC3",
646 SPR_NOACCESS, SPR_NOACCESS,
647 &spr_read_generic, &spr_write_generic,
649 /* XXX : not implemented */
650 spr_register(env, SPR_PMC4, "PMC4",
651 SPR_NOACCESS, SPR_NOACCESS,
652 &spr_read_generic, &spr_write_generic,
654 /* XXX : not implemented */
655 spr_register(env, SPR_SIA, "SIA",
656 SPR_NOACCESS, SPR_NOACCESS,
657 &spr_read_generic, SPR_NOACCESS,
659 /* XXX : not implemented */
660 spr_register(env, SPR_SDA, "SDA",
661 SPR_NOACCESS, SPR_NOACCESS,
662 &spr_read_generic, SPR_NOACCESS,
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,
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 */
704 spr_register(env, SPR_PVR, "PVR",
705 SPR_NOACCESS, SPR_NOACCESS,
706 &spr_read_generic, SPR_NOACCESS,
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);
714 /* Memory management */
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,
725 /* XXX : not implemented */
726 spr_register(env, SPR_HID1, "HID1",
727 SPR_NOACCESS, SPR_NOACCESS,
728 &spr_read_generic, &spr_write_generic,
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);
737 /* Memory management */
742 /* XXX : not implemented */
743 spr_register(env, SPR_L2CR, "L2CR",
744 SPR_NOACCESS, SPR_NOACCESS,
745 &spr_read_generic, &spr_write_generic,
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,
753 /* XXX : not implemented */
754 spr_register(env, SPR_HID1, "HID1",
755 SPR_NOACCESS, SPR_NOACCESS,
756 &spr_read_generic, &spr_write_generic,
760 case CPU_PPC_750FX: /* IBM PPC 750 FX */
761 case CPU_PPC_750GX: /* IBM PPC 750 GX */
762 gen_spr_generic(env);
764 /* Memory management */
766 /* PowerPC 750fx & 750gx has 8 DBATs and 8 IBATs */
771 /* XXX : not implemented */
772 spr_register(env, SPR_L2CR, "L2CR",
773 SPR_NOACCESS, SPR_NOACCESS,
774 &spr_read_generic, &spr_write_generic,
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,
782 /* XXX : not implemented */
783 spr_register(env, SPR_HID1, "HID1",
784 SPR_NOACCESS, SPR_NOACCESS,
785 &spr_read_generic, &spr_write_generic,
787 /* XXX : not implemented */
788 spr_register(env, SPR_750_HID2, "HID2",
789 SPR_NOACCESS, SPR_NOACCESS,
790 &spr_read_generic, &spr_write_generic,
795 gen_spr_generic(env);
798 if (env->nb_BATs == -1)
802 #if defined(PPC_DUMP_CPU)
803 static void dump_sprs (CPUPPCState *env)
806 uint32_t pvr = env->spr[SPR_PVR];
807 uint32_t sr, sw, ur, uw;
810 printf("* SPRs for PVR=%08x\n", pvr);
811 for (i = 0; i < 32; i++) {
812 for (j = 0; j < 32; 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' : '-');
832 /*****************************************************************************/
836 int fflush (FILE *stream);
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)
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)
868 tmp = malloc(0x20 * sizeof(opc_handler_t));
871 fill_new_table(tmp, 0x20);
872 table[idx] = (opc_handler_t *)((unsigned long)tmp | PPC_INDIRECT);
877 static int insert_in_table (opc_handler_t **table, unsigned char idx,
878 opc_handler_t *handler)
880 if (table[idx] != &invalid_handler)
882 table[idx] = handler;
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);
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 "
910 if (!is_indirect_opcode(table[idx1])) {
911 printf("*** ERROR: idx %02x already assigned to a direct "
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);
926 static int register_ind_insn (opc_handler_t **ppc_opcodes,
927 unsigned char idx1, unsigned char idx2,
928 opc_handler_t *handler)
932 ret = register_ind_in_table(ppc_opcodes, idx1, idx2, handler);
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);
946 if (register_ind_in_table(ind_table(ppc_opcodes[idx1]), idx2, idx3,
948 printf("*** ERROR: unable to insert opcode "
949 "[%02x-%02x-%02x]\n", idx1, idx2, idx3);
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)
964 if (register_ind_insn(ppc_opcodes, insn->opc1,
965 insn->opc2, &insn->handler) < 0)
969 if (register_direct_insn(ppc_opcodes, insn->opc1, &insn->handler) < 0)
976 static int test_opcode_table (opc_handler_t **table, int len)
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);
989 table[i] = &invalid_handler;
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);
1017 if (&opc_start < &opc_end) {
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,
1032 #if defined(PPC_DUMP_CPU)
1034 if (opc->opc3 == 0xFF) {
1035 if (opc->opc2 == 0xFF) {
1036 printf(" %02x -- -- (%2d ----) : %s\n",
1037 opc->opc1, opc->opc1, opc->oname);
1039 printf(" %02x %02x -- (%2d %4d) : %s\n",
1040 opc->opc1, opc->opc2, opc->opc1, opc->opc2,
1044 printf(" %02x %02x %02x (%2d %4d) : %s\n",
1045 opc->opc1, opc->opc2, opc->opc3,
1046 opc->opc1, (opc->opc3 << 5) | opc->opc2,
1053 fix_opcode_tables(env->opcodes);
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");
1070 init_ppc_proc(env, def);
1071 #if defined(PPC_DUMP_CPU)
1080 CPUPPCState *cpu_ppc_init(void)
1084 env = qemu_mallocz(sizeof(CPUPPCState));
1089 #if defined (DO_SINGLE_STEP) && 0
1090 /* Single step trace mode */
1094 msr_fp = 1; /* Allow floating point exceptions */
1095 msr_me = 1; /* Allow machine check exceptions */
1096 #if defined(CONFIG_USER_ONLY)
1099 env->nip = 0xFFFFFFFC;
1101 do_compute_hflags(env);
1106 void cpu_ppc_close(CPUPPCState *env)
1108 /* Should also remove all opcode tables... */
1112 /*****************************************************************************/
1113 /* PowerPC CPU definitions */
1114 static ppc_def_t ppc_defs[] =
1122 .pvr_mask = 0xFFFF0000,
1123 .insns_flags = PPC_INSNS_401,
1124 .flags = PPC_FLAGS_401,
1129 /* IOP480 (401 microcontroler) */
1132 .pvr = CPU_PPC_IOP480,
1133 .pvr_mask = 0xFFFF0000,
1134 .insns_flags = PPC_INSNS_401,
1135 .flags = PPC_FLAGS_401,
1143 .pvr = CPU_PPC_403GA,
1144 .pvr_mask = 0xFFFFFF00,
1145 .insns_flags = PPC_INSNS_403,
1146 .flags = PPC_FLAGS_403,
1147 .msr_mask = 0x000000000007D23D,
1154 .pvr = CPU_PPC_403GB,
1155 .pvr_mask = 0xFFFFFF00,
1156 .insns_flags = PPC_INSNS_403,
1157 .flags = PPC_FLAGS_403,
1158 .msr_mask = 0x000000000007D23D,
1165 .pvr = CPU_PPC_403GC,
1166 .pvr_mask = 0xFFFFFF00,
1167 .insns_flags = PPC_INSNS_403,
1168 .flags = PPC_FLAGS_403,
1169 .msr_mask = 0x000000000007D23D,
1176 .pvr = CPU_PPC_403GCX,
1177 .pvr_mask = 0xFFFFFF00,
1178 .insns_flags = PPC_INSNS_403,
1179 .flags = PPC_FLAGS_403,
1180 .msr_mask = 0x000000000007D23D,
1188 .pvr_mask = 0xFFFF0000,
1189 .insns_flags = PPC_INSNS_405,
1190 .flags = PPC_FLAGS_405,
1191 .msr_mask = 0x00000000020EFF30,
1199 .pvr_mask = 0xFFFF0000,
1200 .insns_flags = PPC_INSNS_405,
1201 .flags = PPC_FLAGS_405,
1202 .msr_mask = 0x00000000020EFF30,
1209 .pvr = CPU_PPC_405EP,
1210 .pvr_mask = 0xFFFF0000,
1211 .insns_flags = PPC_INSNS_405,
1212 .flags = PPC_FLAGS_405,
1213 .msr_mask = 0x00000000020EFF30,
1220 .pvr = CPU_PPC_405GPR,
1221 .pvr_mask = 0xFFFF0000,
1222 .insns_flags = PPC_INSNS_405,
1223 .flags = PPC_FLAGS_405,
1224 .msr_mask = 0x00000000020EFF30,
1231 .pvr = CPU_PPC_405D2,
1232 .pvr_mask = 0xFFFF0000,
1233 .insns_flags = PPC_INSNS_405,
1234 .flags = PPC_FLAGS_405,
1235 .msr_mask = 0x00000000020EFF30,
1242 .pvr = CPU_PPC_405D4,
1243 .pvr_mask = 0xFFFF0000,
1244 .insns_flags = PPC_INSNS_405,
1245 .flags = PPC_FLAGS_405,
1246 .msr_mask = 0x00000000020EFF30,
1253 .pvr = CPU_PPC_NPE405H,
1254 .pvr_mask = 0xFFFF0000,
1255 .insns_flags = PPC_INSNS_405,
1256 .flags = PPC_FLAGS_405,
1257 .msr_mask = 0x00000000020EFF30,
1264 .pvr = CPU_PPC_NPE405L,
1265 .pvr_mask = 0xFFFF0000,
1266 .insns_flags = PPC_INSNS_405,
1267 .flags = PPC_FLAGS_405,
1268 .msr_mask = 0x00000000020EFF30,
1275 .pvr = CPU_PPC_STB03,
1276 .pvr_mask = 0xFFFF0000,
1277 .insns_flags = PPC_INSNS_405,
1278 .flags = PPC_FLAGS_405,
1279 .msr_mask = 0x00000000020EFF30,
1286 .pvr = CPU_PPC_STB04,
1287 .pvr_mask = 0xFFFF0000,
1288 .insns_flags = PPC_INSNS_405,
1289 .flags = PPC_FLAGS_405,
1290 .msr_mask = 0x00000000020EFF30,
1297 .pvr = CPU_PPC_STB25,
1298 .pvr_mask = 0xFFFF0000,
1299 .insns_flags = PPC_INSNS_405,
1300 .flags = PPC_FLAGS_405,
1301 .msr_mask = 0x00000000020EFF30,
1308 .pvr = CPU_PPC_440EP,
1309 .pvr_mask = 0xFFFF0000,
1310 .insns_flags = PPC_INSNS_440,
1311 .flags = PPC_FLAGS_440,
1312 .msr_mask = 0x000000000006D630,
1319 .pvr = CPU_PPC_440GP,
1320 .pvr_mask = 0xFFFFFF00,
1321 .insns_flags = PPC_INSNS_440,
1322 .flags = PPC_FLAGS_440,
1323 .msr_mask = 0x000000000006D630,
1330 .pvr = CPU_PPC_440GX,
1331 .pvr_mask = 0xFFFF0000,
1332 .insns_flags = PPC_INSNS_405,
1333 .flags = PPC_FLAGS_440,
1334 .msr_mask = 0x000000000006D630,
1338 /* 32 bits "classic" powerpc */
1344 .pvr_mask = 0xFFFF0000,
1345 .insns_flags = PPC_INSNS_601,
1346 .flags = PPC_FLAGS_601,
1347 .msr_mask = 0x000000000000FD70,
1355 .pvr_mask = 0xFFFF0000,
1356 .insns_flags = PPC_INSNS_602,
1357 .flags = PPC_FLAGS_602,
1358 .msr_mask = 0x0000000000C7FF73,
1366 .pvr_mask = 0xFFFF0000,
1367 .insns_flags = PPC_INSNS_603,
1368 .flags = PPC_FLAGS_603,
1369 .msr_mask = 0x000000000007FF73,
1376 .pvr = CPU_PPC_603E,
1377 .pvr_mask = 0xFFFF0000,
1378 .insns_flags = PPC_INSNS_603,
1379 .flags = PPC_FLAGS_603,
1380 .msr_mask = 0x000000000007FF73,
1384 .pvr = CPU_PPC_603E,
1385 .pvr_mask = 0xFFFF0000,
1386 .insns_flags = PPC_INSNS_603,
1387 .flags = PPC_FLAGS_603,
1388 .msr_mask = 0x000000000007FF73,
1395 .pvr = CPU_PPC_603EV,
1396 .pvr_mask = 0xFFFFF000,
1397 .insns_flags = PPC_INSNS_603,
1398 .flags = PPC_FLAGS_603,
1399 .msr_mask = 0x000000000007FF73,
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,
1422 /* XXX: TODO: according to Motorola UM, this is a derivative to 603e */
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 */
1433 .pvr = CPU_PPC_G2LE,
1434 .pvr_mask = 0xFFFF0000,
1435 .insns_flags = PPC_INSNS_G2,
1436 .flags = PPC_FLAGS_G2,
1437 .msr_mask = 0x000000000007FFF3,
1444 .pvr_mask = 0xFFFF0000,
1445 .insns_flags = PPC_INSNS_604,
1446 .flags = PPC_FLAGS_604,
1447 .msr_mask = 0x000000000005FF77,
1452 .pvr = CPU_PPC_604E,
1453 .pvr_mask = 0xFFFF0000,
1454 .insns_flags = PPC_INSNS_604,
1455 .flags = PPC_FLAGS_604,
1456 .msr_mask = 0x000000000005FF77,
1461 .pvr = CPU_PPC_604R,
1462 .pvr_mask = 0xFFFF0000,
1463 .insns_flags = PPC_INSNS_604,
1464 .flags = PPC_FLAGS_604,
1465 .msr_mask = 0x000000000005FF77,
1471 .pvr_mask = 0xFFFFF000,
1472 .insns_flags = PPC_INSNS_7x0,
1473 .flags = PPC_FLAGS_7x0,
1474 .msr_mask = 0x000000000007FF77,
1481 .pvr_mask = 0xFFFFF000,
1482 .insns_flags = PPC_INSNS_7x0,
1483 .flags = PPC_FLAGS_7x0,
1484 .msr_mask = 0x000000000007FF77,
1489 .pvr_mask = 0xFFFFF000,
1490 .insns_flags = PPC_INSNS_7x0,
1491 .flags = PPC_FLAGS_7x0,
1492 .msr_mask = 0x000000000007FF77,
1500 .pvr_mask = 0xFFFFF000,
1501 .insns_flags = PPC_INSNS_7x5,
1502 .flags = PPC_FLAGS_7x5,
1503 .msr_mask = 0x000000000007FF77,
1506 .name = "Goldfinger",
1508 .pvr_mask = 0xFFFFF000,
1509 .insns_flags = PPC_INSNS_7x5,
1510 .flags = PPC_FLAGS_7x5,
1511 .msr_mask = 0x000000000007FF77,
1518 .pvr_mask = 0xFFFFF000,
1519 .insns_flags = PPC_INSNS_7x0,
1520 .flags = PPC_FLAGS_7x0,
1521 .msr_mask = 0x000000000007FF77,
1528 .pvr_mask = 0xFFFFF000,
1529 .insns_flags = PPC_INSNS_7x5,
1530 .flags = PPC_FLAGS_7x5,
1531 .msr_mask = 0x000000000007FF77,
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,
1557 .pvr = CPU_PPC_74xP,
1558 .pvr_mask = 0xFFFFF000,
1559 .insns_flags = PPC_INSNS_7x5,
1560 .flags = PPC_FLAGS_7x5,
1561 .msr_mask = 0x000000000007FF77,
1567 .pvr = CPU_PPC_74xP,
1568 .pvr_mask = 0xFFFFF000,
1569 .insns_flags = PPC_INSNS_7x0,
1570 .flags = PPC_FLAGS_7x0,
1571 .msr_mask = 0x000000000007FF77,
1577 .pvr = CPU_PPC_74xP,
1578 .pvr_mask = 0xFFFFF000,
1579 .insns_flags = PPC_INSNS_7x5,
1580 .flags = PPC_FLAGS_7x5,
1581 .msr_mask = 0x000000000007FF77,
1584 /* IBM 750CXe (G3 embedded) */
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) */
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) */
1605 .pvr = CPU_PPC_750GX,
1606 .pvr_mask = 0xFFFF0000,
1607 .insns_flags = PPC_INSNS_7x0,
1608 .flags = PPC_FLAGS_7x0,
1609 .msr_mask = 0x000000000007FF77,
1615 .pvr = CPU_PPC_7400,
1616 .pvr_mask = 0xFFFF0000,
1617 .insns_flags = PPC_INSNS_74xx,
1618 .flags = PPC_FLAGS_74xx,
1619 .msr_mask = 0x000000000205FF77,
1626 .pvr = CPU_PPC_7400,
1627 .pvr_mask = 0xFFFF0000,
1628 .insns_flags = PPC_INSNS_74xx,
1629 .flags = PPC_FLAGS_74xx,
1630 .msr_mask = 0x000000000205FF77,
1634 .pvr = CPU_PPC_7400,
1635 .pvr_mask = 0xFFFF0000,
1636 .insns_flags = PPC_INSNS_74xx,
1637 .flags = PPC_FLAGS_74xx,
1638 .msr_mask = 0x000000000205FF77,
1645 .pvr = CPU_PPC_7410,
1646 .pvr_mask = 0xFFFF0000,
1647 .insns_flags = PPC_INSNS_74xx,
1648 .flags = PPC_FLAGS_74xx,
1649 .msr_mask = 0x000000000205FF77,
1653 .pvr = CPU_PPC_7410,
1654 .pvr_mask = 0xFFFF0000,
1655 .insns_flags = PPC_INSNS_74xx,
1656 .flags = PPC_FLAGS_74xx,
1657 .msr_mask = 0x000000000205FF77,
1668 .pvr = CPU_PPC_7450,
1669 .pvr_mask = 0xFFFF0000,
1670 .insns_flags = PPC_INSNS_74xx,
1671 .flags = PPC_FLAGS_74xx,
1672 .msr_mask = 0x000000000205FF77,
1676 .pvr = CPU_PPC_7450,
1677 .pvr_mask = 0xFFFF0000,
1678 .insns_flags = PPC_INSNS_74xx,
1679 .flags = PPC_FLAGS_74xx,
1680 .msr_mask = 0x000000000205FF77,
1688 .pvr = CPU_PPC_7455,
1689 .pvr_mask = 0xFFFF0000,
1690 .insns_flags = PPC_INSNS_74xx,
1691 .flags = PPC_FLAGS_74xx,
1692 .msr_mask = 0x000000000205FF77,
1696 .pvr = CPU_PPC_7455,
1697 .pvr_mask = 0xFFFF0000,
1698 .insns_flags = PPC_INSNS_74xx,
1699 .flags = PPC_FLAGS_74xx,
1700 .msr_mask = 0x000000000205FF77,
1707 .pvr = CPU_PPC_7457,
1708 .pvr_mask = 0xFFFF0000,
1709 .insns_flags = PPC_INSNS_74xx,
1710 .flags = PPC_FLAGS_74xx,
1711 .msr_mask = 0x000000000205FF77,
1715 .pvr = CPU_PPC_7457,
1716 .pvr_mask = 0xFFFF0000,
1717 .insns_flags = PPC_INSNS_74xx,
1718 .flags = PPC_FLAGS_74xx,
1719 .msr_mask = 0x000000000205FF77,
1723 /* PPC 7457A (G4) */
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,
1747 .pvr_mask = 0xFFFF0000,
1748 .insns_flags = PPC_INSNS_620,
1749 .flags = PPC_FLAGS_620,
1750 .msr_mask = 0x800000000005FF73,
1754 /* PPC 630 (POWER3) */
1758 .pvr_mask = 0xFFFF0000,
1759 .insns_flags = PPC_INSNS_630,
1760 .flags = PPC_FLAGS_630,
1766 .pvr_mask = 0xFFFF0000,
1767 .insns_flags = PPC_INSNS_630,
1768 .flags = PPC_FLAGS_630,
1773 /* PPC 631 (Power 3+)*/
1777 .pvr_mask = 0xFFFF0000,
1778 .insns_flags = PPC_INSNS_631,
1779 .flags = PPC_FLAGS_631,
1785 .pvr_mask = 0xFFFF0000,
1786 .insns_flags = PPC_INSNS_631,
1787 .flags = PPC_FLAGS_631,
1795 .pvr = CPU_PPC_POWER4,
1796 .pvr_mask = 0xFFFF0000,
1797 .insns_flags = PPC_INSNS_POWER4,
1798 .flags = PPC_FLAGS_POWER4,
1806 .pvr = CPU_PPC_POWER4P,
1807 .pvr_mask = 0xFFFF0000,
1808 .insns_flags = PPC_INSNS_POWER4,
1809 .flags = PPC_FLAGS_POWER4,
1817 .pvr = CPU_PPC_POWER5,
1818 .pvr_mask = 0xFFFF0000,
1819 .insns_flags = PPC_INSNS_POWER5,
1820 .flags = PPC_FLAGS_POWER5,
1828 .pvr = CPU_PPC_POWER5P,
1829 .pvr_mask = 0xFFFF0000,
1830 .insns_flags = PPC_INSNS_POWER5,
1831 .flags = PPC_FLAGS_POWER5,
1840 .pvr_mask = 0xFFFF0000,
1841 .insns_flags = PPC_INSNS_970,
1842 .flags = PPC_FLAGS_970,
1843 .msr_mask = 0x900000000204FF36,
1847 /* PPC 970FX (G5) */
1850 .pvr = CPU_PPC_970FX,
1851 .pvr_mask = 0xFFFF0000,
1852 .insns_flags = PPC_INSNS_970FX,
1853 .flags = PPC_FLAGS_970FX,
1854 .msr_mask = 0x800000000204FF36,
1858 /* RS64 (Apache/A35) */
1859 /* This one seems to support the whole POWER2 instruction set
1860 * and the PowerPC 64 one.
1864 .pvr = CPU_PPC_RS64,
1865 .pvr_mask = 0xFFFF0000,
1866 .insns_flags = PPC_INSNS_RS64,
1867 .flags = PPC_FLAGS_RS64,
1872 .pvr = CPU_PPC_RS64,
1873 .pvr_mask = 0xFFFF0000,
1874 .insns_flags = PPC_INSNS_RS64,
1875 .flags = PPC_FLAGS_RS64,
1880 .pvr = CPU_PPC_RS64,
1881 .pvr_mask = 0xFFFF0000,
1882 .insns_flags = PPC_INSNS_RS64,
1883 .flags = PPC_FLAGS_RS64,
1888 /* RS64-II (NorthStar/A50) */
1891 .pvr = CPU_PPC_RS64II,
1892 .pvr_mask = 0xFFFF0000,
1893 .insns_flags = PPC_INSNS_RS64,
1894 .flags = PPC_FLAGS_RS64,
1899 .pvr = CPU_PPC_RS64II,
1900 .pvr_mask = 0xFFFF0000,
1901 .insns_flags = PPC_INSNS_RS64,
1902 .flags = PPC_FLAGS_RS64,
1907 .pvr = CPU_PPC_RS64II,
1908 .pvr_mask = 0xFFFF0000,
1909 .insns_flags = PPC_INSNS_RS64,
1910 .flags = PPC_FLAGS_RS64,
1915 /* RS64-III (Pulsar) */
1918 .pvr = CPU_PPC_RS64III,
1919 .pvr_mask = 0xFFFF0000,
1920 .insns_flags = PPC_INSNS_RS64,
1921 .flags = PPC_FLAGS_RS64,
1926 .pvr = CPU_PPC_RS64III,
1927 .pvr_mask = 0xFFFF0000,
1928 .insns_flags = PPC_INSNS_RS64,
1929 .flags = PPC_FLAGS_RS64,
1934 /* RS64-IV (IceStar/IStar/SStar) */
1937 .pvr = CPU_PPC_RS64IV,
1938 .pvr_mask = 0xFFFF0000,
1939 .insns_flags = PPC_INSNS_RS64,
1940 .flags = PPC_FLAGS_RS64,
1945 .pvr = CPU_PPC_RS64IV,
1946 .pvr_mask = 0xFFFF0000,
1947 .insns_flags = PPC_INSNS_RS64,
1948 .flags = PPC_FLAGS_RS64,
1953 .pvr = CPU_PPC_RS64IV,
1954 .pvr_mask = 0xFFFF0000,
1955 .insns_flags = PPC_INSNS_RS64,
1956 .flags = PPC_FLAGS_RS64,
1961 .pvr = CPU_PPC_RS64IV,
1962 .pvr_mask = 0xFFFF0000,
1963 .insns_flags = PPC_INSNS_RS64,
1964 .flags = PPC_FLAGS_RS64,
1970 /* Original POWER */
1974 .pvr_mask = 0xFFFF0000,
1975 .insns_flags = PPC_INSNS_POWER,
1976 .flags = PPC_FLAGS_POWER,
1985 .pvr_mask = 0xFFFF0000,
1986 .insns_flags = PPC_INSNS_POWER,
1987 .flags = PPC_FLAGS_POWER,
1991 /* Generic PowerPCs */
1996 .pvr_mask = 0xFFFF0000,
1997 .insns_flags = PPC_INSNS_PPC64,
1998 .flags = PPC_FLAGS_PPC64,
1999 .msr_mask = 0xA00000000204FF36,
2005 .pvr_mask = 0xFFFF0000,
2006 .insns_flags = PPC_INSNS_PPC32,
2007 .flags = PPC_FLAGS_PPC32,
2008 .msr_mask = 0x000000000005FF77,
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)
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];
2038 int ppc_find_by_pvr (uint32_t pvr, ppc_def_t **def)
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];
2056 void ppc_cpu_list (FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
2060 for (i = 0; ; i++) {
2061 (*cpu_fprintf)(f, "PowerPC '%s' PVR %08x mask %08x\n",
2063 ppc_defs[i].pvr, ppc_defs[i].pvr_mask);
2064 if (strcmp(ppc_defs[i].name, "ppc") == 0)