1 |
/* |
/* |
2 |
* Copyright (C) 2005 Anders Gavare. All rights reserved. |
* Copyright (C) 2005-2006 Anders Gavare. All rights reserved. |
3 |
* |
* |
4 |
* Redistribution and use in source and binary forms, with or without |
* Redistribution and use in source and binary forms, with or without |
5 |
* modification, are permitted provided that the following conditions are met: |
* modification, are permitted provided that the following conditions are met: |
25 |
* SUCH DAMAGE. |
* SUCH DAMAGE. |
26 |
* |
* |
27 |
* |
* |
28 |
* $Id: cpu_ppc.c,v 1.35 2005/11/24 01:15:06 debug Exp $ |
* $Id: cpu_ppc.c,v 1.45 2006/01/24 21:26:01 debug Exp $ |
29 |
* |
* |
30 |
* PowerPC/POWER CPU emulation. |
* PowerPC/POWER CPU emulation. |
31 |
*/ |
*/ |
40 |
#include "machine.h" |
#include "machine.h" |
41 |
#include "memory.h" |
#include "memory.h" |
42 |
#include "misc.h" |
#include "misc.h" |
43 |
|
#include "of.h" |
44 |
#include "opcodes_ppc.h" |
#include "opcodes_ppc.h" |
45 |
#include "ppc_bat.h" |
#include "ppc_bat.h" |
46 |
#include "ppc_pte.h" |
#include "ppc_pte.h" |
95 |
cpu->cd.ppc.bits = cpu->cd.ppc.cpu_type.bits; |
cpu->cd.ppc.bits = cpu->cd.ppc.cpu_type.bits; |
96 |
cpu->cd.ppc.spr[SPR_PVR] = cpu->cd.ppc.cpu_type.pvr; |
cpu->cd.ppc.spr[SPR_PVR] = cpu->cd.ppc.cpu_type.pvr; |
97 |
|
|
98 |
|
cpu->cd.ppc.spr[SPR_IBAT0U] = 0x00001ffc | BAT_Vs; |
99 |
|
cpu->cd.ppc.spr[SPR_IBAT0L] = 0x00000000 | BAT_PP_RW; |
100 |
|
cpu->cd.ppc.spr[SPR_IBAT1U] = 0xc0001ffc | BAT_Vs; |
101 |
|
cpu->cd.ppc.spr[SPR_IBAT1L] = 0x00000000 | BAT_PP_RW; |
102 |
|
cpu->cd.ppc.spr[SPR_IBAT3U] = 0xf0001ffc | BAT_Vs; |
103 |
|
cpu->cd.ppc.spr[SPR_IBAT3L] = 0xf0000000 | BAT_PP_RW; |
104 |
|
cpu->cd.ppc.spr[SPR_DBAT0U] = 0x00001ffc | BAT_Vs; |
105 |
|
cpu->cd.ppc.spr[SPR_DBAT0L] = 0x00000000 | BAT_PP_RW; |
106 |
|
cpu->cd.ppc.spr[SPR_DBAT1U] = 0xc0001ffc | BAT_Vs; |
107 |
|
cpu->cd.ppc.spr[SPR_DBAT1L] = 0x00000000 | BAT_PP_RW; |
108 |
|
cpu->cd.ppc.spr[SPR_DBAT2U] = 0xe0001ffc | BAT_Vs; |
109 |
|
cpu->cd.ppc.spr[SPR_DBAT2L] = 0xe0000000 | BAT_PP_RW; |
110 |
|
cpu->cd.ppc.spr[SPR_DBAT3U] = 0xf0001ffc | BAT_Vs; |
111 |
|
cpu->cd.ppc.spr[SPR_DBAT3L] = 0xf0000000 | BAT_PP_RW; |
112 |
|
|
113 |
cpu->is_32bit = (cpu->cd.ppc.bits == 32)? 1 : 0; |
cpu->is_32bit = (cpu->cd.ppc.bits == 32)? 1 : 0; |
114 |
|
|
115 |
if (cpu->is_32bit) { |
if (cpu->is_32bit) { |
300 |
|
|
301 |
cpu->pc = exception_nr * 0x100; |
cpu->pc = exception_nr * 0x100; |
302 |
if (cpu->cd.ppc.msr & PPC_MSR_IP) |
if (cpu->cd.ppc.msr & PPC_MSR_IP) |
303 |
cpu->pc += 0xfff00000; |
cpu->pc += 0xfff00000ULL; |
304 |
|
|
305 |
if (cpu->is_32bit) |
if (cpu->is_32bit) |
306 |
ppc32_pc_to_pointers(cpu); |
ppc32_pc_to_pointers(cpu); |
341 |
debug("%08x", (int)cpu->cd.ppc.spr[SPR_LR]); |
debug("%08x", (int)cpu->cd.ppc.spr[SPR_LR]); |
342 |
else |
else |
343 |
debug("%016llx", (long long)cpu->cd.ppc.spr[SPR_LR]); |
debug("%016llx", (long long)cpu->cd.ppc.spr[SPR_LR]); |
344 |
debug(" cr = 0x%08x\n", (int)cpu->cd.ppc.cr); |
debug(" cr = 0x%08x", (int)cpu->cd.ppc.cr); |
345 |
|
|
346 |
debug("cpu%i: ctr = 0x", x); |
if (bits32) |
347 |
|
debug(" "); |
348 |
|
else |
349 |
|
debug("\ncpu%i: ", x); |
350 |
|
debug("ctr = 0x", x); |
351 |
if (bits32) |
if (bits32) |
352 |
debug("%08x", (int)cpu->cd.ppc.spr[SPR_CTR]); |
debug("%08x", (int)cpu->cd.ppc.spr[SPR_CTR]); |
353 |
else |
else |
383 |
} |
} |
384 |
|
|
385 |
/* Other special registers: */ |
/* Other special registers: */ |
386 |
debug("cpu%i: srr0 = 0x%016llx srr1 = 0x%016llx\n", x, |
if (bits32) { |
387 |
(long long)cpu->cd.ppc.spr[SPR_SRR0], |
debug("cpu%i: srr0 = 0x%08x srr1 = 0x%08x\n", x, |
388 |
(long long)cpu->cd.ppc.spr[SPR_SRR1]); |
(int)cpu->cd.ppc.spr[SPR_SRR0], |
389 |
|
(int)cpu->cd.ppc.spr[SPR_SRR1]); |
390 |
|
} else { |
391 |
|
debug("cpu%i: srr0 = 0x%016llx srr1 = 0x%016llx\n", x, |
392 |
|
(long long)cpu->cd.ppc.spr[SPR_SRR0], |
393 |
|
(long long)cpu->cd.ppc.spr[SPR_SRR1]); |
394 |
|
} |
395 |
|
debug("cpu%i: msr = ", x); |
396 |
reg_access_msr(cpu, &tmp, 0, 0); |
reg_access_msr(cpu, &tmp, 0, 0); |
397 |
debug("cpu%i: msr = 0x%016llx ", x, (long long)tmp); |
if (bits32) |
398 |
|
debug("0x%08x ", (int)tmp); |
399 |
|
else |
400 |
|
debug("0x%016llx ", (long long)tmp); |
401 |
debug("tb = 0x%08x%08x\n", (int)cpu->cd.ppc.spr[SPR_TBU], |
debug("tb = 0x%08x%08x\n", (int)cpu->cd.ppc.spr[SPR_TBU], |
402 |
(int)cpu->cd.ppc.spr[SPR_TBL]); |
(int)cpu->cd.ppc.spr[SPR_TBL]); |
403 |
debug("cpu%i: dec = 0x%08x hdec = 0x%08x\n", |
debug("cpu%i: dec = 0x%08x", x, (int)cpu->cd.ppc.spr[SPR_DEC]); |
404 |
x, (int)cpu->cd.ppc.spr[SPR_DEC], |
if (!bits32) |
405 |
(int)cpu->cd.ppc.spr[SPR_HDEC]); |
debug(" hdec = 0x%08x\n", |
406 |
|
(int)cpu->cd.ppc.spr[SPR_HDEC]); |
407 |
|
debug("\n"); |
408 |
} |
} |
409 |
|
|
410 |
if (coprocs & 1) { |
if (coprocs & 1) { |
687 |
hi6 = iword >> 26; |
hi6 = iword >> 26; |
688 |
|
|
689 |
switch (hi6) { |
switch (hi6) { |
690 |
|
case 0x4: |
691 |
|
debug("ALTIVEC TODO"); |
692 |
|
/* vxor etc */ |
693 |
|
break; |
694 |
case PPC_HI6_MULLI: |
case PPC_HI6_MULLI: |
695 |
case PPC_HI6_SUBFIC: |
case PPC_HI6_SUBFIC: |
696 |
rt = (iword >> 21) & 31; |
rt = (iword >> 21) & 31; |
1113 |
} |
} |
1114 |
debug("%s%s\tr%i,r%i", mnem, rc? "." : "", rt, ra); |
debug("%s%s\tr%i,r%i", mnem, rc? "." : "", rt, ra); |
1115 |
break; |
break; |
1116 |
|
case PPC_31_WRTEEI: |
1117 |
|
debug("wrteei\t%i", iword & 0x8000? 1 : 0); |
1118 |
|
break; |
1119 |
case PPC_31_ADDZE: |
case PPC_31_ADDZE: |
1120 |
case PPC_31_ADDZEO: |
case PPC_31_ADDZEO: |
1121 |
rt = (iword >> 21) & 31; |
rt = (iword >> 21) & 31; |
1286 |
else |
else |
1287 |
debug("tlbie\tr%i", rb); |
debug("tlbie\tr%i", rb); |
1288 |
break; |
break; |
1289 |
|
case PPC_31_TLBSX_DOT: |
1290 |
|
rs = (iword >> 21) & 31; |
1291 |
|
ra = (iword >> 16) & 31; |
1292 |
|
rb = (iword >> 11) & 31; |
1293 |
|
debug("tlbsx.\tr%i,r%i,r%i", rs, ra, rb); |
1294 |
|
break; |
1295 |
case PPC_31_TLBSYNC: |
case PPC_31_TLBSYNC: |
1296 |
debug("tlbsync"); |
debug("tlbsync"); |
1297 |
break; |
break; |
1469 |
} |
} |
1470 |
debug("%s%s\tr%i,r%i", mnem, rc? "." : "", ra, rs); |
debug("%s%s\tr%i,r%i", mnem, rc? "." : "", ra, rs); |
1471 |
break; |
break; |
1472 |
|
case 359: |
1473 |
|
debug("TODO: ALTIVEC 359"); |
1474 |
|
break; |
1475 |
|
case PPC_31_LVX: |
1476 |
|
debug("lvx\tTODO: ALTIVEC"); |
1477 |
|
break; |
1478 |
|
case PPC_31_STVX: |
1479 |
|
debug("stvx\tTODO: ALTIVEC"); |
1480 |
|
break; |
1481 |
|
case PPC_31_STVXL: |
1482 |
|
debug("stvxl\tTODO: ALTIVEC"); |
1483 |
|
break; |
1484 |
default: |
default: |
1485 |
debug("unimplemented hi6_31, xo = 0x%x", xo); |
debug("unimplemented hi6_31, xo = 0x%x", xo); |
1486 |
} |
} |