/[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 42 - (hide annotations)
Mon Oct 8 16:22:32 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 49727 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1613 2007/06/15 20:11:26 debug Exp $
20070501	Continuing a little on m88k disassembly (control registers,
		more instructions).
		Adding a dummy mvme88k machine mode.
20070502	Re-adding MIPS load/store alignment exceptions.
20070503	Implementing more of the M88K disassembly code.
20070504	Adding disassembly of some more M88K load/store instructions.
		Implementing some relatively simple M88K instructions (br.n,
		xor[.u] imm, and[.u] imm).
20070505	Implementing M88K three-register and, or, xor, and jmp[.n],
		bsr[.n] including function call trace stuff.
		Applying a patch from Bruce M. Simpson which implements the
		SYSCON_BOARD_CPU_CLOCK_FREQ_ID object of the syscon call in
		the yamon PROM emulation.
20070506	Implementing M88K bb0[.n] and bb1[.n], and skeletons for
		ldcr and stcr (although no control regs are implemented yet).
20070509	Found and fixed the bug which caused Linux for QEMU_MIPS to
		stop working in 0.4.5.1: It was a faulty change to the MIPS
		'sc' and 'scd' instructions I made while going through gcc -W
		warnings on 20070428.
20070510	Updating the Linux/QEMU_MIPS section in guestoses.html to
		use mips-test-0.2.tar.gz instead of 0.1.
		A big thank you to Miod Vallat for sending me M88K manuals.
		Implementing more M88K instructions (addu, subu, div[u], mulu,
		ext[u], clr, set, cmp).
20070511	Fixing bugs in the M88K "and" and "and.u" instructions (found
		by comparing against the manual).
		Implementing more M88K instructions (mask[.u], mak, bcnd (auto-
		generated)) and some more control register details.
		Cleanup: Removing the experimental AVR emulation mode and
		corresponding devices; AVR emulation wasn't really meaningful.
		Implementing autogeneration of most M88K loads/stores. The
		rectangle drawing demo (with -O0) for M88K runs :-)
		Beginning on M88K exception handling.
		More M88K instructions: tb0, tb1, rte, sub, jsr[.n].
		Adding some skeleton MVME PROM ("BUG") emulation.
20070512	Fixing a bug in the M88K cmp instruction.
		Adding the M88K lda (scaled register) instruction.
		Fixing bugs in 64-bit (32-bit pairs) M88K loads/stores.
		Removing the unused tick_hz stuff from the machine struct.
		Implementing the M88K xmem instruction. OpenBSD/mvme88k gets
		far enough to display the Copyright banner :-)
		Implementing subu.co (guess), addu.co, addu.ci, ff0, and ff1.
		Adding a dev_mvme187, for MVME187-specific devices/registers.
		OpenBSD/mvme88k prints more boot messages. :)
20070515	Continuing on MVME187 emulation (adding more devices, beginning
		on the CMMUs, etc).
		Adding the M88K and.c, xor.c, and or.c instructions, and making
		sure that mul, div, etc cause exceptions if executed when SFD1
		is disabled.
20070517	Continuing on M88K and MVME187 emulation in general; moving
		the CMMU registers to the CPU struct, separating dev_pcc2 from
		dev_mvme187, and beginning on memory_m88k.c (BATC and PATC).
		Fixing a bug in 64-bit (32-bit pairs) M88K fast stores.
		Implementing the clock part of dev_mk48txx.
		Implementing the M88K fstcr and xcr instructions.
		Implementing m88k_cpu_tlbdump().
		Beginning on the implementation of a separate address space
		for M88K .usr loads/stores.
20070520	Removing the non-working (skeleton) Sandpoint, SonyNEWS, SHARK
		Dnard, and Zaurus machine modes.
		Experimenting with dyntrans to_be_translated read-ahead. It
		seems to give a very small performance increase for MIPS
		emulation, but a large performance degradation for SuperH. Hm.
20070522	Disabling correct SuperH ITLB emulation; it does not seem to be
		necessary in order to let SH4 guest OSes run, and it slows down
		userspace code.
		Implementing "samepage" branches for SuperH emulation, and some
		other minor speed hacks.
20070525	Continuing on M88K memory-related stuff: exceptions, memory
		transaction register contents, etc.
		Implementing the M88K subu.ci instruction.
		Removing the non-working (skeleton) Iyonix machine mode.
		OpenBSD/mvme88k reaches userland :-), starts executing
		/sbin/init's instructions, and issues a few syscalls, before
		crashing.
20070526	Fixing bugs in dev_mk48txx, so that OpenBSD/mvme88k detects
		the correct time-of-day.
		Implementing a generic IRQ controller for the test machines
		(dev_irqc), similar to a proposed patch from Petr Stepan.
		Experimenting some more with translation read-ahead.
		Adding an "expect" script for automated OpenBSD/landisk
		install regression/performance tests.
20070527	Adding a dummy mmEye (SH3) machine mode skeleton.
		FINALLY found the strange M88K bug I have been hunting: I had
		not emulated the SNIP value for exceptions occurring in
		branch delay slots correctly.
		Implementing correct exceptions for 64-bit M88K loads/stores.
		Address to symbol lookups are now disabled when M88K is
		running in usermode (because usermode addresses don't have
		anything to do with supervisor addresses).
20070531	Removing the mmEye machine mode skeleton.
20070604	Some minor code cleanup.
20070605	Moving src/useremul.c into a subdir (src/useremul/), and
		cleaning up some more legacy constructs.
		Adding -Wstrict-aliasing and -fstrict-aliasing detection to
		the configure script.
20070606	Adding a check for broken GCC on Solaris to the configure
		script. (GCC 3.4.3 on Solaris cannot handle static variables
		which are initialized to 0 or NULL. :-/)
		Removing the old (non-working) ARC emulation modes: NEC RD94,
		R94, R96, and R98, and the last traces of Olivetti M700 and
		Deskstation Tyne.
		Removing the non-working skeleton WDSC device (dev_wdsc).
20070607	Thinking about how to use the host's cc + ld at runtime to
		generate native code. (See experiments/native_cc_ld_test.i
		for an example.)
20070608	Adding a program counter sampling timer, which could be useful
		for native code generation experiments.
		The KN02_CSR_NRMMOD bit in the DECstation 5000/200 (KN02) CSR
		should always be set, to allow a 5000/200 PROM to boot.
20070609	Moving out breakpoint details from the machine struct into
		a helper struct, and removing the limit on max nr of
		breakpoints.
20070610	Moving out tick functions into a helper struct as well (which
		also gets rid of the max limit).
20070612	FINALLY figured out why Debian/DECstation stopped working when
		translation read-ahead was enabled: in src/memory_rw.c, the
		call to invalidate_code_translation was made also if the
		memory access was an instruction load (if the page was mapped
		as writable); it shouldn't be called in that case.
20070613	Implementing some more MIPS32/64 revision 2 instructions: di,
		ei, ext, dext, dextm, dextu, and ins.
20070614	Implementing an instruction combination for the NetBSD/arm
		idle loop (making the host not use any cpu if NetBSD/arm
		inside the emulator is not using any cpu).
		Increasing the nr of ARM VPH entries from 128 to 384.
20070615	Removing the ENABLE_arch stuff from the configure script, so
		that all included architectures are included in both release
		and development builds.
		Moving memory related helper functions from misc.c to memory.c.
		Adding preliminary instructions for netbooting NetBSD/pmppc to
		guestoses.html; it doesn't work yet, there are weird timeouts.
		Beginning a total rewrite of the userland emulation modes
		(removing all emulation modes, beginning from scratch with
		NetBSD/MIPS and FreeBSD/Alpha only).
20070616	After fixing a bug in the DEC21143 NIC (the TDSTAT_OWN bit was
		only cleared for the last segment when transmitting, not all
		segments), NetBSD/pmppc boots with root-on-nfs without the
		timeouts. Updating guestoses.html.
		Removing the skeleton PSP (Playstation Portable) mode.
		Moving X11-related stuff in the machine struct into a helper
		struct.
		Cleanup of out-of-memory checks, to use a new CHECK_ALLOCATION
		macro (which prints a meaningful error message).
		Adding a COMMENT to each machine and device (for automagic
		.index comment generation).
		Doing regression testing for the next release.

==============  RELEASE 0.4.6  ==============


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

  ViewVC Help
Powered by ViewVC 1.1.26