/[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 34 - (hide annotations)
Mon Oct 8 16:21:17 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 51809 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1480 2007/02/19 01:34:42 debug Exp $
20061029	Changing usleep(1) calls in the debugger to usleep(10000)
20061107	Adding a new disk image option (-d o...) which sets the ISO9660
		filesystem base offset; also making some other hacks to allow
		NetBSD/dreamcast and homebrew demos/games to boot directly
		from a filesystem image.
		Moving Dreamcast-specific stuff in the documentation to its
		own page (dreamcast.html).
		Adding a border to the Dreamcast PVR framebuffer.
20061108	Adding a -T command line option (again?), for halting the
		emulator on unimplemented memory accesses.
20061109	Continuing on various SH4 and Dreamcast related things.
		The emulator should now halt on more unimplemented device
		accesses, instead of just printing a warning, forcing me to
		actually implement missing stuff :)
20061111	Continuing on SH4 and Dreamcast stuff.
		Adding a bogus Landisk (SH4) machine mode.
20061112	Implementing some parts of the Dreamcast GDROM device. With
		some ugly hacks, NetBSD can (barely) mount an ISO image.
20061113	NetBSD/dreamcast now starts booting from the Live CD image,
		but crashes randomly quite early on in the boot process.
20061122	Beginning on a skeleton interrupt.h and interrupt.c for the
		new interrupt subsystem.
20061124	Continuing on the new interrupt system; taking the first steps
		to attempt to connect CPUs (SuperH and MIPS) and devices
		(dev_cons and SH4 timer interrupts) to it. Many things will
		probably break from now on.
20061125	Converting dev_ns16550, dev_8253 to the new interrupt system.
		Attempting to begin to convert the ISA bus.
20061130	Incorporating a patch from Brian Foley for the configure
		script, which checks for X11 libs in /usr/X11R6/lib64 (which
		is used on some Linux systems).
20061227	Adding a note in the man page about booting from Dreamcast
		CDROM images (i.e. that no external kernel is needed).
20061229	Continuing on the interrupt system rewrite: beginning to
		convert more devices, adding abort() calls for legacy interrupt
		system calls so that everything now _has_ to be rewritten!
		Almost all machine modes are now completely broken.
20061230	More progress on removing old interrupt code, mostly related
		to the ISA bus + devices, the LCA bus (on AlphaBook1), and
		the Footbridge bus (for CATS). And some minor PCI stuff.
		Connecting the ARM cpu to the new interrupt system.
		The CATS, NetWinder, and QEMU_MIPS machine modes now work with
		the new interrupt system :)
20061231	Connecting PowerPC CPUs to the new interrupt system.
		Making PReP machines (IBM 6050) work again.
		Beginning to convert the GT PCI controller (for e.g. Malta
		and Cobalt emulation). Some things work, but not everything.
		Updating Copyright notices for 2007.
20070101	Converting dev_kn02 from legacy style to devinit; the 3max
		machine mode now works with the new interrupt system :-]
20070105	Beginning to convert the SGI O2 machine to the new interrupt
		system; finally converting O2 (IP32) devices to devinit, etc.
20070106	Continuing on the interrupt system redesign/rewrite; KN01
		(PMAX), KN230, and Dreamcast ASIC interrupts should work again,
		moving out stuff from machine.h and devices.h into the
		corresponding devices, beginning the rewrite of i80321
		interrupts, etc.
20070107	Beginning on the rewrite of Eagle interrupt stuff (PReP, etc).
20070117	Beginning the rewrite of Algor (V3) interrupts (finally
		changing dev_v3 into devinit style).
20070118	Removing the "bus" registry concept from machine.h, because
		it was practically meaningless.
		Continuing on the rewrite of Algor V3 ISA interrupts.
20070121	More work on Algor interrupts; they are now working again,
		well enough to run NetBSD/algor. :-)
20070122	Converting VR41xx (HPCmips) interrupts. NetBSD/hpcmips
		can be installed using the new interrupt system :-)
20070123	Making the testmips mode work with the new interrupt system.
20070127	Beginning to convert DEC5800 devices to devinit, and to the
		new interrupt system.
		Converting Playstation 2 devices to devinit, and converting
		the interrupt system. Also fixing a severe bug: the interrupt
		mask register on Playstation 2 is bitwise _toggled_ on writes.
20070128	Removing the dummy NetGear machine mode and the 8250 device
		(which was only used by the NetGear machine).
		Beginning to convert the MacPPC GC (Grand Central) interrupt
		controller to the new interrupt system.
		Converting Jazz interrupts (PICA61 etc.) to the new interrupt
		system. NetBSD/arc can be installed again :-)
		Fixing the JAZZ timer (hardcoding it at 100 Hz, works with
		NetBSD and it is better than a completely dummy timer as it
		was before).
		Converting dev_mp to the new interrupt system, although I
		haven't had time to actually test it yet.
		Completely removing src/machines/interrupts.c, cpu_interrupt
		and cpu_interrupt_ack in src/cpu.c, and
		src/include/machine_interrupts.h! Adding fatal error messages
		+ abort() in the few places that are left to fix.
		Converting dev_z8530 to the new interrupt system.
		FINALLY removing the md_int struct completely from the
		machine struct.
		SH4 fixes (adding a PADDR invalidation in the ITLB replacement
		code in memory_sh.c); the NetBSD/dreamcast LiveCD now runs
		all the way to the login prompt, and can be interacted with :-)
		Converting the CPC700 controller (PCI and interrupt controller
		for PM/PPC) to the new interrupt system.
20070129	Fixing MACE ISA interrupts (SGI IP32 emulation). Both NetBSD/
		sgimips' and OpenBSD/sgi's ramdisk kernels can now be
		interacted with again.
20070130	Moving out the MIPS multi_lw and _sw instruction combinations
		so that they are auto-generated at compile time instead.
20070131	Adding detection of amd64/x86_64 hosts in the configure script,
		for doing initial experiments (again :-) with native code
		generation.
		Adding a -k command line option to set the size of the dyntrans
		cache, and a -B command line option to disable native code
		generation, even if GXemul was compiled with support for
		native code generation for the specific host CPU architecture.
20070201	Experimenting with a skeleton for native code generation.
		Changing the default behaviour, so that native code generation
		is now disabled by default, and has to be enabled by using
		-b on the command line.
20070202	Continuing the native code generation experiments.
		Making PCI interrupts work for Footbridge again.
20070203	More native code generation experiments.
		Removing most of the native code generation experimental code,
		it does not make sense to include any quick hacks like this.
		Minor cleanup/removal of some more legacy MIPS interrupt code.
20070204	Making i80321 interrupts work again (for NetBSD/evbarm etc.),
		and fixing the timer at 100 Hz.
20070206	Experimenting with removing the wdc interrupt slowness hack.
20070207	Lowering the number of dyntrans TLB entries for MIPS from
		192 to 128, resulting in a minor speed improvement.
		Minor optimization to the code invalidation routine in
		cpu_dyntrans.c.
20070208	Increasing (experimentally) the nr of dyntrans instructions per
		loop from 60 to 120.
20070210	Commenting out (experimentally) the dyntrans_device_danger
		detection in memory_rw.c.
		Changing the testmips and baremips machines to use a revision 2
		MIPS64 CPU by default, instead of revision 1.
		Removing the dummy i960, IA64, x86, AVR32, and HP PA-RISC
		files, the PC bios emulation, and the Olivetti M700 (ARC) and
		db64360 emulation modes.
20070211	Adding an "mp" demo to the demos directory, which tests the
		SMP functionality of the testmips machine.
		Fixing PReP interrupts some more. NetBSD/prep now boots again.
20070216	Adding a "nop workaround" for booting Mach/PMAX to the
		documentation; thanks to Artur Bujdoso for the values.
		Converting more of the MacPPC interrupt stuff to the new
		system.
		Beginning to convert BeBox interrupts to the new system.
		PPC603e should NOT have the PPC_NO_DEC flag! Removing it.
		Correcting BeBox clock speed (it was set to 100 in the NetBSD
		bootinfo block, but should be 33000000/4), allowing NetBSD
		to start without using the (incorrect) PPC_NO_DEC hack.
20070217	Implementing (slow) AltiVec vector loads and stores, allowing
		NetBSD/macppc to finally boot using the GENERIC kernel :-)
		Updating the documentation with install instructions for
		NetBSD/macppc.
20070218-19	Regression testing for the release.

==============  RELEASE 0.4.4  ==============


1 dpavlin 14 /*
2 dpavlin 34 * Copyright (C) 2005-2007 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 34 * $Id: cpu_ppc.c,v 1.67 2006/12/30 13:30:54 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 dpavlin 34 #include "interrupt.h"
41 dpavlin 14 #include "machine.h"
42     #include "memory.h"
43     #include "misc.h"
44 dpavlin 22 #include "of.h"
45 dpavlin 14 #include "opcodes_ppc.h"
46 dpavlin 20 #include "ppc_bat.h"
47     #include "ppc_pte.h"
48     #include "ppc_spr.h"
49     #include "ppc_spr_strings.h"
50 dpavlin 32 #include "settings.h"
51 dpavlin 14 #include "symbol.h"
52    
53     #define DYNTRANS_DUALMODE_32
54     #include "tmp_ppc_head.c"
55    
56    
57 dpavlin 20 void ppc_pc_to_pointers(struct cpu *);
58     void ppc32_pc_to_pointers(struct cpu *);
59    
60 dpavlin 34 void ppc_irq_interrupt_assert(struct interrupt *interrupt);
61     void ppc_irq_interrupt_deassert(struct interrupt *interrupt);
62 dpavlin 20
63 dpavlin 34
64 dpavlin 14 /*
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 dpavlin 32 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 dpavlin 14
99     /* Current operating mode: */
100     cpu->cd.ppc.bits = cpu->cd.ppc.cpu_type.bits;
101 dpavlin 20 cpu->cd.ppc.spr[SPR_PVR] = cpu->cd.ppc.cpu_type.pvr;
102 dpavlin 14
103 dpavlin 24 /* cpu->cd.ppc.msr = PPC_MSR_IR | PPC_MSR_DR |
104     PPC_MSR_SF | PPC_MSR_FP; */
105    
106 dpavlin 22 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 dpavlin 14 cpu->is_32bit = (cpu->cd.ppc.bits == 32)? 1 : 0;
122    
123     if (cpu->is_32bit) {
124 dpavlin 28 cpu->run_instr = ppc32_run_instr;
125 dpavlin 14 cpu->update_translation_table = ppc32_update_translation_table;
126 dpavlin 18 cpu->invalidate_translation_caches =
127     ppc32_invalidate_translation_caches;
128 dpavlin 14 cpu->invalidate_code_translation =
129     ppc32_invalidate_code_translation;
130     } else {
131 dpavlin 28 cpu->run_instr = ppc_run_instr;
132 dpavlin 14 cpu->update_translation_table = ppc_update_translation_table;
133 dpavlin 18 cpu->invalidate_translation_caches =
134     ppc_invalidate_translation_caches;
135 dpavlin 14 cpu->invalidate_code_translation =
136     ppc_invalidate_code_translation;
137     }
138    
139 dpavlin 26 cpu->translate_v2p = ppc_translate_v2p;
140 dpavlin 14
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 dpavlin 20 cpu->cd.ppc.spr[SPR_PIR] = cpu_id;
166 dpavlin 14
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 dpavlin 32 /* 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 dpavlin 34 /* 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 dpavlin 14 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 dpavlin 20 void reg_access_msr(struct cpu *cpu, uint64_t *valuep, int writeflag,
301     int check_for_interrupts)
302 dpavlin 14 {
303 dpavlin 20 uint64_t old = cpu->cd.ppc.msr;
304    
305 dpavlin 14 if (valuep == NULL) {
306     fatal("reg_access_msr(): NULL\n");
307     return;
308     }
309    
310 dpavlin 20 if (writeflag) {
311 dpavlin 14 cpu->cd.ppc.msr = *valuep;
312    
313 dpavlin 20 /* 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 dpavlin 14 /* 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 dpavlin 20
339     if (check_for_interrupts && cpu->cd.ppc.msr & PPC_MSR_EE) {
340 dpavlin 30 if (cpu->cd.ppc.dec_intr_pending &&
341     !(cpu->cd.ppc.cpu_type.flags & PPC_NO_DEC)) {
342 dpavlin 20 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 dpavlin 14 }
348    
349    
350     /*
351 dpavlin 20 * 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 dpavlin 24 fatal("[ PPC Exception 0x%x; pc=0x%"PRIx64" ]\n", exception_nr,
366 dpavlin 20 (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 dpavlin 22 cpu->pc += 0xfff00000ULL;
375 dpavlin 20
376     if (cpu->is_32bit)
377     ppc32_pc_to_pointers(cpu);
378     else
379     ppc_pc_to_pointers(cpu);
380     }
381    
382    
383     /*
384 dpavlin 14 * 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 dpavlin 24 debug("%08"PRIx32, (uint32_t)cpu->pc);
406 dpavlin 14 else
407 dpavlin 24 debug("%016"PRIx64, (uint64_t)cpu->pc);
408 dpavlin 14 debug(" <%s>\n", symbol != NULL? symbol : " no symbol ");
409    
410     debug("cpu%i: lr = 0x", x);
411     if (bits32)
412 dpavlin 24 debug("%08"PRIx32, (uint32_t)cpu->cd.ppc.spr[SPR_LR]);
413 dpavlin 14 else
414 dpavlin 24 debug("%016"PRIx64, (uint64_t)cpu->cd.ppc.spr[SPR_LR]);
415     debug(" cr = 0x%08"PRIx32, (uint32_t)cpu->cd.ppc.cr);
416 dpavlin 14
417     if (bits32)
418 dpavlin 22 debug(" ");
419     else
420     debug("\ncpu%i: ", x);
421     debug("ctr = 0x", x);
422     if (bits32)
423 dpavlin 24 debug("%08"PRIx32, (uint32_t)cpu->cd.ppc.spr[SPR_CTR]);
424 dpavlin 14 else
425 dpavlin 24 debug("%016"PRIx64, (uint64_t)cpu->cd.ppc.spr[SPR_CTR]);
426 dpavlin 14
427     debug(" xer = 0x", x);
428     if (bits32)
429 dpavlin 24 debug("%08"PRIx32, (uint32_t)cpu->cd.ppc.spr[SPR_XER]);
430 dpavlin 14 else
431 dpavlin 24 debug("%016"PRIx64, (uint64_t)cpu->cd.ppc.spr[SPR_XER]);
432 dpavlin 14
433 dpavlin 24 debug("\n");
434    
435 dpavlin 14 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 dpavlin 22 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 dpavlin 20 reg_access_msr(cpu, &tmp, 0, 0);
470 dpavlin 22 if (bits32)
471     debug("0x%08x ", (int)tmp);
472     else
473     debug("0x%016llx ", (long long)tmp);
474 dpavlin 20 debug("tb = 0x%08x%08x\n", (int)cpu->cd.ppc.spr[SPR_TBU],
475     (int)cpu->cd.ppc.spr[SPR_TBL]);
476 dpavlin 22 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 dpavlin 14 }
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 dpavlin 20 (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 dpavlin 14 }
543 dpavlin 20
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 dpavlin 32 debug(" sr%-2i = 0x%08x", i, (int)s);
549 dpavlin 20 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 dpavlin 14 }
578    
579    
580     /*
581 dpavlin 24 * 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     static void add_response_word(struct cpu *cpu, char *r, uint64_t value,
591     size_t maxlen, int len)
592     {
593     char *format = (len == 4)? "%08"PRIx64 : "%016"PRIx64;
594     if (len == 4)
595     value &= 0xffffffffULL;
596     if (cpu->byte_order == EMUL_LITTLE_ENDIAN) {
597     if (len == 4) {
598     value = ((value & 0xff) << 24) +
599     ((value & 0xff00) << 8) +
600     ((value & 0xff0000) >> 8) +
601     ((value & 0xff000000) >> 24);
602     } else {
603     value = ((value & 0xff) << 56) +
604     ((value & 0xff00) << 40) +
605     ((value & 0xff0000) << 24) +
606     ((value & 0xff000000ULL) << 8) +
607     ((value & 0xff00000000ULL) >> 8) +
608     ((value & 0xff0000000000ULL) >> 24) +
609     ((value & 0xff000000000000ULL) >> 40) +
610     ((value & 0xff00000000000000ULL) >> 56);
611     }
612     }
613     snprintf(r + strlen(r), maxlen - strlen(r), format, (uint64_t)value);
614     }
615    
616    
617     /*
618     * ppc_cpu_gdb_stub():
619     *
620     * Execute a "remote GDB" command. Returns a newly allocated response string
621     * on success, NULL on failure.
622     */
623     char *ppc_cpu_gdb_stub(struct cpu *cpu, char *cmd)
624     {
625     if (strcmp(cmd, "g") == 0) {
626     int i;
627     char *r;
628     size_t wlen = cpu->is_32bit?
629     sizeof(uint32_t) : sizeof(uint64_t);
630     size_t len = 1 + 76 * wlen;
631     r = malloc(len);
632     if (r == NULL) {
633     fprintf(stderr, "out of memory\n");
634     exit(1);
635     }
636     r[0] = '\0';
637     for (i=0; i<128; i++)
638     add_response_word(cpu, r, i, len, wlen);
639     return r;
640     }
641    
642     if (cmd[0] == 'p') {
643     int regnr = strtol(cmd + 1, NULL, 16);
644     size_t wlen = cpu->is_32bit?
645     sizeof(uint32_t) : sizeof(uint64_t);
646     size_t len = 2 * wlen + 1;
647     char *r = malloc(len);
648     r[0] = '\0';
649     if (regnr >= 0 && regnr <= 31) {
650     add_response_word(cpu, r,
651     cpu->cd.ppc.gpr[regnr], len, wlen);
652     } else if (regnr == 0x40) {
653     add_response_word(cpu, r, cpu->pc, len, wlen);
654     } else if (regnr == 0x42) {
655     add_response_word(cpu, r, cpu->cd.ppc.cr, len, wlen);
656     } else if (regnr == 0x43) {
657     add_response_word(cpu, r, cpu->cd.ppc.spr[SPR_LR],
658     len, wlen);
659     } else if (regnr == 0x44) {
660     add_response_word(cpu, r, cpu->cd.ppc.spr[SPR_CTR],
661     len, wlen);
662     } else if (regnr == 0x45) {
663     add_response_word(cpu, r, cpu->cd.ppc.spr[SPR_XER],
664     len, wlen);
665     } else {
666     /* Unimplemented: */
667     add_response_word(cpu, r, 0xcc000 + regnr, len, wlen);
668     }
669     return r;
670     }
671    
672     fatal("ppc_cpu_gdb_stub(): TODO\n");
673     return NULL;
674     }
675    
676    
677     /*
678 dpavlin 34 * ppc_irq_interrupt_assert():
679 dpavlin 14 */
680 dpavlin 34 void ppc_irq_interrupt_assert(struct interrupt *interrupt)
681 dpavlin 14 {
682 dpavlin 34 struct cpu *cpu = (struct cpu *) interrupt->extra;
683     cpu->cd.ppc.irq_asserted = 1;
684 dpavlin 14 }
685    
686    
687     /*
688 dpavlin 34 * ppc_irq_interrupt_deassert():
689 dpavlin 14 */
690 dpavlin 34 void ppc_irq_interrupt_deassert(struct interrupt *interrupt)
691 dpavlin 14 {
692 dpavlin 34 struct cpu *cpu = (struct cpu *) interrupt->extra;
693     cpu->cd.ppc.irq_asserted = 0;
694 dpavlin 14 }
695    
696    
697     /*
698     * ppc_cpu_disassemble_instr():
699     *
700     * Convert an instruction word into human readable format, for instruction
701     * tracing.
702     *
703     * If running is 1, cpu->pc should be the address of the instruction.
704     *
705     * If running is 0, things that depend on the runtime environment (eg.
706     * register contents) will not be shown, and addr will be used instead of
707     * cpu->pc for relative addresses.
708     */
709     int ppc_cpu_disassemble_instr(struct cpu *cpu, unsigned char *instr,
710 dpavlin 24 int running, uint64_t dumpaddr)
711 dpavlin 14 {
712     int hi6, xo, lev, rt, rs, ra, rb, imm, sh, me, rc, l_bit, oe_bit;
713     int spr, aa_bit, lk_bit, bf, bh, bi, bo, mb, nb, bt, ba, bb, fpreg;
714     int bfa, to, load, wlen, no_rb = 0;
715     uint64_t offset, addr;
716     uint32_t iword;
717     char *symbol, *mnem = "ERROR";
718     int power = cpu->cd.ppc.mode == MODE_POWER;
719    
720     if (running)
721     dumpaddr = cpu->pc;
722    
723     symbol = get_symbol_name(&cpu->machine->symbol_context,
724     dumpaddr, &offset);
725     if (symbol != NULL && offset==0)
726     debug("<%s>\n", symbol);
727    
728     if (cpu->machine->ncpus > 1 && running)
729     debug("cpu%i: ", cpu->cpu_id);
730    
731     if (cpu->cd.ppc.bits == 32)
732     debug("%08x", (int)dumpaddr);
733     else
734     debug("%016llx", (long long)dumpaddr);
735    
736     /* NOTE: Fixed to big-endian. */
737     iword = (instr[0] << 24) + (instr[1] << 16) + (instr[2] << 8)
738     + instr[3];
739    
740     debug(": %08x\t", iword);
741    
742     /*
743     * Decode the instruction:
744     */
745    
746     hi6 = iword >> 26;
747    
748     switch (hi6) {
749 dpavlin 22 case 0x4:
750     debug("ALTIVEC TODO");
751     /* vxor etc */
752     break;
753 dpavlin 14 case PPC_HI6_MULLI:
754     case PPC_HI6_SUBFIC:
755     rt = (iword >> 21) & 31;
756     ra = (iword >> 16) & 31;
757     imm = (int16_t)(iword & 0xffff);
758     switch (hi6) {
759     case PPC_HI6_MULLI:
760     mnem = power? "muli":"mulli";
761     break;
762     case PPC_HI6_SUBFIC:
763     mnem = power? "sfi":"subfic";
764     break;
765     }
766     debug("%s\tr%i,r%i,%i", mnem, rt, ra, imm);
767     break;
768     case PPC_HI6_CMPLI:
769     case PPC_HI6_CMPI:
770     bf = (iword >> 23) & 7;
771     l_bit = (iword >> 21) & 1;
772     ra = (iword >> 16) & 31;
773     if (hi6 == PPC_HI6_CMPLI) {
774     imm = iword & 0xffff;
775     mnem = "cmpl";
776     } else {
777     imm = (int16_t)(iword & 0xffff);
778     mnem = "cmp";
779     }
780     debug("%s%si\t", mnem, l_bit? "d" : "w");
781     if (bf != 0)
782     debug("cr%i,", bf);
783     debug("r%i,%i", ra, imm);
784     break;
785     case PPC_HI6_ADDIC:
786     case PPC_HI6_ADDIC_DOT:
787     rt = (iword >> 21) & 31;
788     ra = (iword >> 16) & 31;
789     rc = hi6 == PPC_HI6_ADDIC_DOT;
790     imm = (int16_t)(iword & 0xffff);
791     mnem = power? "ai":"addic";
792     if (imm < 0 && !power) {
793     mnem = "subic";
794     imm = -imm;
795     }
796     debug("%s%s\tr%i,r%i,%i", mnem, rc?".":"", rt, ra, imm);
797     break;
798     case PPC_HI6_ADDI:
799     rt = (iword >> 21) & 31;
800     ra = (iword >> 16) & 31;
801     imm = (int16_t)(iword & 0xffff);
802     if (ra == 0)
803     debug("li\tr%i,%i", rt, imm);
804     else {
805     mnem = power? "cal":"addi";
806     if (imm < 0 && !power) {
807     mnem = "subi";
808     imm = -imm;
809     }
810     debug("%s\tr%i,r%i,%i", mnem, rt, ra, imm);
811     }
812     break;
813     case PPC_HI6_ADDIS:
814     rt = (iword >> 21) & 31;
815     ra = (iword >> 16) & 31;
816     imm = (int16_t)(iword & 0xffff);
817     if (ra == 0)
818     debug("lis\tr%i,%i", rt, imm);
819     else
820     debug("%s\tr%i,r%i,%i",
821     power? "cau":"addis", rt, ra, imm);
822     break;
823     case PPC_HI6_BC:
824     aa_bit = (iword & 2) >> 1;
825     lk_bit = iword & 1;
826     bo = (iword >> 21) & 31;
827     bi = (iword >> 16) & 31;
828     /* Sign-extend addr: */
829     addr = (int64_t)(int16_t)(iword & 0xfffc);
830     debug("bc");
831     if (lk_bit)
832     debug("l");
833     if (aa_bit)
834     debug("a");
835     else
836     addr += dumpaddr;
837     debug("\t%i,%i,", bo, bi);
838     if (cpu->cd.ppc.bits == 32)
839     addr &= 0xffffffff;
840     if (cpu->cd.ppc.bits == 32)
841     debug("0x%x", (int)addr);
842     else
843     debug("0x%llx", (long long)addr);
844     symbol = get_symbol_name(&cpu->machine->symbol_context,
845     addr, &offset);
846     if (symbol != NULL)
847     debug("\t<%s>", symbol);
848     break;
849     case PPC_HI6_SC:
850     lev = (iword >> 5) & 0x7f;
851     debug("sc");
852     if (lev != 0) {
853     debug("\t%i", lev);
854     if (lev > 1)
855     debug(" (WARNING! reserved value)");
856     }
857     break;
858     case PPC_HI6_B:
859     aa_bit = (iword & 2) >> 1;
860     lk_bit = iword & 1;
861     /* Sign-extend addr: */
862     addr = (int64_t)(int32_t)((iword & 0x03fffffc) << 6);
863     addr = (int64_t)addr >> 6;
864     debug("b");
865     if (lk_bit)
866     debug("l");
867     if (aa_bit)
868     debug("a");
869     else
870     addr += dumpaddr;
871     if (cpu->cd.ppc.bits == 32)
872     addr &= 0xffffffff;
873     if (cpu->cd.ppc.bits == 32)
874     debug("\t0x%x", (int)addr);
875     else
876     debug("\t0x%llx", (long long)addr);
877     symbol = get_symbol_name(&cpu->machine->symbol_context,
878     addr, &offset);
879     if (symbol != NULL)
880     debug("\t<%s>", symbol);
881     break;
882     case PPC_HI6_19:
883     xo = (iword >> 1) & 1023;
884     switch (xo) {
885     case PPC_19_MCRF:
886     bf = (iword >> 23) & 7;
887     bfa = (iword >> 18) & 7;
888     debug("mcrf\tcr%i,cr%i", bf, bfa);
889     break;
890     case PPC_19_RFI:
891     debug("rfi");
892     break;
893     case PPC_19_RFID:
894     debug("rfid");
895     break;
896     case PPC_19_RFSVC:
897     debug("rfsvc%s", power?"":"\t(INVALID for PowerPC)");
898     break;
899     case PPC_19_BCLR:
900     case PPC_19_BCCTR:
901     bo = (iword >> 21) & 31;
902     bi = (iword >> 16) & 31;
903     bh = (iword >> 11) & 3;
904     lk_bit = iword & 1;
905     switch (xo) {
906     case PPC_19_BCLR:
907     mnem = power? "bcr" : "bclr"; break;
908     case PPC_19_BCCTR:
909     mnem = power? "bcc" : "bcctr"; break;
910     }
911     debug("%s%s%s\t%i,%i,%i", mnem, lk_bit? "l" : "",
912     bh? (bh==3? "+" : (bh==2? "-" : "?")) : "",
913     bo, bi, bh);
914     break;
915     case PPC_19_ISYNC:
916     debug("%s", power? "ics" : "isync");
917     break;
918     case PPC_19_CRAND:
919     case PPC_19_CRXOR:
920     case PPC_19_CROR:
921     case PPC_19_CRNAND:
922     case PPC_19_CRNOR:
923     case PPC_19_CRANDC:
924     case PPC_19_CREQV:
925     case PPC_19_CRORC:
926     bt = (iword >> 21) & 31;
927     ba = (iword >> 16) & 31;
928     bb = (iword >> 11) & 31;
929     switch (xo) {
930     case PPC_19_CRAND: mnem = "crand"; break;
931     case PPC_19_CRXOR: mnem = "crxor"; break;
932     case PPC_19_CROR: mnem = "cror"; break;
933     case PPC_19_CRNAND: mnem = "crnand"; break;
934     case PPC_19_CRNOR: mnem = "crnor"; break;
935     case PPC_19_CRANDC: mnem = "crandc"; break;
936     case PPC_19_CREQV: mnem = "creqv"; break;
937     case PPC_19_CRORC: mnem = "crorc"; break;
938     }
939     debug("%s\t%i,%i,%i", mnem, bt, ba, bb);
940     break;
941     default:
942     debug("unimplemented hi6_19, xo = 0x%x", xo);
943     }
944     break;
945 dpavlin 20 case PPC_HI6_RLWNM:
946 dpavlin 14 case PPC_HI6_RLWIMI:
947     case PPC_HI6_RLWINM:
948     rs = (iword >> 21) & 31;
949     ra = (iword >> 16) & 31;
950 dpavlin 20 sh = (iword >> 11) & 31; /* actually rb for rlwnm */
951 dpavlin 14 mb = (iword >> 6) & 31;
952     me = (iword >> 1) & 31;
953     rc = iword & 1;
954     switch (hi6) {
955 dpavlin 20 case PPC_HI6_RLWNM:
956     mnem = power? "rlnm" : "rlwnm"; break;
957 dpavlin 14 case PPC_HI6_RLWIMI:
958     mnem = power? "rlimi" : "rlwimi"; break;
959     case PPC_HI6_RLWINM:
960     mnem = power? "rlinm" : "rlwinm"; break;
961     }
962 dpavlin 20 debug("%s%s\tr%i,r%i,%s%i,%i,%i",
963     mnem, rc?".":"", ra, rs,
964     hi6 == PPC_HI6_RLWNM? "r" : "",
965     sh, mb, me);
966 dpavlin 14 break;
967     case PPC_HI6_ORI:
968     case PPC_HI6_ORIS:
969     case PPC_HI6_XORI:
970     case PPC_HI6_XORIS:
971     case PPC_HI6_ANDI_DOT:
972     case PPC_HI6_ANDIS_DOT:
973     rs = (iword >> 21) & 31;
974     ra = (iword >> 16) & 31;
975     imm = iword & 0xffff;
976     switch (hi6) {
977     case PPC_HI6_ORI:
978     mnem = power? "oril":"ori";
979     break;
980     case PPC_HI6_ORIS:
981     mnem = power? "oriu":"oris";
982     break;
983     case PPC_HI6_XORI:
984     mnem = power? "xoril":"xori";
985     break;
986     case PPC_HI6_XORIS:
987     mnem = power? "xoriu":"xoris";
988     break;
989     case PPC_HI6_ANDI_DOT:
990     mnem = power? "andil.":"andi.";
991     break;
992     case PPC_HI6_ANDIS_DOT:
993     mnem = power? "andiu.":"andis.";
994     break;
995     }
996     if (hi6 == PPC_HI6_ORI && rs == 0 && ra == 0 && imm == 0)
997     debug("nop");
998     else
999     debug("%s\tr%i,r%i,0x%04x", mnem, ra, rs, imm);
1000     break;
1001     case PPC_HI6_30:
1002     xo = (iword >> 2) & 7;
1003     switch (xo) {
1004 dpavlin 24 case PPC_30_RLDICL:
1005 dpavlin 14 case PPC_30_RLDICR:
1006 dpavlin 24 case PPC_30_RLDIMI: /* mb, not me */
1007     mnem = NULL;
1008     switch (xo) {
1009     case PPC_30_RLDICL: mnem = "rldicl"; break;
1010     case PPC_30_RLDICR: mnem = "rldicr"; break;
1011     case PPC_30_RLDIMI: mnem = "rldimi"; break;
1012     }
1013 dpavlin 14 rs = (iword >> 21) & 31;
1014     ra = (iword >> 16) & 31;
1015     sh = ((iword >> 11) & 31) | ((iword & 2) << 4);
1016     me = ((iword >> 6) & 31) | (iword & 0x20);
1017     rc = iword & 1;
1018 dpavlin 24 debug("%s%s\tr%i,r%i,%i,%i",
1019     mnem, rc?".":"", ra, rs, sh, me);
1020 dpavlin 14 break;
1021     default:
1022     debug("unimplemented hi6_30, xo = 0x%x", xo);
1023     }
1024     break;
1025     case PPC_HI6_31:
1026     xo = (iword >> 1) & 1023;
1027     switch (xo) {
1028    
1029     case PPC_31_CMP:
1030     case PPC_31_CMPL:
1031     bf = (iword >> 23) & 7;
1032     l_bit = (iword >> 21) & 1;
1033     ra = (iword >> 16) & 31;
1034     rb = (iword >> 11) & 31;
1035     if (xo == PPC_31_CMPL)
1036     mnem = "cmpl";
1037     else
1038     mnem = "cmp";
1039     debug("%s%s\t", mnem, l_bit? "d" : "w");
1040     if (bf != 0)
1041     debug("cr%i,", bf);
1042     debug("r%i,r%i", ra, rb);
1043     break;
1044     case PPC_31_MFCR:
1045     rt = (iword >> 21) & 31;
1046     debug("mfcr\tr%i", rt);
1047     break;
1048     case PPC_31_MFMSR:
1049     rt = (iword >> 21) & 31;
1050     debug("mfmsr\tr%i", rt);
1051     break;
1052     case PPC_31_MTCRF:
1053     rs = (iword >> 21) & 31;
1054     mb = (iword >> 12) & 255; /* actually fxm, not mb */
1055     debug("mtcrf\t%i,r%i", mb, rs);
1056     break;
1057     case PPC_31_MTMSR:
1058     rs = (iword >> 21) & 31;
1059     l_bit = (iword >> 16) & 1;
1060     debug("mtmsr\tr%i", rs);
1061     if (l_bit)
1062     debug(",%i", l_bit);
1063     break;
1064     case PPC_31_TW:
1065     case PPC_31_TD:
1066     to = (iword >> 21) & 31;
1067     ra = (iword >> 16) & 31;
1068     rb = (iword >> 11) & 31;
1069     switch (xo) {
1070     case PPC_31_TW: mnem = power? "t" : "tw"; break;
1071     case PPC_31_TD: mnem = "td"; break;
1072     }
1073     debug("%s\t%i,r%i,r%i", mnem, to, ra, rb);
1074     break;
1075     case PPC_31_LWARX:
1076     case PPC_31_LDARX:
1077     case PPC_31_LBZX:
1078     case PPC_31_LBZUX:
1079 dpavlin 20 case PPC_31_LHAX:
1080     case PPC_31_LHAUX:
1081 dpavlin 14 case PPC_31_LHZX:
1082     case PPC_31_LHZUX:
1083     case PPC_31_LWZX:
1084     case PPC_31_LWZUX:
1085 dpavlin 20 case PPC_31_LHBRX:
1086     case PPC_31_LWBRX:
1087     case PPC_31_LFDX:
1088     case PPC_31_LFSX:
1089 dpavlin 14 case PPC_31_STWCX_DOT:
1090     case PPC_31_STDCX_DOT:
1091     case PPC_31_STBX:
1092     case PPC_31_STBUX:
1093     case PPC_31_STHX:
1094     case PPC_31_STHUX:
1095     case PPC_31_STWX:
1096     case PPC_31_STWUX:
1097     case PPC_31_STDX:
1098     case PPC_31_STDUX:
1099 dpavlin 20 case PPC_31_STHBRX:
1100     case PPC_31_STWBRX:
1101     case PPC_31_STFDX:
1102     case PPC_31_STFSX:
1103 dpavlin 14 /* rs for stores, rt for loads, actually */
1104 dpavlin 20 load = 0; wlen = 0; fpreg = 0;
1105 dpavlin 14 rs = (iword >> 21) & 31;
1106     ra = (iword >> 16) & 31;
1107     rb = (iword >> 11) & 31;
1108     switch (xo) {
1109     case PPC_31_LWARX: wlen=4;load=1; mnem = "lwarx"; break;
1110     case PPC_31_LDARX: wlen=8;load=1; mnem = "ldarx"; break;
1111     case PPC_31_LBZX: wlen=1;load=1; mnem = "lbzx"; break;
1112     case PPC_31_LBZUX: wlen=1;load=1; mnem = "lbzux"; break;
1113 dpavlin 20 case PPC_31_LHAX: wlen=2;load=1; mnem = "lhax"; break;
1114     case PPC_31_LHAUX: wlen=2;load=1; mnem = "lhaux"; break;
1115 dpavlin 14 case PPC_31_LHZX: wlen=2;load=1; mnem = "lhzx"; break;
1116     case PPC_31_LHZUX: wlen=2;load=1; mnem = "lhzux"; break;
1117     case PPC_31_LWZX: wlen = 4; load = 1;
1118     mnem = power? "lx" : "lwzx";
1119     break;
1120     case PPC_31_LWZUX: wlen = 4; load = 1;
1121     mnem = power? "lux":"lwzux";
1122     break;
1123 dpavlin 20 case PPC_31_LFDX: fpreg = 1; wlen = 8; load = 1;
1124     mnem = "lfdx"; break;
1125     case PPC_31_LFSX: fpreg = 1; wlen = 4; load = 1;
1126     mnem = "lfsx"; break;
1127 dpavlin 14 case PPC_31_STWCX_DOT: wlen=4; mnem = "stwcx."; break;
1128     case PPC_31_STDCX_DOT: wlen=8; mnem = "stdcx."; break;
1129     case PPC_31_STBX: wlen=1; mnem = "stbx"; break;
1130     case PPC_31_STBUX: wlen=1; mnem = "stbux"; break;
1131     case PPC_31_STHX: wlen=2; mnem = "sthx"; break;
1132     case PPC_31_STHUX: wlen=2; mnem = "sthux"; break;
1133     case PPC_31_STWX:
1134     wlen = 4; mnem = power? "stx" : "stwx";
1135     break;
1136     case PPC_31_STWUX:
1137     wlen = 4; mnem = power? "stux" : "stwux";
1138     break;
1139     case PPC_31_STDX: wlen = 8; mnem = "stdx"; break;
1140     case PPC_31_STDUX: wlen = 8; mnem = "stdux"; break;
1141 dpavlin 20 case PPC_31_LHBRX: wlen = 2; mnem = "lhbrx"; break;
1142     case PPC_31_LWBRX: wlen = 4; mnem = power?
1143     "lbrx" : "lwbrx"; break;
1144     case PPC_31_STHBRX: wlen = 2; mnem = "sthbrx"; break;
1145     case PPC_31_STWBRX: wlen = 4; mnem = power?
1146     "stbrx" : "stwbrx"; break;
1147     case PPC_31_STFDX: fpreg = 1; wlen = 8;
1148     mnem = "stfdx"; break;
1149     case PPC_31_STFSX: fpreg = 1; wlen = 4;
1150     mnem = "stfsx"; break;
1151 dpavlin 14 }
1152 dpavlin 20 debug("%s\t%s%i,r%i,r%i", mnem,
1153     fpreg? "f" : "r", rs, ra, rb);
1154 dpavlin 14 if (!running)
1155     break;
1156     addr = (ra==0? 0 : cpu->cd.ppc.gpr[ra]) +
1157     cpu->cd.ppc.gpr[rb];
1158 dpavlin 20 if (cpu->cd.ppc.bits == 32)
1159     addr &= 0xffffffff;
1160 dpavlin 14 symbol = get_symbol_name(&cpu->machine->symbol_context,
1161     addr, &offset);
1162     if (symbol != NULL)
1163     debug(" \t<%s", symbol);
1164     else
1165     debug(" \t<0x%llx", (long long)addr);
1166 dpavlin 20 if (wlen > 0 && !fpreg /* && !reverse */) {
1167 dpavlin 14 /* TODO */
1168     }
1169     debug(">");
1170     break;
1171     case PPC_31_NEG:
1172     case PPC_31_NEGO:
1173     rt = (iword >> 21) & 31;
1174     ra = (iword >> 16) & 31;
1175     oe_bit = (iword >> 10) & 1;
1176     rc = iword & 1;
1177     switch (xo) {
1178     case PPC_31_NEG: mnem = "neg"; break;
1179     case PPC_31_NEGO: mnem = "nego"; break;
1180     }
1181     debug("%s%s\tr%i,r%i", mnem, rc? "." : "", rt, ra);
1182     break;
1183 dpavlin 22 case PPC_31_WRTEEI:
1184     debug("wrteei\t%i", iword & 0x8000? 1 : 0);
1185     break;
1186 dpavlin 24 case PPC_31_MTMSRD:
1187     /* TODO: Just a guess based on MTMSR */
1188     rs = (iword >> 21) & 31;
1189     l_bit = (iword >> 16) & 1;
1190     debug("mtmsrd\tr%i", rs);
1191     if (l_bit)
1192     debug(",%i", l_bit);
1193     break;
1194 dpavlin 14 case PPC_31_ADDZE:
1195     case PPC_31_ADDZEO:
1196     rt = (iword >> 21) & 31;
1197     ra = (iword >> 16) & 31;
1198     oe_bit = (iword >> 10) & 1;
1199     rc = iword & 1;
1200     switch (xo) {
1201     case PPC_31_ADDZE:
1202     mnem = power? "aze" : "addze";
1203     break;
1204     case PPC_31_ADDZEO:
1205     mnem = power? "azeo" : "addzeo";
1206     break;
1207     }
1208     debug("%s%s\tr%i,r%i", mnem, rc? "." : "", rt, ra);
1209     break;
1210     case PPC_31_MTSR:
1211 dpavlin 20 case PPC_31_MFSR:
1212     /* Move to/from segment register */
1213 dpavlin 14 rt = (iword >> 21) & 31;
1214     ra = (iword >> 16) & 15; /* actually: sr */
1215 dpavlin 20 switch (xo) {
1216     case PPC_31_MTSR: mnem = "mtsr"; break;
1217     case PPC_31_MFSR: mnem = "mfsr"; break;
1218     }
1219     debug("%s\tr%i,%i", mnem, rt, ra);
1220 dpavlin 14 break;
1221     case PPC_31_MTSRIN:
1222     case PPC_31_MFSRIN:
1223     /* Move to/from segment register indirect */
1224     rt = (iword >> 21) & 31;
1225     rb = (iword >> 11) & 31;
1226     switch (xo) {
1227     case PPC_31_MTSRIN: mnem = "mtsrin"; break;
1228     case PPC_31_MFSRIN: mnem = "mfsrin"; break;
1229     }
1230     debug("%s\tr%i,r%i", mnem, rt, rb);
1231     break;
1232     case PPC_31_ADDC:
1233     case PPC_31_ADDCO:
1234     case PPC_31_ADDE:
1235     case PPC_31_ADDEO:
1236     case PPC_31_ADDME:
1237     case PPC_31_ADDMEO:
1238     case PPC_31_ADD:
1239     case PPC_31_ADDO:
1240     case PPC_31_MULHW:
1241     case PPC_31_MULHWU:
1242     case PPC_31_MULLW:
1243     case PPC_31_MULLWO:
1244     case PPC_31_SUBF:
1245     case PPC_31_SUBFO:
1246     case PPC_31_SUBFC:
1247     case PPC_31_SUBFCO:
1248     case PPC_31_SUBFE:
1249     case PPC_31_SUBFEO:
1250 dpavlin 20 case PPC_31_SUBFME:
1251     case PPC_31_SUBFMEO:
1252 dpavlin 14 case PPC_31_SUBFZE:
1253     case PPC_31_SUBFZEO:
1254     rt = (iword >> 21) & 31;
1255     ra = (iword >> 16) & 31;
1256     rb = (iword >> 11) & 31;
1257     oe_bit = (iword >> 10) & 1;
1258     rc = iword & 1;
1259     switch (xo) {
1260     case PPC_31_ADDC:
1261     mnem = power? "a" : "addc";
1262     break;
1263     case PPC_31_ADDCO:
1264     mnem = power? "ao" : "addco";
1265     break;
1266     case PPC_31_ADDE:
1267     mnem = power? "ae" : "adde";
1268     break;
1269     case PPC_31_ADDEO:
1270     mnem = power? "aeo" : "addeo";
1271     break;
1272     case PPC_31_ADDME:
1273     mnem = power? "ame" : "addme";
1274     no_rb = 1;
1275     break;
1276     case PPC_31_ADDMEO:
1277     mnem = power? "ameo" : "addmeo";
1278     no_rb = 1;
1279     break;
1280     case PPC_31_ADD:
1281     mnem = power? "cax" : "add";
1282     break;
1283     case PPC_31_ADDO:
1284     mnem = power? "caxo" : "addo";
1285     break;
1286     case PPC_31_MULHW: mnem = "mulhw"; break;
1287     case PPC_31_MULHWU: mnem = "mulhwu"; break;
1288     case PPC_31_MULLW:
1289     mnem = power? "muls" : "mullw";
1290     break;
1291     case PPC_31_MULLWO:
1292     mnem = power? "mulso" : "mullwo";
1293     break;
1294     case PPC_31_SUBF: mnem = "subf"; break;
1295     case PPC_31_SUBFO: mnem = "subfo"; break;
1296     case PPC_31_SUBFC:
1297 dpavlin 20 mnem = power? "sf" : "subfc"; break;
1298 dpavlin 14 case PPC_31_SUBFCO:
1299 dpavlin 20 mnem = power? "sfo" : "subfco"; break;
1300 dpavlin 14 case PPC_31_SUBFE:
1301 dpavlin 20 mnem = power? "sfe" : "subfe"; break;
1302 dpavlin 14 case PPC_31_SUBFEO:
1303 dpavlin 20 mnem = power? "sfeo" : "subfeo"; break;
1304     case PPC_31_SUBFME:
1305     mnem = power? "sfme" : "subfme"; break;
1306     case PPC_31_SUBFMEO:
1307     mnem = power? "sfmeo" : "subfmeo"; break;
1308 dpavlin 14 case PPC_31_SUBFZE:
1309     mnem = power? "sfze" : "subfze";
1310     no_rb = 1;
1311     break;
1312     case PPC_31_SUBFZEO:
1313     mnem = power? "sfzeo" : "subfzeo";
1314     no_rb = 1;
1315     break;
1316     }
1317     debug("%s%s\tr%i,r%i", mnem, rc? "." : "", rt, ra);
1318     if (!no_rb)
1319     debug(",r%i", rb);
1320     break;
1321     case PPC_31_MFSPR:
1322     rt = (iword >> 21) & 31;
1323     spr = ((iword >> 6) & 0x3e0) + ((iword >> 16) & 31);
1324     switch (spr) {
1325 dpavlin 20 /* Some very common ones: */
1326 dpavlin 14 case 8: debug("mflr\tr%i", rt); break;
1327     case 9: debug("mfctr\tr%i", rt); break;
1328     default:debug("mfspr\tr%i,spr%i", rt, spr);
1329     }
1330 dpavlin 20 if (spr == 8 || spr == 9)
1331     debug("\t");
1332     debug("\t<%s%s", running? "read from " : "",
1333     ppc_spr_names[spr]==NULL? "?" : ppc_spr_names[spr]);
1334     if (running) {
1335     if (cpu->cd.ppc.bits == 32)
1336     debug(": 0x%x", (int)
1337     cpu->cd.ppc.spr[spr]);
1338     else
1339     debug(": 0x%llx", (long long)
1340     cpu->cd.ppc.spr[spr]);
1341     }
1342     debug(">");
1343 dpavlin 14 break;
1344 dpavlin 20 case PPC_31_TLBIA:
1345     debug("tlbia");
1346     break;
1347     case PPC_31_SLBIA:
1348     debug("slbia");
1349     break;
1350     case PPC_31_TLBLD:
1351     case PPC_31_TLBLI:
1352     rb = (iword >> 11) & 31;
1353     debug("tlbl%s\tr%i", xo == PPC_31_TLBLD? "d" : "i", rb);
1354     break;
1355 dpavlin 14 case PPC_31_TLBIE:
1356     /* TODO: what is ra? The IBM online docs didn't say */
1357     ra = 0;
1358     rb = (iword >> 11) & 31;
1359     if (power)
1360     debug("tlbi\tr%i,r%i", ra, rb);
1361     else
1362     debug("tlbie\tr%i", rb);
1363     break;
1364 dpavlin 22 case PPC_31_TLBSX_DOT:
1365     rs = (iword >> 21) & 31;
1366     ra = (iword >> 16) & 31;
1367     rb = (iword >> 11) & 31;
1368     debug("tlbsx.\tr%i,r%i,r%i", rs, ra, rb);
1369     break;
1370 dpavlin 14 case PPC_31_TLBSYNC:
1371     debug("tlbsync");
1372     break;
1373     case PPC_31_MFTB:
1374     rt = (iword >> 21) & 31;
1375     spr = ((iword >> 6) & 0x3e0) + ((iword >> 16) & 31);
1376     debug("mftb%s\tr%i", spr==268? "" :
1377     (spr==269? "u" : "?"), rt);
1378     break;
1379     case PPC_31_CNTLZW:
1380     rs = (iword >> 21) & 31;
1381     ra = (iword >> 16) & 31;
1382     rc = iword & 1;
1383     mnem = power? "cntlz" : "cntlzw";
1384     debug("%s%s\tr%i,r%i", mnem, rc? "." : "", ra, rs);
1385     break;
1386     case PPC_31_CLF: /* POWER only */
1387     case PPC_31_CLI: /* POWER only */
1388     case PPC_31_DCLST: /* POWER only */
1389     case PPC_31_DCBF: /* PowerPC only */
1390     case PPC_31_DCBI: /* PowerPC only */
1391     case PPC_31_DCBST: /* PowerPC only */
1392     case PPC_31_DCBTST: /* PowerPC only */
1393     case PPC_31_DCBT: /* PowerPC only */
1394     case PPC_31_ICBI: /* PowerPC only */
1395     case PPC_31_DCBZ: /* POWER/PowerPC */
1396     ra = (iword >> 16) & 31;
1397     rb = (iword >> 11) & 31;
1398     switch (xo) {
1399     case PPC_31_CLF: mnem = "clf"; break;
1400     case PPC_31_CLI: mnem = "cli"; break;
1401     case PPC_31_DCLST: mnem = "dclst"; break;
1402     case PPC_31_DCBF: mnem = "dcbf"; break;
1403     case PPC_31_DCBI: mnem = "dcbi"; break;
1404     case PPC_31_DCBST: mnem = "dcbst"; break;
1405     case PPC_31_DCBTST:mnem = "dcbtst"; break;
1406     case PPC_31_DCBT: mnem = "dcbt"; break;
1407     case PPC_31_ICBI: mnem = "icbi"; break;
1408     case PPC_31_DCBZ: mnem = power ?
1409     "dclz" : "dcbz"; break;
1410     }
1411     debug("%s\tr%i,r%i", mnem, ra, rb);
1412     break;
1413     case PPC_31_SLW:
1414 dpavlin 24 case PPC_31_SLD:
1415 dpavlin 14 case PPC_31_SRAW:
1416     case PPC_31_SRW:
1417     case PPC_31_AND:
1418     case PPC_31_ANDC:
1419     case PPC_31_NOR:
1420 dpavlin 24 case PPC_31_EQV:
1421 dpavlin 14 case PPC_31_OR:
1422     case PPC_31_ORC:
1423     case PPC_31_XOR:
1424     case PPC_31_NAND:
1425     rs = (iword >> 21) & 31;
1426     ra = (iword >> 16) & 31;
1427     rb = (iword >> 11) & 31;
1428     rc = iword & 1;
1429     if (rs == rb && xo == PPC_31_OR)
1430     debug("mr%s\tr%i,r%i", rc? "." : "", ra, rs);
1431     else {
1432     switch (xo) {
1433     case PPC_31_SLW: mnem =
1434     power? "sl" : "slw"; break;
1435 dpavlin 24 case PPC_31_SLD: mnem = "sld"; break;
1436 dpavlin 14 case PPC_31_SRAW: mnem =
1437     power? "sra" : "sraw"; break;
1438     case PPC_31_SRW: mnem =
1439     power? "sr" : "srw"; break;
1440     case PPC_31_AND: mnem = "and"; break;
1441     case PPC_31_NAND: mnem = "nand"; break;
1442     case PPC_31_ANDC: mnem = "andc"; break;
1443     case PPC_31_NOR: mnem = "nor"; break;
1444 dpavlin 24 case PPC_31_EQV: mnem = "eqv"; break;
1445 dpavlin 14 case PPC_31_OR: mnem = "or"; break;
1446     case PPC_31_ORC: mnem = "orc"; break;
1447     case PPC_31_XOR: mnem = "xor"; break;
1448     }
1449     debug("%s%s\tr%i,r%i,r%i", mnem,
1450     rc? "." : "", ra, rs, rb);
1451     }
1452     break;
1453     case PPC_31_DCCCI:
1454     ra = (iword >> 16) & 31;
1455     rb = (iword >> 11) & 31;
1456     debug("dccci\tr%i,r%i", ra, rb);
1457     break;
1458     case PPC_31_ICCCI:
1459     ra = (iword >> 16) & 31;
1460     rb = (iword >> 11) & 31;
1461     debug("iccci\tr%i,r%i", ra, rb);
1462     break;
1463     case PPC_31_DIVW:
1464     case PPC_31_DIVWO:
1465     case PPC_31_DIVWU:
1466     case PPC_31_DIVWUO:
1467     rt = (iword >> 21) & 31;
1468     ra = (iword >> 16) & 31;
1469     rb = (iword >> 11) & 31;
1470     oe_bit = (iword >> 10) & 1;
1471     rc = iword & 1;
1472     switch (xo) {
1473     case PPC_31_DIVWU: mnem = "divwu"; break;
1474     case PPC_31_DIVWUO: mnem = "divwuo"; break;
1475     case PPC_31_DIVW: mnem = "divw"; break;
1476     case PPC_31_DIVWO: mnem = "divwo"; break;
1477     }
1478     debug("%s%s\tr%i,r%i,r%i", mnem, rc? "." : "",
1479     rt, ra, rb);
1480     break;
1481     case PPC_31_MTSPR:
1482     rs = (iword >> 21) & 31;
1483     spr = ((iword >> 6) & 0x3e0) + ((iword >> 16) & 31);
1484     switch (spr) {
1485 dpavlin 20 /* Some very common ones: */
1486 dpavlin 14 case 8: debug("mtlr\tr%i", rs); break;
1487     case 9: debug("mtctr\tr%i", rs); break;
1488     default:debug("mtspr\tspr%i,r%i", spr, rs);
1489     }
1490 dpavlin 20 if (spr == 8 || spr == 9)
1491     debug("\t");
1492     debug("\t<%s%s", running? "write to " : "",
1493     ppc_spr_names[spr]==NULL? "?" : ppc_spr_names[spr]);
1494     if (running) {
1495     if (cpu->cd.ppc.bits == 32)
1496     debug(": 0x%x", (int)
1497     cpu->cd.ppc.gpr[rs]);
1498     else
1499     debug(": 0x%llx", (long long)
1500     cpu->cd.ppc.gpr[rs]);
1501     }
1502     debug(">");
1503 dpavlin 14 break;
1504     case PPC_31_SYNC:
1505     debug("%s", power? "dcs" : "sync");
1506     break;
1507     case PPC_31_LSWI:
1508     case PPC_31_STSWI:
1509     rs = (iword >> 21) & 31; /* lwsi uses rt */
1510     ra = (iword >> 16) & 31;
1511     nb = (iword >> 11) & 31;
1512     switch (xo) {
1513     case PPC_31_LSWI:
1514     mnem = power? "lsi" : "lswi"; break;
1515     case PPC_31_STSWI:
1516     mnem = power? "stsi" : "stswi"; break;
1517     }
1518     debug("%s\tr%i,r%i,%i", mnem, rs, ra, nb);
1519     break;
1520     case PPC_31_SRAWI:
1521     rs = (iword >> 21) & 31;
1522     ra = (iword >> 16) & 31;
1523     sh = (iword >> 11) & 31;
1524     rc = iword & 1;
1525     mnem = power? "srai" : "srawi";
1526     debug("%s%s\tr%i,r%i,%i", mnem,
1527     rc? "." : "", ra, rs, sh);
1528     break;
1529 dpavlin 24 case PPC_31_DSSALL:
1530     debug("dssall");
1531     break;
1532 dpavlin 14 case PPC_31_EIEIO:
1533     debug("%s", power? "eieio?" : "eieio");
1534     break;
1535     case PPC_31_EXTSB:
1536     case PPC_31_EXTSH:
1537     case PPC_31_EXTSW:
1538     rs = (iword >> 21) & 31;
1539     ra = (iword >> 16) & 31;
1540     rc = iword & 1;
1541     switch (xo) {
1542     case PPC_31_EXTSB:
1543     mnem = power? "exts" : "extsb";
1544     break;
1545     case PPC_31_EXTSH:
1546     mnem = "extsh";
1547     break;
1548     case PPC_31_EXTSW:
1549     mnem = "extsw";
1550     break;
1551     }
1552     debug("%s%s\tr%i,r%i", mnem, rc? "." : "", ra, rs);
1553     break;
1554 dpavlin 22 case PPC_31_LVX:
1555 dpavlin 24 case PPC_31_LVXL:
1556 dpavlin 22 case PPC_31_STVX:
1557     case PPC_31_STVXL:
1558 dpavlin 24 rs = (iword >> 21) & 31; /* vs for stores, */
1559     ra = (iword >> 16) & 31; /* rs=vl for loads */
1560     rb = (iword >> 11) & 31;
1561     rc = iword & 1;
1562     switch (xo) {
1563     case PPC_31_LVX: mnem = "lvx"; break;
1564     case PPC_31_LVXL: mnem = "lvxl"; break;
1565     case PPC_31_STVX: mnem = "stvx"; break;
1566     case PPC_31_STVXL: mnem = "stvxl"; break;
1567     }
1568     debug("%s%s\tv%i,r%i,r%i", mnem, rc? "." : "",
1569     rs, ra, rb);
1570 dpavlin 22 break;
1571 dpavlin 14 default:
1572     debug("unimplemented hi6_31, xo = 0x%x", xo);
1573     }
1574     break;
1575 dpavlin 20 case PPC_HI6_LD:
1576 dpavlin 14 case PPC_HI6_LWZ:
1577     case PPC_HI6_LWZU:
1578     case PPC_HI6_LHZ:
1579     case PPC_HI6_LHZU:
1580     case PPC_HI6_LHA:
1581     case PPC_HI6_LHAU:
1582     case PPC_HI6_LBZ:
1583     case PPC_HI6_LBZU:
1584 dpavlin 20 case PPC_HI6_LFD:
1585     case PPC_HI6_LFS:
1586 dpavlin 14 case PPC_HI6_LMW:
1587 dpavlin 20 case PPC_HI6_STD:
1588 dpavlin 14 case PPC_HI6_STW:
1589     case PPC_HI6_STWU:
1590     case PPC_HI6_STH:
1591     case PPC_HI6_STHU:
1592     case PPC_HI6_STB:
1593     case PPC_HI6_STBU:
1594     case PPC_HI6_STMW:
1595     case PPC_HI6_STFD:
1596 dpavlin 20 case PPC_HI6_STFS:
1597 dpavlin 14 /* NOTE: Loads use rt, not rs, but are otherwise similar
1598     to stores */
1599     load = 0; wlen = 0;
1600     rs = (iword >> 21) & 31;
1601     ra = (iword >> 16) & 31;
1602     imm = (int16_t)(iword & 0xffff);
1603     fpreg = 0;
1604     switch (hi6) {
1605 dpavlin 20 case PPC_HI6_LD: load=1; wlen = 8; mnem = "ld"; break;
1606 dpavlin 14 case PPC_HI6_LWZ: load=1; wlen = 4;
1607     mnem = power? "l" : "lwz"; break;
1608     case PPC_HI6_LWZU: load=1; wlen = 4;
1609     mnem = power? "lu" : "lwzu"; break;
1610     case PPC_HI6_LHZ: load=1; wlen = 2;
1611     mnem = "lhz"; break;
1612     case PPC_HI6_LHZU: load=1; wlen = 2;
1613     mnem = "lhzu"; break;
1614     case PPC_HI6_LHA: load=2; wlen = 2;
1615     mnem = "lha"; break;
1616     case PPC_HI6_LHAU: load=2; wlen = 2;
1617     mnem = "lhau"; break;
1618     case PPC_HI6_LBZ: load=1; wlen = 1;
1619     mnem = "lbz"; break;
1620     case PPC_HI6_LBZU: load=1; wlen = 1;
1621     mnem = "lbzu"; break;
1622 dpavlin 20 case PPC_HI6_LFD: load=1; fpreg=1; wlen=8; mnem = "lfd"; break;
1623     case PPC_HI6_LFS: load=1; fpreg=1; wlen=4; mnem = "lfs"; break;
1624     case PPC_HI6_STD: wlen=8; mnem = "std"; break;
1625 dpavlin 14 case PPC_HI6_STW: wlen=4; mnem = power? "st" : "stw"; break;
1626     case PPC_HI6_STWU: wlen=4; mnem = power? "stu" : "stwu"; break;
1627     case PPC_HI6_STH: wlen=2; mnem = "sth"; break;
1628     case PPC_HI6_STHU: wlen=2; mnem = "sthu"; break;
1629     case PPC_HI6_STB: wlen=1; mnem = "stb"; break;
1630     case PPC_HI6_STBU: wlen=1; mnem = "stbu"; break;
1631     case PPC_HI6_LMW: load=1; mnem = power? "lm" : "lmw"; break;
1632     case PPC_HI6_STMW: mnem = power? "stm" : "stmw"; break;
1633 dpavlin 20 case PPC_HI6_STFD: fpreg=1; wlen=8; mnem = "stfd"; break;
1634     case PPC_HI6_STFS: fpreg=1; wlen=4; mnem = "stfs"; break;
1635 dpavlin 14 }
1636     debug("%s\t", mnem);
1637     if (fpreg)
1638     debug("f");
1639     else
1640     debug("r");
1641     debug("%i,%i(r%i)", rs, imm, ra);
1642     if (!running)
1643     break;
1644     addr = (ra==0? 0 : cpu->cd.ppc.gpr[ra]) + imm;
1645 dpavlin 20 if (cpu->cd.ppc.bits == 32)
1646     addr &= 0xffffffff;
1647 dpavlin 14 symbol = get_symbol_name(&cpu->machine->symbol_context,
1648     addr, &offset);
1649     if (symbol != NULL)
1650     debug(" \t<%s", symbol);
1651     else
1652     debug(" \t<0x%llx", (long long)addr);
1653     if (wlen > 0 && load && wlen > 0) {
1654     unsigned char tw[8];
1655     uint64_t tdata = 0;
1656     int i, res = cpu->memory_rw(cpu, cpu->mem, addr, tw,
1657     wlen, MEM_READ, NO_EXCEPTIONS);
1658     if (res) {
1659     if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
1660     for (i=0; i<wlen; i++) {
1661     tdata <<= 8;
1662     tdata |= tw[wlen-1-i];
1663     }
1664     else
1665     for (i=0; i<wlen; i++) {
1666     tdata <<= 8;
1667     tdata |= tw[i];
1668     }
1669     debug(": ");
1670     if (wlen >= 4) {
1671     symbol = get_symbol_name(&cpu->machine->
1672     symbol_context, tdata, &offset);
1673     if (symbol != NULL)
1674     debug("%s", symbol);
1675     else
1676     debug("0x%llx",
1677     (long long)tdata);
1678     } else {
1679     /* TODO: if load==2, then this is
1680     a _signed_ load. */
1681     debug("0x%llx", (long long)tdata);
1682     }
1683     } else
1684     debug(": unreadable");
1685     }
1686     if (wlen > 0 && !load && wlen > 0) {
1687     int64_t tdata = 0;
1688     int i;
1689     for (i=0; i<wlen; i++)
1690     tdata |= (cpu->cd.ppc.gpr[rs] &
1691 dpavlin 20 ((uint64_t)0xff << (i*8)));
1692 dpavlin 14 debug(": ");
1693     if (wlen >= 4) {
1694     symbol = get_symbol_name(&cpu->machine->
1695     symbol_context, tdata, &offset);
1696     if (symbol != NULL)
1697     debug("%s", symbol);
1698     else
1699 dpavlin 20 debug("0x%llx", (long long)tdata);
1700 dpavlin 14 } else {
1701     if (tdata > -256 && tdata < 256)
1702     debug("%i", (int)tdata);
1703     else
1704     debug("0x%llx", (long long)tdata);
1705     }
1706     }
1707     debug(">");
1708     break;
1709 dpavlin 20 case PPC_HI6_59:
1710     xo = (iword >> 1) & 1023;
1711     /* NOTE: Some floating point instructions only use the
1712     lowest 5 bits of xo, some use all 10 bits! */
1713     switch (xo & 31) {
1714     case PPC_59_FDIVS:
1715     case PPC_59_FSUBS:
1716     case PPC_59_FADDS:
1717     case PPC_59_FMULS:
1718     case PPC_59_FMADDS:
1719     rt = (iword >> 21) & 31;
1720     ra = (iword >> 16) & 31;
1721     rb = (iword >> 11) & 31;
1722     rs = (iword >> 6) & 31; /* actually frc */
1723     rc = iword & 1;
1724     switch (xo & 31) {
1725     case PPC_59_FDIVS: mnem = "fdivs"; break;
1726     case PPC_59_FSUBS: mnem = "fsubs"; break;
1727     case PPC_59_FADDS: mnem = "fadds"; break;
1728     case PPC_59_FMULS: mnem = "fmuls"; break;
1729     case PPC_59_FMADDS: mnem = "fmadds"; break;
1730     }
1731     debug("%s%s\t", mnem, rc? "." : "");
1732     switch (xo & 31) {
1733     case PPC_59_FMULS:
1734     debug("f%i,f%i,f%i", rt, ra, rs);
1735     break;
1736     case PPC_59_FMADDS:
1737     debug("f%i,f%i,f%i,f%i", rt, ra, rs, rb);
1738     break;
1739     default:debug("f%i,f%i,f%i", rt, ra, rb);
1740     }
1741     break;
1742     default:/* TODO: similar to hi6_63 */
1743     debug("unimplemented hi6_59, xo = 0x%x", xo);
1744     }
1745     break;
1746 dpavlin 14 case PPC_HI6_63:
1747     xo = (iword >> 1) & 1023;
1748 dpavlin 20 /* NOTE: Some floating point instructions only use the
1749     lowest 5 bits of xo, some use all 10 bits! */
1750     switch (xo & 31) {
1751     case PPC_63_FDIV:
1752     case PPC_63_FSUB:
1753     case PPC_63_FADD:
1754     case PPC_63_FMUL:
1755     case PPC_63_FMSUB:
1756     case PPC_63_FMADD:
1757 dpavlin 14 rt = (iword >> 21) & 31;
1758     ra = (iword >> 16) & 31;
1759     rb = (iword >> 11) & 31;
1760 dpavlin 20 rs = (iword >> 6) & 31; /* actually frc */
1761 dpavlin 14 rc = iword & 1;
1762 dpavlin 20 switch (xo & 31) {
1763     case PPC_63_FDIV:
1764     mnem = power? "fd" : "fdiv"; break;
1765     case PPC_63_FSUB:
1766     mnem = power? "fs" : "fsub"; break;
1767     case PPC_63_FADD:
1768     mnem = power? "fa" : "fadd"; break;
1769     case PPC_63_FMUL:
1770     mnem = power? "fm" : "fmul"; break;
1771     case PPC_63_FMSUB:
1772     mnem = power? "fms" : "fmsub"; break;
1773     case PPC_63_FMADD:
1774     mnem = power? "fma" : "fmadd"; break;
1775     }
1776     debug("%s%s\t", mnem, rc? "." : "");
1777     switch (xo & 31) {
1778     case PPC_63_FMUL:
1779     debug("f%i,f%i,f%i", rt, ra, rs);
1780     break;
1781     case PPC_63_FMADD:
1782     debug("f%i,f%i,f%i,f%i", rt, ra, rs, rb);
1783     break;
1784     default:debug("f%i,f%i,f%i", rt, ra, rb);
1785     }
1786     break;
1787     default:rt = (iword >> 21) & 31;
1788     ra = (iword >> 16) & 31;
1789     rb = (iword >> 11) & 31;
1790     rc = iword & 1;
1791 dpavlin 14 switch (xo) {
1792 dpavlin 20 case PPC_63_FCMPU:
1793     case PPC_63_FRSP:
1794     case PPC_63_FCTIWZ:
1795     case PPC_63_FNEG:
1796 dpavlin 14 case PPC_63_FMR:
1797 dpavlin 20 case PPC_63_FNABS:
1798     case PPC_63_FABS:
1799     switch (xo) {
1800     case PPC_63_FCMPU: mnem = "fcmpu"; break;
1801     case PPC_63_FCTIWZ:
1802     mnem = power? "fcirz" : "fctiwz"; break;
1803     case PPC_63_FRSP: mnem = "frsp"; break;
1804     case PPC_63_FNEG: mnem = "fneg"; break;
1805     case PPC_63_FMR: mnem = "fmr"; break;
1806     case PPC_63_FNABS: mnem = "fnabs"; break;
1807     case PPC_63_FABS: mnem = "fabs"; break;
1808     }
1809     debug("%s%s\t", mnem, rc? "." : "");
1810     switch (xo) {
1811     case PPC_63_FCMPU:
1812     debug("%i,f%i,f%i", rt >> 2, ra, rb);
1813     break;
1814     case PPC_63_FCTIWZ:
1815     case PPC_63_FRSP:
1816     case PPC_63_FNEG:
1817     case PPC_63_FMR:
1818     case PPC_63_FNABS:
1819     case PPC_63_FABS:
1820     debug("f%i,f%i", rt, rb);
1821     break;
1822     default:debug("f%i,f%i,f%i", rt, ra, rb);
1823     }
1824 dpavlin 14 break;
1825 dpavlin 20 case PPC_63_MFFS:
1826     debug("mffs%s\tf%i", rc?".":"", rt);
1827     break;
1828     case PPC_63_MTFSF:
1829     ra = (iword >> 17) & 255; /* flm */
1830     debug("mtfsf%s\t0x%02x,f%i", rc?".":"", ra, rb);
1831     break;
1832     default:debug("unimplemented hi6_63, xo = 0x%x", xo);
1833 dpavlin 14 }
1834     }
1835     break;
1836     default:
1837     /* TODO */
1838     debug("unimplemented hi6 = 0x%02x", hi6);
1839     }
1840    
1841     debug("\n");
1842     return sizeof(iword);
1843     }
1844    
1845    
1846     /*
1847 dpavlin 20 * debug_spr_usage():
1848     *
1849     * Helper function. To speed up overall development speed of the emulator,
1850     * all SPR accesses are allowed. This function causes unknown/unimplemented
1851     * SPRs to give a warning.
1852     */
1853     static void debug_spr_usage(uint64_t pc, int spr)
1854     {
1855     static uint32_t spr_used[1024 / sizeof(uint32_t)];
1856     static int initialized = 0;
1857    
1858     if (!initialized) {
1859     memset(spr_used, 0, sizeof(spr_used));
1860     initialized = 1;
1861     }
1862    
1863     spr &= 1023;
1864     if (spr_used[spr >> 2] & (1 << (spr & 3)))
1865     return;
1866    
1867     switch (spr) {
1868     /* Known/implemented SPRs: */
1869     case SPR_XER:
1870     case SPR_LR:
1871     case SPR_CTR:
1872     case SPR_DSISR:
1873     case SPR_DAR:
1874     case SPR_DEC:
1875     case SPR_SDR1:
1876     case SPR_SRR0:
1877     case SPR_SRR1:
1878     case SPR_SPRG0:
1879     case SPR_SPRG1:
1880     case SPR_SPRG2:
1881     case SPR_SPRG3:
1882     case SPR_PVR:
1883     case SPR_DMISS:
1884     case SPR_DCMP:
1885     case SPR_HASH1:
1886     case SPR_HASH2:
1887     case SPR_IMISS:
1888     case SPR_ICMP:
1889     case SPR_DBSR:
1890     case SPR_PIR:
1891     break;
1892     default:if (spr >= SPR_IBAT0U && spr <= SPR_DBAT3L) {
1893     break;
1894     } else
1895     fatal("[ using UNIMPLEMENTED spr %i (%s), pc = "
1896     "0x%llx ]\n", spr, ppc_spr_names[spr] == NULL?
1897     "UNKNOWN" : ppc_spr_names[spr], (long long)pc);
1898     }
1899    
1900     spr_used[spr >> 2] |= (1 << (spr & 3));
1901     }
1902    
1903    
1904     /*
1905 dpavlin 14 * update_cr0():
1906     *
1907     * Sets the top 4 bits of the CR register.
1908     */
1909     void update_cr0(struct cpu *cpu, uint64_t value)
1910     {
1911     int c;
1912    
1913     if (cpu->cd.ppc.bits == 64) {
1914     if ((int64_t)value < 0)
1915     c = 8;
1916     else if ((int64_t)value > 0)
1917     c = 4;
1918     else
1919     c = 2;
1920     } else {
1921     if ((int32_t)value < 0)
1922     c = 8;
1923     else if ((int32_t)value > 0)
1924     c = 4;
1925     else
1926     c = 2;
1927     }
1928    
1929     /* SO bit, copied from XER: */
1930 dpavlin 20 c |= ((cpu->cd.ppc.spr[SPR_XER] >> 31) & 1);
1931 dpavlin 14
1932     cpu->cd.ppc.cr &= ~((uint32_t)0xf << 28);
1933     cpu->cd.ppc.cr |= ((uint32_t)c << 28);
1934     }
1935    
1936    
1937     #include "memory_ppc.c"
1938    
1939    
1940     #include "tmp_ppc_tail.c"
1941    
1942 dpavlin 24

  ViewVC Help
Powered by ViewVC 1.1.26