/[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 20 - (hide annotations)
Mon Oct 8 16:19:23 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 46541 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1055 2005/11/25 22:48:36 debug Exp $
20051031	Adding disassembly support for more ARM instructions (clz,
		smul* etc), and adding a hack to support "new tiny" pages
		for StrongARM.
20051101	Minor documentation updates (NetBSD 2.0.2 -> 2.1, and OpenBSD
		3.7 -> 3.8, and lots of testing).
		Changing from 1-sector PIO mode 0 transfers to 128-sector PIO
		mode 3 (in dev_wdc).
		Various minor ARM dyntrans updates (pc-relative loads from
		within the same page as the instruction are now treated as
		constant "mov").
20051102	Re-enabling instruction combinations (they were accidentally
		disabled).
		Dyntrans TLB entries are now overwritten using a round-robin
		scheme instead of randomly. This increases performance.
		Fixing a typo in file.c (thanks to Chuan-Hua Chang for
		noticing it).
		Experimenting with adding ATAPI support to dev_wdc (to make
		emulated *BSD detect cdroms as cdroms, not harddisks).
20051104	Various minor updates.
20051105	Continuing on the ATAPI emulation. Seems to work well enough
		for a NetBSD/cats installation, but not OpenBSD/cats.
		Various other updates.
20051106	Modifying the -Y command line option to allow scaleup with
		certain graphic controllers (only dev_vga so far), not just
		scaledown.
		Some minor dyntrans cleanups.
20051107	Beginning a cleanup up the PCI subsystem (removing the
		read_register hack, etc).
20051108	Continuing the cleanup; splitting up some pci devices into a
		normal autodev device and some separate pci glue code.
20051109	Continuing on the PCI bus stuff; all old pci_*.c have been
		incorporated into normal devices and/or rewritten as glue code
		only, adding a dummy Intel 82371AB PIIX4 for Malta (not really
		tested yet).
		Minor pckbc fix so that Linux doesn't complain.
		Working on the DEC 21143 NIC (ethernet mac rom stuff mostly).
		Various other minor fixes.
20051110	Some more ARM dyntrans fine-tuning (e.g. some instruction
		combinations (cmps followed by conditional branch within the
		same page) and special cases for DPIs with regform when the
		shifter isn't used).
20051111	ARM dyntrans updates: O(n)->O(1) for just-mark-as-non-
		writable in the generic pc_to_pointers function, and some other
		minor hacks.
		Merging Cobalt and evbmips (Malta) ISA interrupt handling,
		and some minor fixes to allow Linux to accept harddisk irqs.
20051112	Minor device updates (pckbc, dec21143, lpt, ...), most
		importantly fixing the ALI M1543/M5229 so that harddisk irqs
		work with Linux/CATS.
20051113	Some more generalizations of the PCI subsystem.
		Finally took the time to add a hack for SCSI CDROM TOCs; this
		enables OpenBSD to use partition 'a' (as needed by the OpenBSD
		installer), and Windows NT's installer to get a bit further.
		Also fixing dev_wdc to allow Linux to detect ATAPI CDROMs.
		Continuing on the DEC 21143.
20051114	Minor ARM dyntrans tweaks; ARM cmps+branch optimization when
		comparing with 0, and generalizing the xchg instr. comb.
		Adding disassembly of ARM mrrc/mcrr and q{,d}{add,sub}.
20051115	Continuing on various PPC things (BATs, other address trans-
		lation things, various loads/stores, BeBox emulation, etc.).
		Beginning to work on PPC interrupt/exception support.
20051116	Factoring out some code which initializes legacy ISA devices
		from those machines that use them (bus_isa).
		Continuing on PPC interrupt/exception support.
20051117	Minor Malta fixes: RTC year offset = 80, disabling a speed hack
		which caused NetBSD to detect a too fast cpu, and adding a new
		hack to make Linux detect a faster cpu.
		Continuing on the Artesyn PM/PPC emulation mode.
		Adding an Algor emulation skeleton (P4032 and P5064);
		implementing some of the basics.
		Continuing on PPC emulation in general; usage of unimplemented
		SPRs is now easier to track, continuing on memory/exception
		related issues, etc.
20051118	More work on PPC emulation (tgpr0..3, exception handling,
		memory stuff, syscalls, etc.).
20051119	Changing the ARM dyntrans code to mostly use cpu->pc, and not
		necessarily use arm reg 15. Seems to work.
		Various PPC updates; continuing on the PReP emulation mode.
20051120	Adding a workaround/hack to dev_mc146818 to allow NetBSD/prep
		to detect the clock.
20051121	More cleanup of the PCI bus (memory and I/O bases, etc).
		Continuing on various PPC things (decrementer and timebase,
		WDCs on obio (on PReP) use irq 13, not 14/15).
20051122	Continuing on the CPC700 controller (interrupts etc) for PMPPC,
		and on PPC stuff in general.
		Finally! After some bug fixes to the virtual to physical addr
		translation, NetBSD/{prep,pmppc} 2.1 reach userland and are
		stable enough to be interacted with.
		More PCI updates; reverse-endian device access for PowerPC etc.
20051123	Generalizing the IEEE floating point subsystem (moving it out
		from src/cpus/cpu_mips_coproc.c into a new src/float_emul.c).
		Input via slave xterms was sometimes not really working; fixing
		this for ns16550, and a warning message is now displayed if
		multiple non-xterm consoles are active.
		Adding some PPC floating point support, etc.
		Various interrupt related updates (dev_wdc, _ns16550, _8259,
		and the isa32 common code in machine.c).
		NetBSD/prep can now be installed! :-) (Well, with some manual
		commands necessary before running sysinst.) Updating the
		documentation and various other things to reflect this.
20051124	Various minor documentation updates.
		Continuing the work on the DEC 21143 NIC.
20051125	LOTS of work on the 21143. Both OpenBSD and NetBSD work fine
		with it now, except that OpenBSD sometimes gives a time-out
		warning.
		Minor documentation updates.

==============  RELEASE 0.3.7  ==============


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

  ViewVC Help
Powered by ViewVC 1.1.26