25 |
* SUCH DAMAGE. |
* SUCH DAMAGE. |
26 |
* |
* |
27 |
* |
* |
28 |
* $Id: cpu_ppc.c,v 1.61 2005/04/01 16:44:36 debug Exp $ |
* $Id: cpu_ppc.c,v 1.63 2005/06/26 22:23:42 debug Exp $ |
29 |
* |
* |
30 |
* PowerPC/POWER CPU emulation. |
* PowerPC/POWER CPU emulation. |
31 |
*/ |
*/ |
77 |
* ppc_cpu_new(): |
* ppc_cpu_new(): |
78 |
* |
* |
79 |
* Create a new PPC cpu object. |
* Create a new PPC cpu object. |
80 |
|
* |
81 |
|
* Returns 1 on success, 0 if there was no matching PPC processor with |
82 |
|
* this cpu_type_name. |
83 |
*/ |
*/ |
84 |
struct cpu *ppc_cpu_new(struct memory *mem, struct machine *machine, |
int ppc_cpu_new(struct cpu *cpu, struct memory *mem, struct machine *machine, |
85 |
int cpu_id, char *cpu_type_name) |
int cpu_id, char *cpu_type_name) |
86 |
{ |
{ |
|
struct cpu *cpu; |
|
87 |
int any_cache = 0; |
int any_cache = 0; |
88 |
int i, found; |
int i, found; |
89 |
struct ppc_cpu_type_def cpu_type_defs[] = PPC_CPU_TYPE_DEFS; |
struct ppc_cpu_type_def cpu_type_defs[] = PPC_CPU_TYPE_DEFS; |
99 |
i++; |
i++; |
100 |
} |
} |
101 |
if (found == -1) |
if (found == -1) |
102 |
return NULL; |
return 0; |
|
|
|
|
cpu = malloc(sizeof(struct cpu)); |
|
|
if (cpu == NULL) { |
|
|
fprintf(stderr, "out of memory\n"); |
|
|
exit(1); |
|
|
} |
|
103 |
|
|
|
memset(cpu, 0, sizeof(struct cpu)); |
|
104 |
cpu->memory_rw = ppc_memory_rw; |
cpu->memory_rw = ppc_memory_rw; |
105 |
cpu->cd.ppc.cpu_type = cpu_type_defs[found]; |
cpu->cd.ppc.cpu_type = cpu_type_defs[found]; |
106 |
cpu->name = cpu->cd.ppc.cpu_type.name; |
cpu->name = cpu->cd.ppc.cpu_type.name; |
|
cpu->mem = mem; |
|
|
cpu->machine = machine; |
|
|
cpu->cpu_id = cpu_id; |
|
107 |
cpu->byte_order = EMUL_BIG_ENDIAN; |
cpu->byte_order = EMUL_BIG_ENDIAN; |
108 |
cpu->cd.ppc.mode = MODE_PPC; /* TODO */ |
cpu->cd.ppc.mode = MODE_PPC; /* TODO */ |
109 |
cpu->cd.ppc.of_emul_addr = 0xff000000; /* TODO */ |
cpu->cd.ppc.of_emul_addr = 0xff000000; /* TODO */ |
110 |
|
|
111 |
/* Current operating mode: */ |
/* Current operating mode: */ |
112 |
cpu->cd.ppc.bits = cpu->cd.ppc.cpu_type.bits; |
cpu->cd.ppc.bits = cpu->cd.ppc.cpu_type.bits; |
|
cpu->bootstrap_cpu_flag = 0; |
|
|
cpu->running = 0; |
|
113 |
|
|
114 |
/* Only show name and caches etc for CPU nr 0 (in SMP machines): */ |
/* Only show name and caches etc for CPU nr 0 (in SMP machines): */ |
115 |
if (cpu_id == 0) { |
if (cpu_id == 0) { |
140 |
/* Some default stack pointer value. TODO: move this? */ |
/* Some default stack pointer value. TODO: move this? */ |
141 |
cpu->cd.ppc.gpr[1] = machine->physical_ram_in_mb * 1048576 - 4096; |
cpu->cd.ppc.gpr[1] = machine->physical_ram_in_mb * 1048576 - 4096; |
142 |
|
|
143 |
return cpu; |
return 1; |
144 |
} |
} |
145 |
|
|
146 |
|
|
1028 |
case PPC_31_SYNC: |
case PPC_31_SYNC: |
1029 |
debug("%s", power? "dcs" : "sync"); |
debug("%s", power? "dcs" : "sync"); |
1030 |
break; |
break; |
1031 |
|
case PPC_31_LSWI: |
1032 |
case PPC_31_STSWI: |
case PPC_31_STSWI: |
1033 |
rs = (iword >> 21) & 31; |
rs = (iword >> 21) & 31; /* lwsi uses rt */ |
1034 |
ra = (iword >> 16) & 31; |
ra = (iword >> 16) & 31; |
1035 |
nb = (iword >> 11) & 31; |
nb = (iword >> 11) & 31; |
1036 |
debug("%s\tr%i,r%i,%i", power? "stsi" : "stswi", |
switch (xo) { |
1037 |
rs, ra, nb); |
case PPC_31_LSWI: |
1038 |
|
mnem = power? "lsi" : "lswi"; break; |
1039 |
|
case PPC_31_STSWI: |
1040 |
|
mnem = power? "stsi" : "stswi"; break; |
1041 |
|
} |
1042 |
|
debug("%s\tr%i,r%i,%i", mnem, rs, ra, nb); |
1043 |
if (running) |
if (running) |
1044 |
goto disasm_ret_nonewline; |
goto disasm_ret_nonewline; |
1045 |
break; |
break; |
2457 |
/* TODO: actually sync */ |
/* TODO: actually sync */ |
2458 |
break; |
break; |
2459 |
|
|
2460 |
|
case PPC_31_LSWI: |
2461 |
case PPC_31_STSWI: |
case PPC_31_STSWI: |
2462 |
rs = (iword >> 21) & 31; |
rs = (iword >> 21) & 31; |
2463 |
ra = (iword >> 16) & 31; |
ra = (iword >> 16) & 31; |
2469 |
else |
else |
2470 |
addr = cpu->cd.ppc.gpr[ra]; |
addr = cpu->cd.ppc.gpr[ra]; |
2471 |
|
|
2472 |
|
load = 0; |
2473 |
|
if (xo == PPC_31_LSWI) |
2474 |
|
load = 1; |
2475 |
|
|
2476 |
if (cpu->machine->instruction_trace) { |
if (cpu->machine->instruction_trace) { |
2477 |
if (cpu->cd.ppc.bits == 32) |
if (cpu->cd.ppc.bits == 32) |
2478 |
debug("\t[0x%08llx", (long long)addr); |
debug("\t[0x%08llx", (long long)addr); |
2481 |
} |
} |
2482 |
|
|
2483 |
i = 24; |
i = 24; |
2484 |
r = 0; /* There can be multiple errors */ |
r = 0; /* Error count. */ |
2485 |
while (nb > 0) { |
while (nb-- > 0) { |
2486 |
tmp_data[0] = cpu->cd.ppc.gpr[rs] >> i; |
if (load) { |
2487 |
if (cpu->memory_rw(cpu, cpu->mem, addr, |
/* (Actually rt should be used.) */ |
2488 |
tmp_data, 1, MEM_WRITE, CACHE_DATA) |
if (cpu->memory_rw(cpu, cpu->mem, addr, |
2489 |
!= MEMORY_ACCESS_OK) |
tmp_data, 1, MEM_READ, CACHE_DATA) |
2490 |
r++; |
!= MEMORY_ACCESS_OK) { |
2491 |
nb--; addr++; i-=8; |
r++; |
2492 |
|
break; |
2493 |
|
} |
2494 |
|
if (i == 24) |
2495 |
|
cpu->cd.ppc.gpr[rs] = 0; |
2496 |
|
cpu->cd.ppc.gpr[rs] |= |
2497 |
|
(tmp_data[0] << i); |
2498 |
|
} else { |
2499 |
|
tmp_data[0] = cpu->cd.ppc.gpr[rs] >> i; |
2500 |
|
if (cpu->memory_rw(cpu, cpu->mem, addr, |
2501 |
|
tmp_data, 1, MEM_WRITE, CACHE_DATA) |
2502 |
|
!= MEMORY_ACCESS_OK) { |
2503 |
|
r++; |
2504 |
|
break; |
2505 |
|
} |
2506 |
|
} |
2507 |
|
addr++; i-=8; |
2508 |
if (i < 0) { |
if (i < 0) { |
2509 |
i = 24; |
i = 24; |
2510 |
rs = (rs + 1) % 32; |
rs = (rs + 1) % 32; |
2520 |
|
|
2521 |
if (r > 0) { |
if (r > 0) { |
2522 |
/* TODO: exception */ |
/* TODO: exception */ |
2523 |
|
fatal("TODO: exception.\n"); |
2524 |
return 0; |
return 0; |
2525 |
} |
} |
2526 |
break; |
break; |