/[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 44 - (show annotations)
Mon Oct 8 16:22:56 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 49821 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1632 2007/09/11 21:46:35 debug Exp $
20070616	Implementing the MIPS32/64 revision 2 "ror" instruction.
20070617	Adding a struct for each physpage which keeps track of which
		ranges within that page (base offset, length) that are
		continuously translatable. When running with native code
		generation enabled (-b), a range is added after each read-
		ahead loop.
		Experimenting with using the physical program counter sample
		data (implemented 20070608) together with the "translatable
		range" information, to figure out which physical address ranges
		would be worth translating to native code (if the number of
		samples falling within a range is above a certain threshold).
20070618	Adding automagic building of .index comment files for
		src/file/, src/promemul/, src src/useremul/ as well.
		Adding a "has been translated" bit to the ranges, so that only
		not-yet-translated ranges will be sampled.
20070619	Moving src/cpu.c and src/memory_rw.c into src/cpus/,
		src/device.c into src/devices/, and src/machine.c into
		src/machines/.
		Creating a skeleton cc/ld native backend module; beginning on
		the function which will detect cc command line, etc.
20070620	Continuing on the native code generation infrastructure.
20070621	Moving src/x11.c and src/console.c into a new src/console/
		subdir (for everything that is console or framebuffer related).
		Moving src/symbol*.c into a new src/symbol/, which should
		contain anything that is symbol handling related.
20070624	Making the program counter sampling threshold a "settings
		variable" (sampling_threshold), i.e. it can now be changed
		during runtime.
		Switching the RELEASE notes format from plain text to HTML.
		If the TMPDIR environment variable is set, it is used instead
		of "/tmp" for temporary files.
		Continuing on the cc/ld backend: simple .c code is generated,
		the compiler and linker are called, etc.
		Adding detection of host architecture to the configure script
		(again), and adding icache invalidation support (only
		implemented for Alpha hosts so far).
20070625	Simplifying the program counter sampling mechanism.
20070626	Removing the cc/ld native code generation stuff, program
		counter sampling, etc; it would not have worked well in the
		general case.
20070627	Removing everything related to native code generation.
20070629	Removing the (practically unusable) support for multiple
		emulations. (The single emulation allowed now still supports
		multiple simultaneous machines, as before.)
		Beginning on PCCTWO and M88K interrupts.
20070723	Adding a dummy skeleton for emulation of M32R processors.
20070901	Fixing a warning found by "gcc version 4.3.0 20070817
		(experimental)" on amd64.
20070905	Removing some more traces of the old "multiple emulations"
		code.
		Also looking in /usr/local/include and /usr/local/lib for
		X11 libs, when running configure.
20070909	Minor updates to the guest OS install instructions, in
		preparation for the NetBSD 4.0 release.
20070918	More testing of NetBSD 4.0 RC1.

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 (%s), pc = "
1823 "0x%"PRIx64" ]\n", 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