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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 42 - (show annotations)
Mon Oct 8 16:22:32 2007 UTC (16 years, 5 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 /*
2 * Copyright (C) 2005-2007 Anders Gavare. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * 3. The name of the author may not be used to endorse or promote products
13 * derived from this software without specific prior written permission.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 *
27 *
28 * $Id: cpu_ppc.c,v 1.70 2007/06/15 00:41:21 debug Exp $
29 *
30 * PowerPC/POWER CPU emulation.
31 */
32
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <ctype.h>
37
38 #include "cpu.h"
39 #include "devices.h"
40 #include "interrupt.h"
41 #include "machine.h"
42 #include "memory.h"
43 #include "misc.h"
44 #include "of.h"
45 #include "opcodes_ppc.h"
46 #include "ppc_bat.h"
47 #include "ppc_pte.h"
48 #include "ppc_spr.h"
49 #include "ppc_spr_strings.h"
50 #include "settings.h"
51 #include "symbol.h"
52 #include "timer.h"
53 #include "useremul.h"
54
55
56 #define DYNTRANS_DUALMODE_32
57 #include "tmp_ppc_head.c"
58
59
60 extern int native_code_translation_enabled;
61
62 void ppc_pc_to_pointers(struct cpu *);
63 void ppc32_pc_to_pointers(struct cpu *);
64
65 void ppc_irq_interrupt_assert(struct interrupt *interrupt);
66 void ppc_irq_interrupt_deassert(struct interrupt *interrupt);
67
68
69 /*
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 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
104 /* Current operating mode: */
105 cpu->cd.ppc.bits = cpu->cd.ppc.cpu_type.bits;
106 cpu->cd.ppc.spr[SPR_PVR] = cpu->cd.ppc.cpu_type.pvr;
107
108 /* cpu->cd.ppc.msr = PPC_MSR_IR | PPC_MSR_DR |
109 PPC_MSR_SF | PPC_MSR_FP; */
110
111 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 cpu->is_32bit = (cpu->cd.ppc.bits == 32)? 1 : 0;
127
128 if (cpu->is_32bit) {
129 cpu->run_instr = ppc32_run_instr;
130 cpu->update_translation_table = ppc32_update_translation_table;
131 cpu->invalidate_translation_caches =
132 ppc32_invalidate_translation_caches;
133 cpu->invalidate_code_translation =
134 ppc32_invalidate_code_translation;
135 } else {
136 cpu->run_instr = ppc_run_instr;
137 cpu->update_translation_table = ppc_update_translation_table;
138 cpu->invalidate_translation_caches =
139 ppc_invalidate_translation_caches;
140 cpu->invalidate_code_translation =
141 ppc_invalidate_code_translation;
142 }
143
144 cpu->translate_v2p = ppc_translate_v2p;
145
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 cpu->cd.ppc.spr[SPR_PIR] = cpu_id;
171
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 /* 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 /* 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 if (native_code_translation_enabled)
242 cpu->sampling_timer = timer_add(CPU_SAMPLE_TIMER_HZ,
243 ppc_timer_sample_tick, cpu);
244
245 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 void reg_access_msr(struct cpu *cpu, uint64_t *valuep, int writeflag,
310 int check_for_interrupts)
311 {
312 uint64_t old = cpu->cd.ppc.msr;
313
314 if (valuep == NULL) {
315 fatal("reg_access_msr(): NULL\n");
316 return;
317 }
318
319 if (writeflag) {
320 cpu->cd.ppc.msr = *valuep;
321
322 /* 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 /* 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
348 if (check_for_interrupts && cpu->cd.ppc.msr & PPC_MSR_EE) {
349 if (cpu->cd.ppc.dec_intr_pending &&
350 !(cpu->cd.ppc.cpu_type.flags & PPC_NO_DEC)) {
351 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 }
357
358
359 /*
360 * 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 fatal("[ PPC Exception 0x%x; pc=0x%"PRIx64" ]\n", exception_nr,
375 (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 cpu->pc += 0xfff00000ULL;
384
385 if (cpu->is_32bit)
386 ppc32_pc_to_pointers(cpu);
387 else
388 ppc_pc_to_pointers(cpu);
389 }
390
391
392 /*
393 * 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 debug("%08"PRIx32, (uint32_t)cpu->pc);
415 else
416 debug("%016"PRIx64, (uint64_t)cpu->pc);
417 debug(" <%s>\n", symbol != NULL? symbol : " no symbol ");
418
419 debug("cpu%i: lr = 0x", x);
420 if (bits32)
421 debug("%08"PRIx32, (uint32_t)cpu->cd.ppc.spr[SPR_LR]);
422 else
423 debug("%016"PRIx64, (uint64_t)cpu->cd.ppc.spr[SPR_LR]);
424 debug(" cr = 0x%08"PRIx32, (uint32_t)cpu->cd.ppc.cr);
425
426 if (bits32)
427 debug(" ");
428 else
429 debug("\ncpu%i: ", x);
430 debug("ctr = 0x", x);
431 if (bits32)
432 debug("%08"PRIx32, (uint32_t)cpu->cd.ppc.spr[SPR_CTR]);
433 else
434 debug("%016"PRIx64, (uint64_t)cpu->cd.ppc.spr[SPR_CTR]);
435
436 debug(" xer = 0x", x);
437 if (bits32)
438 debug("%08"PRIx32, (uint32_t)cpu->cd.ppc.spr[SPR_XER]);
439 else
440 debug("%016"PRIx64, (uint64_t)cpu->cd.ppc.spr[SPR_XER]);
441
442 debug("\n");
443
444 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 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 reg_access_msr(cpu, &tmp, 0, 0);
479 if (bits32)
480 debug("0x%08x ", (int)tmp);
481 else
482 debug("0x%016llx ", (long long)tmp);
483 debug("tb = 0x%08x%08x\n", (int)cpu->cd.ppc.spr[SPR_TBU],
484 (int)cpu->cd.ppc.spr[SPR_TBL]);
485 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 }
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 (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 }
552
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 debug(" sr%-2i = 0x%08x", i, (int)s);
558 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 }
587
588
589 /*
590 * 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 * ppc_irq_interrupt_assert():
601 */
602 void ppc_irq_interrupt_assert(struct interrupt *interrupt)
603 {
604 struct cpu *cpu = (struct cpu *) interrupt->extra;
605 cpu->cd.ppc.irq_asserted = 1;
606 }
607
608
609 /*
610 * ppc_irq_interrupt_deassert():
611 */
612 void ppc_irq_interrupt_deassert(struct interrupt *interrupt)
613 {
614 struct cpu *cpu = (struct cpu *) interrupt->extra;
615 cpu->cd.ppc.irq_asserted = 0;
616 }
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 int running, uint64_t dumpaddr)
633 {
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 case 0x4:
672 debug("ALTIVEC TODO");
673 /* vxor etc */
674 break;
675 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 case PPC_HI6_RLWNM:
868 case PPC_HI6_RLWIMI:
869 case PPC_HI6_RLWINM:
870 rs = (iword >> 21) & 31;
871 ra = (iword >> 16) & 31;
872 sh = (iword >> 11) & 31; /* actually rb for rlwnm */
873 mb = (iword >> 6) & 31;
874 me = (iword >> 1) & 31;
875 rc = iword & 1;
876 switch (hi6) {
877 case PPC_HI6_RLWNM:
878 mnem = power? "rlnm" : "rlwnm"; break;
879 case PPC_HI6_RLWIMI:
880 mnem = power? "rlimi" : "rlwimi"; break;
881 case PPC_HI6_RLWINM:
882 mnem = power? "rlinm" : "rlwinm"; break;
883 }
884 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 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 case PPC_30_RLDICL:
927 case PPC_30_RLDICR:
928 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 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 debug("%s%s\tr%i,r%i,%i,%i",
941 mnem, rc?".":"", ra, rs, sh, me);
942 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 case PPC_31_LHAX:
1002 case PPC_31_LHAUX:
1003 case PPC_31_LHZX:
1004 case PPC_31_LHZUX:
1005 case PPC_31_LWZX:
1006 case PPC_31_LWZUX:
1007 case PPC_31_LHBRX:
1008 case PPC_31_LWBRX:
1009 case PPC_31_LFDX:
1010 case PPC_31_LFSX:
1011 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 case PPC_31_STHBRX:
1022 case PPC_31_STWBRX:
1023 case PPC_31_STFDX:
1024 case PPC_31_STFSX:
1025 /* rs for stores, rt for loads, actually */
1026 load = 0; wlen = 0; fpreg = 0;
1027 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 case PPC_31_LHAX: wlen=2;load=1; mnem = "lhax"; break;
1036 case PPC_31_LHAUX: wlen=2;load=1; mnem = "lhaux"; break;
1037 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 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 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 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 }
1074 debug("%s\t%s%i,r%i,r%i", mnem,
1075 fpreg? "f" : "r", rs, ra, rb);
1076 if (!running)
1077 break;
1078 addr = (ra==0? 0 : cpu->cd.ppc.gpr[ra]) +
1079 cpu->cd.ppc.gpr[rb];
1080 if (cpu->cd.ppc.bits == 32)
1081 addr &= 0xffffffff;
1082 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 if (wlen > 0 && !fpreg /* && !reverse */) {
1089 /* 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 case PPC_31_WRTEEI:
1106 debug("wrteei\t%i", iword & 0x8000? 1 : 0);
1107 break;
1108 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 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 case PPC_31_MFSR:
1134 /* Move to/from segment register */
1135 rt = (iword >> 21) & 31;
1136 ra = (iword >> 16) & 15; /* actually: sr */
1137 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 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 case PPC_31_SUBFME:
1173 case PPC_31_SUBFMEO:
1174 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 mnem = power? "sf" : "subfc"; break;
1220 case PPC_31_SUBFCO:
1221 mnem = power? "sfo" : "subfco"; break;
1222 case PPC_31_SUBFE:
1223 mnem = power? "sfe" : "subfe"; break;
1224 case PPC_31_SUBFEO:
1225 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 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 /* Some very common ones: */
1248 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 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 break;
1266 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 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 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 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 case PPC_31_SLD:
1337 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 case PPC_31_EQV:
1343 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 case PPC_31_SLD: mnem = "sld"; break;
1358 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 case PPC_31_EQV: mnem = "eqv"; break;
1367 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 /* Some very common ones: */
1408 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 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 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 case PPC_31_DSSALL:
1452 debug("dssall");
1453 break;
1454 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 case PPC_31_LVX:
1477 case PPC_31_LVXL:
1478 case PPC_31_STVX:
1479 case PPC_31_STVXL:
1480 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 break;
1493 default:
1494 debug("unimplemented hi6_31, xo = 0x%x", xo);
1495 }
1496 break;
1497 case PPC_HI6_LD:
1498 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 case PPC_HI6_LFD:
1507 case PPC_HI6_LFS:
1508 case PPC_HI6_LMW:
1509 case PPC_HI6_STD:
1510 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 case PPC_HI6_STFS:
1519 /* 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 case PPC_HI6_LD: load=1; wlen = 8; mnem = "ld"; break;
1528 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 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 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 case PPC_HI6_STFD: fpreg=1; wlen=8; mnem = "stfd"; break;
1556 case PPC_HI6_STFS: fpreg=1; wlen=4; mnem = "stfs"; break;
1557 }
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 if (cpu->cd.ppc.bits == 32)
1568 addr &= 0xffffffff;
1569 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 ((uint64_t)0xff << (i*8)));
1614 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 debug("0x%llx", (long long)tdata);
1622 } 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 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 case PPC_HI6_63:
1669 xo = (iword >> 1) & 1023;
1670 /* 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 rt = (iword >> 21) & 31;
1680 ra = (iword >> 16) & 31;
1681 rb = (iword >> 11) & 31;
1682 rs = (iword >> 6) & 31; /* actually frc */
1683 rc = iword & 1;
1684 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 switch (xo) {
1714 case PPC_63_FCMPU:
1715 case PPC_63_FRSP:
1716 case PPC_63_FCTIWZ:
1717 case PPC_63_FNEG:
1718 case PPC_63_FMR:
1719 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 break;
1747 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 }
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 * 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 * 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 c |= ((cpu->cd.ppc.spr[SPR_XER] >> 31) & 1);
1853
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

  ViewVC Help
Powered by ViewVC 1.1.26