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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 24 - (hide annotations)
Mon Oct 8 16:19:56 2007 UTC (16 years, 6 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 dpavlin 14 /*
2 dpavlin 22 * Copyright (C) 2005-2006 Anders Gavare. All rights reserved.
3 dpavlin 14 *
4     * Redistribution and use in source and binary forms, with or without
5     * modification, are permitted provided that the following conditions are met:
6     *
7     * 1. Redistributions of source code must retain the above copyright
8     * notice, this list of conditions and the following disclaimer.
9     * 2. Redistributions in binary form must reproduce the above copyright
10     * notice, this list of conditions and the following disclaimer in the
11     * documentation and/or other materials provided with the distribution.
12     * 3. The name of the author may not be used to endorse or promote products
13     * derived from this software without specific prior written permission.
14     *
15     * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16     * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17     * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18     * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19     * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20     * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21     * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22     * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23     * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24     * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25     * SUCH DAMAGE.
26     *
27     *
28 dpavlin 24 * $Id: cpu_ppc.c,v 1.58 2006/06/16 18:31:26 debug Exp $
29 dpavlin 14 *
30     * PowerPC/POWER CPU emulation.
31     */
32    
33     #include <stdio.h>
34     #include <stdlib.h>
35     #include <string.h>
36     #include <ctype.h>
37    
38     #include "cpu.h"
39     #include "devices.h"
40     #include "machine.h"
41     #include "memory.h"
42     #include "misc.h"
43 dpavlin 22 #include "of.h"
44 dpavlin 14 #include "opcodes_ppc.h"
45 dpavlin 20 #include "ppc_bat.h"
46     #include "ppc_pte.h"
47     #include "ppc_spr.h"
48     #include "ppc_spr_strings.h"
49 dpavlin 14 #include "symbol.h"
50    
51     #define DYNTRANS_DUALMODE_32
52     #include "tmp_ppc_head.c"
53    
54    
55 dpavlin 20 void ppc_pc_to_pointers(struct cpu *);
56     void ppc32_pc_to_pointers(struct cpu *);
57    
58    
59 dpavlin 14 /*
60     * ppc_cpu_new():
61     *
62     * Create a new PPC cpu object.
63     *
64     * Returns 1 on success, 0 if there was no matching PPC processor with
65     * this cpu_type_name.
66     */
67     int ppc_cpu_new(struct cpu *cpu, struct memory *mem, struct machine *machine,
68     int cpu_id, char *cpu_type_name)
69     {
70     int any_cache = 0;
71     int i, found;
72     struct ppc_cpu_type_def cpu_type_defs[] = PPC_CPU_TYPE_DEFS;
73    
74     /* Scan the cpu_type_defs list for this cpu type: */
75     i = 0;
76     found = -1;
77     while (i >= 0 && cpu_type_defs[i].name != NULL) {
78     if (strcasecmp(cpu_type_defs[i].name, cpu_type_name) == 0) {
79     found = i;
80     break;
81     }
82     i++;
83     }
84     if (found == -1)
85     return 0;
86    
87     cpu->memory_rw = ppc_memory_rw;
88    
89     cpu->cd.ppc.cpu_type = cpu_type_defs[found];
90     cpu->name = cpu->cd.ppc.cpu_type.name;
91     cpu->byte_order = EMUL_BIG_ENDIAN;
92     cpu->cd.ppc.mode = MODE_PPC; /* TODO */
93    
94     /* Current operating mode: */
95     cpu->cd.ppc.bits = cpu->cd.ppc.cpu_type.bits;
96 dpavlin 20 cpu->cd.ppc.spr[SPR_PVR] = cpu->cd.ppc.cpu_type.pvr;
97 dpavlin 14
98 dpavlin 24 /* cpu->cd.ppc.msr = PPC_MSR_IR | PPC_MSR_DR |
99     PPC_MSR_SF | PPC_MSR_FP; */
100    
101 dpavlin 22 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 dpavlin 14 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 dpavlin 18 cpu->invalidate_translation_caches =
121     ppc32_invalidate_translation_caches;
122 dpavlin 14 cpu->invalidate_code_translation =
123     ppc32_invalidate_code_translation;
124     } else {
125     cpu->update_translation_table = ppc_update_translation_table;
126 dpavlin 18 cpu->invalidate_translation_caches =
127     ppc_invalidate_translation_caches;
128 dpavlin 14 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 dpavlin 20 cpu->cd.ppc.spr[SPR_PIR] = cpu_id;
159 dpavlin 14
160     /* Some default stack pointer value. TODO: move this? */
161     cpu->cd.ppc.gpr[1] = machine->physical_ram_in_mb * 1048576 - 4096;
162    
163 dpavlin 24 ppc_init_64bit_dummy_tables(cpu);
164    
165 dpavlin 14 /*
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 dpavlin 20 void reg_access_msr(struct cpu *cpu, uint64_t *valuep, int writeflag,
236     int check_for_interrupts)
237 dpavlin 14 {
238 dpavlin 20 uint64_t old = cpu->cd.ppc.msr;
239    
240 dpavlin 14 if (valuep == NULL) {
241     fatal("reg_access_msr(): NULL\n");
242     return;
243     }
244    
245 dpavlin 20 if (writeflag) {
246 dpavlin 14 cpu->cd.ppc.msr = *valuep;
247    
248 dpavlin 20 /* 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 dpavlin 14 /* 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 dpavlin 20
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 dpavlin 14 }
282    
283    
284     /*
285 dpavlin 20 * 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 dpavlin 24 fatal("[ PPC Exception 0x%x; pc=0x%"PRIx64" ]\n", exception_nr,
300 dpavlin 20 (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 dpavlin 22 cpu->pc += 0xfff00000ULL;
309 dpavlin 20
310     if (cpu->is_32bit)
311     ppc32_pc_to_pointers(cpu);
312     else
313     ppc_pc_to_pointers(cpu);
314     }
315    
316    
317     /*
318 dpavlin 14 * 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 dpavlin 24 debug("%08"PRIx32, (uint32_t)cpu->pc);
340 dpavlin 14 else
341 dpavlin 24 debug("%016"PRIx64, (uint64_t)cpu->pc);
342 dpavlin 14 debug(" <%s>\n", symbol != NULL? symbol : " no symbol ");
343    
344     debug("cpu%i: lr = 0x", x);
345     if (bits32)
346 dpavlin 24 debug("%08"PRIx32, (uint32_t)cpu->cd.ppc.spr[SPR_LR]);
347 dpavlin 14 else
348 dpavlin 24 debug("%016"PRIx64, (uint64_t)cpu->cd.ppc.spr[SPR_LR]);
349     debug(" cr = 0x%08"PRIx32, (uint32_t)cpu->cd.ppc.cr);
350 dpavlin 14
351     if (bits32)
352 dpavlin 22 debug(" ");
353     else
354     debug("\ncpu%i: ", x);
355     debug("ctr = 0x", x);
356     if (bits32)
357 dpavlin 24 debug("%08"PRIx32, (uint32_t)cpu->cd.ppc.spr[SPR_CTR]);
358 dpavlin 14 else
359 dpavlin 24 debug("%016"PRIx64, (uint64_t)cpu->cd.ppc.spr[SPR_CTR]);
360 dpavlin 14
361     debug(" xer = 0x", x);
362     if (bits32)
363 dpavlin 24 debug("%08"PRIx32, (uint32_t)cpu->cd.ppc.spr[SPR_XER]);
364 dpavlin 14 else
365 dpavlin 24 debug("%016"PRIx64, (uint64_t)cpu->cd.ppc.spr[SPR_XER]);
366 dpavlin 14
367 dpavlin 24 debug("\n");
368    
369 dpavlin 14 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 dpavlin 22 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 dpavlin 20 reg_access_msr(cpu, &tmp, 0, 0);
404 dpavlin 22 if (bits32)
405     debug("0x%08x ", (int)tmp);
406     else
407     debug("0x%016llx ", (long long)tmp);
408 dpavlin 20 debug("tb = 0x%08x%08x\n", (int)cpu->cd.ppc.spr[SPR_TBU],
409     (int)cpu->cd.ppc.spr[SPR_TBL]);
410 dpavlin 22 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 dpavlin 14 }
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 dpavlin 20 (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 dpavlin 14 }
477 dpavlin 20
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 dpavlin 14 }
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 dpavlin 20 m->cpus[cpunr]->cd.ppc.spr[SPR_LR] = *valuep;
542 dpavlin 14 else
543 dpavlin 20 *valuep = m->cpus[cpunr]->cd.ppc.spr[SPR_LR];
544 dpavlin 14 *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 dpavlin 20 m->cpus[cpunr]->cd.ppc.spr[SPR_DEC] = *valuep;
554 dpavlin 14 else
555 dpavlin 20 *valuep = m->cpus[cpunr]->cd.ppc.spr[SPR_DEC];
556 dpavlin 14 *match_register = 1;
557     } else if (strcasecmp(name, "hdec") == 0) {
558     if (writeflag)
559 dpavlin 20 m->cpus[cpunr]->cd.ppc.spr[SPR_HDEC] = *valuep;
560 dpavlin 14 else
561 dpavlin 20 *valuep = m->cpus[cpunr]->cd.ppc.spr[SPR_HDEC];
562 dpavlin 14 *match_register = 1;
563     } else if (strcasecmp(name, "ctr") == 0) {
564     if (writeflag)
565 dpavlin 20 m->cpus[cpunr]->cd.ppc.spr[SPR_CTR] = *valuep;
566 dpavlin 14 else
567 dpavlin 20 *valuep = m->cpus[cpunr]->cd.ppc.spr[SPR_CTR];
568 dpavlin 14 *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 dpavlin 20 m->cpus[cpunr]->cd.ppc.spr[SPR_XER] = *valuep;
581 dpavlin 14 else
582 dpavlin 20 *valuep = m->cpus[cpunr]->cd.ppc.spr[SPR_XER];
583 dpavlin 14 *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 dpavlin 24 * 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 dpavlin 20 * ppc_cpu_interrupt():
702 dpavlin 14 *
703 dpavlin 20 * 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 dpavlin 14 *
706 dpavlin 20 * TODO: don't hardcode to BeBox!
707 dpavlin 14 */
708     int ppc_cpu_interrupt(struct cpu *cpu, uint64_t irq_nr)
709     {
710 dpavlin 20 /* 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 dpavlin 14 }
723    
724    
725     /*
726     * ppc_cpu_interrupt_ack():
727     */
728     int ppc_cpu_interrupt_ack(struct cpu *cpu, uint64_t irq_nr)
729     {
730 dpavlin 20 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 dpavlin 14 }
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 dpavlin 24 int running, uint64_t dumpaddr)
756 dpavlin 14 {
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 dpavlin 22 case 0x4:
795     debug("ALTIVEC TODO");
796     /* vxor etc */
797     break;
798 dpavlin 14 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 dpavlin 20 case PPC_HI6_RLWNM:
991 dpavlin 14 case PPC_HI6_RLWIMI:
992     case PPC_HI6_RLWINM:
993     rs = (iword >> 21) & 31;
994     ra = (iword >> 16) & 31;
995 dpavlin 20 sh = (iword >> 11) & 31; /* actually rb for rlwnm */
996 dpavlin 14 mb = (iword >> 6) & 31;
997     me = (iword >> 1) & 31;
998     rc = iword & 1;
999     switch (hi6) {
1000 dpavlin 20 case PPC_HI6_RLWNM:
1001     mnem = power? "rlnm" : "rlwnm"; break;
1002 dpavlin 14 case PPC_HI6_RLWIMI:
1003     mnem = power? "rlimi" : "rlwimi"; break;
1004     case PPC_HI6_RLWINM:
1005     mnem = power? "rlinm" : "rlwinm"; break;
1006     }
1007 dpavlin 20 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 dpavlin 14 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 dpavlin 24 case PPC_30_RLDICL:
1050 dpavlin 14 case PPC_30_RLDICR:
1051 dpavlin 24 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 dpavlin 14 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 dpavlin 24 debug("%s%s\tr%i,r%i,%i,%i",
1064     mnem, rc?".":"", ra, rs, sh, me);
1065 dpavlin 14 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 dpavlin 20 case PPC_31_LHAX:
1125     case PPC_31_LHAUX:
1126 dpavlin 14 case PPC_31_LHZX:
1127     case PPC_31_LHZUX:
1128     case PPC_31_LWZX:
1129     case PPC_31_LWZUX:
1130 dpavlin 20 case PPC_31_LHBRX:
1131     case PPC_31_LWBRX:
1132     case PPC_31_LFDX:
1133     case PPC_31_LFSX:
1134 dpavlin 14 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 dpavlin 20 case PPC_31_STHBRX:
1145     case PPC_31_STWBRX:
1146     case PPC_31_STFDX:
1147     case PPC_31_STFSX:
1148 dpavlin 14 /* rs for stores, rt for loads, actually */
1149 dpavlin 20 load = 0; wlen = 0; fpreg = 0;
1150 dpavlin 14 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 dpavlin 20 case PPC_31_LHAX: wlen=2;load=1; mnem = "lhax"; break;
1159     case PPC_31_LHAUX: wlen=2;load=1; mnem = "lhaux"; break;
1160 dpavlin 14 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 dpavlin 20 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 dpavlin 14 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 dpavlin 20 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 dpavlin 14 }
1197 dpavlin 20 debug("%s\t%s%i,r%i,r%i", mnem,
1198     fpreg? "f" : "r", rs, ra, rb);
1199 dpavlin 14 if (!running)
1200     break;
1201     addr = (ra==0? 0 : cpu->cd.ppc.gpr[ra]) +
1202     cpu->cd.ppc.gpr[rb];
1203 dpavlin 20 if (cpu->cd.ppc.bits == 32)
1204     addr &= 0xffffffff;
1205 dpavlin 14 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 dpavlin 20 if (wlen > 0 && !fpreg /* && !reverse */) {
1212 dpavlin 14 /* 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 dpavlin 22 case PPC_31_WRTEEI:
1229     debug("wrteei\t%i", iword & 0x8000? 1 : 0);
1230     break;
1231 dpavlin 24 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 dpavlin 14 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 dpavlin 20 case PPC_31_MFSR:
1257     /* Move to/from segment register */
1258 dpavlin 14 rt = (iword >> 21) & 31;
1259     ra = (iword >> 16) & 15; /* actually: sr */
1260 dpavlin 20 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 dpavlin 14 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 dpavlin 20 case PPC_31_SUBFME:
1296     case PPC_31_SUBFMEO:
1297 dpavlin 14 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 dpavlin 20 mnem = power? "sf" : "subfc"; break;
1343 dpavlin 14 case PPC_31_SUBFCO:
1344 dpavlin 20 mnem = power? "sfo" : "subfco"; break;
1345 dpavlin 14 case PPC_31_SUBFE:
1346 dpavlin 20 mnem = power? "sfe" : "subfe"; break;
1347 dpavlin 14 case PPC_31_SUBFEO:
1348 dpavlin 20 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 dpavlin 14 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 dpavlin 20 /* Some very common ones: */
1371 dpavlin 14 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 dpavlin 20 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 dpavlin 14 break;
1389 dpavlin 20 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 dpavlin 14 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 dpavlin 22 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 dpavlin 14 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 dpavlin 24 case PPC_31_SLD:
1460 dpavlin 14 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 dpavlin 24 case PPC_31_EQV:
1466 dpavlin 14 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 dpavlin 24 case PPC_31_SLD: mnem = "sld"; break;
1481 dpavlin 14 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 dpavlin 24 case PPC_31_EQV: mnem = "eqv"; break;
1490 dpavlin 14 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 dpavlin 20 /* Some very common ones: */
1531 dpavlin 14 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 dpavlin 20 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 dpavlin 14 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 dpavlin 24 case PPC_31_DSSALL:
1575     debug("dssall");
1576     break;
1577 dpavlin 14 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 dpavlin 22 case PPC_31_LVX:
1600 dpavlin 24 case PPC_31_LVXL:
1601 dpavlin 22 case PPC_31_STVX:
1602     case PPC_31_STVXL:
1603 dpavlin 24 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 dpavlin 22 break;
1616 dpavlin 14 default:
1617     debug("unimplemented hi6_31, xo = 0x%x", xo);
1618     }
1619     break;
1620 dpavlin 20 case PPC_HI6_LD:
1621 dpavlin 14 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 dpavlin 20 case PPC_HI6_LFD:
1630     case PPC_HI6_LFS:
1631 dpavlin 14 case PPC_HI6_LMW:
1632 dpavlin 20 case PPC_HI6_STD:
1633 dpavlin 14 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 dpavlin 20 case PPC_HI6_STFS:
1642 dpavlin 14 /* 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 dpavlin 20 case PPC_HI6_LD: load=1; wlen = 8; mnem = "ld"; break;
1651 dpavlin 14 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 dpavlin 20 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 dpavlin 14 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 dpavlin 20 case PPC_HI6_STFD: fpreg=1; wlen=8; mnem = "stfd"; break;
1679     case PPC_HI6_STFS: fpreg=1; wlen=4; mnem = "stfs"; break;
1680 dpavlin 14 }
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 dpavlin 20 if (cpu->cd.ppc.bits == 32)
1691     addr &= 0xffffffff;
1692 dpavlin 14 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 dpavlin 20 ((uint64_t)0xff << (i*8)));
1737 dpavlin 14 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 dpavlin 20 debug("0x%llx", (long long)tdata);
1745 dpavlin 14 } 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 dpavlin 20 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 dpavlin 14 case PPC_HI6_63:
1792     xo = (iword >> 1) & 1023;
1793 dpavlin 20 /* 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 dpavlin 14 rt = (iword >> 21) & 31;
1803     ra = (iword >> 16) & 31;
1804     rb = (iword >> 11) & 31;
1805 dpavlin 20 rs = (iword >> 6) & 31; /* actually frc */
1806 dpavlin 14 rc = iword & 1;
1807 dpavlin 20 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 dpavlin 14 switch (xo) {
1837 dpavlin 20 case PPC_63_FCMPU:
1838     case PPC_63_FRSP:
1839     case PPC_63_FCTIWZ:
1840     case PPC_63_FNEG:
1841 dpavlin 14 case PPC_63_FMR:
1842 dpavlin 20 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 dpavlin 14 break;
1870 dpavlin 20 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 dpavlin 14 }
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 dpavlin 20 * 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 dpavlin 14 * 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 dpavlin 20 c |= ((cpu->cd.ppc.spr[SPR_XER] >> 31) & 1);
1976 dpavlin 14
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 dpavlin 24

  ViewVC Help
Powered by ViewVC 1.1.26