/[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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 22 - (hide annotations)
Mon Oct 8 16:19:37 2007 UTC (13 years, 3 months ago) by dpavlin
File MIME type: text/plain
File size: 48189 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1121 2006/02/18 21:03:08 debug Exp $
20051126	Cobalt and PReP now work with the 21143 NIC.
		Continuing on Alpha dyntrans things.
		Fixing some more left-shift-by-24 to unsigned.
20051127	Working on OpenFirmware emulation; major cleanup/redesign.
		Progress on MacPPC emulation: NetBSD detects two CPUs (when
		running with -n 2), framebuffer output (for text) works.
		Adding quick-hack Bandit PCI controller and "gc" interrupt
		controller for MacPPC.
20051128	Changing from a Bandit to a Uni-North controller for macppc.
		Continuing on OpenFirmware and MacPPC emulation in general
		(obio controller, and wdc attached to the obio seems to work).
20051129	More work on MacPPC emulation (adding a dummy ADB controller).
		Continuing the PCI bus cleanup (endianness and tag composition)
		and rewriting all PCI controllers' access functions.
20051130	Various minor PPC dyntrans optimizations.
		Manually inlining some parts of the framebuffer redraw routine.
		Slowly beginning the conversion of the old MIPS emulation into
		dyntrans (but this will take quite some time to get right).
		Generalizing quick_pc_to_pointers.
20051201	Documentation update (David Muse has made available a kernel
		which simplifies Debian/DECstation installation).
		Continuing on the ADB bus controller.
20051202	Beginning a rewrite of the Zilog serial controller (dev_zs).
20051203	Continuing on the zs rewrite (now called dev_z8530); conversion
		to devinit style.
		Reworking some of the input-only vs output-only vs input-output
		details of src/console.c, better warning messages, and adding
		a debug dump.
		Removing the concept of "device state"; it wasn't really used.
		Changing some debug output (-vv should now be used to show all
		details about devices and busses; not shown during normal
		startup anymore).
		Beginning on some SPARC instruction disassembly support.
20051204	Minor PPC updates (WALNUT skeleton stuff).
		Continuing on the MIPS dyntrans rewrite.
		More progress on the ADB controller (a keyboard is "detected"
		by NetBSD and OpenBSD).
		Downgrading OpenBSD/arc as a guest OS from "working" to
		"almost working" in the documentation.
		Progress on Algor emulation ("v3" PCI controller).
20051205	Minor updates.
20051207	Sorting devices according to address; this reduces complexity
		of device lookups from O(n) to O(log n) in memory_rw (but no
		real performance increase (yet) in experiments).
20051210	Beginning the work on native dyntrans backends (by making a
		simple skeleton; so far only for Alpha hosts).
20051211	Some very minor SPARC updates.
20051215	Fixing a bug in the MIPS mul (note: not mult) instruction,
		so it also works with non-64-bit emulation. (Thanks to Alec
		Voropay for noticing the problem.)
20051216	More work on the fake/empty/simple/skeleton/whatever backend;
		performance doesn't increase, so this isn't really worth it,
		but it was probably worth it to prepare for a real backend
		later.
20051219	More instr call statistics gathering and analysis stuff.
20051220	Another fix for MIPS 'mul'. Also converting mul and {d,}cl{o,z}
		to dyntrans.
		memory_ppc.c syntax error fix (noticed by Peter Valchev).
		Beginning to move out machines from src/machine.c into
		individual files in src/machines (in a way similar to the
		autodev system for devices).
20051222	Updating the documentation regarding NetBSD/pmax 3.0.
20051223	- " - NetBSD/cats 3.0.
20051225	- " - NetBSD/hpcmips 3.0.
20051226	Continuing on the machine registry redesign.
		Adding support for ARM rrx (33-bit rotate).
		Fixing some signed/unsigned issues (exposed by gcc -W).
20051227	Fixing the bug which prevented a NetBSD/prep 3.0 install kernel
		from starting (triggered when an mtmsr was the last instruction
		on a page). Unfortunately not enough to get the kernel to run
		as well as the 2.1 kernels did.
20051230	Some dyntrans refactoring.
20051231	Continuing on the machine registry redesign.
20060101-10	Continuing... moving more machines. Moving MD interrupt stuff
		from machine.c into a new src/machines/interrupts.c.
20060114	Adding various mvmeppc machine skeletons.
20060115	Continuing on mvme* stuff. NetBSD/mvmeppc prints boot messages
		(for MVME1600) and reaches the root device prompt, but no
		specific hardware devices are emulated yet.
20060116	Minor updates to the mvme1600 emulation mode; the Eagle PCI bus
		seems to work without much modification, and a 21143 can be
		detected, interrupts might work (but untested so far).
		Adding a fake MK48Txx (mkclock) device, for NetBSD/mvmeppc.
20060121	Adding an aux control register for ARM. (A BIG thank you to
		Olivier Houchard for tracking down this bug.)
20060122	Adding more ARM instructions (smulXY), and dev_iq80321_7seg.
20060124	Adding disassembly of more ARM instructions (mia*, mra/mar),
		and some semi-bogus XScale and i80321 registers.
20060201-02	Various minor updates. Moving the last machines out of
		machine.c.
20060204	Adding a -c command line option, for running debugger commands
		before the simulation starts, but after all files have been
		loaded.
		Minor iq80321-related updates.
20060209	Minor hacks (DEVINIT macro, etc).
		Preparing for the generalization of the 64-bit dyntrans address
		translation subsystem.
20060216	Adding ARM ldrd (double-register load).
20060217	Continuing on various ARM-related stuff.
20060218	More progress on the ATA/wdc emulation for NetBSD/iq80321.
		NetBSD/evbarm can now be installed :-)  Updating the docs, etc.
		Continuing on Algor emulation.

==============  RELEASE 0.3.8  ==============


1 dpavlin 14 /*
2 dpavlin 22 * Copyright (C) 2005-2006 Anders Gavare. All rights reserved.
3 dpavlin 14 *
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 dpavlin 22 * $Id: cpu_ppc.c,v 1.45 2006/01/24 21:26:01 debug Exp $
29 dpavlin 14 *
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 dpavlin 22 #include "of.h"
44 dpavlin 14 #include "opcodes_ppc.h"
45 dpavlin 20 #include "ppc_bat.h"
46     #include "ppc_pte.h"
47     #include "ppc_spr.h"
48     #include "ppc_spr_strings.h"
49 dpavlin 14 #include "symbol.h"
50    
51     #define DYNTRANS_DUALMODE_32
52     #include "tmp_ppc_head.c"
53    
54    
55 dpavlin 20 void ppc_pc_to_pointers(struct cpu *);
56     void ppc32_pc_to_pointers(struct cpu *);
57    
58    
59 dpavlin 14 /*
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 dpavlin 20 cpu->cd.ppc.spr[SPR_PVR] = cpu->cd.ppc.cpu_type.pvr;
97 dpavlin 14
98 dpavlin 22 cpu->cd.ppc.spr[SPR_IBAT0U] = 0x00001ffc | BAT_Vs;
99     cpu->cd.ppc.spr[SPR_IBAT0L] = 0x00000000 | BAT_PP_RW;
100     cpu->cd.ppc.spr[SPR_IBAT1U] = 0xc0001ffc | BAT_Vs;
101     cpu->cd.ppc.spr[SPR_IBAT1L] = 0x00000000 | BAT_PP_RW;
102     cpu->cd.ppc.spr[SPR_IBAT3U] = 0xf0001ffc | BAT_Vs;
103     cpu->cd.ppc.spr[SPR_IBAT3L] = 0xf0000000 | BAT_PP_RW;
104     cpu->cd.ppc.spr[SPR_DBAT0U] = 0x00001ffc | BAT_Vs;
105     cpu->cd.ppc.spr[SPR_DBAT0L] = 0x00000000 | BAT_PP_RW;
106     cpu->cd.ppc.spr[SPR_DBAT1U] = 0xc0001ffc | BAT_Vs;
107     cpu->cd.ppc.spr[SPR_DBAT1L] = 0x00000000 | BAT_PP_RW;
108     cpu->cd.ppc.spr[SPR_DBAT2U] = 0xe0001ffc | BAT_Vs;
109     cpu->cd.ppc.spr[SPR_DBAT2L] = 0xe0000000 | BAT_PP_RW;
110     cpu->cd.ppc.spr[SPR_DBAT3U] = 0xf0001ffc | BAT_Vs;
111     cpu->cd.ppc.spr[SPR_DBAT3L] = 0xf0000000 | BAT_PP_RW;
112    
113 dpavlin 14 cpu->is_32bit = (cpu->cd.ppc.bits == 32)? 1 : 0;
114    
115     if (cpu->is_32bit) {
116     cpu->update_translation_table = ppc32_update_translation_table;
117 dpavlin 18 cpu->invalidate_translation_caches =
118     ppc32_invalidate_translation_caches;
119 dpavlin 14 cpu->invalidate_code_translation =
120     ppc32_invalidate_code_translation;
121     } else {
122     cpu->update_translation_table = ppc_update_translation_table;
123 dpavlin 18 cpu->invalidate_translation_caches =
124     ppc_invalidate_translation_caches;
125 dpavlin 14 cpu->invalidate_code_translation =
126     ppc_invalidate_code_translation;
127     }
128    
129     cpu->translate_address = ppc_translate_address;
130    
131     /* Only show name and caches etc for CPU nr 0 (in SMP machines): */
132     if (cpu_id == 0) {
133     debug("%s", cpu->cd.ppc.cpu_type.name);
134    
135     if (cpu->cd.ppc.cpu_type.icache_shift != 0)
136     any_cache = 1;
137     if (cpu->cd.ppc.cpu_type.dcache_shift != 0)
138     any_cache = 1;
139     if (cpu->cd.ppc.cpu_type.l2cache_shift != 0)
140     any_cache = 1;
141    
142     if (any_cache) {
143     debug(" (I+D = %i+%i KB",
144     (int)(1 << (cpu->cd.ppc.cpu_type.icache_shift-10)),
145     (int)(1 << (cpu->cd.ppc.cpu_type.dcache_shift-10)));
146     if (cpu->cd.ppc.cpu_type.l2cache_shift != 0) {
147     debug(", L2 = %i KB",
148     (int)(1 << (cpu->cd.ppc.cpu_type.
149     l2cache_shift-10)));
150     }
151     debug(")");
152     }
153     }
154    
155 dpavlin 20 cpu->cd.ppc.spr[SPR_PIR] = cpu_id;
156 dpavlin 14
157     /* Some default stack pointer value. TODO: move this? */
158     cpu->cd.ppc.gpr[1] = machine->physical_ram_in_mb * 1048576 - 4096;
159    
160     /*
161     * NOTE/TODO: Ugly hack for OpenFirmware emulation:
162     */
163     if (cpu->machine->prom_emulation)
164     cpu->cd.ppc.of_emul_addr = 0xfff00000;
165    
166     return 1;
167     }
168    
169    
170     /*
171     * ppc_cpu_list_available_types():
172     *
173     * Print a list of available PPC CPU types.
174     */
175     void ppc_cpu_list_available_types(void)
176     {
177     int i, j;
178     struct ppc_cpu_type_def tdefs[] = PPC_CPU_TYPE_DEFS;
179    
180     i = 0;
181     while (tdefs[i].name != NULL) {
182     debug("%s", tdefs[i].name);
183     for (j=10 - strlen(tdefs[i].name); j>0; j--)
184     debug(" ");
185     i++;
186     if ((i % 6) == 0 || tdefs[i].name == NULL)
187     debug("\n");
188     }
189     }
190    
191    
192     /*
193     * ppc_cpu_dumpinfo():
194     */
195     void ppc_cpu_dumpinfo(struct cpu *cpu)
196     {
197     struct ppc_cpu_type_def *ct = &cpu->cd.ppc.cpu_type;
198    
199     debug(" (%i-bit ", cpu->cd.ppc.bits);
200    
201     switch (cpu->cd.ppc.mode) {
202     case MODE_PPC:
203     debug("PPC");
204     break;
205     case MODE_POWER:
206     debug("POWER");
207     break;
208     default:
209     debug("_INTERNAL ERROR_");
210     }
211    
212     debug(", I+D = %i+%i KB",
213     (1 << ct->icache_shift) / 1024,
214     (1 << ct->dcache_shift) / 1024);
215    
216     if (ct->l2cache_shift) {
217     int kb = (1 << ct->l2cache_shift) / 1024;
218     debug(", L2 = %i %cB",
219     kb >= 1024? kb / 1024 : kb,
220     kb >= 1024? 'M' : 'K');
221     }
222    
223     debug(")\n");
224     }
225    
226    
227     /*
228     * reg_access_msr():
229     */
230 dpavlin 20 void reg_access_msr(struct cpu *cpu, uint64_t *valuep, int writeflag,
231     int check_for_interrupts)
232 dpavlin 14 {
233 dpavlin 20 uint64_t old = cpu->cd.ppc.msr;
234    
235 dpavlin 14 if (valuep == NULL) {
236     fatal("reg_access_msr(): NULL\n");
237     return;
238     }
239    
240 dpavlin 20 if (writeflag) {
241 dpavlin 14 cpu->cd.ppc.msr = *valuep;
242    
243 dpavlin 20 /* Switching between temporary and real gpr 0..3? */
244     if ((old & PPC_MSR_TGPR) != (cpu->cd.ppc.msr & PPC_MSR_TGPR)) {
245     int i;
246     for (i=0; i<PPC_N_TGPRS; i++) {
247     uint64_t t = cpu->cd.ppc.gpr[i];
248     cpu->cd.ppc.gpr[i] = cpu->cd.ppc.tgpr[i];
249     cpu->cd.ppc.tgpr[i] = t;
250     }
251     }
252    
253     if (cpu->cd.ppc.msr & PPC_MSR_IP) {
254     fatal("\n[ Reboot hack for NetBSD/prep. TODO: "
255     "fix this. ]\n");
256     cpu->running = 0;
257     }
258     }
259    
260 dpavlin 14 /* TODO: Is the little-endian bit writable? */
261    
262     cpu->cd.ppc.msr &= ~PPC_MSR_LE;
263     if (cpu->byte_order != EMUL_BIG_ENDIAN)
264     cpu->cd.ppc.msr |= PPC_MSR_LE;
265    
266     if (!writeflag)
267     *valuep = cpu->cd.ppc.msr;
268 dpavlin 20
269     if (check_for_interrupts && cpu->cd.ppc.msr & PPC_MSR_EE) {
270     if (cpu->cd.ppc.dec_intr_pending) {
271     ppc_exception(cpu, PPC_EXCEPTION_DEC);
272     cpu->cd.ppc.dec_intr_pending = 0;
273     } else if (cpu->cd.ppc.irq_asserted)
274     ppc_exception(cpu, PPC_EXCEPTION_EI);
275     }
276 dpavlin 14 }
277    
278    
279     /*
280 dpavlin 20 * ppc_exception():
281     */
282     void ppc_exception(struct cpu *cpu, int exception_nr)
283     {
284     /* Save PC and MSR: */
285     cpu->cd.ppc.spr[SPR_SRR0] = cpu->pc;
286    
287     if (exception_nr >= 0x10 && exception_nr <= 0x13)
288     cpu->cd.ppc.spr[SPR_SRR1] = (cpu->cd.ppc.msr & 0xffff)
289     | (cpu->cd.ppc.cr & 0xf0000000);
290     else
291     cpu->cd.ppc.spr[SPR_SRR1] = (cpu->cd.ppc.msr & 0x87c0ffff);
292    
293     if (!quiet_mode)
294     fatal("[ PPC Exception 0x%x; pc=0x%llx ]\n", exception_nr,
295     (long long)cpu->pc);
296    
297     /* Disable External Interrupts, Recoverable Interrupt Mode,
298     and go to Supervisor mode */
299     cpu->cd.ppc.msr &= ~(PPC_MSR_EE | PPC_MSR_RI | PPC_MSR_PR);
300    
301     cpu->pc = exception_nr * 0x100;
302     if (cpu->cd.ppc.msr & PPC_MSR_IP)
303 dpavlin 22 cpu->pc += 0xfff00000ULL;
304 dpavlin 20
305     if (cpu->is_32bit)
306     ppc32_pc_to_pointers(cpu);
307     else
308     ppc_pc_to_pointers(cpu);
309     }
310    
311    
312     /*
313 dpavlin 14 * ppc_cpu_register_dump():
314     *
315     * Dump cpu registers in a relatively readable format.
316     *
317     * gprs: set to non-zero to dump GPRs and some special-purpose registers.
318     * coprocs: if bit i is set, then we should dump registers from coproc i.
319     */
320     void ppc_cpu_register_dump(struct cpu *cpu, int gprs, int coprocs)
321     {
322     char *symbol;
323     uint64_t offset, tmp;
324     int i, x = cpu->cpu_id;
325     int bits32 = cpu->cd.ppc.bits == 32;
326    
327     if (gprs) {
328     /* Special registers (pc, ...) first: */
329     symbol = get_symbol_name(&cpu->machine->symbol_context,
330     cpu->pc, &offset);
331    
332     debug("cpu%i: pc = 0x", x);
333     if (bits32)
334     debug("%08x", (int)cpu->pc);
335     else
336     debug("%016llx", (long long)cpu->pc);
337     debug(" <%s>\n", symbol != NULL? symbol : " no symbol ");
338    
339     debug("cpu%i: lr = 0x", x);
340     if (bits32)
341 dpavlin 20 debug("%08x", (int)cpu->cd.ppc.spr[SPR_LR]);
342 dpavlin 14 else
343 dpavlin 20 debug("%016llx", (long long)cpu->cd.ppc.spr[SPR_LR]);
344 dpavlin 22 debug(" cr = 0x%08x", (int)cpu->cd.ppc.cr);
345 dpavlin 14
346     if (bits32)
347 dpavlin 22 debug(" ");
348     else
349     debug("\ncpu%i: ", x);
350     debug("ctr = 0x", x);
351     if (bits32)
352 dpavlin 20 debug("%08x", (int)cpu->cd.ppc.spr[SPR_CTR]);
353 dpavlin 14 else
354 dpavlin 20 debug("%016llx", (long long)cpu->cd.ppc.spr[SPR_CTR]);
355 dpavlin 14
356     debug(" xer = 0x", x);
357     if (bits32)
358 dpavlin 20 debug("%08x\n", (int)cpu->cd.ppc.spr[SPR_XER]);
359 dpavlin 14 else
360 dpavlin 20 debug("%016llx\n", (long long)cpu->cd.ppc.spr[SPR_XER]);
361 dpavlin 14
362     if (bits32) {
363     /* 32-bit: */
364     for (i=0; i<PPC_NGPRS; i++) {
365     if ((i % 4) == 0)
366     debug("cpu%i:", x);
367     debug(" r%02i = 0x%08x ", i,
368     (int)cpu->cd.ppc.gpr[i]);
369     if ((i % 4) == 3)
370     debug("\n");
371     }
372     } else {
373     /* 64-bit: */
374     for (i=0; i<PPC_NGPRS; i++) {
375     int r = (i >> 1) + ((i & 1) << 4);
376     if ((i % 2) == 0)
377     debug("cpu%i:", x);
378     debug(" r%02i = 0x%016llx ", r,
379     (long long)cpu->cd.ppc.gpr[r]);
380     if ((i % 2) == 1)
381     debug("\n");
382     }
383     }
384    
385     /* Other special registers: */
386 dpavlin 22 if (bits32) {
387     debug("cpu%i: srr0 = 0x%08x srr1 = 0x%08x\n", x,
388     (int)cpu->cd.ppc.spr[SPR_SRR0],
389     (int)cpu->cd.ppc.spr[SPR_SRR1]);
390     } else {
391     debug("cpu%i: srr0 = 0x%016llx srr1 = 0x%016llx\n", x,
392     (long long)cpu->cd.ppc.spr[SPR_SRR0],
393     (long long)cpu->cd.ppc.spr[SPR_SRR1]);
394     }
395     debug("cpu%i: msr = ", x);
396 dpavlin 20 reg_access_msr(cpu, &tmp, 0, 0);
397 dpavlin 22 if (bits32)
398     debug("0x%08x ", (int)tmp);
399     else
400     debug("0x%016llx ", (long long)tmp);
401 dpavlin 20 debug("tb = 0x%08x%08x\n", (int)cpu->cd.ppc.spr[SPR_TBU],
402     (int)cpu->cd.ppc.spr[SPR_TBL]);
403 dpavlin 22 debug("cpu%i: dec = 0x%08x", x, (int)cpu->cd.ppc.spr[SPR_DEC]);
404     if (!bits32)
405     debug(" hdec = 0x%08x\n",
406     (int)cpu->cd.ppc.spr[SPR_HDEC]);
407     debug("\n");
408 dpavlin 14 }
409    
410     if (coprocs & 1) {
411     debug("cpu%i: fpscr = 0x%08x\n", x, (int)cpu->cd.ppc.fpscr);
412    
413     /* TODO: show floating-point values :-) */
414    
415     /* TODO: 32-bit fprs on 32-bit PPC cpus? */
416    
417     for (i=0; i<PPC_NFPRS; i++) {
418     if ((i % 2) == 0)
419     debug("cpu%i:", x);
420     debug(" f%02i = 0x%016llx ", i,
421     (long long)cpu->cd.ppc.fpr[i]);
422     if ((i % 2) == 1)
423     debug("\n");
424     }
425     }
426    
427     if (coprocs & 2) {
428     debug("cpu%i: sdr1 = 0x%llx\n", x,
429 dpavlin 20 (long long)cpu->cd.ppc.spr[SPR_SDR1]);
430     if (cpu->cd.ppc.cpu_type.flags & PPC_601)
431     debug("cpu%i: PPC601-style, TODO!\n");
432     else {
433     for (i=0; i<8; i++) {
434     int spr = SPR_IBAT0U + i*2;
435     uint32_t upper = cpu->cd.ppc.spr[spr];
436     uint32_t lower = cpu->cd.ppc.spr[spr+1];
437     uint32_t len = (((upper & BAT_BL) << 15)
438     | 0x1ffff) + 1;
439     debug("cpu%i: %sbat%i: u=0x%08x l=0x%08x ",
440     x, i<4? "i" : "d", i&3, upper, lower);
441     if (!(upper & BAT_V)) {
442     debug(" (not valid)\n");
443     continue;
444     }
445     if (len < 1048576)
446     debug(" (%i KB, ", len >> 10);
447     else
448     debug(" (%i MB, ", len >> 20);
449     if (upper & BAT_Vu)
450     debug("user, ");
451     if (upper & BAT_Vs)
452     debug("supervisor, ");
453     if (lower & (BAT_W | BAT_I | BAT_M | BAT_G))
454     debug("%s%s%s%s, ",
455     lower & BAT_W? "W" : "",
456     lower & BAT_I? "I" : "",
457     lower & BAT_M? "M" : "",
458     lower & BAT_G? "G" : "");
459     switch (lower & BAT_PP) {
460     case BAT_PP_NONE: debug("NO access"); break;
461     case BAT_PP_RO_S: debug("read-only, soft");
462     break;
463     case BAT_PP_RO: debug("read-only"); break;
464     case BAT_PP_RW: debug("read/write"); break;
465     }
466     debug(")\n");
467     }
468     }
469 dpavlin 14 }
470 dpavlin 20
471     if (coprocs & 4) {
472     for (i=0; i<16; i++) {
473     uint32_t s = cpu->cd.ppc.sr[i];
474     debug("cpu%i:", x);
475     debug(" sr%2i = 0x%08x", i, (int)s);
476     s &= (SR_TYPE | SR_SUKEY | SR_PRKEY | SR_NOEXEC);
477     if (s != 0) {
478     debug(" (");
479     if (s & SR_TYPE) {
480     debug("NON-memory type");
481     s &= ~SR_TYPE;
482     if (s != 0)
483     debug(", ");
484     }
485     if (s & SR_SUKEY) {
486     debug("supervisor-key");
487     s &= ~SR_SUKEY;
488     if (s != 0)
489     debug(", ");
490     }
491     if (s & SR_PRKEY) {
492     debug("user-key");
493     s &= ~SR_PRKEY;
494     if (s != 0)
495     debug(", ");
496     }
497     if (s & SR_NOEXEC)
498     debug("NOEXEC");
499     debug(")");
500     }
501     debug("\n");
502     }
503     }
504 dpavlin 14 }
505    
506    
507     /*
508     * ppc_cpu_register_match():
509     */
510     void ppc_cpu_register_match(struct machine *m, char *name,
511     int writeflag, uint64_t *valuep, int *match_register)
512     {
513     int cpunr = 0;
514    
515     /* CPU number: */
516    
517     /* TODO */
518    
519     /* Register name: */
520     if (strcasecmp(name, "pc") == 0) {
521     if (writeflag) {
522     m->cpus[cpunr]->pc = *valuep;
523     } else
524     *valuep = m->cpus[cpunr]->pc;
525     *match_register = 1;
526     } else if (strcasecmp(name, "msr") == 0) {
527     if (writeflag)
528     m->cpus[cpunr]->cd.ppc.msr = *valuep;
529     else
530     *valuep = m->cpus[cpunr]->cd.ppc.msr;
531     *match_register = 1;
532     } else if (strcasecmp(name, "lr") == 0) {
533     if (writeflag)
534 dpavlin 20 m->cpus[cpunr]->cd.ppc.spr[SPR_LR] = *valuep;
535 dpavlin 14 else
536 dpavlin 20 *valuep = m->cpus[cpunr]->cd.ppc.spr[SPR_LR];
537 dpavlin 14 *match_register = 1;
538     } else if (strcasecmp(name, "cr") == 0) {
539     if (writeflag)
540     m->cpus[cpunr]->cd.ppc.cr = *valuep;
541     else
542     *valuep = m->cpus[cpunr]->cd.ppc.cr;
543     *match_register = 1;
544     } else if (strcasecmp(name, "dec") == 0) {
545     if (writeflag)
546 dpavlin 20 m->cpus[cpunr]->cd.ppc.spr[SPR_DEC] = *valuep;
547 dpavlin 14 else
548 dpavlin 20 *valuep = m->cpus[cpunr]->cd.ppc.spr[SPR_DEC];
549 dpavlin 14 *match_register = 1;
550     } else if (strcasecmp(name, "hdec") == 0) {
551     if (writeflag)
552 dpavlin 20 m->cpus[cpunr]->cd.ppc.spr[SPR_HDEC] = *valuep;
553 dpavlin 14 else
554 dpavlin 20 *valuep = m->cpus[cpunr]->cd.ppc.spr[SPR_HDEC];
555 dpavlin 14 *match_register = 1;
556     } else if (strcasecmp(name, "ctr") == 0) {
557     if (writeflag)
558 dpavlin 20 m->cpus[cpunr]->cd.ppc.spr[SPR_CTR] = *valuep;
559 dpavlin 14 else
560 dpavlin 20 *valuep = m->cpus[cpunr]->cd.ppc.spr[SPR_CTR];
561 dpavlin 14 *match_register = 1;
562     } else if (name[0] == 'r' && isdigit((int)name[1])) {
563     int nr = atoi(name + 1);
564     if (nr >= 0 && nr < PPC_NGPRS) {
565     if (writeflag) {
566     m->cpus[cpunr]->cd.ppc.gpr[nr] = *valuep;
567     } else
568     *valuep = m->cpus[cpunr]->cd.ppc.gpr[nr];
569     *match_register = 1;
570     }
571     } else if (strcasecmp(name, "xer") == 0) {
572     if (writeflag)
573 dpavlin 20 m->cpus[cpunr]->cd.ppc.spr[SPR_XER] = *valuep;
574 dpavlin 14 else
575 dpavlin 20 *valuep = m->cpus[cpunr]->cd.ppc.spr[SPR_XER];
576 dpavlin 14 *match_register = 1;
577     } else if (strcasecmp(name, "fpscr") == 0) {
578     if (writeflag)
579     m->cpus[cpunr]->cd.ppc.fpscr = *valuep;
580     else
581     *valuep = m->cpus[cpunr]->cd.ppc.fpscr;
582     *match_register = 1;
583     } else if (name[0] == 'f' && isdigit((int)name[1])) {
584     int nr = atoi(name + 1);
585     if (nr >= 0 && nr < PPC_NFPRS) {
586     if (writeflag) {
587     m->cpus[cpunr]->cd.ppc.fpr[nr] = *valuep;
588     } else
589     *valuep = m->cpus[cpunr]->cd.ppc.fpr[nr];
590     *match_register = 1;
591     }
592     }
593     }
594    
595    
596     /*
597 dpavlin 20 * ppc_cpu_interrupt():
598 dpavlin 14 *
599 dpavlin 20 * 0..31 are used as BeBox interrupt numbers, 32..47 = ISA,
600     * 64 is used as a "re-assert" signal to cpu->machine->md_interrupt().
601 dpavlin 14 *
602 dpavlin 20 * TODO: don't hardcode to BeBox!
603 dpavlin 14 */
604     int ppc_cpu_interrupt(struct cpu *cpu, uint64_t irq_nr)
605     {
606 dpavlin 20 /* fatal("ppc_cpu_interrupt(): 0x%x\n", (int)irq_nr); */
607     if (irq_nr <= 64) {
608     if (cpu->machine->md_interrupt != NULL)
609     cpu->machine->md_interrupt(
610     cpu->machine, cpu, irq_nr, 1);
611     else
612     fatal("ppc_cpu_interrupt(): md_interrupt == NULL\n");
613     } else {
614     /* Assert PPC IRQ: */
615     cpu->cd.ppc.irq_asserted = 1;
616     }
617     return 1;
618 dpavlin 14 }
619    
620    
621     /*
622     * ppc_cpu_interrupt_ack():
623     */
624     int ppc_cpu_interrupt_ack(struct cpu *cpu, uint64_t irq_nr)
625     {
626 dpavlin 20 if (irq_nr <= 64) {
627     if (cpu->machine->md_interrupt != NULL)
628     cpu->machine->md_interrupt(cpu->machine,
629     cpu, irq_nr, 0);
630     } else {
631     /* De-assert PPC IRQ: */
632     cpu->cd.ppc.irq_asserted = 0;
633     }
634     return 1;
635 dpavlin 14 }
636    
637    
638     /*
639     * ppc_cpu_disassemble_instr():
640     *
641     * Convert an instruction word into human readable format, for instruction
642     * tracing.
643     *
644     * If running is 1, cpu->pc should be the address of the instruction.
645     *
646     * If running is 0, things that depend on the runtime environment (eg.
647     * register contents) will not be shown, and addr will be used instead of
648     * cpu->pc for relative addresses.
649     */
650     int ppc_cpu_disassemble_instr(struct cpu *cpu, unsigned char *instr,
651     int running, uint64_t dumpaddr, int bintrans)
652     {
653     int hi6, xo, lev, rt, rs, ra, rb, imm, sh, me, rc, l_bit, oe_bit;
654     int spr, aa_bit, lk_bit, bf, bh, bi, bo, mb, nb, bt, ba, bb, fpreg;
655     int bfa, to, load, wlen, no_rb = 0;
656     uint64_t offset, addr;
657     uint32_t iword;
658     char *symbol, *mnem = "ERROR";
659     int power = cpu->cd.ppc.mode == MODE_POWER;
660    
661     if (running)
662     dumpaddr = cpu->pc;
663    
664     symbol = get_symbol_name(&cpu->machine->symbol_context,
665     dumpaddr, &offset);
666     if (symbol != NULL && offset==0)
667     debug("<%s>\n", symbol);
668    
669     if (cpu->machine->ncpus > 1 && running)
670     debug("cpu%i: ", cpu->cpu_id);
671    
672     if (cpu->cd.ppc.bits == 32)
673     debug("%08x", (int)dumpaddr);
674     else
675     debug("%016llx", (long long)dumpaddr);
676    
677     /* NOTE: Fixed to big-endian. */
678     iword = (instr[0] << 24) + (instr[1] << 16) + (instr[2] << 8)
679     + instr[3];
680    
681     debug(": %08x\t", iword);
682    
683     /*
684     * Decode the instruction:
685     */
686    
687     hi6 = iword >> 26;
688    
689     switch (hi6) {
690 dpavlin 22 case 0x4:
691     debug("ALTIVEC TODO");
692     /* vxor etc */
693     break;
694 dpavlin 14 case PPC_HI6_MULLI:
695     case PPC_HI6_SUBFIC:
696     rt = (iword >> 21) & 31;
697     ra = (iword >> 16) & 31;
698     imm = (int16_t)(iword & 0xffff);
699     switch (hi6) {
700     case PPC_HI6_MULLI:
701     mnem = power? "muli":"mulli";
702     break;
703     case PPC_HI6_SUBFIC:
704     mnem = power? "sfi":"subfic";
705     break;
706     }
707     debug("%s\tr%i,r%i,%i", mnem, rt, ra, imm);
708     break;
709     case PPC_HI6_CMPLI:
710     case PPC_HI6_CMPI:
711     bf = (iword >> 23) & 7;
712     l_bit = (iword >> 21) & 1;
713     ra = (iword >> 16) & 31;
714     if (hi6 == PPC_HI6_CMPLI) {
715     imm = iword & 0xffff;
716     mnem = "cmpl";
717     } else {
718     imm = (int16_t)(iword & 0xffff);
719     mnem = "cmp";
720     }
721     debug("%s%si\t", mnem, l_bit? "d" : "w");
722     if (bf != 0)
723     debug("cr%i,", bf);
724     debug("r%i,%i", ra, imm);
725     break;
726     case PPC_HI6_ADDIC:
727     case PPC_HI6_ADDIC_DOT:
728     rt = (iword >> 21) & 31;
729     ra = (iword >> 16) & 31;
730     rc = hi6 == PPC_HI6_ADDIC_DOT;
731     imm = (int16_t)(iword & 0xffff);
732     mnem = power? "ai":"addic";
733     if (imm < 0 && !power) {
734     mnem = "subic";
735     imm = -imm;
736     }
737     debug("%s%s\tr%i,r%i,%i", mnem, rc?".":"", rt, ra, imm);
738     break;
739     case PPC_HI6_ADDI:
740     rt = (iword >> 21) & 31;
741     ra = (iword >> 16) & 31;
742     imm = (int16_t)(iword & 0xffff);
743     if (ra == 0)
744     debug("li\tr%i,%i", rt, imm);
745     else {
746     mnem = power? "cal":"addi";
747     if (imm < 0 && !power) {
748     mnem = "subi";
749     imm = -imm;
750     }
751     debug("%s\tr%i,r%i,%i", mnem, rt, ra, imm);
752     }
753     break;
754     case PPC_HI6_ADDIS:
755     rt = (iword >> 21) & 31;
756     ra = (iword >> 16) & 31;
757     imm = (int16_t)(iword & 0xffff);
758     if (ra == 0)
759     debug("lis\tr%i,%i", rt, imm);
760     else
761     debug("%s\tr%i,r%i,%i",
762     power? "cau":"addis", rt, ra, imm);
763     break;
764     case PPC_HI6_BC:
765     aa_bit = (iword & 2) >> 1;
766     lk_bit = iword & 1;
767     bo = (iword >> 21) & 31;
768     bi = (iword >> 16) & 31;
769     /* Sign-extend addr: */
770     addr = (int64_t)(int16_t)(iword & 0xfffc);
771     debug("bc");
772     if (lk_bit)
773     debug("l");
774     if (aa_bit)
775     debug("a");
776     else
777     addr += dumpaddr;
778     debug("\t%i,%i,", bo, bi);
779     if (cpu->cd.ppc.bits == 32)
780     addr &= 0xffffffff;
781     if (cpu->cd.ppc.bits == 32)
782     debug("0x%x", (int)addr);
783     else
784     debug("0x%llx", (long long)addr);
785     symbol = get_symbol_name(&cpu->machine->symbol_context,
786     addr, &offset);
787     if (symbol != NULL)
788     debug("\t<%s>", symbol);
789     break;
790     case PPC_HI6_SC:
791     lev = (iword >> 5) & 0x7f;
792     debug("sc");
793     if (lev != 0) {
794     debug("\t%i", lev);
795     if (lev > 1)
796     debug(" (WARNING! reserved value)");
797     }
798     break;
799     case PPC_HI6_B:
800     aa_bit = (iword & 2) >> 1;
801     lk_bit = iword & 1;
802     /* Sign-extend addr: */
803     addr = (int64_t)(int32_t)((iword & 0x03fffffc) << 6);
804     addr = (int64_t)addr >> 6;
805     debug("b");
806     if (lk_bit)
807     debug("l");
808     if (aa_bit)
809     debug("a");
810     else
811     addr += dumpaddr;
812     if (cpu->cd.ppc.bits == 32)
813     addr &= 0xffffffff;
814     if (cpu->cd.ppc.bits == 32)
815     debug("\t0x%x", (int)addr);
816     else
817     debug("\t0x%llx", (long long)addr);
818     symbol = get_symbol_name(&cpu->machine->symbol_context,
819     addr, &offset);
820     if (symbol != NULL)
821     debug("\t<%s>", symbol);
822     break;
823     case PPC_HI6_19:
824     xo = (iword >> 1) & 1023;
825     switch (xo) {
826     case PPC_19_MCRF:
827     bf = (iword >> 23) & 7;
828     bfa = (iword >> 18) & 7;
829     debug("mcrf\tcr%i,cr%i", bf, bfa);
830     break;
831     case PPC_19_RFI:
832     debug("rfi");
833     break;
834     case PPC_19_RFID:
835     debug("rfid");
836     break;
837     case PPC_19_RFSVC:
838     debug("rfsvc%s", power?"":"\t(INVALID for PowerPC)");
839     break;
840     case PPC_19_BCLR:
841     case PPC_19_BCCTR:
842     bo = (iword >> 21) & 31;
843     bi = (iword >> 16) & 31;
844     bh = (iword >> 11) & 3;
845     lk_bit = iword & 1;
846     switch (xo) {
847     case PPC_19_BCLR:
848     mnem = power? "bcr" : "bclr"; break;
849     case PPC_19_BCCTR:
850     mnem = power? "bcc" : "bcctr"; break;
851     }
852     debug("%s%s%s\t%i,%i,%i", mnem, lk_bit? "l" : "",
853     bh? (bh==3? "+" : (bh==2? "-" : "?")) : "",
854     bo, bi, bh);
855     break;
856     case PPC_19_ISYNC:
857     debug("%s", power? "ics" : "isync");
858     break;
859     case PPC_19_CRAND:
860     case PPC_19_CRXOR:
861     case PPC_19_CROR:
862     case PPC_19_CRNAND:
863     case PPC_19_CRNOR:
864     case PPC_19_CRANDC:
865     case PPC_19_CREQV:
866     case PPC_19_CRORC:
867     bt = (iword >> 21) & 31;
868     ba = (iword >> 16) & 31;
869     bb = (iword >> 11) & 31;
870     switch (xo) {
871     case PPC_19_CRAND: mnem = "crand"; break;
872     case PPC_19_CRXOR: mnem = "crxor"; break;
873     case PPC_19_CROR: mnem = "cror"; break;
874     case PPC_19_CRNAND: mnem = "crnand"; break;
875     case PPC_19_CRNOR: mnem = "crnor"; break;
876     case PPC_19_CRANDC: mnem = "crandc"; break;
877     case PPC_19_CREQV: mnem = "creqv"; break;
878     case PPC_19_CRORC: mnem = "crorc"; break;
879     }
880     debug("%s\t%i,%i,%i", mnem, bt, ba, bb);
881     break;
882     default:
883     debug("unimplemented hi6_19, xo = 0x%x", xo);
884     }
885     break;
886 dpavlin 20 case PPC_HI6_RLWNM:
887 dpavlin 14 case PPC_HI6_RLWIMI:
888     case PPC_HI6_RLWINM:
889     rs = (iword >> 21) & 31;
890     ra = (iword >> 16) & 31;
891 dpavlin 20 sh = (iword >> 11) & 31; /* actually rb for rlwnm */
892 dpavlin 14 mb = (iword >> 6) & 31;
893     me = (iword >> 1) & 31;
894     rc = iword & 1;
895     switch (hi6) {
896 dpavlin 20 case PPC_HI6_RLWNM:
897     mnem = power? "rlnm" : "rlwnm"; break;
898 dpavlin 14 case PPC_HI6_RLWIMI:
899     mnem = power? "rlimi" : "rlwimi"; break;
900     case PPC_HI6_RLWINM:
901     mnem = power? "rlinm" : "rlwinm"; break;
902     }
903 dpavlin 20 debug("%s%s\tr%i,r%i,%s%i,%i,%i",
904     mnem, rc?".":"", ra, rs,
905     hi6 == PPC_HI6_RLWNM? "r" : "",
906     sh, mb, me);
907 dpavlin 14 break;
908     case PPC_HI6_ORI:
909     case PPC_HI6_ORIS:
910     case PPC_HI6_XORI:
911     case PPC_HI6_XORIS:
912     case PPC_HI6_ANDI_DOT:
913     case PPC_HI6_ANDIS_DOT:
914     rs = (iword >> 21) & 31;
915     ra = (iword >> 16) & 31;
916     imm = iword & 0xffff;
917     switch (hi6) {
918     case PPC_HI6_ORI:
919     mnem = power? "oril":"ori";
920     break;
921     case PPC_HI6_ORIS:
922     mnem = power? "oriu":"oris";
923     break;
924     case PPC_HI6_XORI:
925     mnem = power? "xoril":"xori";
926     break;
927     case PPC_HI6_XORIS:
928     mnem = power? "xoriu":"xoris";
929     break;
930     case PPC_HI6_ANDI_DOT:
931     mnem = power? "andil.":"andi.";
932     break;
933     case PPC_HI6_ANDIS_DOT:
934     mnem = power? "andiu.":"andis.";
935     break;
936     }
937     if (hi6 == PPC_HI6_ORI && rs == 0 && ra == 0 && imm == 0)
938     debug("nop");
939     else
940     debug("%s\tr%i,r%i,0x%04x", mnem, ra, rs, imm);
941     break;
942     case PPC_HI6_30:
943     xo = (iword >> 2) & 7;
944     switch (xo) {
945     case PPC_30_RLDICR:
946     rs = (iword >> 21) & 31;
947     ra = (iword >> 16) & 31;
948     sh = ((iword >> 11) & 31) | ((iword & 2) << 4);
949     me = ((iword >> 6) & 31) | (iword & 0x20);
950     rc = iword & 1;
951     debug("rldicr%s\tr%i,r%i,%i,%i",
952     rc?".":"", ra, rs, sh, me);
953     break;
954     default:
955     debug("unimplemented hi6_30, xo = 0x%x", xo);
956     }
957     break;
958     case PPC_HI6_31:
959     xo = (iword >> 1) & 1023;
960     switch (xo) {
961    
962     case PPC_31_CMP:
963     case PPC_31_CMPL:
964     bf = (iword >> 23) & 7;
965     l_bit = (iword >> 21) & 1;
966     ra = (iword >> 16) & 31;
967     rb = (iword >> 11) & 31;
968     if (xo == PPC_31_CMPL)
969     mnem = "cmpl";
970     else
971     mnem = "cmp";
972     debug("%s%s\t", mnem, l_bit? "d" : "w");
973     if (bf != 0)
974     debug("cr%i,", bf);
975     debug("r%i,r%i", ra, rb);
976     break;
977     case PPC_31_MFCR:
978     rt = (iword >> 21) & 31;
979     debug("mfcr\tr%i", rt);
980     break;
981     case PPC_31_MFMSR:
982     rt = (iword >> 21) & 31;
983     debug("mfmsr\tr%i", rt);
984     break;
985     case PPC_31_MTCRF:
986     rs = (iword >> 21) & 31;
987     mb = (iword >> 12) & 255; /* actually fxm, not mb */
988     debug("mtcrf\t%i,r%i", mb, rs);
989     break;
990     case PPC_31_MTMSR:
991     rs = (iword >> 21) & 31;
992     l_bit = (iword >> 16) & 1;
993     debug("mtmsr\tr%i", rs);
994     if (l_bit)
995     debug(",%i", l_bit);
996     break;
997     case PPC_31_TW:
998     case PPC_31_TD:
999     to = (iword >> 21) & 31;
1000     ra = (iword >> 16) & 31;
1001     rb = (iword >> 11) & 31;
1002     switch (xo) {
1003     case PPC_31_TW: mnem = power? "t" : "tw"; break;
1004     case PPC_31_TD: mnem = "td"; break;
1005     }
1006     debug("%s\t%i,r%i,r%i", mnem, to, ra, rb);
1007     break;
1008     case PPC_31_LWARX:
1009     case PPC_31_LDARX:
1010     case PPC_31_LBZX:
1011     case PPC_31_LBZUX:
1012 dpavlin 20 case PPC_31_LHAX:
1013     case PPC_31_LHAUX:
1014 dpavlin 14 case PPC_31_LHZX:
1015     case PPC_31_LHZUX:
1016     case PPC_31_LWZX:
1017     case PPC_31_LWZUX:
1018 dpavlin 20 case PPC_31_LHBRX:
1019     case PPC_31_LWBRX:
1020     case PPC_31_LFDX:
1021     case PPC_31_LFSX:
1022 dpavlin 14 case PPC_31_STWCX_DOT:
1023     case PPC_31_STDCX_DOT:
1024     case PPC_31_STBX:
1025     case PPC_31_STBUX:
1026     case PPC_31_STHX:
1027     case PPC_31_STHUX:
1028     case PPC_31_STWX:
1029     case PPC_31_STWUX:
1030     case PPC_31_STDX:
1031     case PPC_31_STDUX:
1032 dpavlin 20 case PPC_31_STHBRX:
1033     case PPC_31_STWBRX:
1034     case PPC_31_STFDX:
1035     case PPC_31_STFSX:
1036 dpavlin 14 /* rs for stores, rt for loads, actually */
1037 dpavlin 20 load = 0; wlen = 0; fpreg = 0;
1038 dpavlin 14 rs = (iword >> 21) & 31;
1039     ra = (iword >> 16) & 31;
1040     rb = (iword >> 11) & 31;
1041     switch (xo) {
1042     case PPC_31_LWARX: wlen=4;load=1; mnem = "lwarx"; break;
1043     case PPC_31_LDARX: wlen=8;load=1; mnem = "ldarx"; break;
1044     case PPC_31_LBZX: wlen=1;load=1; mnem = "lbzx"; break;
1045     case PPC_31_LBZUX: wlen=1;load=1; mnem = "lbzux"; break;
1046 dpavlin 20 case PPC_31_LHAX: wlen=2;load=1; mnem = "lhax"; break;
1047     case PPC_31_LHAUX: wlen=2;load=1; mnem = "lhaux"; break;
1048 dpavlin 14 case PPC_31_LHZX: wlen=2;load=1; mnem = "lhzx"; break;
1049     case PPC_31_LHZUX: wlen=2;load=1; mnem = "lhzux"; break;
1050     case PPC_31_LWZX: wlen = 4; load = 1;
1051     mnem = power? "lx" : "lwzx";
1052     break;
1053     case PPC_31_LWZUX: wlen = 4; load = 1;
1054     mnem = power? "lux":"lwzux";
1055     break;
1056 dpavlin 20 case PPC_31_LFDX: fpreg = 1; wlen = 8; load = 1;
1057     mnem = "lfdx"; break;
1058     case PPC_31_LFSX: fpreg = 1; wlen = 4; load = 1;
1059     mnem = "lfsx"; break;
1060 dpavlin 14 case PPC_31_STWCX_DOT: wlen=4; mnem = "stwcx."; break;
1061     case PPC_31_STDCX_DOT: wlen=8; mnem = "stdcx."; break;
1062     case PPC_31_STBX: wlen=1; mnem = "stbx"; break;
1063     case PPC_31_STBUX: wlen=1; mnem = "stbux"; break;
1064     case PPC_31_STHX: wlen=2; mnem = "sthx"; break;
1065     case PPC_31_STHUX: wlen=2; mnem = "sthux"; break;
1066     case PPC_31_STWX:
1067     wlen = 4; mnem = power? "stx" : "stwx";
1068     break;
1069     case PPC_31_STWUX:
1070     wlen = 4; mnem = power? "stux" : "stwux";
1071     break;
1072     case PPC_31_STDX: wlen = 8; mnem = "stdx"; break;
1073     case PPC_31_STDUX: wlen = 8; mnem = "stdux"; break;
1074 dpavlin 20 case PPC_31_LHBRX: wlen = 2; mnem = "lhbrx"; break;
1075     case PPC_31_LWBRX: wlen = 4; mnem = power?
1076     "lbrx" : "lwbrx"; break;
1077     case PPC_31_STHBRX: wlen = 2; mnem = "sthbrx"; break;
1078     case PPC_31_STWBRX: wlen = 4; mnem = power?
1079     "stbrx" : "stwbrx"; break;
1080     case PPC_31_STFDX: fpreg = 1; wlen = 8;
1081     mnem = "stfdx"; break;
1082     case PPC_31_STFSX: fpreg = 1; wlen = 4;
1083     mnem = "stfsx"; break;
1084 dpavlin 14 }
1085 dpavlin 20 debug("%s\t%s%i,r%i,r%i", mnem,
1086     fpreg? "f" : "r", rs, ra, rb);
1087 dpavlin 14 if (!running)
1088     break;
1089     addr = (ra==0? 0 : cpu->cd.ppc.gpr[ra]) +
1090     cpu->cd.ppc.gpr[rb];
1091 dpavlin 20 if (cpu->cd.ppc.bits == 32)
1092     addr &= 0xffffffff;
1093 dpavlin 14 symbol = get_symbol_name(&cpu->machine->symbol_context,
1094     addr, &offset);
1095     if (symbol != NULL)
1096     debug(" \t<%s", symbol);
1097     else
1098     debug(" \t<0x%llx", (long long)addr);
1099 dpavlin 20 if (wlen > 0 && !fpreg /* && !reverse */) {
1100 dpavlin 14 /* TODO */
1101     }
1102     debug(">");
1103     break;
1104     case PPC_31_NEG:
1105     case PPC_31_NEGO:
1106     rt = (iword >> 21) & 31;
1107     ra = (iword >> 16) & 31;
1108     oe_bit = (iword >> 10) & 1;
1109     rc = iword & 1;
1110     switch (xo) {
1111     case PPC_31_NEG: mnem = "neg"; break;
1112     case PPC_31_NEGO: mnem = "nego"; break;
1113     }
1114     debug("%s%s\tr%i,r%i", mnem, rc? "." : "", rt, ra);
1115     break;
1116 dpavlin 22 case PPC_31_WRTEEI:
1117     debug("wrteei\t%i", iword & 0x8000? 1 : 0);
1118     break;
1119 dpavlin 14 case PPC_31_ADDZE:
1120     case PPC_31_ADDZEO:
1121     rt = (iword >> 21) & 31;
1122     ra = (iword >> 16) & 31;
1123     oe_bit = (iword >> 10) & 1;
1124     rc = iword & 1;
1125     switch (xo) {
1126     case PPC_31_ADDZE:
1127     mnem = power? "aze" : "addze";
1128     break;
1129     case PPC_31_ADDZEO:
1130     mnem = power? "azeo" : "addzeo";
1131     break;
1132     }
1133     debug("%s%s\tr%i,r%i", mnem, rc? "." : "", rt, ra);
1134     break;
1135     case PPC_31_MTSR:
1136 dpavlin 20 case PPC_31_MFSR:
1137     /* Move to/from segment register */
1138 dpavlin 14 rt = (iword >> 21) & 31;
1139     ra = (iword >> 16) & 15; /* actually: sr */
1140 dpavlin 20 switch (xo) {
1141     case PPC_31_MTSR: mnem = "mtsr"; break;
1142     case PPC_31_MFSR: mnem = "mfsr"; break;
1143     }
1144     debug("%s\tr%i,%i", mnem, rt, ra);
1145 dpavlin 14 break;
1146     case PPC_31_MTSRIN:
1147     case PPC_31_MFSRIN:
1148     /* Move to/from segment register indirect */
1149     rt = (iword >> 21) & 31;
1150     rb = (iword >> 11) & 31;
1151     switch (xo) {
1152     case PPC_31_MTSRIN: mnem = "mtsrin"; break;
1153     case PPC_31_MFSRIN: mnem = "mfsrin"; break;
1154     }
1155     debug("%s\tr%i,r%i", mnem, rt, rb);
1156     break;
1157     case PPC_31_ADDC:
1158     case PPC_31_ADDCO:
1159     case PPC_31_ADDE:
1160     case PPC_31_ADDEO:
1161     case PPC_31_ADDME:
1162     case PPC_31_ADDMEO:
1163     case PPC_31_ADD:
1164     case PPC_31_ADDO:
1165     case PPC_31_MULHW:
1166     case PPC_31_MULHWU:
1167     case PPC_31_MULLW:
1168     case PPC_31_MULLWO:
1169     case PPC_31_SUBF:
1170     case PPC_31_SUBFO:
1171     case PPC_31_SUBFC:
1172     case PPC_31_SUBFCO:
1173     case PPC_31_SUBFE:
1174     case PPC_31_SUBFEO:
1175 dpavlin 20 case PPC_31_SUBFME:
1176     case PPC_31_SUBFMEO:
1177 dpavlin 14 case PPC_31_SUBFZE:
1178     case PPC_31_SUBFZEO:
1179     rt = (iword >> 21) & 31;
1180     ra = (iword >> 16) & 31;
1181     rb = (iword >> 11) & 31;
1182     oe_bit = (iword >> 10) & 1;
1183     rc = iword & 1;
1184     switch (xo) {
1185     case PPC_31_ADDC:
1186     mnem = power? "a" : "addc";
1187     break;
1188     case PPC_31_ADDCO:
1189     mnem = power? "ao" : "addco";
1190     break;
1191     case PPC_31_ADDE:
1192     mnem = power? "ae" : "adde";
1193     break;
1194     case PPC_31_ADDEO:
1195     mnem = power? "aeo" : "addeo";
1196     break;
1197     case PPC_31_ADDME:
1198     mnem = power? "ame" : "addme";
1199     no_rb = 1;
1200     break;
1201     case PPC_31_ADDMEO:
1202     mnem = power? "ameo" : "addmeo";
1203     no_rb = 1;
1204     break;
1205     case PPC_31_ADD:
1206     mnem = power? "cax" : "add";
1207     break;
1208     case PPC_31_ADDO:
1209     mnem = power? "caxo" : "addo";
1210     break;
1211     case PPC_31_MULHW: mnem = "mulhw"; break;
1212     case PPC_31_MULHWU: mnem = "mulhwu"; break;
1213     case PPC_31_MULLW:
1214     mnem = power? "muls" : "mullw";
1215     break;
1216     case PPC_31_MULLWO:
1217     mnem = power? "mulso" : "mullwo";
1218     break;
1219     case PPC_31_SUBF: mnem = "subf"; break;
1220     case PPC_31_SUBFO: mnem = "subfo"; break;
1221     case PPC_31_SUBFC:
1222 dpavlin 20 mnem = power? "sf" : "subfc"; break;
1223 dpavlin 14 case PPC_31_SUBFCO:
1224 dpavlin 20 mnem = power? "sfo" : "subfco"; break;
1225 dpavlin 14 case PPC_31_SUBFE:
1226 dpavlin 20 mnem = power? "sfe" : "subfe"; break;
1227 dpavlin 14 case PPC_31_SUBFEO:
1228 dpavlin 20 mnem = power? "sfeo" : "subfeo"; break;
1229     case PPC_31_SUBFME:
1230     mnem = power? "sfme" : "subfme"; break;
1231     case PPC_31_SUBFMEO:
1232     mnem = power? "sfmeo" : "subfmeo"; break;
1233 dpavlin 14 case PPC_31_SUBFZE:
1234     mnem = power? "sfze" : "subfze";
1235     no_rb = 1;
1236     break;
1237     case PPC_31_SUBFZEO:
1238     mnem = power? "sfzeo" : "subfzeo";
1239     no_rb = 1;
1240     break;
1241     }
1242     debug("%s%s\tr%i,r%i", mnem, rc? "." : "", rt, ra);
1243     if (!no_rb)
1244     debug(",r%i", rb);
1245     break;
1246     case PPC_31_MFSPR:
1247     rt = (iword >> 21) & 31;
1248     spr = ((iword >> 6) & 0x3e0) + ((iword >> 16) & 31);
1249     switch (spr) {
1250 dpavlin 20 /* Some very common ones: */
1251 dpavlin 14 case 8: debug("mflr\tr%i", rt); break;
1252     case 9: debug("mfctr\tr%i", rt); break;
1253     default:debug("mfspr\tr%i,spr%i", rt, spr);
1254     }
1255 dpavlin 20 if (spr == 8 || spr == 9)
1256     debug("\t");
1257     debug("\t<%s%s", running? "read from " : "",
1258     ppc_spr_names[spr]==NULL? "?" : ppc_spr_names[spr]);
1259     if (running) {
1260     if (cpu->cd.ppc.bits == 32)
1261     debug(": 0x%x", (int)
1262     cpu->cd.ppc.spr[spr]);
1263     else
1264     debug(": 0x%llx", (long long)
1265     cpu->cd.ppc.spr[spr]);
1266     }
1267     debug(">");
1268 dpavlin 14 break;
1269 dpavlin 20 case PPC_31_TLBIA:
1270     debug("tlbia");
1271     break;
1272     case PPC_31_SLBIA:
1273     debug("slbia");
1274     break;
1275     case PPC_31_TLBLD:
1276     case PPC_31_TLBLI:
1277     rb = (iword >> 11) & 31;
1278     debug("tlbl%s\tr%i", xo == PPC_31_TLBLD? "d" : "i", rb);
1279     break;
1280 dpavlin 14 case PPC_31_TLBIE:
1281     /* TODO: what is ra? The IBM online docs didn't say */
1282     ra = 0;
1283     rb = (iword >> 11) & 31;
1284     if (power)
1285     debug("tlbi\tr%i,r%i", ra, rb);
1286     else
1287     debug("tlbie\tr%i", rb);
1288     break;
1289 dpavlin 22 case PPC_31_TLBSX_DOT:
1290     rs = (iword >> 21) & 31;
1291     ra = (iword >> 16) & 31;
1292     rb = (iword >> 11) & 31;
1293     debug("tlbsx.\tr%i,r%i,r%i", rs, ra, rb);
1294     break;
1295 dpavlin 14 case PPC_31_TLBSYNC:
1296     debug("tlbsync");
1297     break;
1298     case PPC_31_MFTB:
1299     rt = (iword >> 21) & 31;
1300     spr = ((iword >> 6) & 0x3e0) + ((iword >> 16) & 31);
1301     debug("mftb%s\tr%i", spr==268? "" :
1302     (spr==269? "u" : "?"), rt);
1303     break;
1304     case PPC_31_CNTLZW:
1305     rs = (iword >> 21) & 31;
1306     ra = (iword >> 16) & 31;
1307     rc = iword & 1;
1308     mnem = power? "cntlz" : "cntlzw";
1309     debug("%s%s\tr%i,r%i", mnem, rc? "." : "", ra, rs);
1310     break;
1311     case PPC_31_CLF: /* POWER only */
1312     case PPC_31_CLI: /* POWER only */
1313     case PPC_31_DCLST: /* POWER only */
1314     case PPC_31_DCBF: /* PowerPC only */
1315     case PPC_31_DCBI: /* PowerPC only */
1316     case PPC_31_DCBST: /* PowerPC only */
1317     case PPC_31_DCBTST: /* PowerPC only */
1318     case PPC_31_DCBT: /* PowerPC only */
1319     case PPC_31_ICBI: /* PowerPC only */
1320     case PPC_31_DCBZ: /* POWER/PowerPC */
1321     ra = (iword >> 16) & 31;
1322     rb = (iword >> 11) & 31;
1323     switch (xo) {
1324     case PPC_31_CLF: mnem = "clf"; break;
1325     case PPC_31_CLI: mnem = "cli"; break;
1326     case PPC_31_DCLST: mnem = "dclst"; break;
1327     case PPC_31_DCBF: mnem = "dcbf"; break;
1328     case PPC_31_DCBI: mnem = "dcbi"; break;
1329     case PPC_31_DCBST: mnem = "dcbst"; break;
1330     case PPC_31_DCBTST:mnem = "dcbtst"; break;
1331     case PPC_31_DCBT: mnem = "dcbt"; break;
1332     case PPC_31_ICBI: mnem = "icbi"; break;
1333     case PPC_31_DCBZ: mnem = power ?
1334     "dclz" : "dcbz"; break;
1335     }
1336     debug("%s\tr%i,r%i", mnem, ra, rb);
1337     break;
1338     case PPC_31_SLW:
1339     case PPC_31_SRAW:
1340     case PPC_31_SRW:
1341     case PPC_31_AND:
1342     case PPC_31_ANDC:
1343     case PPC_31_NOR:
1344     case PPC_31_OR:
1345     case PPC_31_ORC:
1346     case PPC_31_XOR:
1347     case PPC_31_NAND:
1348     rs = (iword >> 21) & 31;
1349     ra = (iword >> 16) & 31;
1350     rb = (iword >> 11) & 31;
1351     rc = iword & 1;
1352     if (rs == rb && xo == PPC_31_OR)
1353     debug("mr%s\tr%i,r%i", rc? "." : "", ra, rs);
1354     else {
1355     switch (xo) {
1356     case PPC_31_SLW: mnem =
1357     power? "sl" : "slw"; break;
1358     case PPC_31_SRAW: mnem =
1359     power? "sra" : "sraw"; break;
1360     case PPC_31_SRW: mnem =
1361     power? "sr" : "srw"; break;
1362     case PPC_31_AND: mnem = "and"; break;
1363     case PPC_31_NAND: mnem = "nand"; break;
1364     case PPC_31_ANDC: mnem = "andc"; break;
1365     case PPC_31_NOR: mnem = "nor"; break;
1366     case PPC_31_OR: mnem = "or"; break;
1367     case PPC_31_ORC: mnem = "orc"; break;
1368     case PPC_31_XOR: mnem = "xor"; break;
1369     }
1370     debug("%s%s\tr%i,r%i,r%i", mnem,
1371     rc? "." : "", ra, rs, rb);
1372     }
1373     break;
1374     case PPC_31_DCCCI:
1375     ra = (iword >> 16) & 31;
1376     rb = (iword >> 11) & 31;
1377     debug("dccci\tr%i,r%i", ra, rb);
1378     break;
1379     case PPC_31_ICCCI:
1380     ra = (iword >> 16) & 31;
1381     rb = (iword >> 11) & 31;
1382     debug("iccci\tr%i,r%i", ra, rb);
1383     break;
1384     case PPC_31_DIVW:
1385     case PPC_31_DIVWO:
1386     case PPC_31_DIVWU:
1387     case PPC_31_DIVWUO:
1388     rt = (iword >> 21) & 31;
1389     ra = (iword >> 16) & 31;
1390     rb = (iword >> 11) & 31;
1391     oe_bit = (iword >> 10) & 1;
1392     rc = iword & 1;
1393     switch (xo) {
1394     case PPC_31_DIVWU: mnem = "divwu"; break;
1395     case PPC_31_DIVWUO: mnem = "divwuo"; break;
1396     case PPC_31_DIVW: mnem = "divw"; break;
1397     case PPC_31_DIVWO: mnem = "divwo"; break;
1398     }
1399     debug("%s%s\tr%i,r%i,r%i", mnem, rc? "." : "",
1400     rt, ra, rb);
1401     break;
1402     case PPC_31_MTSPR:
1403     rs = (iword >> 21) & 31;
1404     spr = ((iword >> 6) & 0x3e0) + ((iword >> 16) & 31);
1405     switch (spr) {
1406 dpavlin 20 /* Some very common ones: */
1407 dpavlin 14 case 8: debug("mtlr\tr%i", rs); break;
1408     case 9: debug("mtctr\tr%i", rs); break;
1409     default:debug("mtspr\tspr%i,r%i", spr, rs);
1410     }
1411 dpavlin 20 if (spr == 8 || spr == 9)
1412     debug("\t");
1413     debug("\t<%s%s", running? "write to " : "",
1414     ppc_spr_names[spr]==NULL? "?" : ppc_spr_names[spr]);
1415     if (running) {
1416     if (cpu->cd.ppc.bits == 32)
1417     debug(": 0x%x", (int)
1418     cpu->cd.ppc.gpr[rs]);
1419     else
1420     debug(": 0x%llx", (long long)
1421     cpu->cd.ppc.gpr[rs]);
1422     }
1423     debug(">");
1424 dpavlin 14 break;
1425     case PPC_31_SYNC:
1426     debug("%s", power? "dcs" : "sync");
1427     break;
1428     case PPC_31_LSWI:
1429     case PPC_31_STSWI:
1430     rs = (iword >> 21) & 31; /* lwsi uses rt */
1431     ra = (iword >> 16) & 31;
1432     nb = (iword >> 11) & 31;
1433     switch (xo) {
1434     case PPC_31_LSWI:
1435     mnem = power? "lsi" : "lswi"; break;
1436     case PPC_31_STSWI:
1437     mnem = power? "stsi" : "stswi"; break;
1438     }
1439     debug("%s\tr%i,r%i,%i", mnem, rs, ra, nb);
1440     break;
1441     case PPC_31_SRAWI:
1442     rs = (iword >> 21) & 31;
1443     ra = (iword >> 16) & 31;
1444     sh = (iword >> 11) & 31;
1445     rc = iword & 1;
1446     mnem = power? "srai" : "srawi";
1447     debug("%s%s\tr%i,r%i,%i", mnem,
1448     rc? "." : "", ra, rs, sh);
1449     break;
1450     case PPC_31_EIEIO:
1451     debug("%s", power? "eieio?" : "eieio");
1452     break;
1453     case PPC_31_EXTSB:
1454     case PPC_31_EXTSH:
1455     case PPC_31_EXTSW:
1456     rs = (iword >> 21) & 31;
1457     ra = (iword >> 16) & 31;
1458     rc = iword & 1;
1459     switch (xo) {
1460     case PPC_31_EXTSB:
1461     mnem = power? "exts" : "extsb";
1462     break;
1463     case PPC_31_EXTSH:
1464     mnem = "extsh";
1465     break;
1466     case PPC_31_EXTSW:
1467     mnem = "extsw";
1468     break;
1469     }
1470     debug("%s%s\tr%i,r%i", mnem, rc? "." : "", ra, rs);
1471     break;
1472 dpavlin 22 case 359:
1473     debug("TODO: ALTIVEC 359");
1474     break;
1475     case PPC_31_LVX:
1476     debug("lvx\tTODO: ALTIVEC");
1477     break;
1478     case PPC_31_STVX:
1479     debug("stvx\tTODO: ALTIVEC");
1480     break;
1481     case PPC_31_STVXL:
1482     debug("stvxl\tTODO: ALTIVEC");
1483     break;
1484 dpavlin 14 default:
1485     debug("unimplemented hi6_31, xo = 0x%x", xo);
1486     }
1487     break;
1488 dpavlin 20 case PPC_HI6_LD:
1489 dpavlin 14 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 dpavlin 20 case PPC_HI6_LFD:
1498     case PPC_HI6_LFS:
1499 dpavlin 14 case PPC_HI6_LMW:
1500 dpavlin 20 case PPC_HI6_STD:
1501 dpavlin 14 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 dpavlin 20 case PPC_HI6_STFS:
1510 dpavlin 14 /* 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 dpavlin 20 case PPC_HI6_LD: load=1; wlen = 8; mnem = "ld"; break;
1519 dpavlin 14 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 dpavlin 20 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 dpavlin 14 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 dpavlin 20 case PPC_HI6_STFD: fpreg=1; wlen=8; mnem = "stfd"; break;
1547     case PPC_HI6_STFS: fpreg=1; wlen=4; mnem = "stfs"; break;
1548 dpavlin 14 }
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 dpavlin 20 if (cpu->cd.ppc.bits == 32)
1559     addr &= 0xffffffff;
1560 dpavlin 14 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 dpavlin 20 ((uint64_t)0xff << (i*8)));
1605 dpavlin 14 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 dpavlin 20 debug("0x%llx", (long long)tdata);
1613 dpavlin 14 } 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 dpavlin 20 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 dpavlin 14 case PPC_HI6_63:
1660     xo = (iword >> 1) & 1023;
1661 dpavlin 20 /* 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 dpavlin 14 rt = (iword >> 21) & 31;
1671     ra = (iword >> 16) & 31;
1672     rb = (iword >> 11) & 31;
1673 dpavlin 20 rs = (iword >> 6) & 31; /* actually frc */
1674 dpavlin 14 rc = iword & 1;
1675 dpavlin 20 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 dpavlin 14 switch (xo) {
1705 dpavlin 20 case PPC_63_FCMPU:
1706     case PPC_63_FRSP:
1707     case PPC_63_FCTIWZ:
1708     case PPC_63_FNEG:
1709 dpavlin 14 case PPC_63_FMR:
1710 dpavlin 20 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 dpavlin 14 break;
1738 dpavlin 20 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 dpavlin 14 }
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 dpavlin 20 * 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 dpavlin 14 * 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 dpavlin 20 c |= ((cpu->cd.ppc.spr[SPR_XER] >> 31) & 1);
1844 dpavlin 14
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    

  ViewVC Help
Powered by ViewVC 1.1.26