/[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 24 - (show annotations)
Mon Oct 8 16:19:56 2007 UTC (16 years, 5 months ago) by dpavlin
File MIME type: text/plain
File size: 51691 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1256 2006/06/23 20:43:44 debug Exp $
20060219	Various minor updates. Removing the old MIPS16 skeleton code,
		because it will need to be rewritten for dyntrans anyway.
20060220-22	Removing the non-working dyntrans backend support.
		Continuing on the 64-bit dyntrans virtual memory generalization.
20060223	More work on the 64-bit vm generalization.
20060225	Beginning on MIPS dyntrans load/store instructions.
		Minor PPC updates (64-bit load/store, etc).
		Fixes for the variable-instruction-length framework, some
		minor AVR updates (a simple Hello World program works!).
		Beginning on a skeleton for automatically generating documen-
		tation (for devices etc.).
20060226	PPC updates (adding some more 64-bit instructions, etc).
		AVR updates (more instructions).
		FINALLY found and fixed the zs bug, making NetBSD/macppc
		accept the serial console.
20060301	Adding more AVR instructions.
20060304	Continuing on AVR-related stuff. Beginning on a framework for
		cycle-accurate device emulation. Adding an experimental "PAL
		TV" device (just a dummy so far).
20060305	Adding more AVR instructions.
		Adding a dummy epcom serial controller (for TS7200 emulation).
20060310	Removing the emul() command from configuration files, so only
		net() and machine() are supported.
		Minor progress on the MIPS dyntrans rewrite.
20060311	Continuing on the MIPS dyntrans rewrite (adding more
		instructions, etc).
20060315	Adding more instructions (sllv, srav, srlv, bgtz[l], blez[l],
		beql, bnel, slti[u], various loads and stores).
20060316	Removing the ALWAYS_SIGNEXTEND_32 option, since it was rarely
		used.
		Adding more MIPS dyntrans instructions, and fixing bugs.
20060318	Implementing fast loads/stores for MIPS dyntrans (big/little
		endian, 32-bit and 64-bit modes).
20060320	Making MIPS dyntrans the default configure option; use
		"--enable-oldmips" to use the old bintrans system.
		Adding MIPS dyntrans dmult[u]; minor updates.
20060322	Continuing... adding some more instructions.
		Adding a simple skeleton for demangling C++ "_ZN" symbols.
20060323	Moving src/debugger.c into a new directory (src/debugger/).
20060324	Fixing the hack used to load PPC ELFs (useful for relocated
		Linux/ppc kernels), and adding a dummy G3 machine mode.
20060325-26	Beginning to experiment with GDB remote serial protocol
		connections; adding a -G command line option for selecting
		which TCP port to listen to.
20060330	Beginning a major cleanup to replace things like "0x%016llx"
		with more correct "0x%016"PRIx64, etc.
		Continuing on the GDB remote serial protocol support.
20060331	More cleanup, and some minor GDB remote progress.
20060402	Adding a hack to the configure script, to allow compilation
		on systems that lack PRIx64 etc.
20060406	Removing the temporary FreeBSD/arm hack in dev_ns16550.c and
		replacing it with a better fix from Olivier Houchard.
20060407	A remote debugger (gdb or ddd) can now start and stop the
		emulator using the GDB remote serial protocol, and registers
		and memory can be read. MIPS only for now.
20060408	More GDB progress: single-stepping also works, and also adding
		support for ARM, PowerPC, and Alpha targets.
		Continuing on the delay-slot-across-page-boundary issue.
20060412	Minor update: beginning to add support for the SPARC target
		to the remote GDB functionality.
20060414	Various MIPS updates: adding more instructions for dyntrans
		(eret, add), and making some exceptions work. Fixing a bug
		in dmult[u].
		Implementing the first SPARC instructions (sethi, or).
20060415	Adding "magic trap" instructions so that PROM calls can be
		software emulated in MIPS dyntrans.
		Adding more MIPS dyntrans instructions (ddiv, dadd) and
		fixing another bug in dmult.
20060416	More MIPS dyntrans progress: adding [d]addi, movn, movz, dsllv,
		rfi, an ugly hack for supporting R2000/R3000 style faked caches,
		preliminary interrupt support, and various other updates and
		bugfixes.
20060417	Adding more SPARC instructions (add, sub, sll[x], sra[x],
		srl[x]), and useful SPARC header definitions.
		Adding the first (trivial) x86/AMD64 dyntrans instructions (nop,
		cli/sti, stc/clc, std/cld, simple mov, inc ax). Various other
		x86 updates related to variable instruction length stuff.
		Adding unaligned loads/stores to the MIPS dyntrans mode (but
		still using the pre-dyntrans (slow) imlementation).
20060419	Fixing a MIPS dyntrans exception-in-delay-slot bug.
		Removing the old "show opcode statistics" functionality, since
		it wasn't really useful and isn't implemented for dyntrans.
		Single-stepping (or running with instruction trace) now looks
		ok with dyntrans with delay-slot architectures.
20060420	Minor hacks (removing the -B command line option when compiled
		for non-bintrans, and some other very minor updates).
		Adding (slow) MIPS dyntrans load-linked/store-conditional.
20060422	Applying fixes for bugs discovered by Nils Weller's nwcc
		(static DEC memmap => now per machine, and adding an extern
		keyword in cpu_arm_instr.c).
		Finally found one of the MIPS dyntrans bugs that I've been
		looking for (copy/paste spelling error BIG vs LITTLE endian in
		cpu_mips_instr_loadstore.c for 16-bit fast stores).
		FINALLY found the major MIPS dyntrans bug: slti vs sltiu
		signed/unsigned code in cpu_mips_instr.c. :-)
		Adding more MIPS dyntrans instructions (lwc1, swc1, bgezal[l],
		ctc1, tlt[u], tge[u], tne, beginning on rdhwr).
		NetBSD/hpcmips can now reach userland when using dyntrans :-)
		Adding some more x86 dyntrans instructions.
		Finally removed the old Alpha-specific virtual memory code,
		and replaced it with the generic 64-bit version.
		Beginning to add disassembly support for SPECIAL3 MIPS opcodes.
20060423	Continuing on the delay-slot-across-page-boundary issue;
		adding an end_of_page2 ic slot (like I had planned before, but
		had removed for some reason).
		Adding a quick-and-dirty fallback to legacy coprocessor 1
		code (i.e. skipping dyntrans implementation for now).
		NetBSD/hpcmips and NetBSD/pmax (when running on an emulated
		R4400) can now be installed and run. :-)  (Many bugs left
		to fix, though.)
		Adding more MIPS dyntrans instructions: madd[u], msub[u].
		Cleaning up the SPECIAL2 vs R5900/TX79/C790 "MMI" opcode
		maps somewhat (disassembly and dyntrans instruction decoding).
20060424	Adding an isa_revision field to mips_cpu_types.h, and making
		sure that SPECIAL3 opcodes cause Reserved Instruction
		exceptions on MIPS32/64 revisions lower than 2.
		Adding the SPARC 'ba', 'call', 'jmpl/retl', 'and', and 'xor'
		instructions.
20060425	Removing the -m command line option ("run at most x 
		instructions") and -T ("single_step_on_bad_addr"), because
		they never worked correctly with dyntrans anyway.
		Freshening up the man page.
20060428	Adding more MIPS dyntrans instructions: bltzal[l], idle.
		Enabling MIPS dyntrans compare interrupts.
20060429	FINALLY found the weird dyntrans bug, causing NetBSD etc. to
		behave strangely: some floating point code (conditional
		coprocessor branches) could not be reused from the old
		non-dyntrans code. The "quick-and-dirty fallback" only appeared
		to work. Fixing by implementing bc1* for MIPS dyntrans.
		More MIPS instructions: [d]sub, sdc1, ldc1, dmtc1, dmfc1, cfc0.
		Freshening up MIPS floating point disassembly appearance.
20060430	Continuing on C790/R5900/TX79 disassembly; implementing 128-bit
		"por" and "pextlw".
20060504	Disabling -u (userland emulation) unless compiled as unstable
		development version.
		Beginning on freshening up the testmachine include files,
		to make it easier to reuse those files (placing them in
		src/include/testmachine/), and beginning on a set of "demos"
		or "tutorials" for the testmachine functionality.
		Minor updates to the MIPS GDB remote protocol stub.
		Refreshing doc/experiments.html and gdb_remote.html.
		Enabling Alpha emulation in the stable release configuration,
		even though no guest OSes for Alpha can run yet.
20060505	Adding a generic 'settings' object, which will contain
		references to settable variables (which will later be possible
		to access using the debugger).
20060506	Updating dev_disk and corresponding demo/documentation (and
		switching from SCSI to IDE disk types, so it actually works
		with current test machines :-).
20060510	Adding a -D_LARGEFILE_SOURCE hack for 64-bit Linux hosts,
		so that fseeko() doesn't give a warning.
		Updating the section about how dyntrans works (the "runnable
		IR") in doc/intro.html.
		Instruction updates (some x64=1 checks, some more R5900
		dyntrans stuff: better mul/mult separation from MIPS32/64,
		adding ei and di).
		Updating MIPS cpuregs.h to a newer one (from NetBSD).
		Adding more MIPS dyntrans instructions: deret, ehb.
20060514	Adding disassembly and beginning implementation of SPARC wr
		and wrpr instructions.
20060515	Adding a SUN SPARC machine mode, with dummy SS20 and Ultra1
		machines. Adding the 32-bit "rd psr" instruction.
20060517	Disassembly support for the general SPARC rd instruction.
		Partial implementation of the cmp (subcc) instruction.
		Some other minor updates (making sure that R5900 processors
		start up with the EIE bit enabled, otherwise Linux/playstation2
		receives no interrupts).
20060519	Minor MIPS updates/cleanups.
20060521	Moving the MeshCube machine into evbmips; this seems to work
		reasonably well with a snapshot of a NetBSD MeshCube kernel.
		Cleanup/fix of MIPS config0 register initialization.
20060529	Minor MIPS fixes, including a sign-extension fix to the
		unaligned load/store code, which makes NetBSD/pmax on R3000
		work better with dyntrans. (Ultrix and Linux/DECstation still
		don't work, though.)
20060530	Minor updates to the Alpha machine mode: adding an AlphaBook
		mode, an LCA bus (forwarding accesses to an ISA bus), etc.
20060531	Applying a bugfix for the MIPS dyntrans sc[d] instruction from
		Ondrej Palkovsky. (Many thanks.)
20060601	Minifix to allow ARM immediate msr instruction to not give
		an error for some valid values.
		More Alpha updates.
20060602	Some minor Alpha updates.
20060603	Adding the Alpha cmpbge instruction. NetBSD/alpha prints its
		first boot messages :-) on an emulated Alphabook 1.
20060612	Minor updates; adding a dev_ether.h include file for the
		testmachine ether device. Continuing the hunt for the dyntrans
		bug which makes Linux and Ultrix on DECstation behave
		strangely... FINALLY found it! It seems to be related to
		invalidation of the translation cache, on tlbw{r,i}. There
		also seems to be some remaining interrupt-related problems.
20060614	Correcting the implementation of ldc1/sdc1 for MIPS dyntrans
		(so that it uses 16 32-bit registers if the FR bit in the
		status register is not set).
20060616	REMOVING BINTRANS COMPLETELY!
		Removing the old MIPS interpretation mode.
		Removing the MFHILO_DELAY and instruction delay stuff, because
		they wouldn't work with dyntrans anyway.
20060617	Some documentation updates (adding "NetBSD-archive" to some
		URLs, and new Debian/DECstation installation screenshots).
		Removing the "tracenull" and "enable-caches" configure options.
		Improving MIPS dyntrans performance somewhat (only invalidate
		translations if necessary, on writes to the entryhi register,
		instead of doing it for all cop0 writes).
20060618	More cleanup after the removal of the old MIPS emulation.
		Trying to fix the MIPS dyntrans performance bugs/bottlenecks;
		only semi-successful so far (for R3000).
20060620	Minor update to allow clean compilation again on Tru64/Alpha.
20060622	MIPS cleanup and fixes (removing the pc_last stuff, which
		doesn't make sense with dyntrans anyway, and fixing a cross-
		page-delay-slot-with-exception case in end_of_page).
		Removing the old max_random_cycles_per_chunk stuff, and the
		concept of cycles vs instructions for MIPS emulation.
		FINALLY found and fixed the bug which caused NetBSD/pmax
		clocks to behave strangely (it was a load to the zero register,
		which was treated as a NOP; now it is treated as a load to a
		dummy scratch register).
20060623	Increasing the dyntrans chunk size back to
		N_SAFE_DYNTRANS_LIMIT, instead of N_SAFE_DYNTRANS_LIMIT/2.
		Preparing for a quick release, even though there are known
		bugs, and performance for non-R3000 MIPS emulation is very
		poor. :-/
		Reverting to half the dyntrans chunk size again, because
		NetBSD/cats seemed less stable with full size chunks. :(
		NetBSD/sgimips 3.0 can now run :-)  (With release 0.3.8, only
		NetBSD/sgimips 2.1 worked, not 3.0.)

==============  RELEASE 0.4.0  ==============


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

  ViewVC Help
Powered by ViewVC 1.1.26