/[gxemul]/trunk/src/cpus/cpu_ppc.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 34 - (show annotations)
Mon Oct 8 16:21:17 2007 UTC (16 years, 5 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 /*
2 * Copyright (C) 2005-2007 Anders Gavare. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * 3. The name of the author may not be used to endorse or promote products
13 * derived from this software without specific prior written permission.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 *
27 *
28 * $Id: cpu_ppc.c,v 1.67 2006/12/30 13:30:54 debug Exp $
29 *
30 * PowerPC/POWER CPU emulation.
31 */
32
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <ctype.h>
37
38 #include "cpu.h"
39 #include "devices.h"
40 #include "interrupt.h"
41 #include "machine.h"
42 #include "memory.h"
43 #include "misc.h"
44 #include "of.h"
45 #include "opcodes_ppc.h"
46 #include "ppc_bat.h"
47 #include "ppc_pte.h"
48 #include "ppc_spr.h"
49 #include "ppc_spr_strings.h"
50 #include "settings.h"
51 #include "symbol.h"
52
53 #define DYNTRANS_DUALMODE_32
54 #include "tmp_ppc_head.c"
55
56
57 void ppc_pc_to_pointers(struct cpu *);
58 void ppc32_pc_to_pointers(struct cpu *);
59
60 void ppc_irq_interrupt_assert(struct interrupt *interrupt);
61 void ppc_irq_interrupt_deassert(struct interrupt *interrupt);
62
63
64 /*
65 * ppc_cpu_new():
66 *
67 * Create a new PPC cpu object.
68 *
69 * Returns 1 on success, 0 if there was no matching PPC processor with
70 * this cpu_type_name.
71 */
72 int ppc_cpu_new(struct cpu *cpu, struct memory *mem, struct machine *machine,
73 int cpu_id, char *cpu_type_name)
74 {
75 int any_cache = 0;
76 int i, found;
77 struct ppc_cpu_type_def cpu_type_defs[] = PPC_CPU_TYPE_DEFS;
78
79 /* Scan the cpu_type_defs list for this cpu type: */
80 i = 0;
81 found = -1;
82 while (i >= 0 && cpu_type_defs[i].name != NULL) {
83 if (strcasecmp(cpu_type_defs[i].name, cpu_type_name) == 0) {
84 found = i;
85 break;
86 }
87 i++;
88 }
89 if (found == -1)
90 return 0;
91
92 cpu->memory_rw = ppc_memory_rw;
93
94 cpu->cd.ppc.cpu_type = cpu_type_defs[found];
95 cpu->name = cpu->cd.ppc.cpu_type.name;
96 cpu->byte_order = EMUL_BIG_ENDIAN;
97 cpu->cd.ppc.mode = MODE_PPC; /* TODO */
98
99 /* Current operating mode: */
100 cpu->cd.ppc.bits = cpu->cd.ppc.cpu_type.bits;
101 cpu->cd.ppc.spr[SPR_PVR] = cpu->cd.ppc.cpu_type.pvr;
102
103 /* cpu->cd.ppc.msr = PPC_MSR_IR | PPC_MSR_DR |
104 PPC_MSR_SF | PPC_MSR_FP; */
105
106 cpu->cd.ppc.spr[SPR_IBAT0U] = 0x00001ffc | BAT_Vs;
107 cpu->cd.ppc.spr[SPR_IBAT0L] = 0x00000000 | BAT_PP_RW;
108 cpu->cd.ppc.spr[SPR_IBAT1U] = 0xc0001ffc | BAT_Vs;
109 cpu->cd.ppc.spr[SPR_IBAT1L] = 0x00000000 | BAT_PP_RW;
110 cpu->cd.ppc.spr[SPR_IBAT3U] = 0xf0001ffc | BAT_Vs;
111 cpu->cd.ppc.spr[SPR_IBAT3L] = 0xf0000000 | BAT_PP_RW;
112 cpu->cd.ppc.spr[SPR_DBAT0U] = 0x00001ffc | BAT_Vs;
113 cpu->cd.ppc.spr[SPR_DBAT0L] = 0x00000000 | BAT_PP_RW;
114 cpu->cd.ppc.spr[SPR_DBAT1U] = 0xc0001ffc | BAT_Vs;
115 cpu->cd.ppc.spr[SPR_DBAT1L] = 0x00000000 | BAT_PP_RW;
116 cpu->cd.ppc.spr[SPR_DBAT2U] = 0xe0001ffc | BAT_Vs;
117 cpu->cd.ppc.spr[SPR_DBAT2L] = 0xe0000000 | BAT_PP_RW;
118 cpu->cd.ppc.spr[SPR_DBAT3U] = 0xf0001ffc | BAT_Vs;
119 cpu->cd.ppc.spr[SPR_DBAT3L] = 0xf0000000 | BAT_PP_RW;
120
121 cpu->is_32bit = (cpu->cd.ppc.bits == 32)? 1 : 0;
122
123 if (cpu->is_32bit) {
124 cpu->run_instr = ppc32_run_instr;
125 cpu->update_translation_table = ppc32_update_translation_table;
126 cpu->invalidate_translation_caches =
127 ppc32_invalidate_translation_caches;
128 cpu->invalidate_code_translation =
129 ppc32_invalidate_code_translation;
130 } else {
131 cpu->run_instr = ppc_run_instr;
132 cpu->update_translation_table = ppc_update_translation_table;
133 cpu->invalidate_translation_caches =
134 ppc_invalidate_translation_caches;
135 cpu->invalidate_code_translation =
136 ppc_invalidate_code_translation;
137 }
138
139 cpu->translate_v2p = ppc_translate_v2p;
140
141 /* Only show name and caches etc for CPU nr 0 (in SMP machines): */
142 if (cpu_id == 0) {
143 debug("%s", cpu->cd.ppc.cpu_type.name);
144
145 if (cpu->cd.ppc.cpu_type.icache_shift != 0)
146 any_cache = 1;
147 if (cpu->cd.ppc.cpu_type.dcache_shift != 0)
148 any_cache = 1;
149 if (cpu->cd.ppc.cpu_type.l2cache_shift != 0)
150 any_cache = 1;
151
152 if (any_cache) {
153 debug(" (I+D = %i+%i KB",
154 (int)(1 << (cpu->cd.ppc.cpu_type.icache_shift-10)),
155 (int)(1 << (cpu->cd.ppc.cpu_type.dcache_shift-10)));
156 if (cpu->cd.ppc.cpu_type.l2cache_shift != 0) {
157 debug(", L2 = %i KB",
158 (int)(1 << (cpu->cd.ppc.cpu_type.
159 l2cache_shift-10)));
160 }
161 debug(")");
162 }
163 }
164
165 cpu->cd.ppc.spr[SPR_PIR] = cpu_id;
166
167 /* Some default stack pointer value. TODO: move this? */
168 cpu->cd.ppc.gpr[1] = machine->physical_ram_in_mb * 1048576 - 4096;
169
170 /*
171 * NOTE/TODO: Ugly hack for OpenFirmware emulation:
172 */
173 if (cpu->machine->prom_emulation)
174 cpu->cd.ppc.of_emul_addr = 0xfff00000;
175
176 /* Add all register names to the settings: */
177 CPU_SETTINGS_ADD_REGISTER64("pc", cpu->pc);
178 CPU_SETTINGS_ADD_REGISTER64("msr", cpu->cd.ppc.msr);
179 CPU_SETTINGS_ADD_REGISTER64("ctr", cpu->cd.ppc.spr[SPR_CTR]);
180 CPU_SETTINGS_ADD_REGISTER64("xer", cpu->cd.ppc.spr[SPR_XER]);
181 CPU_SETTINGS_ADD_REGISTER64("dec", cpu->cd.ppc.spr[SPR_DEC]);
182 CPU_SETTINGS_ADD_REGISTER64("hdec", cpu->cd.ppc.spr[SPR_HDEC]);
183 CPU_SETTINGS_ADD_REGISTER64("srr0", cpu->cd.ppc.spr[SPR_SRR0]);
184 CPU_SETTINGS_ADD_REGISTER64("srr1", cpu->cd.ppc.spr[SPR_SRR1]);
185 CPU_SETTINGS_ADD_REGISTER64("sdr1", cpu->cd.ppc.spr[SPR_SDR1]);
186 CPU_SETTINGS_ADD_REGISTER64("ibat0u", cpu->cd.ppc.spr[SPR_IBAT0U]);
187 CPU_SETTINGS_ADD_REGISTER64("ibat0l", cpu->cd.ppc.spr[SPR_IBAT0L]);
188 CPU_SETTINGS_ADD_REGISTER64("ibat1u", cpu->cd.ppc.spr[SPR_IBAT1U]);
189 CPU_SETTINGS_ADD_REGISTER64("ibat1l", cpu->cd.ppc.spr[SPR_IBAT1L]);
190 CPU_SETTINGS_ADD_REGISTER64("ibat2u", cpu->cd.ppc.spr[SPR_IBAT2U]);
191 CPU_SETTINGS_ADD_REGISTER64("ibat2l", cpu->cd.ppc.spr[SPR_IBAT2L]);
192 CPU_SETTINGS_ADD_REGISTER64("ibat3u", cpu->cd.ppc.spr[SPR_IBAT3U]);
193 CPU_SETTINGS_ADD_REGISTER64("ibat3l", cpu->cd.ppc.spr[SPR_IBAT3L]);
194 CPU_SETTINGS_ADD_REGISTER64("dbat0u", cpu->cd.ppc.spr[SPR_DBAT0U]);
195 CPU_SETTINGS_ADD_REGISTER64("dbat0l", cpu->cd.ppc.spr[SPR_DBAT0L]);
196 CPU_SETTINGS_ADD_REGISTER64("dbat1u", cpu->cd.ppc.spr[SPR_DBAT1U]);
197 CPU_SETTINGS_ADD_REGISTER64("dbat1l", cpu->cd.ppc.spr[SPR_DBAT1L]);
198 CPU_SETTINGS_ADD_REGISTER64("dbat2u", cpu->cd.ppc.spr[SPR_DBAT2U]);
199 CPU_SETTINGS_ADD_REGISTER64("dbat2l", cpu->cd.ppc.spr[SPR_DBAT2L]);
200 CPU_SETTINGS_ADD_REGISTER64("dbat3u", cpu->cd.ppc.spr[SPR_DBAT3U]);
201 CPU_SETTINGS_ADD_REGISTER64("dbat3l", cpu->cd.ppc.spr[SPR_DBAT3L]);
202 CPU_SETTINGS_ADD_REGISTER64("lr", cpu->cd.ppc.spr[SPR_LR]);
203 CPU_SETTINGS_ADD_REGISTER32("cr", cpu->cd.ppc.cr);
204 CPU_SETTINGS_ADD_REGISTER32("fpscr", cpu->cd.ppc.fpscr);
205 /* Integer GPRs, floating point registers, and segment registers: */
206 for (i=0; i<PPC_NGPRS; i++) {
207 char tmpstr[5];
208 snprintf(tmpstr, sizeof(tmpstr), "r%i", i);
209 CPU_SETTINGS_ADD_REGISTER64(tmpstr, cpu->cd.ppc.gpr[i]);
210 }
211 for (i=0; i<PPC_NFPRS; i++) {
212 char tmpstr[5];
213 snprintf(tmpstr, sizeof(tmpstr), "f%i", i);
214 CPU_SETTINGS_ADD_REGISTER64(tmpstr, cpu->cd.ppc.fpr[i]);
215 }
216 for (i=0; i<16; i++) {
217 char tmpstr[5];
218 snprintf(tmpstr, sizeof(tmpstr), "sr%i", i);
219 CPU_SETTINGS_ADD_REGISTER32(tmpstr, cpu->cd.ppc.sr[i]);
220 }
221
222 /* Register the CPU as an interrupt handler: */
223 {
224 struct interrupt template;
225 char name[150];
226 snprintf(name, sizeof(name), "%s", cpu->path);
227 memset(&template, 0, sizeof(template));
228 template.line = 0;
229 template.name = name;
230 template.extra = cpu;
231 template.interrupt_assert = ppc_irq_interrupt_assert;
232 template.interrupt_deassert = ppc_irq_interrupt_deassert;
233 interrupt_handler_register(&template);
234 }
235
236 return 1;
237 }
238
239
240 /*
241 * ppc_cpu_list_available_types():
242 *
243 * Print a list of available PPC CPU types.
244 */
245 void ppc_cpu_list_available_types(void)
246 {
247 int i, j;
248 struct ppc_cpu_type_def tdefs[] = PPC_CPU_TYPE_DEFS;
249
250 i = 0;
251 while (tdefs[i].name != NULL) {
252 debug("%s", tdefs[i].name);
253 for (j=10 - strlen(tdefs[i].name); j>0; j--)
254 debug(" ");
255 i++;
256 if ((i % 6) == 0 || tdefs[i].name == NULL)
257 debug("\n");
258 }
259 }
260
261
262 /*
263 * ppc_cpu_dumpinfo():
264 */
265 void ppc_cpu_dumpinfo(struct cpu *cpu)
266 {
267 struct ppc_cpu_type_def *ct = &cpu->cd.ppc.cpu_type;
268
269 debug(" (%i-bit ", cpu->cd.ppc.bits);
270
271 switch (cpu->cd.ppc.mode) {
272 case MODE_PPC:
273 debug("PPC");
274 break;
275 case MODE_POWER:
276 debug("POWER");
277 break;
278 default:
279 debug("_INTERNAL ERROR_");
280 }
281
282 debug(", I+D = %i+%i KB",
283 (1 << ct->icache_shift) / 1024,
284 (1 << ct->dcache_shift) / 1024);
285
286 if (ct->l2cache_shift) {
287 int kb = (1 << ct->l2cache_shift) / 1024;
288 debug(", L2 = %i %cB",
289 kb >= 1024? kb / 1024 : kb,
290 kb >= 1024? 'M' : 'K');
291 }
292
293 debug(")\n");
294 }
295
296
297 /*
298 * reg_access_msr():
299 */
300 void reg_access_msr(struct cpu *cpu, uint64_t *valuep, int writeflag,
301 int check_for_interrupts)
302 {
303 uint64_t old = cpu->cd.ppc.msr;
304
305 if (valuep == NULL) {
306 fatal("reg_access_msr(): NULL\n");
307 return;
308 }
309
310 if (writeflag) {
311 cpu->cd.ppc.msr = *valuep;
312
313 /* Switching between temporary and real gpr 0..3? */
314 if ((old & PPC_MSR_TGPR) != (cpu->cd.ppc.msr & PPC_MSR_TGPR)) {
315 int i;
316 for (i=0; i<PPC_N_TGPRS; i++) {
317 uint64_t t = cpu->cd.ppc.gpr[i];
318 cpu->cd.ppc.gpr[i] = cpu->cd.ppc.tgpr[i];
319 cpu->cd.ppc.tgpr[i] = t;
320 }
321 }
322
323 if (cpu->cd.ppc.msr & PPC_MSR_IP) {
324 fatal("\n[ Reboot hack for NetBSD/prep. TODO: "
325 "fix this. ]\n");
326 cpu->running = 0;
327 }
328 }
329
330 /* TODO: Is the little-endian bit writable? */
331
332 cpu->cd.ppc.msr &= ~PPC_MSR_LE;
333 if (cpu->byte_order != EMUL_BIG_ENDIAN)
334 cpu->cd.ppc.msr |= PPC_MSR_LE;
335
336 if (!writeflag)
337 *valuep = cpu->cd.ppc.msr;
338
339 if (check_for_interrupts && cpu->cd.ppc.msr & PPC_MSR_EE) {
340 if (cpu->cd.ppc.dec_intr_pending &&
341 !(cpu->cd.ppc.cpu_type.flags & PPC_NO_DEC)) {
342 ppc_exception(cpu, PPC_EXCEPTION_DEC);
343 cpu->cd.ppc.dec_intr_pending = 0;
344 } else if (cpu->cd.ppc.irq_asserted)
345 ppc_exception(cpu, PPC_EXCEPTION_EI);
346 }
347 }
348
349
350 /*
351 * ppc_exception():
352 */
353 void ppc_exception(struct cpu *cpu, int exception_nr)
354 {
355 /* Save PC and MSR: */
356 cpu->cd.ppc.spr[SPR_SRR0] = cpu->pc;
357
358 if (exception_nr >= 0x10 && exception_nr <= 0x13)
359 cpu->cd.ppc.spr[SPR_SRR1] = (cpu->cd.ppc.msr & 0xffff)
360 | (cpu->cd.ppc.cr & 0xf0000000);
361 else
362 cpu->cd.ppc.spr[SPR_SRR1] = (cpu->cd.ppc.msr & 0x87c0ffff);
363
364 if (!quiet_mode)
365 fatal("[ PPC Exception 0x%x; pc=0x%"PRIx64" ]\n", exception_nr,
366 (long long)cpu->pc);
367
368 /* Disable External Interrupts, Recoverable Interrupt Mode,
369 and go to Supervisor mode */
370 cpu->cd.ppc.msr &= ~(PPC_MSR_EE | PPC_MSR_RI | PPC_MSR_PR);
371
372 cpu->pc = exception_nr * 0x100;
373 if (cpu->cd.ppc.msr & PPC_MSR_IP)
374 cpu->pc += 0xfff00000ULL;
375
376 if (cpu->is_32bit)
377 ppc32_pc_to_pointers(cpu);
378 else
379 ppc_pc_to_pointers(cpu);
380 }
381
382
383 /*
384 * ppc_cpu_register_dump():
385 *
386 * Dump cpu registers in a relatively readable format.
387 *
388 * gprs: set to non-zero to dump GPRs and some special-purpose registers.
389 * coprocs: if bit i is set, then we should dump registers from coproc i.
390 */
391 void ppc_cpu_register_dump(struct cpu *cpu, int gprs, int coprocs)
392 {
393 char *symbol;
394 uint64_t offset, tmp;
395 int i, x = cpu->cpu_id;
396 int bits32 = cpu->cd.ppc.bits == 32;
397
398 if (gprs) {
399 /* Special registers (pc, ...) first: */
400 symbol = get_symbol_name(&cpu->machine->symbol_context,
401 cpu->pc, &offset);
402
403 debug("cpu%i: pc = 0x", x);
404 if (bits32)
405 debug("%08"PRIx32, (uint32_t)cpu->pc);
406 else
407 debug("%016"PRIx64, (uint64_t)cpu->pc);
408 debug(" <%s>\n", symbol != NULL? symbol : " no symbol ");
409
410 debug("cpu%i: lr = 0x", x);
411 if (bits32)
412 debug("%08"PRIx32, (uint32_t)cpu->cd.ppc.spr[SPR_LR]);
413 else
414 debug("%016"PRIx64, (uint64_t)cpu->cd.ppc.spr[SPR_LR]);
415 debug(" cr = 0x%08"PRIx32, (uint32_t)cpu->cd.ppc.cr);
416
417 if (bits32)
418 debug(" ");
419 else
420 debug("\ncpu%i: ", x);
421 debug("ctr = 0x", x);
422 if (bits32)
423 debug("%08"PRIx32, (uint32_t)cpu->cd.ppc.spr[SPR_CTR]);
424 else
425 debug("%016"PRIx64, (uint64_t)cpu->cd.ppc.spr[SPR_CTR]);
426
427 debug(" xer = 0x", x);
428 if (bits32)
429 debug("%08"PRIx32, (uint32_t)cpu->cd.ppc.spr[SPR_XER]);
430 else
431 debug("%016"PRIx64, (uint64_t)cpu->cd.ppc.spr[SPR_XER]);
432
433 debug("\n");
434
435 if (bits32) {
436 /* 32-bit: */
437 for (i=0; i<PPC_NGPRS; i++) {
438 if ((i % 4) == 0)
439 debug("cpu%i:", x);
440 debug(" r%02i = 0x%08x ", i,
441 (int)cpu->cd.ppc.gpr[i]);
442 if ((i % 4) == 3)
443 debug("\n");
444 }
445 } else {
446 /* 64-bit: */
447 for (i=0; i<PPC_NGPRS; i++) {
448 int r = (i >> 1) + ((i & 1) << 4);
449 if ((i % 2) == 0)
450 debug("cpu%i:", x);
451 debug(" r%02i = 0x%016llx ", r,
452 (long long)cpu->cd.ppc.gpr[r]);
453 if ((i % 2) == 1)
454 debug("\n");
455 }
456 }
457
458 /* Other special registers: */
459 if (bits32) {
460 debug("cpu%i: srr0 = 0x%08x srr1 = 0x%08x\n", x,
461 (int)cpu->cd.ppc.spr[SPR_SRR0],
462 (int)cpu->cd.ppc.spr[SPR_SRR1]);
463 } else {
464 debug("cpu%i: srr0 = 0x%016llx srr1 = 0x%016llx\n", x,
465 (long long)cpu->cd.ppc.spr[SPR_SRR0],
466 (long long)cpu->cd.ppc.spr[SPR_SRR1]);
467 }
468 debug("cpu%i: msr = ", x);
469 reg_access_msr(cpu, &tmp, 0, 0);
470 if (bits32)
471 debug("0x%08x ", (int)tmp);
472 else
473 debug("0x%016llx ", (long long)tmp);
474 debug("tb = 0x%08x%08x\n", (int)cpu->cd.ppc.spr[SPR_TBU],
475 (int)cpu->cd.ppc.spr[SPR_TBL]);
476 debug("cpu%i: dec = 0x%08x", x, (int)cpu->cd.ppc.spr[SPR_DEC]);
477 if (!bits32)
478 debug(" hdec = 0x%08x\n",
479 (int)cpu->cd.ppc.spr[SPR_HDEC]);
480 debug("\n");
481 }
482
483 if (coprocs & 1) {
484 debug("cpu%i: fpscr = 0x%08x\n", x, (int)cpu->cd.ppc.fpscr);
485
486 /* TODO: show floating-point values :-) */
487
488 /* TODO: 32-bit fprs on 32-bit PPC cpus? */
489
490 for (i=0; i<PPC_NFPRS; i++) {
491 if ((i % 2) == 0)
492 debug("cpu%i:", x);
493 debug(" f%02i = 0x%016llx ", i,
494 (long long)cpu->cd.ppc.fpr[i]);
495 if ((i % 2) == 1)
496 debug("\n");
497 }
498 }
499
500 if (coprocs & 2) {
501 debug("cpu%i: sdr1 = 0x%llx\n", x,
502 (long long)cpu->cd.ppc.spr[SPR_SDR1]);
503 if (cpu->cd.ppc.cpu_type.flags & PPC_601)
504 debug("cpu%i: PPC601-style, TODO!\n");
505 else {
506 for (i=0; i<8; i++) {
507 int spr = SPR_IBAT0U + i*2;
508 uint32_t upper = cpu->cd.ppc.spr[spr];
509 uint32_t lower = cpu->cd.ppc.spr[spr+1];
510 uint32_t len = (((upper & BAT_BL) << 15)
511 | 0x1ffff) + 1;
512 debug("cpu%i: %sbat%i: u=0x%08x l=0x%08x ",
513 x, i<4? "i" : "d", i&3, upper, lower);
514 if (!(upper & BAT_V)) {
515 debug(" (not valid)\n");
516 continue;
517 }
518 if (len < 1048576)
519 debug(" (%i KB, ", len >> 10);
520 else
521 debug(" (%i MB, ", len >> 20);
522 if (upper & BAT_Vu)
523 debug("user, ");
524 if (upper & BAT_Vs)
525 debug("supervisor, ");
526 if (lower & (BAT_W | BAT_I | BAT_M | BAT_G))
527 debug("%s%s%s%s, ",
528 lower & BAT_W? "W" : "",
529 lower & BAT_I? "I" : "",
530 lower & BAT_M? "M" : "",
531 lower & BAT_G? "G" : "");
532 switch (lower & BAT_PP) {
533 case BAT_PP_NONE: debug("NO access"); break;
534 case BAT_PP_RO_S: debug("read-only, soft");
535 break;
536 case BAT_PP_RO: debug("read-only"); break;
537 case BAT_PP_RW: debug("read/write"); break;
538 }
539 debug(")\n");
540 }
541 }
542 }
543
544 if (coprocs & 4) {
545 for (i=0; i<16; i++) {
546 uint32_t s = cpu->cd.ppc.sr[i];
547 debug("cpu%i:", x);
548 debug(" sr%-2i = 0x%08x", i, (int)s);
549 s &= (SR_TYPE | SR_SUKEY | SR_PRKEY | SR_NOEXEC);
550 if (s != 0) {
551 debug(" (");
552 if (s & SR_TYPE) {
553 debug("NON-memory type");
554 s &= ~SR_TYPE;
555 if (s != 0)
556 debug(", ");
557 }
558 if (s & SR_SUKEY) {
559 debug("supervisor-key");
560 s &= ~SR_SUKEY;
561 if (s != 0)
562 debug(", ");
563 }
564 if (s & SR_PRKEY) {
565 debug("user-key");
566 s &= ~SR_PRKEY;
567 if (s != 0)
568 debug(", ");
569 }
570 if (s & SR_NOEXEC)
571 debug("NOEXEC");
572 debug(")");
573 }
574 debug("\n");
575 }
576 }
577 }
578
579
580 /*
581 * ppc_cpu_tlbdump():
582 *
583 * Not currently used for PPC.
584 */
585 void ppc_cpu_tlbdump(struct machine *m, int x, int rawflag)
586 {
587 }
588
589
590 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 * ppc_irq_interrupt_assert():
679 */
680 void ppc_irq_interrupt_assert(struct interrupt *interrupt)
681 {
682 struct cpu *cpu = (struct cpu *) interrupt->extra;
683 cpu->cd.ppc.irq_asserted = 1;
684 }
685
686
687 /*
688 * ppc_irq_interrupt_deassert():
689 */
690 void ppc_irq_interrupt_deassert(struct interrupt *interrupt)
691 {
692 struct cpu *cpu = (struct cpu *) interrupt->extra;
693 cpu->cd.ppc.irq_asserted = 0;
694 }
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 int running, uint64_t dumpaddr)
711 {
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 case 0x4:
750 debug("ALTIVEC TODO");
751 /* vxor etc */
752 break;
753 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 case PPC_HI6_RLWNM:
946 case PPC_HI6_RLWIMI:
947 case PPC_HI6_RLWINM:
948 rs = (iword >> 21) & 31;
949 ra = (iword >> 16) & 31;
950 sh = (iword >> 11) & 31; /* actually rb for rlwnm */
951 mb = (iword >> 6) & 31;
952 me = (iword >> 1) & 31;
953 rc = iword & 1;
954 switch (hi6) {
955 case PPC_HI6_RLWNM:
956 mnem = power? "rlnm" : "rlwnm"; break;
957 case PPC_HI6_RLWIMI:
958 mnem = power? "rlimi" : "rlwimi"; break;
959 case PPC_HI6_RLWINM:
960 mnem = power? "rlinm" : "rlwinm"; break;
961 }
962 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 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 case PPC_30_RLDICL:
1005 case PPC_30_RLDICR:
1006 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 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 debug("%s%s\tr%i,r%i,%i,%i",
1019 mnem, rc?".":"", ra, rs, sh, me);
1020 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 case PPC_31_LHAX:
1080 case PPC_31_LHAUX:
1081 case PPC_31_LHZX:
1082 case PPC_31_LHZUX:
1083 case PPC_31_LWZX:
1084 case PPC_31_LWZUX:
1085 case PPC_31_LHBRX:
1086 case PPC_31_LWBRX:
1087 case PPC_31_LFDX:
1088 case PPC_31_LFSX:
1089 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 case PPC_31_STHBRX:
1100 case PPC_31_STWBRX:
1101 case PPC_31_STFDX:
1102 case PPC_31_STFSX:
1103 /* rs for stores, rt for loads, actually */
1104 load = 0; wlen = 0; fpreg = 0;
1105 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 case PPC_31_LHAX: wlen=2;load=1; mnem = "lhax"; break;
1114 case PPC_31_LHAUX: wlen=2;load=1; mnem = "lhaux"; break;
1115 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 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 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 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 }
1152 debug("%s\t%s%i,r%i,r%i", mnem,
1153 fpreg? "f" : "r", rs, ra, rb);
1154 if (!running)
1155 break;
1156 addr = (ra==0? 0 : cpu->cd.ppc.gpr[ra]) +
1157 cpu->cd.ppc.gpr[rb];
1158 if (cpu->cd.ppc.bits == 32)
1159 addr &= 0xffffffff;
1160 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 if (wlen > 0 && !fpreg /* && !reverse */) {
1167 /* 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 case PPC_31_WRTEEI:
1184 debug("wrteei\t%i", iword & 0x8000? 1 : 0);
1185 break;
1186 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 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 case PPC_31_MFSR:
1212 /* Move to/from segment register */
1213 rt = (iword >> 21) & 31;
1214 ra = (iword >> 16) & 15; /* actually: sr */
1215 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 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 case PPC_31_SUBFME:
1251 case PPC_31_SUBFMEO:
1252 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 mnem = power? "sf" : "subfc"; break;
1298 case PPC_31_SUBFCO:
1299 mnem = power? "sfo" : "subfco"; break;
1300 case PPC_31_SUBFE:
1301 mnem = power? "sfe" : "subfe"; break;
1302 case PPC_31_SUBFEO:
1303 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 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 /* Some very common ones: */
1326 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 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 break;
1344 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 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 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 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 case PPC_31_SLD:
1415 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 case PPC_31_EQV:
1421 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 case PPC_31_SLD: mnem = "sld"; break;
1436 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 case PPC_31_EQV: mnem = "eqv"; break;
1445 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 /* Some very common ones: */
1486 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 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 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 case PPC_31_DSSALL:
1530 debug("dssall");
1531 break;
1532 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 case PPC_31_LVX:
1555 case PPC_31_LVXL:
1556 case PPC_31_STVX:
1557 case PPC_31_STVXL:
1558 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 break;
1571 default:
1572 debug("unimplemented hi6_31, xo = 0x%x", xo);
1573 }
1574 break;
1575 case PPC_HI6_LD:
1576 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 case PPC_HI6_LFD:
1585 case PPC_HI6_LFS:
1586 case PPC_HI6_LMW:
1587 case PPC_HI6_STD:
1588 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 case PPC_HI6_STFS:
1597 /* 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 case PPC_HI6_LD: load=1; wlen = 8; mnem = "ld"; break;
1606 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 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 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 case PPC_HI6_STFD: fpreg=1; wlen=8; mnem = "stfd"; break;
1634 case PPC_HI6_STFS: fpreg=1; wlen=4; mnem = "stfs"; break;
1635 }
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 if (cpu->cd.ppc.bits == 32)
1646 addr &= 0xffffffff;
1647 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 ((uint64_t)0xff << (i*8)));
1692 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 debug("0x%llx", (long long)tdata);
1700 } 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 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 case PPC_HI6_63:
1747 xo = (iword >> 1) & 1023;
1748 /* 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 rt = (iword >> 21) & 31;
1758 ra = (iword >> 16) & 31;
1759 rb = (iword >> 11) & 31;
1760 rs = (iword >> 6) & 31; /* actually frc */
1761 rc = iword & 1;
1762 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 switch (xo) {
1792 case PPC_63_FCMPU:
1793 case PPC_63_FRSP:
1794 case PPC_63_FCTIWZ:
1795 case PPC_63_FNEG:
1796 case PPC_63_FMR:
1797 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 break;
1825 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 }
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 * 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 * 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 c |= ((cpu->cd.ppc.spr[SPR_XER] >> 31) & 1);
1931
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

  ViewVC Help
Powered by ViewVC 1.1.26