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 %08llx\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)