/[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 28 - (show annotations)
Mon Oct 8 16:20:26 2007 UTC (13 years, 1 month ago) by dpavlin
File MIME type: text/plain
File size: 51717 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1298 2006/07/22 11:27:46 debug Exp $
20060626	Continuing on SPARC emulation (beginning on the 'save'
		instruction, register windows, etc).
20060629	Planning statistics gathering (new -s command line option),
		and renaming speed_tricks to allow_instruction_combinations.
20060630	Some minor manual page updates.
		Various cleanups.
		Implementing the -s command line option.
20060701	FINALLY found the bug which prevented Linux and Ultrix from
		running without the ugly hack in the R2000/R3000 cache isol
		code; it was the phystranslation hint array which was buggy.
		Removing the phystranslation hint code completely, for now.
20060702	Minor dyntrans cleanups; invalidation of physpages now only
		invalidate those parts of a page that have actually been
		translated. (32 parts per page.)
		Some MIPS non-R3000 speed fixes.
		Experimenting with MIPS instruction combination for some
		addiu+bne+sw loops, and sw+sw+sw.
		Adding support (again) for larger-than-4KB pages in MIPS tlbw*.
		Continuing on SPARC emulation: adding load/store instructions.
20060704	Fixing a virtual vs physical page shift bug in the new tlbw*
		implementation. Problem noticed by Jakub Jermar. (Many thanks.)
		Moving rfe and eret to cpu_mips_instr.c, since that is the
		only place that uses them nowadays.
20060705	Removing the BSD license from the "testmachine" include files,
		placing them in the public domain instead; this enables the
		testmachine stuff to be used from projects which are
		incompatible with the BSD license for some reason.
20060707	Adding instruction combinations for the R2000/R3000 L1
		I-cache invalidation code used by NetBSD/pmax 3.0, lui+addiu,
		various branches followed by addiu or nop, and jr ra followed
		by addiu. The time it takes to perform a full NetBSD/pmax R3000
		install on the laptop has dropped from 573 seconds to 539. :-)
20060708	Adding a framebuffer controller device (dev_fbctrl), which so
		far can be used to change the fb resolution during runtime, but
		in the future will also be useful for accelerated block fill/
		copy, and possibly also simplified character output.
		Adding an instruction combination for NetBSD/pmax' strlen.
20060709	Minor fixes: reading raw files in src/file.c wasn't memblock
		aligned, removing buggy multi_sw MIPS instruction combination,
		etc.
20060711	Adding a machine_qemu.c, which contains a "qemu_mips" machine.
		(It mimics QEMU's MIPS machine mode, so that a test kernel
		made for QEMU_MIPS also can run in GXemul... at least to some
		extent.)  Adding a short section about how to run this mode to
		doc/guestoses.html.
20060714	Misc. minor code cleanups.
20060715	Applying a patch which adds getchar() to promemul/yamon.c
		(from Oleksandr Tymoshenko).
		Adding yamon.h from NetBSD, and rewriting yamon.c to use it
		(instead of ugly hardcoded numbers) + some cleanup.
20060716	Found and fixed the bug which broke single-stepping of 64-bit
		programs between 0.4.0 and 0.4.0.1 (caused by too quick
		refactoring and no testing). Hopefully this fix will not
		break too many other things.
20060718	Continuing on the 8253 PIT; it now works with Linux/QEMU_MIPS.
		Re-adding the sw+sw+sw instr comb (the problem was that I had
		ignored endian issues); however, it doesn't seem to give any
		big performance gain.
20060720	Adding a dummy Transputer mode (T414, T800 etc) skeleton (only
		the 'j' and 'ldc' instructions are implemented so far). :-}
20060721	Adding gtreg.h from NetBSD, updating dev_gt.c to use it, plus
		misc. other updates to get Linux 2.6 for evbmips/malta working
		(thanks to Alec Voropay for the details).
		FINALLY found and fixed the bug which made tlbw* for non-R3000
		buggy; it was a reference count problem in the dyntrans core.
20060722	Testing stuff; things seem stable enough for a new release.

==============  RELEASE 0.4.1  ==============


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

  ViewVC Help
Powered by ViewVC 1.1.26