/[gxemul]/trunk/src/cpus/cpu_ppc.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Contents of /trunk/src/cpus/cpu_ppc.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 46 - (show annotations)
Wed Oct 10 21:07:01 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 49833 byte(s)
first cut at emulating DSM G600 -- serial port work and not much else...
1 /*
2 * Copyright (C) 2005-2007 Anders Gavare. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * 3. The name of the author may not be used to endorse or promote products
13 * derived from this software without specific prior written permission.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 *
27 *
28 * $Id: cpu_ppc.c,v 1.72 2007/06/28 13:36:46 debug Exp $
29 *
30 * PowerPC/POWER CPU emulation.
31 */
32
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <ctype.h>
37
38 #include "cpu.h"
39 #include "devices.h"
40 #include "interrupt.h"
41 #include "machine.h"
42 #include "memory.h"
43 #include "misc.h"
44 #include "of.h"
45 #include "opcodes_ppc.h"
46 #include "ppc_bat.h"
47 #include "ppc_pte.h"
48 #include "ppc_spr.h"
49 #include "ppc_spr_strings.h"
50 #include "settings.h"
51 #include "symbol.h"
52 #include "useremul.h"
53
54
55 #define DYNTRANS_DUALMODE_32
56 #include "tmp_ppc_head.c"
57
58
59 void ppc_pc_to_pointers(struct cpu *);
60 void ppc32_pc_to_pointers(struct cpu *);
61
62 void ppc_irq_interrupt_assert(struct interrupt *interrupt);
63 void ppc_irq_interrupt_deassert(struct interrupt *interrupt);
64
65
66 /*
67 * ppc_cpu_new():
68 *
69 * Create a new PPC cpu object.
70 *
71 * Returns 1 on success, 0 if there was no matching PPC processor with
72 * this cpu_type_name.
73 */
74 int ppc_cpu_new(struct cpu *cpu, struct memory *mem, struct machine *machine,
75 int cpu_id, char *cpu_type_name)
76 {
77 int any_cache = 0;
78 int i, found;
79 struct ppc_cpu_type_def cpu_type_defs[] = PPC_CPU_TYPE_DEFS;
80
81 /* Scan the cpu_type_defs list for this cpu type: */
82 i = 0;
83 found = -1;
84 while (i >= 0 && cpu_type_defs[i].name != NULL) {
85 if (strcasecmp(cpu_type_defs[i].name, cpu_type_name) == 0) {
86 found = i;
87 break;
88 }
89 i++;
90 }
91 if (found == -1)
92 return 0;
93
94 cpu->memory_rw = ppc_memory_rw;
95
96 cpu->cd.ppc.cpu_type = cpu_type_defs[found];
97 cpu->name = cpu->cd.ppc.cpu_type.name;
98 cpu->byte_order = EMUL_BIG_ENDIAN;
99 cpu->cd.ppc.mode = MODE_PPC; /* TODO */
100
101 /* Current operating mode: */
102 cpu->cd.ppc.bits = cpu->cd.ppc.cpu_type.bits;
103 cpu->cd.ppc.spr[SPR_PVR] = cpu->cd.ppc.cpu_type.pvr;
104
105 /* cpu->cd.ppc.msr = PPC_MSR_IR | PPC_MSR_DR |
106 PPC_MSR_SF | PPC_MSR_FP; */
107
108 cpu->cd.ppc.spr[SPR_IBAT0U] = 0x00001ffc | BAT_Vs;
109 cpu->cd.ppc.spr[SPR_IBAT0L] = 0x00000000 | BAT_PP_RW;
110 cpu->cd.ppc.spr[SPR_IBAT1U] = 0xc0001ffc | BAT_Vs;
111 cpu->cd.ppc.spr[SPR_IBAT1L] = 0x00000000 | BAT_PP_RW;
112 cpu->cd.ppc.spr[SPR_IBAT3U] = 0xf0001ffc | BAT_Vs;
113 cpu->cd.ppc.spr[SPR_IBAT3L] = 0xf0000000 | BAT_PP_RW;
114 cpu->cd.ppc.spr[SPR_DBAT0U] = 0x00001ffc | BAT_Vs;
115 cpu->cd.ppc.spr[SPR_DBAT0L] = 0x00000000 | BAT_PP_RW;
116 cpu->cd.ppc.spr[SPR_DBAT1U] = 0xc0001ffc | BAT_Vs;
117 cpu->cd.ppc.spr[SPR_DBAT1L] = 0x00000000 | BAT_PP_RW;
118 cpu->cd.ppc.spr[SPR_DBAT2U] = 0xe0001ffc | BAT_Vs;
119 cpu->cd.ppc.spr[SPR_DBAT2L] = 0xe0000000 | BAT_PP_RW;
120 cpu->cd.ppc.spr[SPR_DBAT3U] = 0xf0001ffc | BAT_Vs;
121 cpu->cd.ppc.spr[SPR_DBAT3L] = 0xf0000000 | BAT_PP_RW;
122
123 cpu->is_32bit = (cpu->cd.ppc.bits == 32)? 1 : 0;
124
125 if (cpu->is_32bit) {
126 cpu->run_instr = ppc32_run_instr;
127 cpu->update_translation_table = ppc32_update_translation_table;
128 cpu->invalidate_translation_caches =
129 ppc32_invalidate_translation_caches;
130 cpu->invalidate_code_translation =
131 ppc32_invalidate_code_translation;
132 } else {
133 cpu->run_instr = ppc_run_instr;
134 cpu->update_translation_table = ppc_update_translation_table;
135 cpu->invalidate_translation_caches =
136 ppc_invalidate_translation_caches;
137 cpu->invalidate_code_translation =
138 ppc_invalidate_code_translation;
139 }
140
141 cpu->translate_v2p = ppc_translate_v2p;
142
143 /* Only show name and caches etc for CPU nr 0 (in SMP machines): */
144 if (cpu_id == 0) {
145 debug("%s", cpu->cd.ppc.cpu_type.name);
146
147 if (cpu->cd.ppc.cpu_type.icache_shift != 0)
148 any_cache = 1;
149 if (cpu->cd.ppc.cpu_type.dcache_shift != 0)
150 any_cache = 1;
151 if (cpu->cd.ppc.cpu_type.l2cache_shift != 0)
152 any_cache = 1;
153
154 if (any_cache) {
155 debug(" (I+D = %i+%i KB",
156 (int)(1 << (cpu->cd.ppc.cpu_type.icache_shift-10)),
157 (int)(1 << (cpu->cd.ppc.cpu_type.dcache_shift-10)));
158 if (cpu->cd.ppc.cpu_type.l2cache_shift != 0) {
159 debug(", L2 = %i KB",
160 (int)(1 << (cpu->cd.ppc.cpu_type.
161 l2cache_shift-10)));
162 }
163 debug(")");
164 }
165 }
166
167 cpu->cd.ppc.spr[SPR_PIR] = cpu_id;
168
169 /* Some default stack pointer value. TODO: move this? */
170 cpu->cd.ppc.gpr[1] = machine->physical_ram_in_mb * 1048576 - 4096;
171
172 /*
173 * NOTE/TODO: Ugly hack for OpenFirmware emulation:
174 */
175 if (cpu->machine->prom_emulation)
176 cpu->cd.ppc.of_emul_addr = 0xfff00000;
177
178 /* Add all register names to the settings: */
179 CPU_SETTINGS_ADD_REGISTER64("pc", cpu->pc);
180 CPU_SETTINGS_ADD_REGISTER64("msr", cpu->cd.ppc.msr);
181 CPU_SETTINGS_ADD_REGISTER64("ctr", cpu->cd.ppc.spr[SPR_CTR]);
182 CPU_SETTINGS_ADD_REGISTER64("xer", cpu->cd.ppc.spr[SPR_XER]);
183 CPU_SETTINGS_ADD_REGISTER64("dec", cpu->cd.ppc.spr[SPR_DEC]);
184 CPU_SETTINGS_ADD_REGISTER64("hdec", cpu->cd.ppc.spr[SPR_HDEC]);
185 CPU_SETTINGS_ADD_REGISTER64("srr0", cpu->cd.ppc.spr[SPR_SRR0]);
186 CPU_SETTINGS_ADD_REGISTER64("srr1", cpu->cd.ppc.spr[SPR_SRR1]);
187 CPU_SETTINGS_ADD_REGISTER64("sdr1", cpu->cd.ppc.spr[SPR_SDR1]);
188 CPU_SETTINGS_ADD_REGISTER64("ibat0u", cpu->cd.ppc.spr[SPR_IBAT0U]);
189 CPU_SETTINGS_ADD_REGISTER64("ibat0l", cpu->cd.ppc.spr[SPR_IBAT0L]);
190 CPU_SETTINGS_ADD_REGISTER64("ibat1u", cpu->cd.ppc.spr[SPR_IBAT1U]);
191 CPU_SETTINGS_ADD_REGISTER64("ibat1l", cpu->cd.ppc.spr[SPR_IBAT1L]);
192 CPU_SETTINGS_ADD_REGISTER64("ibat2u", cpu->cd.ppc.spr[SPR_IBAT2U]);
193 CPU_SETTINGS_ADD_REGISTER64("ibat2l", cpu->cd.ppc.spr[SPR_IBAT2L]);
194 CPU_SETTINGS_ADD_REGISTER64("ibat3u", cpu->cd.ppc.spr[SPR_IBAT3U]);
195 CPU_SETTINGS_ADD_REGISTER64("ibat3l", cpu->cd.ppc.spr[SPR_IBAT3L]);
196 CPU_SETTINGS_ADD_REGISTER64("dbat0u", cpu->cd.ppc.spr[SPR_DBAT0U]);
197 CPU_SETTINGS_ADD_REGISTER64("dbat0l", cpu->cd.ppc.spr[SPR_DBAT0L]);
198 CPU_SETTINGS_ADD_REGISTER64("dbat1u", cpu->cd.ppc.spr[SPR_DBAT1U]);
199 CPU_SETTINGS_ADD_REGISTER64("dbat1l", cpu->cd.ppc.spr[SPR_DBAT1L]);
200 CPU_SETTINGS_ADD_REGISTER64("dbat2u", cpu->cd.ppc.spr[SPR_DBAT2U]);
201 CPU_SETTINGS_ADD_REGISTER64("dbat2l", cpu->cd.ppc.spr[SPR_DBAT2L]);
202 CPU_SETTINGS_ADD_REGISTER64("dbat3u", cpu->cd.ppc.spr[SPR_DBAT3U]);
203 CPU_SETTINGS_ADD_REGISTER64("dbat3l", cpu->cd.ppc.spr[SPR_DBAT3L]);
204 CPU_SETTINGS_ADD_REGISTER64("lr", cpu->cd.ppc.spr[SPR_LR]);
205 CPU_SETTINGS_ADD_REGISTER32("cr", cpu->cd.ppc.cr);
206 CPU_SETTINGS_ADD_REGISTER32("fpscr", cpu->cd.ppc.fpscr);
207 /* Integer GPRs, floating point registers, and segment registers: */
208 for (i=0; i<PPC_NGPRS; i++) {
209 char tmpstr[5];
210 snprintf(tmpstr, sizeof(tmpstr), "r%i", i);
211 CPU_SETTINGS_ADD_REGISTER64(tmpstr, cpu->cd.ppc.gpr[i]);
212 }
213 for (i=0; i<PPC_NFPRS; i++) {
214 char tmpstr[5];
215 snprintf(tmpstr, sizeof(tmpstr), "f%i", i);
216 CPU_SETTINGS_ADD_REGISTER64(tmpstr, cpu->cd.ppc.fpr[i]);
217 }
218 for (i=0; i<16; i++) {
219 char tmpstr[5];
220 snprintf(tmpstr, sizeof(tmpstr), "sr%i", i);
221 CPU_SETTINGS_ADD_REGISTER32(tmpstr, cpu->cd.ppc.sr[i]);
222 }
223
224 /* Register the CPU as an interrupt handler: */
225 {
226 struct interrupt template;
227 char name[150];
228 snprintf(name, sizeof(name), "%s", cpu->path);
229 memset(&template, 0, sizeof(template));
230 template.line = 0;
231 template.name = name;
232 template.extra = cpu;
233 template.interrupt_assert = ppc_irq_interrupt_assert;
234 template.interrupt_deassert = ppc_irq_interrupt_deassert;
235 interrupt_handler_register(&template);
236 }
237
238 return 1;
239 }
240
241
242 /*
243 * ppc_cpu_list_available_types():
244 *
245 * Print a list of available PPC CPU types.
246 */
247 void ppc_cpu_list_available_types(void)
248 {
249 int i, j;
250 struct ppc_cpu_type_def tdefs[] = PPC_CPU_TYPE_DEFS;
251
252 i = 0;
253 while (tdefs[i].name != NULL) {
254 debug("%s", tdefs[i].name);
255 for (j=10 - strlen(tdefs[i].name); j>0; j--)
256 debug(" ");
257 i++;
258 if ((i % 6) == 0 || tdefs[i].name == NULL)
259 debug("\n");
260 }
261 }
262
263
264 /*
265 * ppc_cpu_dumpinfo():
266 */
267 void ppc_cpu_dumpinfo(struct cpu *cpu)
268 {
269 struct ppc_cpu_type_def *ct = &cpu->cd.ppc.cpu_type;
270
271 debug(" (%i-bit ", cpu->cd.ppc.bits);
272
273 switch (cpu->cd.ppc.mode) {
274 case MODE_PPC:
275 debug("PPC");
276 break;
277 case MODE_POWER:
278 debug("POWER");
279 break;
280 default:
281 debug("_INTERNAL ERROR_");
282 }
283
284 debug(", I+D = %i+%i KB",
285 (1 << ct->icache_shift) / 1024,
286 (1 << ct->dcache_shift) / 1024);
287
288 if (ct->l2cache_shift) {
289 int kb = (1 << ct->l2cache_shift) / 1024;
290 debug(", L2 = %i %cB",
291 kb >= 1024? kb / 1024 : kb,
292 kb >= 1024? 'M' : 'K');
293 }
294
295 debug(")\n");
296 }
297
298
299 /*
300 * reg_access_msr():
301 */
302 void reg_access_msr(struct cpu *cpu, uint64_t *valuep, int writeflag,
303 int check_for_interrupts)
304 {
305 uint64_t old = cpu->cd.ppc.msr;
306
307 if (valuep == NULL) {
308 fatal("reg_access_msr(): NULL\n");
309 return;
310 }
311
312 if (writeflag) {
313 cpu->cd.ppc.msr = *valuep;
314
315 /* Switching between temporary and real gpr 0..3? */
316 if ((old & PPC_MSR_TGPR) != (cpu->cd.ppc.msr & PPC_MSR_TGPR)) {
317 int i;
318 for (i=0; i<PPC_N_TGPRS; i++) {
319 uint64_t t = cpu->cd.ppc.gpr[i];
320 cpu->cd.ppc.gpr[i] = cpu->cd.ppc.tgpr[i];
321 cpu->cd.ppc.tgpr[i] = t;
322 }
323 }
324
325 if (cpu->cd.ppc.msr & PPC_MSR_IP) {
326 fatal("\n[ Reboot hack for NetBSD/prep. TODO: "
327 "fix this. ]\n");
328 cpu->running = 0;
329 }
330 }
331
332 /* TODO: Is the little-endian bit writable? */
333
334 cpu->cd.ppc.msr &= ~PPC_MSR_LE;
335 if (cpu->byte_order != EMUL_BIG_ENDIAN)
336 cpu->cd.ppc.msr |= PPC_MSR_LE;
337
338 if (!writeflag)
339 *valuep = cpu->cd.ppc.msr;
340
341 if (check_for_interrupts && cpu->cd.ppc.msr & PPC_MSR_EE) {
342 if (cpu->cd.ppc.dec_intr_pending &&
343 !(cpu->cd.ppc.cpu_type.flags & PPC_NO_DEC)) {
344 ppc_exception(cpu, PPC_EXCEPTION_DEC);
345 cpu->cd.ppc.dec_intr_pending = 0;
346 } else if (cpu->cd.ppc.irq_asserted)
347 ppc_exception(cpu, PPC_EXCEPTION_EI);
348 }
349 }
350
351
352 /*
353 * ppc_exception():
354 */
355 void ppc_exception(struct cpu *cpu, int exception_nr)
356 {
357 /* Save PC and MSR: */
358 cpu->cd.ppc.spr[SPR_SRR0] = cpu->pc;
359
360 if (exception_nr >= 0x10 && exception_nr <= 0x13)
361 cpu->cd.ppc.spr[SPR_SRR1] = (cpu->cd.ppc.msr & 0xffff)
362 | (cpu->cd.ppc.cr & 0xf0000000);
363 else
364 cpu->cd.ppc.spr[SPR_SRR1] = (cpu->cd.ppc.msr & 0x87c0ffff);
365
366 if (!quiet_mode)
367 fatal("[ PPC Exception 0x%x; pc=0x%"PRIx64" ]\n",
368 exception_nr, cpu->pc);
369
370 /* Disable External Interrupts, Recoverable Interrupt Mode,
371 and go to Supervisor mode */
372 cpu->cd.ppc.msr &= ~(PPC_MSR_EE | PPC_MSR_RI | PPC_MSR_PR);
373
374 cpu->pc = exception_nr * 0x100;
375 if (cpu->cd.ppc.msr & PPC_MSR_IP)
376 cpu->pc += 0xfff00000ULL;
377
378 if (cpu->is_32bit)
379 ppc32_pc_to_pointers(cpu);
380 else
381 ppc_pc_to_pointers(cpu);
382 }
383
384
385 /*
386 * ppc_cpu_register_dump():
387 *
388 * Dump cpu registers in a relatively readable format.
389 *
390 * gprs: set to non-zero to dump GPRs and some special-purpose registers.
391 * coprocs: if bit i is set, then we should dump registers from coproc i.
392 */
393 void ppc_cpu_register_dump(struct cpu *cpu, int gprs, int coprocs)
394 {
395 char *symbol;
396 uint64_t offset, tmp;
397 int i, x = cpu->cpu_id;
398 int bits32 = cpu->cd.ppc.bits == 32;
399
400 if (gprs) {
401 /* Special registers (pc, ...) first: */
402 symbol = get_symbol_name(&cpu->machine->symbol_context,
403 cpu->pc, &offset);
404
405 debug("cpu%i: pc = 0x", x);
406 if (bits32)
407 debug("%08"PRIx32, (uint32_t)cpu->pc);
408 else
409 debug("%016"PRIx64, (uint64_t)cpu->pc);
410 debug(" <%s>\n", symbol != NULL? symbol : " no symbol ");
411
412 debug("cpu%i: lr = 0x", x);
413 if (bits32)
414 debug("%08"PRIx32, (uint32_t)cpu->cd.ppc.spr[SPR_LR]);
415 else
416 debug("%016"PRIx64, (uint64_t)cpu->cd.ppc.spr[SPR_LR]);
417 debug(" cr = 0x%08"PRIx32, (uint32_t)cpu->cd.ppc.cr);
418
419 if (bits32)
420 debug(" ");
421 else
422 debug("\ncpu%i: ", x);
423 debug("ctr = 0x", x);
424 if (bits32)
425 debug("%08"PRIx32, (uint32_t)cpu->cd.ppc.spr[SPR_CTR]);
426 else
427 debug("%016"PRIx64, (uint64_t)cpu->cd.ppc.spr[SPR_CTR]);
428
429 debug(" xer = 0x", x);
430 if (bits32)
431 debug("%08"PRIx32, (uint32_t)cpu->cd.ppc.spr[SPR_XER]);
432 else
433 debug("%016"PRIx64, (uint64_t)cpu->cd.ppc.spr[SPR_XER]);
434
435 debug("\n");
436
437 if (bits32) {
438 /* 32-bit: */
439 for (i=0; i<PPC_NGPRS; i++) {
440 if ((i % 4) == 0)
441 debug("cpu%i:", x);
442 debug(" r%02i = 0x%08"PRIx32" ", i,
443 (uint32_t) cpu->cd.ppc.gpr[i]);
444 if ((i % 4) == 3)
445 debug("\n");
446 }
447 } else {
448 /* 64-bit: */
449 for (i=0; i<PPC_NGPRS; i++) {
450 int r = (i >> 1) + ((i & 1) << 4);
451 if ((i % 2) == 0)
452 debug("cpu%i:", x);
453 debug(" r%02i = 0x%016"PRIx64" ", r,
454 (uint64_t) cpu->cd.ppc.gpr[r]);
455 if ((i % 2) == 1)
456 debug("\n");
457 }
458 }
459
460 /* Other special registers: */
461 if (bits32) {
462 debug("cpu%i: srr0 = 0x%08"PRIx32
463 " srr1 = 0x%08"PRIx32"\n", x,
464 (uint32_t) cpu->cd.ppc.spr[SPR_SRR0],
465 (uint32_t) cpu->cd.ppc.spr[SPR_SRR1]);
466 } else {
467 debug("cpu%i: srr0 = 0x%016"PRIx64
468 " srr1 = 0x%016"PRIx64"\n", x,
469 (uint64_t) cpu->cd.ppc.spr[SPR_SRR0],
470 (uint64_t) cpu->cd.ppc.spr[SPR_SRR1]);
471 }
472
473 debug("cpu%i: msr = ", x);
474 reg_access_msr(cpu, &tmp, 0, 0);
475 if (bits32)
476 debug("0x%08"PRIx32, (uint32_t) tmp);
477 else
478 debug("0x%016"PRIx64, (uint64_t) tmp);
479
480 debug(" tb = 0x%08"PRIx32"%08"PRIx32"\n",
481 (uint32_t) cpu->cd.ppc.spr[SPR_TBU],
482 (uint32_t) cpu->cd.ppc.spr[SPR_TBL]);
483
484 debug("cpu%i: dec = 0x%08"PRIx32,
485 x, (uint32_t) cpu->cd.ppc.spr[SPR_DEC]);
486 if (!bits32)
487 debug(" hdec = 0x%08"PRIx32"\n",
488 (uint32_t) cpu->cd.ppc.spr[SPR_HDEC]);
489
490 debug("\n");
491 }
492
493 if (coprocs & 1) {
494 debug("cpu%i: fpscr = 0x%08"PRIx32"\n",
495 x, (uint32_t) cpu->cd.ppc.fpscr);
496
497 /* TODO: show floating-point values :-) */
498
499 /* TODO: 32-bit fprs on 32-bit PPC cpus? */
500
501 for (i=0; i<PPC_NFPRS; i++) {
502 if ((i % 2) == 0)
503 debug("cpu%i:", x);
504 debug(" f%02i = 0x%016"PRIx64" ", i,
505 (uint64_t) cpu->cd.ppc.fpr[i]);
506 if ((i % 2) == 1)
507 debug("\n");
508 }
509 }
510
511 if (coprocs & 2) {
512 debug("cpu%i: sdr1 = 0x%"PRIx64"\n", x,
513 (uint64_t) cpu->cd.ppc.spr[SPR_SDR1]);
514 if (cpu->cd.ppc.cpu_type.flags & PPC_601)
515 debug("cpu%i: PPC601-style, TODO!\n");
516 else {
517 for (i=0; i<8; i++) {
518 int spr = SPR_IBAT0U + i*2;
519 uint32_t upper = cpu->cd.ppc.spr[spr];
520 uint32_t lower = cpu->cd.ppc.spr[spr+1];
521 uint32_t len = (((upper & BAT_BL) << 15)
522 | 0x1ffff) + 1;
523 debug("cpu%i: %sbat%i: u=0x%08"PRIx32
524 " l=0x%08"PRIx32" ",
525 x, i<4? "i" : "d", i&3, upper, lower);
526 if (!(upper & BAT_V)) {
527 debug(" (not valid)\n");
528 continue;
529 }
530 if (len < 1048576)
531 debug(" (%i KB, ", len >> 10);
532 else
533 debug(" (%i MB, ", len >> 20);
534 if (upper & BAT_Vu)
535 debug("user, ");
536 if (upper & BAT_Vs)
537 debug("supervisor, ");
538 if (lower & (BAT_W | BAT_I | BAT_M | BAT_G))
539 debug("%s%s%s%s, ",
540 lower & BAT_W? "W" : "",
541 lower & BAT_I? "I" : "",
542 lower & BAT_M? "M" : "",
543 lower & BAT_G? "G" : "");
544 switch (lower & BAT_PP) {
545 case BAT_PP_NONE: debug("NO access"); break;
546 case BAT_PP_RO_S: debug("read-only, soft");
547 break;
548 case BAT_PP_RO: debug("read-only"); break;
549 case BAT_PP_RW: debug("read/write"); break;
550 }
551 debug(")\n");
552 }
553 }
554 }
555
556 if (coprocs & 4) {
557 for (i=0; i<16; i++) {
558 uint32_t s = cpu->cd.ppc.sr[i];
559
560 debug("cpu%i:", x);
561 debug(" sr%-2i = 0x%08"PRIx32, i, s);
562
563 s &= (SR_TYPE | SR_SUKEY | SR_PRKEY | SR_NOEXEC);
564 if (s != 0) {
565 debug(" (");
566 if (s & SR_TYPE) {
567 debug("NON-memory type");
568 s &= ~SR_TYPE;
569 if (s != 0)
570 debug(", ");
571 }
572 if (s & SR_SUKEY) {
573 debug("supervisor-key");
574 s &= ~SR_SUKEY;
575 if (s != 0)
576 debug(", ");
577 }
578 if (s & SR_PRKEY) {
579 debug("user-key");
580 s &= ~SR_PRKEY;
581 if (s != 0)
582 debug(", ");
583 }
584 if (s & SR_NOEXEC)
585 debug("NOEXEC");
586 debug(")");
587 }
588 debug("\n");
589 }
590 }
591 }
592
593
594 /*
595 * ppc_cpu_tlbdump():
596 *
597 * Not currently used for PPC.
598 */
599 void ppc_cpu_tlbdump(struct machine *m, int x, int rawflag)
600 {
601 }
602
603
604 /*
605 * ppc_irq_interrupt_assert():
606 */
607 void ppc_irq_interrupt_assert(struct interrupt *interrupt)
608 {
609 struct cpu *cpu = (struct cpu *) interrupt->extra;
610 cpu->cd.ppc.irq_asserted = 1;
611 }
612
613
614 /*
615 * ppc_irq_interrupt_deassert():
616 */
617 void ppc_irq_interrupt_deassert(struct interrupt *interrupt)
618 {
619 struct cpu *cpu = (struct cpu *) interrupt->extra;
620 cpu->cd.ppc.irq_asserted = 0;
621 }
622
623
624 /*
625 * ppc_cpu_disassemble_instr():
626 *
627 * Convert an instruction word into human readable format, for instruction
628 * tracing.
629 *
630 * If running is 1, cpu->pc should be the address of the instruction.
631 *
632 * If running is 0, things that depend on the runtime environment (eg.
633 * register contents) will not be shown, and addr will be used instead of
634 * cpu->pc for relative addresses.
635 */
636 int ppc_cpu_disassemble_instr(struct cpu *cpu, unsigned char *instr,
637 int running, uint64_t dumpaddr)
638 {
639 int hi6, xo, lev, rt, rs, ra, rb, imm, sh, me, rc, l_bit, oe_bit;
640 int spr, aa_bit, lk_bit, bf, bh, bi, bo, mb, nb, bt, ba, bb, fpreg;
641 int bfa, to, load, wlen, no_rb = 0;
642 uint64_t offset, addr;
643 uint32_t iword;
644 char *symbol, *mnem = "ERROR";
645 int power = cpu->cd.ppc.mode == MODE_POWER;
646
647 if (running)
648 dumpaddr = cpu->pc;
649
650 symbol = get_symbol_name(&cpu->machine->symbol_context,
651 dumpaddr, &offset);
652 if (symbol != NULL && offset==0)
653 debug("<%s>\n", symbol);
654
655 if (cpu->machine->ncpus > 1 && running)
656 debug("cpu%i: ", cpu->cpu_id);
657
658 if (cpu->cd.ppc.bits == 32)
659 debug("%08"PRIx32, (uint32_t) dumpaddr);
660 else
661 debug("%016"PRIx64, (uint64_t) dumpaddr);
662
663 /* NOTE: Fixed to big-endian. */
664 iword = (instr[0] << 24) + (instr[1] << 16) + (instr[2] << 8)
665 + instr[3];
666
667 debug(": %08"PRIx32"\t", iword);
668
669 /*
670 * Decode the instruction:
671 */
672
673 hi6 = iword >> 26;
674
675 switch (hi6) {
676 case 0x4:
677 debug("ALTIVEC TODO");
678 /* vxor etc */
679 break;
680 case PPC_HI6_MULLI:
681 case PPC_HI6_SUBFIC:
682 rt = (iword >> 21) & 31;
683 ra = (iword >> 16) & 31;
684 imm = (int16_t)(iword & 0xffff);
685 switch (hi6) {
686 case PPC_HI6_MULLI:
687 mnem = power? "muli":"mulli";
688 break;
689 case PPC_HI6_SUBFIC:
690 mnem = power? "sfi":"subfic";
691 break;
692 }
693 debug("%s\tr%i,r%i,%i", mnem, rt, ra, imm);
694 break;
695 case PPC_HI6_CMPLI:
696 case PPC_HI6_CMPI:
697 bf = (iword >> 23) & 7;
698 l_bit = (iword >> 21) & 1;
699 ra = (iword >> 16) & 31;
700 if (hi6 == PPC_HI6_CMPLI) {
701 imm = iword & 0xffff;
702 mnem = "cmpl";
703 } else {
704 imm = (int16_t)(iword & 0xffff);
705 mnem = "cmp";
706 }
707 debug("%s%si\t", mnem, l_bit? "d" : "w");
708 if (bf != 0)
709 debug("cr%i,", bf);
710 debug("r%i,%i", ra, imm);
711 break;
712 case PPC_HI6_ADDIC:
713 case PPC_HI6_ADDIC_DOT:
714 rt = (iword >> 21) & 31;
715 ra = (iword >> 16) & 31;
716 rc = hi6 == PPC_HI6_ADDIC_DOT;
717 imm = (int16_t)(iword & 0xffff);
718 mnem = power? "ai":"addic";
719 if (imm < 0 && !power) {
720 mnem = "subic";
721 imm = -imm;
722 }
723 debug("%s%s\tr%i,r%i,%i", mnem, rc?".":"", rt, ra, imm);
724 break;
725 case PPC_HI6_ADDI:
726 rt = (iword >> 21) & 31;
727 ra = (iword >> 16) & 31;
728 imm = (int16_t)(iword & 0xffff);
729 if (ra == 0)
730 debug("li\tr%i,%i", rt, imm);
731 else {
732 mnem = power? "cal":"addi";
733 if (imm < 0 && !power) {
734 mnem = "subi";
735 imm = -imm;
736 }
737 debug("%s\tr%i,r%i,%i", mnem, rt, ra, imm);
738 }
739 break;
740 case PPC_HI6_ADDIS:
741 rt = (iword >> 21) & 31;
742 ra = (iword >> 16) & 31;
743 imm = (int16_t)(iword & 0xffff);
744 if (ra == 0)
745 debug("lis\tr%i,%i", rt, imm);
746 else
747 debug("%s\tr%i,r%i,%i",
748 power? "cau":"addis", rt, ra, imm);
749 break;
750 case PPC_HI6_BC:
751 aa_bit = (iword & 2) >> 1;
752 lk_bit = iword & 1;
753 bo = (iword >> 21) & 31;
754 bi = (iword >> 16) & 31;
755 /* Sign-extend addr: */
756 addr = (int64_t)(int16_t)(iword & 0xfffc);
757 debug("bc");
758 if (lk_bit)
759 debug("l");
760 if (aa_bit)
761 debug("a");
762 else
763 addr += dumpaddr;
764 debug("\t%i,%i,", bo, bi);
765 if (cpu->cd.ppc.bits == 32)
766 addr &= 0xffffffff;
767 if (cpu->cd.ppc.bits == 32)
768 debug("0x%"PRIx32, (uint32_t) addr);
769 else
770 debug("0x%"PRIx64, (uint64_t) addr);
771 symbol = get_symbol_name(&cpu->machine->symbol_context,
772 addr, &offset);
773 if (symbol != NULL)
774 debug("\t<%s>", symbol);
775 break;
776 case PPC_HI6_SC:
777 lev = (iword >> 5) & 0x7f;
778 debug("sc");
779 if (lev != 0) {
780 debug("\t%i", lev);
781 if (lev > 1)
782 debug(" (WARNING! reserved value)");
783 }
784 break;
785 case PPC_HI6_B:
786 aa_bit = (iword & 2) >> 1;
787 lk_bit = iword & 1;
788 /* Sign-extend addr: */
789 addr = (int64_t)(int32_t)((iword & 0x03fffffc) << 6);
790 addr = (int64_t)addr >> 6;
791 debug("b");
792 if (lk_bit)
793 debug("l");
794 if (aa_bit)
795 debug("a");
796 else
797 addr += dumpaddr;
798 if (cpu->cd.ppc.bits == 32)
799 addr &= 0xffffffff;
800 if (cpu->cd.ppc.bits == 32)
801 debug("\t0x%"PRIx32, (uint32_t) addr);
802 else
803 debug("\t0x%"PRIx64, (uint64_t) addr);
804 symbol = get_symbol_name(&cpu->machine->symbol_context,
805 addr, &offset);
806 if (symbol != NULL)
807 debug("\t<%s>", symbol);
808 break;
809 case PPC_HI6_19:
810 xo = (iword >> 1) & 1023;
811 switch (xo) {
812 case PPC_19_MCRF:
813 bf = (iword >> 23) & 7;
814 bfa = (iword >> 18) & 7;
815 debug("mcrf\tcr%i,cr%i", bf, bfa);
816 break;
817 case PPC_19_RFI:
818 debug("rfi");
819 break;
820 case PPC_19_RFID:
821 debug("rfid");
822 break;
823 case PPC_19_RFSVC:
824 debug("rfsvc%s", power?"":"\t(INVALID for PowerPC)");
825 break;
826 case PPC_19_BCLR:
827 case PPC_19_BCCTR:
828 bo = (iword >> 21) & 31;
829 bi = (iword >> 16) & 31;
830 bh = (iword >> 11) & 3;
831 lk_bit = iword & 1;
832 switch (xo) {
833 case PPC_19_BCLR:
834 mnem = power? "bcr" : "bclr"; break;
835 case PPC_19_BCCTR:
836 mnem = power? "bcc" : "bcctr"; break;
837 }
838 debug("%s%s%s\t%i,%i,%i", mnem, lk_bit? "l" : "",
839 bh? (bh==3? "+" : (bh==2? "-" : "?")) : "",
840 bo, bi, bh);
841 break;
842 case PPC_19_ISYNC:
843 debug("%s", power? "ics" : "isync");
844 break;
845 case PPC_19_CRAND:
846 case PPC_19_CRXOR:
847 case PPC_19_CROR:
848 case PPC_19_CRNAND:
849 case PPC_19_CRNOR:
850 case PPC_19_CRANDC:
851 case PPC_19_CREQV:
852 case PPC_19_CRORC:
853 bt = (iword >> 21) & 31;
854 ba = (iword >> 16) & 31;
855 bb = (iword >> 11) & 31;
856 switch (xo) {
857 case PPC_19_CRAND: mnem = "crand"; break;
858 case PPC_19_CRXOR: mnem = "crxor"; break;
859 case PPC_19_CROR: mnem = "cror"; break;
860 case PPC_19_CRNAND: mnem = "crnand"; break;
861 case PPC_19_CRNOR: mnem = "crnor"; break;
862 case PPC_19_CRANDC: mnem = "crandc"; break;
863 case PPC_19_CREQV: mnem = "creqv"; break;
864 case PPC_19_CRORC: mnem = "crorc"; break;
865 }
866 debug("%s\t%i,%i,%i", mnem, bt, ba, bb);
867 break;
868 default:
869 debug("unimplemented hi6_19, xo = 0x%x", xo);
870 }
871 break;
872 case PPC_HI6_RLWNM:
873 case PPC_HI6_RLWIMI:
874 case PPC_HI6_RLWINM:
875 rs = (iword >> 21) & 31;
876 ra = (iword >> 16) & 31;
877 sh = (iword >> 11) & 31; /* actually rb for rlwnm */
878 mb = (iword >> 6) & 31;
879 me = (iword >> 1) & 31;
880 rc = iword & 1;
881 switch (hi6) {
882 case PPC_HI6_RLWNM:
883 mnem = power? "rlnm" : "rlwnm"; break;
884 case PPC_HI6_RLWIMI:
885 mnem = power? "rlimi" : "rlwimi"; break;
886 case PPC_HI6_RLWINM:
887 mnem = power? "rlinm" : "rlwinm"; break;
888 }
889 debug("%s%s\tr%i,r%i,%s%i,%i,%i",
890 mnem, rc?".":"", ra, rs,
891 hi6 == PPC_HI6_RLWNM? "r" : "",
892 sh, mb, me);
893 break;
894 case PPC_HI6_ORI:
895 case PPC_HI6_ORIS:
896 case PPC_HI6_XORI:
897 case PPC_HI6_XORIS:
898 case PPC_HI6_ANDI_DOT:
899 case PPC_HI6_ANDIS_DOT:
900 rs = (iword >> 21) & 31;
901 ra = (iword >> 16) & 31;
902 imm = iword & 0xffff;
903 switch (hi6) {
904 case PPC_HI6_ORI:
905 mnem = power? "oril":"ori";
906 break;
907 case PPC_HI6_ORIS:
908 mnem = power? "oriu":"oris";
909 break;
910 case PPC_HI6_XORI:
911 mnem = power? "xoril":"xori";
912 break;
913 case PPC_HI6_XORIS:
914 mnem = power? "xoriu":"xoris";
915 break;
916 case PPC_HI6_ANDI_DOT:
917 mnem = power? "andil.":"andi.";
918 break;
919 case PPC_HI6_ANDIS_DOT:
920 mnem = power? "andiu.":"andis.";
921 break;
922 }
923 if (hi6 == PPC_HI6_ORI && rs == 0 && ra == 0 && imm == 0)
924 debug("nop");
925 else
926 debug("%s\tr%i,r%i,0x%04x", mnem, ra, rs, imm);
927 break;
928 case PPC_HI6_30:
929 xo = (iword >> 2) & 7;
930 switch (xo) {
931 case PPC_30_RLDICL:
932 case PPC_30_RLDICR:
933 case PPC_30_RLDIMI: /* mb, not me */
934 mnem = NULL;
935 switch (xo) {
936 case PPC_30_RLDICL: mnem = "rldicl"; break;
937 case PPC_30_RLDICR: mnem = "rldicr"; break;
938 case PPC_30_RLDIMI: mnem = "rldimi"; break;
939 }
940 rs = (iword >> 21) & 31;
941 ra = (iword >> 16) & 31;
942 sh = ((iword >> 11) & 31) | ((iword & 2) << 4);
943 me = ((iword >> 6) & 31) | (iword & 0x20);
944 rc = iword & 1;
945 debug("%s%s\tr%i,r%i,%i,%i",
946 mnem, rc?".":"", ra, rs, sh, me);
947 break;
948 default:
949 debug("unimplemented hi6_30, xo = 0x%x", xo);
950 }
951 break;
952 case PPC_HI6_31:
953 xo = (iword >> 1) & 1023;
954 switch (xo) {
955
956 case PPC_31_CMP:
957 case PPC_31_CMPL:
958 bf = (iword >> 23) & 7;
959 l_bit = (iword >> 21) & 1;
960 ra = (iword >> 16) & 31;
961 rb = (iword >> 11) & 31;
962 if (xo == PPC_31_CMPL)
963 mnem = "cmpl";
964 else
965 mnem = "cmp";
966 debug("%s%s\t", mnem, l_bit? "d" : "w");
967 if (bf != 0)
968 debug("cr%i,", bf);
969 debug("r%i,r%i", ra, rb);
970 break;
971 case PPC_31_MFCR:
972 rt = (iword >> 21) & 31;
973 debug("mfcr\tr%i", rt);
974 break;
975 case PPC_31_MFMSR:
976 rt = (iword >> 21) & 31;
977 debug("mfmsr\tr%i", rt);
978 break;
979 case PPC_31_MTCRF:
980 rs = (iword >> 21) & 31;
981 mb = (iword >> 12) & 255; /* actually fxm, not mb */
982 debug("mtcrf\t%i,r%i", mb, rs);
983 break;
984 case PPC_31_MTMSR:
985 rs = (iword >> 21) & 31;
986 l_bit = (iword >> 16) & 1;
987 debug("mtmsr\tr%i", rs);
988 if (l_bit)
989 debug(",%i", l_bit);
990 break;
991 case PPC_31_TW:
992 case PPC_31_TD:
993 to = (iword >> 21) & 31;
994 ra = (iword >> 16) & 31;
995 rb = (iword >> 11) & 31;
996 switch (xo) {
997 case PPC_31_TW: mnem = power? "t" : "tw"; break;
998 case PPC_31_TD: mnem = "td"; break;
999 }
1000 debug("%s\t%i,r%i,r%i", mnem, to, ra, rb);
1001 break;
1002 case PPC_31_LWARX:
1003 case PPC_31_LDARX:
1004 case PPC_31_LBZX:
1005 case PPC_31_LBZUX:
1006 case PPC_31_LHAX:
1007 case PPC_31_LHAUX:
1008 case PPC_31_LHZX:
1009 case PPC_31_LHZUX:
1010 case PPC_31_LWZX:
1011 case PPC_31_LWZUX:
1012 case PPC_31_LHBRX:
1013 case PPC_31_LWBRX:
1014 case PPC_31_LFDX:
1015 case PPC_31_LFSX:
1016 case PPC_31_STWCX_DOT:
1017 case PPC_31_STDCX_DOT:
1018 case PPC_31_STBX:
1019 case PPC_31_STBUX:
1020 case PPC_31_STHX:
1021 case PPC_31_STHUX:
1022 case PPC_31_STWX:
1023 case PPC_31_STWUX:
1024 case PPC_31_STDX:
1025 case PPC_31_STDUX:
1026 case PPC_31_STHBRX:
1027 case PPC_31_STWBRX:
1028 case PPC_31_STFDX:
1029 case PPC_31_STFSX:
1030 /* rs for stores, rt for loads, actually */
1031 load = 0; wlen = 0; fpreg = 0;
1032 rs = (iword >> 21) & 31;
1033 ra = (iword >> 16) & 31;
1034 rb = (iword >> 11) & 31;
1035 switch (xo) {
1036 case PPC_31_LWARX: wlen=4;load=1; mnem = "lwarx"; break;
1037 case PPC_31_LDARX: wlen=8;load=1; mnem = "ldarx"; break;
1038 case PPC_31_LBZX: wlen=1;load=1; mnem = "lbzx"; break;
1039 case PPC_31_LBZUX: wlen=1;load=1; mnem = "lbzux"; break;
1040 case PPC_31_LHAX: wlen=2;load=1; mnem = "lhax"; break;
1041 case PPC_31_LHAUX: wlen=2;load=1; mnem = "lhaux"; break;
1042 case PPC_31_LHZX: wlen=2;load=1; mnem = "lhzx"; break;
1043 case PPC_31_LHZUX: wlen=2;load=1; mnem = "lhzux"; break;
1044 case PPC_31_LWZX: wlen = 4; load = 1;
1045 mnem = power? "lx" : "lwzx";
1046 break;
1047 case PPC_31_LWZUX: wlen = 4; load = 1;
1048 mnem = power? "lux":"lwzux";
1049 break;
1050 case PPC_31_LFDX: fpreg = 1; wlen = 8; load = 1;
1051 mnem = "lfdx"; break;
1052 case PPC_31_LFSX: fpreg = 1; wlen = 4; load = 1;
1053 mnem = "lfsx"; break;
1054 case PPC_31_STWCX_DOT: wlen=4; mnem = "stwcx."; break;
1055 case PPC_31_STDCX_DOT: wlen=8; mnem = "stdcx."; break;
1056 case PPC_31_STBX: wlen=1; mnem = "stbx"; break;
1057 case PPC_31_STBUX: wlen=1; mnem = "stbux"; break;
1058 case PPC_31_STHX: wlen=2; mnem = "sthx"; break;
1059 case PPC_31_STHUX: wlen=2; mnem = "sthux"; break;
1060 case PPC_31_STWX:
1061 wlen = 4; mnem = power? "stx" : "stwx";
1062 break;
1063 case PPC_31_STWUX:
1064 wlen = 4; mnem = power? "stux" : "stwux";
1065 break;
1066 case PPC_31_STDX: wlen = 8; mnem = "stdx"; break;
1067 case PPC_31_STDUX: wlen = 8; mnem = "stdux"; break;
1068 case PPC_31_LHBRX: wlen = 2; mnem = "lhbrx"; break;
1069 case PPC_31_LWBRX: wlen = 4; mnem = power?
1070 "lbrx" : "lwbrx"; break;
1071 case PPC_31_STHBRX: wlen = 2; mnem = "sthbrx"; break;
1072 case PPC_31_STWBRX: wlen = 4; mnem = power?
1073 "stbrx" : "stwbrx"; break;
1074 case PPC_31_STFDX: fpreg = 1; wlen = 8;
1075 mnem = "stfdx"; break;
1076 case PPC_31_STFSX: fpreg = 1; wlen = 4;
1077 mnem = "stfsx"; break;
1078 }
1079 debug("%s\t%s%i,r%i,r%i", mnem,
1080 fpreg? "f" : "r", rs, ra, rb);
1081 if (!running)
1082 break;
1083 addr = (ra==0? 0 : cpu->cd.ppc.gpr[ra]) +
1084 cpu->cd.ppc.gpr[rb];
1085 if (cpu->cd.ppc.bits == 32)
1086 addr &= 0xffffffff;
1087 symbol = get_symbol_name(&cpu->machine->symbol_context,
1088 addr, &offset);
1089 if (symbol != NULL)
1090 debug(" \t<%s", symbol);
1091 else
1092 debug(" \t<0x%"PRIx64, (uint64_t) addr);
1093 if (wlen > 0 && !fpreg /* && !reverse */) {
1094 /* TODO */
1095 }
1096 debug(">");
1097 break;
1098 case PPC_31_NEG:
1099 case PPC_31_NEGO:
1100 rt = (iword >> 21) & 31;
1101 ra = (iword >> 16) & 31;
1102 oe_bit = (iword >> 10) & 1;
1103 rc = iword & 1;
1104 switch (xo) {
1105 case PPC_31_NEG: mnem = "neg"; break;
1106 case PPC_31_NEGO: mnem = "nego"; break;
1107 }
1108 debug("%s%s\tr%i,r%i", mnem, rc? "." : "", rt, ra);
1109 break;
1110 case PPC_31_WRTEEI:
1111 debug("wrteei\t%i", iword & 0x8000? 1 : 0);
1112 break;
1113 case PPC_31_MTMSRD:
1114 /* TODO: Just a guess based on MTMSR */
1115 rs = (iword >> 21) & 31;
1116 l_bit = (iword >> 16) & 1;
1117 debug("mtmsrd\tr%i", rs);
1118 if (l_bit)
1119 debug(",%i", l_bit);
1120 break;
1121 case PPC_31_ADDZE:
1122 case PPC_31_ADDZEO:
1123 rt = (iword >> 21) & 31;
1124 ra = (iword >> 16) & 31;
1125 oe_bit = (iword >> 10) & 1;
1126 rc = iword & 1;
1127 switch (xo) {
1128 case PPC_31_ADDZE:
1129 mnem = power? "aze" : "addze";
1130 break;
1131 case PPC_31_ADDZEO:
1132 mnem = power? "azeo" : "addzeo";
1133 break;
1134 }
1135 debug("%s%s\tr%i,r%i", mnem, rc? "." : "", rt, ra);
1136 break;
1137 case PPC_31_MTSR:
1138 case PPC_31_MFSR:
1139 /* Move to/from segment register */
1140 rt = (iword >> 21) & 31;
1141 ra = (iword >> 16) & 15; /* actually: sr */
1142 switch (xo) {
1143 case PPC_31_MTSR: mnem = "mtsr"; break;
1144 case PPC_31_MFSR: mnem = "mfsr"; break;
1145 }
1146 debug("%s\tr%i,%i", mnem, rt, ra);
1147 break;
1148 case PPC_31_MTSRIN:
1149 case PPC_31_MFSRIN:
1150 /* Move to/from segment register indirect */
1151 rt = (iword >> 21) & 31;
1152 rb = (iword >> 11) & 31;
1153 switch (xo) {
1154 case PPC_31_MTSRIN: mnem = "mtsrin"; break;
1155 case PPC_31_MFSRIN: mnem = "mfsrin"; break;
1156 }
1157 debug("%s\tr%i,r%i", mnem, rt, rb);
1158 break;
1159 case PPC_31_ADDC:
1160 case PPC_31_ADDCO:
1161 case PPC_31_ADDE:
1162 case PPC_31_ADDEO:
1163 case PPC_31_ADDME:
1164 case PPC_31_ADDMEO:
1165 case PPC_31_ADD:
1166 case PPC_31_ADDO:
1167 case PPC_31_MULHW:
1168 case PPC_31_MULHWU:
1169 case PPC_31_MULLW:
1170 case PPC_31_MULLWO:
1171 case PPC_31_SUBF:
1172 case PPC_31_SUBFO:
1173 case PPC_31_SUBFC:
1174 case PPC_31_SUBFCO:
1175 case PPC_31_SUBFE:
1176 case PPC_31_SUBFEO:
1177 case PPC_31_SUBFME:
1178 case PPC_31_SUBFMEO:
1179 case PPC_31_SUBFZE:
1180 case PPC_31_SUBFZEO:
1181 rt = (iword >> 21) & 31;
1182 ra = (iword >> 16) & 31;
1183 rb = (iword >> 11) & 31;
1184 oe_bit = (iword >> 10) & 1;
1185 rc = iword & 1;
1186 switch (xo) {
1187 case PPC_31_ADDC:
1188 mnem = power? "a" : "addc";
1189 break;
1190 case PPC_31_ADDCO:
1191 mnem = power? "ao" : "addco";
1192 break;
1193 case PPC_31_ADDE:
1194 mnem = power? "ae" : "adde";
1195 break;
1196 case PPC_31_ADDEO:
1197 mnem = power? "aeo" : "addeo";
1198 break;
1199 case PPC_31_ADDME:
1200 mnem = power? "ame" : "addme";
1201 no_rb = 1;
1202 break;
1203 case PPC_31_ADDMEO:
1204 mnem = power? "ameo" : "addmeo";
1205 no_rb = 1;
1206 break;
1207 case PPC_31_ADD:
1208 mnem = power? "cax" : "add";
1209 break;
1210 case PPC_31_ADDO:
1211 mnem = power? "caxo" : "addo";
1212 break;
1213 case PPC_31_MULHW: mnem = "mulhw"; break;
1214 case PPC_31_MULHWU: mnem = "mulhwu"; break;
1215 case PPC_31_MULLW:
1216 mnem = power? "muls" : "mullw";
1217 break;
1218 case PPC_31_MULLWO:
1219 mnem = power? "mulso" : "mullwo";
1220 break;
1221 case PPC_31_SUBF: mnem = "subf"; break;
1222 case PPC_31_SUBFO: mnem = "subfo"; break;
1223 case PPC_31_SUBFC:
1224 mnem = power? "sf" : "subfc"; break;
1225 case PPC_31_SUBFCO:
1226 mnem = power? "sfo" : "subfco"; break;
1227 case PPC_31_SUBFE:
1228 mnem = power? "sfe" : "subfe"; break;
1229 case PPC_31_SUBFEO:
1230 mnem = power? "sfeo" : "subfeo"; break;
1231 case PPC_31_SUBFME:
1232 mnem = power? "sfme" : "subfme"; break;
1233 case PPC_31_SUBFMEO:
1234 mnem = power? "sfmeo" : "subfmeo"; break;
1235 case PPC_31_SUBFZE:
1236 mnem = power? "sfze" : "subfze";
1237 no_rb = 1;
1238 break;
1239 case PPC_31_SUBFZEO:
1240 mnem = power? "sfzeo" : "subfzeo";
1241 no_rb = 1;
1242 break;
1243 }
1244 debug("%s%s\tr%i,r%i", mnem, rc? "." : "", rt, ra);
1245 if (!no_rb)
1246 debug(",r%i", rb);
1247 break;
1248 case PPC_31_MFSPR:
1249 rt = (iword >> 21) & 31;
1250 spr = ((iword >> 6) & 0x3e0) + ((iword >> 16) & 31);
1251 switch (spr) {
1252 /* Some very common ones: */
1253 case 8: debug("mflr\tr%i", rt); break;
1254 case 9: debug("mfctr\tr%i", rt); break;
1255 default:debug("mfspr\tr%i,spr%i", rt, spr);
1256 }
1257 if (spr == 8 || spr == 9)
1258 debug("\t");
1259 debug("\t<%s%s", running? "read from " : "",
1260 ppc_spr_names[spr]==NULL? "?" : ppc_spr_names[spr]);
1261 if (running) {
1262 if (cpu->cd.ppc.bits == 32)
1263 debug(": 0x%"PRIx32, (uint32_t)
1264 cpu->cd.ppc.spr[spr]);
1265 else
1266 debug(": 0x%"PRIx64, (uint64_t)
1267 cpu->cd.ppc.spr[spr]);
1268 }
1269 debug(">");
1270 break;
1271 case PPC_31_TLBIA:
1272 debug("tlbia");
1273 break;
1274 case PPC_31_SLBIA:
1275 debug("slbia");
1276 break;
1277 case PPC_31_TLBLD:
1278 case PPC_31_TLBLI:
1279 rb = (iword >> 11) & 31;
1280 debug("tlbl%s\tr%i", xo == PPC_31_TLBLD? "d" : "i", rb);
1281 break;
1282 case PPC_31_TLBIE:
1283 /* TODO: what is ra? The IBM online docs didn't say */
1284 ra = 0;
1285 rb = (iword >> 11) & 31;
1286 if (power)
1287 debug("tlbi\tr%i,r%i", ra, rb);
1288 else
1289 debug("tlbie\tr%i", rb);
1290 break;
1291 case PPC_31_TLBSX_DOT:
1292 rs = (iword >> 21) & 31;
1293 ra = (iword >> 16) & 31;
1294 rb = (iword >> 11) & 31;
1295 debug("tlbsx.\tr%i,r%i,r%i", rs, ra, rb);
1296 break;
1297 case PPC_31_TLBSYNC:
1298 debug("tlbsync");
1299 break;
1300 case PPC_31_MFTB:
1301 rt = (iword >> 21) & 31;
1302 spr = ((iword >> 6) & 0x3e0) + ((iword >> 16) & 31);
1303 debug("mftb%s\tr%i", spr==268? "" :
1304 (spr==269? "u" : "?"), rt);
1305 break;
1306 case PPC_31_CNTLZW:
1307 rs = (iword >> 21) & 31;
1308 ra = (iword >> 16) & 31;
1309 rc = iword & 1;
1310 mnem = power? "cntlz" : "cntlzw";
1311 debug("%s%s\tr%i,r%i", mnem, rc? "." : "", ra, rs);
1312 break;
1313 case PPC_31_CLF: /* POWER only */
1314 case PPC_31_CLI: /* POWER only */
1315 case PPC_31_DCLST: /* POWER only */
1316 case PPC_31_DCBF: /* PowerPC only */
1317 case PPC_31_DCBI: /* PowerPC only */
1318 case PPC_31_DCBST: /* PowerPC only */
1319 case PPC_31_DCBTST: /* PowerPC only */
1320 case PPC_31_DCBT: /* PowerPC only */
1321 case PPC_31_ICBI: /* PowerPC only */
1322 case PPC_31_DCBZ: /* POWER/PowerPC */
1323 ra = (iword >> 16) & 31;
1324 rb = (iword >> 11) & 31;
1325 switch (xo) {
1326 case PPC_31_CLF: mnem = "clf"; break;
1327 case PPC_31_CLI: mnem = "cli"; break;
1328 case PPC_31_DCLST: mnem = "dclst"; break;
1329 case PPC_31_DCBF: mnem = "dcbf"; break;
1330 case PPC_31_DCBI: mnem = "dcbi"; break;
1331 case PPC_31_DCBST: mnem = "dcbst"; break;
1332 case PPC_31_DCBTST:mnem = "dcbtst"; break;
1333 case PPC_31_DCBT: mnem = "dcbt"; break;
1334 case PPC_31_ICBI: mnem = "icbi"; break;
1335 case PPC_31_DCBZ: mnem = power ?
1336 "dclz" : "dcbz"; break;
1337 }
1338 debug("%s\tr%i,r%i", mnem, ra, rb);
1339 break;
1340 case PPC_31_SLW:
1341 case PPC_31_SLD:
1342 case PPC_31_SRAW:
1343 case PPC_31_SRW:
1344 case PPC_31_AND:
1345 case PPC_31_ANDC:
1346 case PPC_31_NOR:
1347 case PPC_31_EQV:
1348 case PPC_31_OR:
1349 case PPC_31_ORC:
1350 case PPC_31_XOR:
1351 case PPC_31_NAND:
1352 rs = (iword >> 21) & 31;
1353 ra = (iword >> 16) & 31;
1354 rb = (iword >> 11) & 31;
1355 rc = iword & 1;
1356 if (rs == rb && xo == PPC_31_OR)
1357 debug("mr%s\tr%i,r%i", rc? "." : "", ra, rs);
1358 else {
1359 switch (xo) {
1360 case PPC_31_SLW: mnem =
1361 power? "sl" : "slw"; break;
1362 case PPC_31_SLD: mnem = "sld"; break;
1363 case PPC_31_SRAW: mnem =
1364 power? "sra" : "sraw"; break;
1365 case PPC_31_SRW: mnem =
1366 power? "sr" : "srw"; break;
1367 case PPC_31_AND: mnem = "and"; break;
1368 case PPC_31_NAND: mnem = "nand"; break;
1369 case PPC_31_ANDC: mnem = "andc"; break;
1370 case PPC_31_NOR: mnem = "nor"; break;
1371 case PPC_31_EQV: mnem = "eqv"; break;
1372 case PPC_31_OR: mnem = "or"; break;
1373 case PPC_31_ORC: mnem = "orc"; break;
1374 case PPC_31_XOR: mnem = "xor"; break;
1375 }
1376 debug("%s%s\tr%i,r%i,r%i", mnem,
1377 rc? "." : "", ra, rs, rb);
1378 }
1379 break;
1380 case PPC_31_DCCCI:
1381 ra = (iword >> 16) & 31;
1382 rb = (iword >> 11) & 31;
1383 debug("dccci\tr%i,r%i", ra, rb);
1384 break;
1385 case PPC_31_ICCCI:
1386 ra = (iword >> 16) & 31;
1387 rb = (iword >> 11) & 31;
1388 debug("iccci\tr%i,r%i", ra, rb);
1389 break;
1390 case PPC_31_DIVW:
1391 case PPC_31_DIVWO:
1392 case PPC_31_DIVWU:
1393 case PPC_31_DIVWUO:
1394 rt = (iword >> 21) & 31;
1395 ra = (iword >> 16) & 31;
1396 rb = (iword >> 11) & 31;
1397 oe_bit = (iword >> 10) & 1;
1398 rc = iword & 1;
1399 switch (xo) {
1400 case PPC_31_DIVWU: mnem = "divwu"; break;
1401 case PPC_31_DIVWUO: mnem = "divwuo"; break;
1402 case PPC_31_DIVW: mnem = "divw"; break;
1403 case PPC_31_DIVWO: mnem = "divwo"; break;
1404 }
1405 debug("%s%s\tr%i,r%i,r%i", mnem, rc? "." : "",
1406 rt, ra, rb);
1407 break;
1408 case PPC_31_MTSPR:
1409 rs = (iword >> 21) & 31;
1410 spr = ((iword >> 6) & 0x3e0) + ((iword >> 16) & 31);
1411 switch (spr) {
1412 /* Some very common ones: */
1413 case 8: debug("mtlr\tr%i", rs); break;
1414 case 9: debug("mtctr\tr%i", rs); break;
1415 default:debug("mtspr\tspr%i,r%i", spr, rs);
1416 }
1417 if (spr == 8 || spr == 9)
1418 debug("\t");
1419 debug("\t<%s%s", running? "write to " : "",
1420 ppc_spr_names[spr]==NULL? "?" : ppc_spr_names[spr]);
1421 if (running) {
1422 if (cpu->cd.ppc.bits == 32)
1423 debug(": 0x%"PRIx32, (uint32_t)
1424 cpu->cd.ppc.gpr[rs]);
1425 else
1426 debug(": 0x%"PRIx64, (uint64_t)
1427 cpu->cd.ppc.gpr[rs]);
1428 }
1429 debug(">");
1430 break;
1431 case PPC_31_SYNC:
1432 debug("%s", power? "dcs" : "sync");
1433 break;
1434 case PPC_31_LSWI:
1435 case PPC_31_STSWI:
1436 rs = (iword >> 21) & 31; /* lwsi uses rt */
1437 ra = (iword >> 16) & 31;
1438 nb = (iword >> 11) & 31;
1439 switch (xo) {
1440 case PPC_31_LSWI:
1441 mnem = power? "lsi" : "lswi"; break;
1442 case PPC_31_STSWI:
1443 mnem = power? "stsi" : "stswi"; break;
1444 }
1445 debug("%s\tr%i,r%i,%i", mnem, rs, ra, nb);
1446 break;
1447 case PPC_31_SRAWI:
1448 rs = (iword >> 21) & 31;
1449 ra = (iword >> 16) & 31;
1450 sh = (iword >> 11) & 31;
1451 rc = iword & 1;
1452 mnem = power? "srai" : "srawi";
1453 debug("%s%s\tr%i,r%i,%i", mnem,
1454 rc? "." : "", ra, rs, sh);
1455 break;
1456 case PPC_31_DSSALL:
1457 debug("dssall");
1458 break;
1459 case PPC_31_EIEIO:
1460 debug("%s", power? "eieio?" : "eieio");
1461 break;
1462 case PPC_31_EXTSB:
1463 case PPC_31_EXTSH:
1464 case PPC_31_EXTSW:
1465 rs = (iword >> 21) & 31;
1466 ra = (iword >> 16) & 31;
1467 rc = iword & 1;
1468 switch (xo) {
1469 case PPC_31_EXTSB:
1470 mnem = power? "exts" : "extsb";
1471 break;
1472 case PPC_31_EXTSH:
1473 mnem = "extsh";
1474 break;
1475 case PPC_31_EXTSW:
1476 mnem = "extsw";
1477 break;
1478 }
1479 debug("%s%s\tr%i,r%i", mnem, rc? "." : "", ra, rs);
1480 break;
1481 case PPC_31_LVX:
1482 case PPC_31_LVXL:
1483 case PPC_31_STVX:
1484 case PPC_31_STVXL:
1485 rs = (iword >> 21) & 31; /* vs for stores, */
1486 ra = (iword >> 16) & 31; /* rs=vl for loads */
1487 rb = (iword >> 11) & 31;
1488 rc = iword & 1;
1489 switch (xo) {
1490 case PPC_31_LVX: mnem = "lvx"; break;
1491 case PPC_31_LVXL: mnem = "lvxl"; break;
1492 case PPC_31_STVX: mnem = "stvx"; break;
1493 case PPC_31_STVXL: mnem = "stvxl"; break;
1494 }
1495 debug("%s%s\tv%i,r%i,r%i", mnem, rc? "." : "",
1496 rs, ra, rb);
1497 break;
1498 default:
1499 debug("unimplemented hi6_31, xo = 0x%x", xo);
1500 }
1501 break;
1502 case PPC_HI6_LD:
1503 case PPC_HI6_LWZ:
1504 case PPC_HI6_LWZU:
1505 case PPC_HI6_LHZ:
1506 case PPC_HI6_LHZU:
1507 case PPC_HI6_LHA:
1508 case PPC_HI6_LHAU:
1509 case PPC_HI6_LBZ:
1510 case PPC_HI6_LBZU:
1511 case PPC_HI6_LFD:
1512 case PPC_HI6_LFS:
1513 case PPC_HI6_LMW:
1514 case PPC_HI6_STD:
1515 case PPC_HI6_STW:
1516 case PPC_HI6_STWU:
1517 case PPC_HI6_STH:
1518 case PPC_HI6_STHU:
1519 case PPC_HI6_STB:
1520 case PPC_HI6_STBU:
1521 case PPC_HI6_STMW:
1522 case PPC_HI6_STFD:
1523 case PPC_HI6_STFS:
1524 /* NOTE: Loads use rt, not rs, but are otherwise similar
1525 to stores */
1526 load = 0; wlen = 0;
1527 rs = (iword >> 21) & 31;
1528 ra = (iword >> 16) & 31;
1529 imm = (int16_t)(iword & 0xffff);
1530 fpreg = 0;
1531 switch (hi6) {
1532 case PPC_HI6_LD: load=1; wlen = 8; mnem = "ld"; break;
1533 case PPC_HI6_LWZ: load=1; wlen = 4;
1534 mnem = power? "l" : "lwz"; break;
1535 case PPC_HI6_LWZU: load=1; wlen = 4;
1536 mnem = power? "lu" : "lwzu"; break;
1537 case PPC_HI6_LHZ: load=1; wlen = 2;
1538 mnem = "lhz"; break;
1539 case PPC_HI6_LHZU: load=1; wlen = 2;
1540 mnem = "lhzu"; break;
1541 case PPC_HI6_LHA: load=2; wlen = 2;
1542 mnem = "lha"; break;
1543 case PPC_HI6_LHAU: load=2; wlen = 2;
1544 mnem = "lhau"; break;
1545 case PPC_HI6_LBZ: load=1; wlen = 1;
1546 mnem = "lbz"; break;
1547 case PPC_HI6_LBZU: load=1; wlen = 1;
1548 mnem = "lbzu"; break;
1549 case PPC_HI6_LFD: load=1; fpreg=1; wlen=8; mnem = "lfd"; break;
1550 case PPC_HI6_LFS: load=1; fpreg=1; wlen=4; mnem = "lfs"; break;
1551 case PPC_HI6_STD: wlen=8; mnem = "std"; break;
1552 case PPC_HI6_STW: wlen=4; mnem = power? "st" : "stw"; break;
1553 case PPC_HI6_STWU: wlen=4; mnem = power? "stu" : "stwu"; break;
1554 case PPC_HI6_STH: wlen=2; mnem = "sth"; break;
1555 case PPC_HI6_STHU: wlen=2; mnem = "sthu"; break;
1556 case PPC_HI6_STB: wlen=1; mnem = "stb"; break;
1557 case PPC_HI6_STBU: wlen=1; mnem = "stbu"; break;
1558 case PPC_HI6_LMW: load=1; mnem = power? "lm" : "lmw"; break;
1559 case PPC_HI6_STMW: mnem = power? "stm" : "stmw"; break;
1560 case PPC_HI6_STFD: fpreg=1; wlen=8; mnem = "stfd"; break;
1561 case PPC_HI6_STFS: fpreg=1; wlen=4; mnem = "stfs"; break;
1562 }
1563 debug("%s\t", mnem);
1564 if (fpreg)
1565 debug("f");
1566 else
1567 debug("r");
1568 debug("%i,%i(r%i)", rs, imm, ra);
1569 if (!running)
1570 break;
1571 addr = (ra==0? 0 : cpu->cd.ppc.gpr[ra]) + imm;
1572 if (cpu->cd.ppc.bits == 32)
1573 addr &= 0xffffffff;
1574 symbol = get_symbol_name(&cpu->machine->symbol_context,
1575 addr, &offset);
1576 if (symbol != NULL)
1577 debug(" \t<%s", symbol);
1578 else
1579 debug(" \t<0x%"PRIx64, (uint64_t) addr);
1580 if (wlen > 0 && load && wlen > 0) {
1581 unsigned char tw[8];
1582 uint64_t tdata = 0;
1583 int i, res = cpu->memory_rw(cpu, cpu->mem, addr, tw,
1584 wlen, MEM_READ, NO_EXCEPTIONS);
1585 if (res) {
1586 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
1587 for (i=0; i<wlen; i++) {
1588 tdata <<= 8;
1589 tdata |= tw[wlen-1-i];
1590 }
1591 else
1592 for (i=0; i<wlen; i++) {
1593 tdata <<= 8;
1594 tdata |= tw[i];
1595 }
1596 debug(": ");
1597 if (wlen >= 4) {
1598 symbol = get_symbol_name(&cpu->machine->
1599 symbol_context, tdata, &offset);
1600 if (symbol != NULL)
1601 debug("%s", symbol);
1602 else
1603 debug("0x%"PRIx64,
1604 (uint64_t) tdata);
1605 } else {
1606 /* TODO: if load==2, then this is
1607 a _signed_ load. */
1608 debug("0x%"PRIx64, (uint64_t) tdata);
1609 }
1610 } else
1611 debug(": unreadable");
1612 }
1613 if (wlen > 0 && !load && wlen > 0) {
1614 int64_t tdata = 0;
1615 int i;
1616 for (i=0; i<wlen; i++)
1617 tdata |= (cpu->cd.ppc.gpr[rs] &
1618 ((uint64_t)0xff << (i*8)));
1619 debug(": ");
1620 if (wlen >= 4) {
1621 symbol = get_symbol_name(&cpu->machine->
1622 symbol_context, tdata, &offset);
1623 if (symbol != NULL)
1624 debug("%s", symbol);
1625 else
1626 debug("0x%"PRIx64, (uint64_t) tdata);
1627 } else {
1628 if (tdata > -256 && tdata < 256)
1629 debug("%i", (int)tdata);
1630 else
1631 debug("0x%"PRIx64, (uint64_t) tdata);
1632 }
1633 }
1634 debug(">");
1635 break;
1636 case PPC_HI6_59:
1637 xo = (iword >> 1) & 1023;
1638 /* NOTE: Some floating point instructions only use the
1639 lowest 5 bits of xo, some use all 10 bits! */
1640 switch (xo & 31) {
1641 case PPC_59_FDIVS:
1642 case PPC_59_FSUBS:
1643 case PPC_59_FADDS:
1644 case PPC_59_FMULS:
1645 case PPC_59_FMADDS:
1646 rt = (iword >> 21) & 31;
1647 ra = (iword >> 16) & 31;
1648 rb = (iword >> 11) & 31;
1649 rs = (iword >> 6) & 31; /* actually frc */
1650 rc = iword & 1;
1651 switch (xo & 31) {
1652 case PPC_59_FDIVS: mnem = "fdivs"; break;
1653 case PPC_59_FSUBS: mnem = "fsubs"; break;
1654 case PPC_59_FADDS: mnem = "fadds"; break;
1655 case PPC_59_FMULS: mnem = "fmuls"; break;
1656 case PPC_59_FMADDS: mnem = "fmadds"; break;
1657 }
1658 debug("%s%s\t", mnem, rc? "." : "");
1659 switch (xo & 31) {
1660 case PPC_59_FMULS:
1661 debug("f%i,f%i,f%i", rt, ra, rs);
1662 break;
1663 case PPC_59_FMADDS:
1664 debug("f%i,f%i,f%i,f%i", rt, ra, rs, rb);
1665 break;
1666 default:debug("f%i,f%i,f%i", rt, ra, rb);
1667 }
1668 break;
1669 default:/* TODO: similar to hi6_63 */
1670 debug("unimplemented hi6_59, xo = 0x%x", xo);
1671 }
1672 break;
1673 case PPC_HI6_63:
1674 xo = (iword >> 1) & 1023;
1675 /* NOTE: Some floating point instructions only use the
1676 lowest 5 bits of xo, some use all 10 bits! */
1677 switch (xo & 31) {
1678 case PPC_63_FDIV:
1679 case PPC_63_FSUB:
1680 case PPC_63_FADD:
1681 case PPC_63_FMUL:
1682 case PPC_63_FMSUB:
1683 case PPC_63_FMADD:
1684 rt = (iword >> 21) & 31;
1685 ra = (iword >> 16) & 31;
1686 rb = (iword >> 11) & 31;
1687 rs = (iword >> 6) & 31; /* actually frc */
1688 rc = iword & 1;
1689 switch (xo & 31) {
1690 case PPC_63_FDIV:
1691 mnem = power? "fd" : "fdiv"; break;
1692 case PPC_63_FSUB:
1693 mnem = power? "fs" : "fsub"; break;
1694 case PPC_63_FADD:
1695 mnem = power? "fa" : "fadd"; break;
1696 case PPC_63_FMUL:
1697 mnem = power? "fm" : "fmul"; break;
1698 case PPC_63_FMSUB:
1699 mnem = power? "fms" : "fmsub"; break;
1700 case PPC_63_FMADD:
1701 mnem = power? "fma" : "fmadd"; break;
1702 }
1703 debug("%s%s\t", mnem, rc? "." : "");
1704 switch (xo & 31) {
1705 case PPC_63_FMUL:
1706 debug("f%i,f%i,f%i", rt, ra, rs);
1707 break;
1708 case PPC_63_FMADD:
1709 debug("f%i,f%i,f%i,f%i", rt, ra, rs, rb);
1710 break;
1711 default:debug("f%i,f%i,f%i", rt, ra, rb);
1712 }
1713 break;
1714 default:rt = (iword >> 21) & 31;
1715 ra = (iword >> 16) & 31;
1716 rb = (iword >> 11) & 31;
1717 rc = iword & 1;
1718 switch (xo) {
1719 case PPC_63_FCMPU:
1720 case PPC_63_FRSP:
1721 case PPC_63_FCTIWZ:
1722 case PPC_63_FNEG:
1723 case PPC_63_FMR:
1724 case PPC_63_FNABS:
1725 case PPC_63_FABS:
1726 switch (xo) {
1727 case PPC_63_FCMPU: mnem = "fcmpu"; break;
1728 case PPC_63_FCTIWZ:
1729 mnem = power? "fcirz" : "fctiwz"; break;
1730 case PPC_63_FRSP: mnem = "frsp"; break;
1731 case PPC_63_FNEG: mnem = "fneg"; break;
1732 case PPC_63_FMR: mnem = "fmr"; break;
1733 case PPC_63_FNABS: mnem = "fnabs"; break;
1734 case PPC_63_FABS: mnem = "fabs"; break;
1735 }
1736 debug("%s%s\t", mnem, rc? "." : "");
1737 switch (xo) {
1738 case PPC_63_FCMPU:
1739 debug("%i,f%i,f%i", rt >> 2, ra, rb);
1740 break;
1741 case PPC_63_FCTIWZ:
1742 case PPC_63_FRSP:
1743 case PPC_63_FNEG:
1744 case PPC_63_FMR:
1745 case PPC_63_FNABS:
1746 case PPC_63_FABS:
1747 debug("f%i,f%i", rt, rb);
1748 break;
1749 default:debug("f%i,f%i,f%i", rt, ra, rb);
1750 }
1751 break;
1752 case PPC_63_MFFS:
1753 debug("mffs%s\tf%i", rc?".":"", rt);
1754 break;
1755 case PPC_63_MTFSF:
1756 ra = (iword >> 17) & 255; /* flm */
1757 debug("mtfsf%s\t0x%02x,f%i", rc?".":"", ra, rb);
1758 break;
1759 default:debug("unimplemented hi6_63, xo = 0x%x", xo);
1760 }
1761 }
1762 break;
1763 default:
1764 /* TODO */
1765 debug("unimplemented hi6 = 0x%02x", hi6);
1766 }
1767
1768 debug("\n");
1769 return sizeof(iword);
1770 }
1771
1772
1773 /*
1774 * debug_spr_usage():
1775 *
1776 * Helper function. To speed up overall development speed of the emulator,
1777 * all SPR accesses are allowed. This function causes unknown/unimplemented
1778 * SPRs to give a warning.
1779 */
1780 static void debug_spr_usage(uint64_t pc, int spr)
1781 {
1782 static uint32_t spr_used[1024 / sizeof(uint32_t)];
1783 static int initialized = 0;
1784
1785 if (!initialized) {
1786 memset(spr_used, 0, sizeof(spr_used));
1787 initialized = 1;
1788 }
1789
1790 spr &= 1023;
1791 if (spr_used[spr >> 2] & (1 << (spr & 3)))
1792 return;
1793
1794 switch (spr) {
1795 /* Known/implemented SPRs: */
1796 case SPR_XER:
1797 case SPR_LR:
1798 case SPR_CTR:
1799 case SPR_DSISR:
1800 case SPR_DAR:
1801 case SPR_DEC:
1802 case SPR_SDR1:
1803 case SPR_SRR0:
1804 case SPR_SRR1:
1805 case SPR_SPRG0:
1806 case SPR_SPRG1:
1807 case SPR_SPRG2:
1808 case SPR_SPRG3:
1809 case SPR_PVR:
1810 case SPR_DMISS:
1811 case SPR_DCMP:
1812 case SPR_HASH1:
1813 case SPR_HASH2:
1814 case SPR_IMISS:
1815 case SPR_ICMP:
1816 case SPR_DBSR:
1817 case SPR_PIR:
1818 break;
1819 default:if (spr >= SPR_IBAT0U && spr <= SPR_DBAT3L) {
1820 break;
1821 } else
1822 fatal("[ using UNIMPLEMENTED spr %i 0x%04x (%s), pc = "
1823 "0x%"PRIx64" ]\n", spr, spr, ppc_spr_names[spr] == NULL?
1824 "UNKNOWN" : ppc_spr_names[spr], (uint64_t) pc);
1825 }
1826
1827 spr_used[spr >> 2] |= (1 << (spr & 3));
1828 }
1829
1830
1831 /*
1832 * update_cr0():
1833 *
1834 * Sets the top 4 bits of the CR register.
1835 */
1836 void update_cr0(struct cpu *cpu, uint64_t value)
1837 {
1838 int c;
1839
1840 if (cpu->cd.ppc.bits == 64) {
1841 if ((int64_t)value < 0)
1842 c = 8;
1843 else if ((int64_t)value > 0)
1844 c = 4;
1845 else
1846 c = 2;
1847 } else {
1848 if ((int32_t)value < 0)
1849 c = 8;
1850 else if ((int32_t)value > 0)
1851 c = 4;
1852 else
1853 c = 2;
1854 }
1855
1856 /* SO bit, copied from XER: */
1857 c |= ((cpu->cd.ppc.spr[SPR_XER] >> 31) & 1);
1858
1859 cpu->cd.ppc.cr &= ~((uint32_t)0xf << 28);
1860 cpu->cd.ppc.cr |= ((uint32_t)c << 28);
1861 }
1862
1863
1864 #include "memory_ppc.c"
1865
1866
1867 #include "tmp_ppc_tail.c"
1868
1869

  ViewVC Help
Powered by ViewVC 1.1.26