/[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 38 - (show annotations)
Mon Oct 8 16:21:53 2007 UTC (16 years, 5 months ago) by dpavlin
File MIME type: text/plain
File size: 49511 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1515 2007/04/14 05:39:46 debug Exp $
20070324	Adding a "--debug" option to the configure script, to disable
		optimizations in unstable development builds.
		Moving out SCSI-specific stuff from diskimage.c into a new
		diskimage_scsicmd.c.
		Applying Hĺvard Eidnes' patch for SCSICDROM_READ_DISKINFO and
		SCSICDROM_READ_TRACKINFO. (Not really tested yet.)
		Implementing disk image "overlays" (to allow simple roll-back
		to previous disk state). Adding a 'V' disk flag for this, and
		updating the man page and misc.html.
20070325	Stability fix to cpu_dyntrans.c, when multiple physical pages
		share the same initial table entry. (The ppp == NULL check
		should be physpage_ofs == 0.) Bug found by analysing GXemul
		against a version patched for Godson.
		Fixing a second occurance of the same problem (also in
		cpu_dyntrans.c).
		Fixing a MAJOR physical page leak in cpu_dyntrans.c; pages
		weren't _added_ to the set of translated pages, they _replaced_
		all previous pages. It's amazing that this bug has been able
		to live for this long. (Triggered when emulating >128MB RAM.)
20070326	Removing the GDB debugging stub support; it was too hackish
		and ugly.
20070328	Moving around some native code generation skeleton code.
20070329	The -lm check in the configure script now also checks for sin()
		in addition to sqrt(). (Thanks to Nigel Horne for noticing that
		sqrt was not enough on Fedora Core 6.) (Not verified yet.)
20070330	Fixing an indexing bug in dev_sh4.c, found by using gcc version
		4.3.0 20070323.
20070331	Some more experimentation with native code generation.
20070404	Attempting to fix some more SH4 SCIF interrupt bugs; rewriting
		the SH interrupt assertion/deassertion code somewhat.
20070410	Splitting src/file.c into separate files in src/file/.
		Cleanup: Removing the dummy TS7200, Walnut, PB1000, and
		Meshcube emulation modes, and dev_epcom and dev_au1x00.
		Removing the experimental CHIP8/RCA180x code; it wasn't really
		working much lately, anyway. It was fun while it lasted.
		Also removing the experimental Transputer CPU support.
20070412	Moving the section about how the dynamic translation system
		works from intro.html to a separate translation.html file.
		Minor SH fixes; attempting to get OpenBSD/landisk to run
		without randomly bugging out, but no success yet.
20070413	SH SCI (serial bit interface) should now work together with a
		(new) RS5C313 clock device (for Landisk emulation).
20070414	Moving Redhat/MIPS down from supported to experimental, in
		guestoses.html.
		Preparing for a new release; doing some regression testing etc.

==============  RELEASE 0.4.5  ==============


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

  ViewVC Help
Powered by ViewVC 1.1.26