/[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 14 - (hide annotations)
Mon Oct 8 16:18:51 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 37988 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.982 2005/10/07 22:45:32 debug Exp $
20050816	Some success in decoding the way the SGI O2 PROM draws graphics
		during bootup; lines/rectangles and bitmaps work, enough to
		show the bootlogo etc. :-)
		Adding more PPC instructions, and (dummy) BAT registers.
20050817	Updating the pckbc to support scancode type 3 keyboards
		(required in order to interact with the SGI O2 PROM).
		Adding more PPC instructions.
20050818	Adding more ARM instructions; general register forms.
		Importing armreg.h from NetBSD (ARM cpu ids). Adding a (dummy)
		CATS machine mode (using SA110 as the default CPU).
		Continuing on general dyntrans related stuff.
20050819	Register forms for ARM load/stores. Gaah! The Compaq C Compiler
		bug is triggered for ARM loads as well, not just PPC :-(
		Adding full support for ARM PC-relative load/stores, and load/
		stores where the PC register is the destination register.
		Adding support for ARM a.out binaries.
20050820	Continuing to add more ARM instructions, and correcting some
		bugs. Continuing on CATS emulation.
		More work on the PPC stuff.
20050821	Minor PPC and ARM updates. Adding more machine types.
20050822	All ARM "data processing instructions" are now generated
		automatically.
20050824	Beginning the work on the ARM system control coprocessor.
		Adding support for ARM halfword load/stores, and signed loads.
20050825	Fixing an important bug related to the ARM condition codes.
		OpenBSD/zaurus and NetBSD/netwinder now print some boot
		messages. :)
		Adding a dummy SH (Hitachi SuperH) cpu family.
		Beginning to add some ARM virtual address translation.
		MIPS bugfixes: unaligned PC now cause an ADEL exception (at
		least for non-bintrans execution), and ADEL/ADES (not
		TLBL/TLBS) are used if userland tries to access kernel space.
		(Thanks to Joshua Wise for making me aware of these bugs.)
20050827	More work on the ARM emulation, and various other updates.
20050828	More ARM updates.
		Finally taking the time to work on translation invalidation
		(i.e. invalidating translated code mappings when memory is
		written to). Hopefully this doesn't break anything.
20050829	Moving CPU related files from src/ to a new subdir, src/cpus/.
		Moving PROM emulation stuff from src/ to src/promemul/.
		Better debug instruction trace for ARM loads and stores.
20050830	Various ARM updates (correcting CMP flag calculation, etc).
20050831	PPC instruction updates. (Flag fixes, etc.)
20050901	Various minor PPC and ARM instruction emulation updates.
		Minor OpenFirmware emulation updates.
20050903	Adding support for adding arbitrary ARM coprocessors (with
		the i80321 I/O coprocessor as a first test).
		Various other ARM and PPC updates.
20050904	Adding some SHcompact disassembly routines.
20050907	(Re)adding a dummy HPPA CPU module, and a dummy i960 module.
20050908	Began hacking on some Apple Partition Table support.
20050909	Adding support for loading Mach-O (Darwin PPC) binaries.
20050910	Fixing an ARM bug (Carry flag was incorrectly updated for some
		data processing instructions); OpenBSD/cats and NetBSD/
		netwinder get quite a bit further now.
		Applying a patch to dev_wdc, and a one-liner to dev_pcic, to
		make them work better when emulating new versions of OpenBSD.
		(Thanks to Alexander Yurchenko for the patches.)
		Also doing some other minor updates to dev_wdc. (Some cleanup,
		and finally converting to devinit, etc.)
20050912	IRIX doesn't have u_int64_t by default (noticed by Andreas
		<avr@gnulinux.nl>); configure updated to reflect this.
		Working on ARM register bank switching, CPSR vs SPSR issues,
		and beginning the work on interrupt/exception support.
20050913	Various minor ARM updates (speeding up load/store multiple,
		and fixing a ROR bug in R(); NetBSD/cats now boots as far as
		OpenBSD/cats).
20050917	Adding a dummy Atmel AVR (8-bit) cpu family skeleton.
20050918	Various minor updates.
20050919	Symbols are now loaded from Mach-O executables.
		Continuing the work on adding ARM exception support.
20050920	More work on ARM stuff: OpenBSD/cats and NetBSD/cats reach
		userland! :-)
20050921	Some more progress on ARM interrupt specifics.
20050923	Fixing linesize for VR4121 (patch by Yurchenko). Also fixing
		linesizes/cachesizes for some other VR4xxx.
		Adding a dummy Acer Labs M1543 PCI-ISA bridge (for CATS) and a
		dummy Symphony Labs 83C553 bridge (for Netwinder), usable by 
		dev_footbridge.
20050924	Some PPC progress.
20050925	More PPC progress.
20050926	PPC progress (fixing some bugs etc); Darwin's kernel gets
		slightly further than before.
20050928	Various updates: footbridge/ISA/pciide stuff, and finally
		fixing the VGA text scroll-by-changing-the-base-offset bug.
20050930	Adding a dummy S3 ViRGE pci card for CATS emulation, which
		both NetBSD and OpenBSD detects as VGA.
		Continuing on Footbridge (timers, ISA interrupt stuff).
20051001	Continuing... there are still bugs, probably interrupt-
		related.
20051002	More work on the Footbridge (interrupt stuff).
20051003	Various minor updates. (Trying to find the bug(s).)
20051004	Continuing on the ARM stuff.
20051005	More ARM-related fixes.
20051007	FINALLY! Found and fixed 2 ARM bugs: 1 memory related, and the
		other was because of an error in the ARM manual (load multiple
		with the S-bit set should _NOT_ load usermode registers, as the
		manual says, but it should load saved registers, which may or
		may not happen to be usermode registers).
		NetBSD/cats and OpenBSD/cats seem to install fine now :-)
		except for a minor bug at the end of the OpenBSD/cats install.
		Updating the documentation, preparing for the next release.
20051008	Continuing with release testing and cleanup.

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     * $Id: cpu_ppc.c,v 1.12 2005/09/24 23:44:18 debug Exp $
29     *
30     * PowerPC/POWER CPU emulation.
31     */
32    
33     #include <stdio.h>
34     #include <stdlib.h>
35     #include <string.h>
36     #include <ctype.h>
37    
38     #include "cpu.h"
39     #include "devices.h"
40     #include "machine.h"
41     #include "memory.h"
42     #include "misc.h"
43     #include "opcodes_ppc.h"
44     #include "symbol.h"
45    
46     #define DYNTRANS_DUALMODE_32
47     #include "tmp_ppc_head.c"
48    
49    
50     /*
51     * ppc_cpu_new():
52     *
53     * Create a new PPC cpu object.
54     *
55     * Returns 1 on success, 0 if there was no matching PPC processor with
56     * this cpu_type_name.
57     */
58     int ppc_cpu_new(struct cpu *cpu, struct memory *mem, struct machine *machine,
59     int cpu_id, char *cpu_type_name)
60     {
61     int any_cache = 0;
62     int i, found;
63     struct ppc_cpu_type_def cpu_type_defs[] = PPC_CPU_TYPE_DEFS;
64    
65     /* Scan the cpu_type_defs list for this cpu type: */
66     i = 0;
67     found = -1;
68     while (i >= 0 && cpu_type_defs[i].name != NULL) {
69     if (strcasecmp(cpu_type_defs[i].name, cpu_type_name) == 0) {
70     found = i;
71     break;
72     }
73     i++;
74     }
75     if (found == -1)
76     return 0;
77    
78     cpu->memory_rw = ppc_memory_rw;
79    
80     cpu->cd.ppc.cpu_type = cpu_type_defs[found];
81     cpu->name = cpu->cd.ppc.cpu_type.name;
82     cpu->byte_order = EMUL_BIG_ENDIAN;
83     cpu->cd.ppc.mode = MODE_PPC; /* TODO */
84    
85     /* Current operating mode: */
86     cpu->cd.ppc.bits = cpu->cd.ppc.cpu_type.bits;
87     cpu->cd.ppc.pvr = cpu->cd.ppc.cpu_type.pvr;
88    
89     cpu->is_32bit = (cpu->cd.ppc.bits == 32)? 1 : 0;
90    
91     if (cpu->is_32bit) {
92     cpu->update_translation_table = ppc32_update_translation_table;
93     cpu->invalidate_translation_caches_paddr =
94     ppc32_invalidate_translation_caches_paddr;
95     cpu->invalidate_code_translation =
96     ppc32_invalidate_code_translation;
97     } else {
98     cpu->update_translation_table = ppc_update_translation_table;
99     cpu->invalidate_translation_caches_paddr =
100     ppc_invalidate_translation_caches_paddr;
101     cpu->invalidate_code_translation =
102     ppc_invalidate_code_translation;
103     }
104    
105     cpu->translate_address = ppc_translate_address;
106    
107     /* Only show name and caches etc for CPU nr 0 (in SMP machines): */
108     if (cpu_id == 0) {
109     debug("%s", cpu->cd.ppc.cpu_type.name);
110    
111     if (cpu->cd.ppc.cpu_type.icache_shift != 0)
112     any_cache = 1;
113     if (cpu->cd.ppc.cpu_type.dcache_shift != 0)
114     any_cache = 1;
115     if (cpu->cd.ppc.cpu_type.l2cache_shift != 0)
116     any_cache = 1;
117    
118     if (any_cache) {
119     debug(" (I+D = %i+%i KB",
120     (int)(1 << (cpu->cd.ppc.cpu_type.icache_shift-10)),
121     (int)(1 << (cpu->cd.ppc.cpu_type.dcache_shift-10)));
122     if (cpu->cd.ppc.cpu_type.l2cache_shift != 0) {
123     debug(", L2 = %i KB",
124     (int)(1 << (cpu->cd.ppc.cpu_type.
125     l2cache_shift-10)));
126     }
127     debug(")");
128     }
129     }
130    
131     cpu->cd.ppc.pir = cpu_id;
132    
133     /* Some default stack pointer value. TODO: move this? */
134     cpu->cd.ppc.gpr[1] = machine->physical_ram_in_mb * 1048576 - 4096;
135    
136     /*
137     * NOTE/TODO: Ugly hack for OpenFirmware emulation:
138     */
139     if (cpu->machine->prom_emulation)
140     cpu->cd.ppc.of_emul_addr = 0xfff00000;
141    
142     return 1;
143     }
144    
145    
146     /*
147     * ppc_cpu_list_available_types():
148     *
149     * Print a list of available PPC CPU types.
150     */
151     void ppc_cpu_list_available_types(void)
152     {
153     int i, j;
154     struct ppc_cpu_type_def tdefs[] = PPC_CPU_TYPE_DEFS;
155    
156     i = 0;
157     while (tdefs[i].name != NULL) {
158     debug("%s", tdefs[i].name);
159     for (j=10 - strlen(tdefs[i].name); j>0; j--)
160     debug(" ");
161     i++;
162     if ((i % 6) == 0 || tdefs[i].name == NULL)
163     debug("\n");
164     }
165     }
166    
167    
168     /*
169     * ppc_cpu_dumpinfo():
170     */
171     void ppc_cpu_dumpinfo(struct cpu *cpu)
172     {
173     struct ppc_cpu_type_def *ct = &cpu->cd.ppc.cpu_type;
174    
175     debug(" (%i-bit ", cpu->cd.ppc.bits);
176    
177     switch (cpu->cd.ppc.mode) {
178     case MODE_PPC:
179     debug("PPC");
180     break;
181     case MODE_POWER:
182     debug("POWER");
183     break;
184     default:
185     debug("_INTERNAL ERROR_");
186     }
187    
188     debug(", I+D = %i+%i KB",
189     (1 << ct->icache_shift) / 1024,
190     (1 << ct->dcache_shift) / 1024);
191    
192     if (ct->l2cache_shift) {
193     int kb = (1 << ct->l2cache_shift) / 1024;
194     debug(", L2 = %i %cB",
195     kb >= 1024? kb / 1024 : kb,
196     kb >= 1024? 'M' : 'K');
197     }
198    
199     debug(")\n");
200     }
201    
202    
203     /*
204     * reg_access_msr():
205     */
206     void reg_access_msr(struct cpu *cpu, uint64_t *valuep, int writeflag)
207     {
208     if (valuep == NULL) {
209     fatal("reg_access_msr(): NULL\n");
210     return;
211     }
212    
213     if (writeflag)
214     cpu->cd.ppc.msr = *valuep;
215    
216     /* TODO: Is the little-endian bit writable? */
217    
218     cpu->cd.ppc.msr &= ~PPC_MSR_LE;
219     if (cpu->byte_order != EMUL_BIG_ENDIAN)
220     cpu->cd.ppc.msr |= PPC_MSR_LE;
221    
222     if (!writeflag)
223     *valuep = cpu->cd.ppc.msr;
224     }
225    
226    
227     /*
228     * ppc_cpu_register_dump():
229     *
230     * Dump cpu registers in a relatively readable format.
231     *
232     * gprs: set to non-zero to dump GPRs and some special-purpose registers.
233     * coprocs: if bit i is set, then we should dump registers from coproc i.
234     */
235     void ppc_cpu_register_dump(struct cpu *cpu, int gprs, int coprocs)
236     {
237     char *symbol;
238     uint64_t offset, tmp;
239     int i, x = cpu->cpu_id;
240     int bits32 = cpu->cd.ppc.bits == 32;
241    
242     if (gprs) {
243     /* Special registers (pc, ...) first: */
244     symbol = get_symbol_name(&cpu->machine->symbol_context,
245     cpu->pc, &offset);
246    
247     debug("cpu%i: pc = 0x", x);
248     if (bits32)
249     debug("%08x", (int)cpu->pc);
250     else
251     debug("%016llx", (long long)cpu->pc);
252     debug(" <%s>\n", symbol != NULL? symbol : " no symbol ");
253    
254     debug("cpu%i: lr = 0x", x);
255     if (bits32)
256     debug("%08x", (int)cpu->cd.ppc.lr);
257     else
258     debug("%016llx", (long long)cpu->cd.ppc.lr);
259     debug(" cr = 0x%08x\n", (int)cpu->cd.ppc.cr);
260    
261     debug("cpu%i: ctr = 0x", x);
262     if (bits32)
263     debug("%08x", (int)cpu->cd.ppc.ctr);
264     else
265     debug("%016llx", (long long)cpu->cd.ppc.ctr);
266    
267     debug(" xer = 0x", x);
268     if (bits32)
269     debug("%08x\n", (int)cpu->cd.ppc.xer);
270     else
271     debug("%016llx\n", (long long)cpu->cd.ppc.xer);
272    
273     if (bits32) {
274     /* 32-bit: */
275     for (i=0; i<PPC_NGPRS; i++) {
276     if ((i % 4) == 0)
277     debug("cpu%i:", x);
278     debug(" r%02i = 0x%08x ", i,
279     (int)cpu->cd.ppc.gpr[i]);
280     if ((i % 4) == 3)
281     debug("\n");
282     }
283     } else {
284     /* 64-bit: */
285     for (i=0; i<PPC_NGPRS; i++) {
286     int r = (i >> 1) + ((i & 1) << 4);
287     if ((i % 2) == 0)
288     debug("cpu%i:", x);
289     debug(" r%02i = 0x%016llx ", r,
290     (long long)cpu->cd.ppc.gpr[r]);
291     if ((i % 2) == 1)
292     debug("\n");
293     }
294     }
295    
296     /* Other special registers: */
297     debug("cpu%i: srr0 = 0x%016llx srr1 = 0x%016llx\n", x,
298     (long long)cpu->cd.ppc.srr0, (long long)cpu->cd.ppc.srr1);
299     reg_access_msr(cpu, &tmp, 0);
300     debug("cpu%i: msr = 0x%016llx ", x, (long long)tmp);
301     debug("tb = 0x%08x%08x\n",
302     (int)cpu->cd.ppc.tbu, (int)cpu->cd.ppc.tbl);
303     debug("cpu%i: dec = 0x%08x hdec = 0x%08x\n",
304     x, (int)cpu->cd.ppc.dec, (int)cpu->cd.ppc.hdec);
305     }
306    
307     if (coprocs & 1) {
308     debug("cpu%i: fpscr = 0x%08x\n", x, (int)cpu->cd.ppc.fpscr);
309    
310     /* TODO: show floating-point values :-) */
311    
312     /* TODO: 32-bit fprs on 32-bit PPC cpus? */
313    
314     for (i=0; i<PPC_NFPRS; i++) {
315     if ((i % 2) == 0)
316     debug("cpu%i:", x);
317     debug(" f%02i = 0x%016llx ", i,
318     (long long)cpu->cd.ppc.fpr[i]);
319     if ((i % 2) == 1)
320     debug("\n");
321     }
322     }
323    
324     if (coprocs & 2) {
325     debug("cpu%i: sdr1 = 0x%llx\n", x,
326     (long long)cpu->cd.ppc.sdr1);
327     for (i=0; i<4; i++)
328     debug("cpu%i: ibat%iu = 0x%08x ibat%il = 0x%08x\n",
329     x, i, cpu->cd.ppc.ibat_u[i],
330     i, cpu->cd.ppc.ibat_l[i]);
331     for (i=0; i<4; i++)
332     debug("cpu%i: dbat%iu = 0x%08x dbat%il = 0x%08x\n",
333     x, i, cpu->cd.ppc.dbat_u[i],
334     i, cpu->cd.ppc.dbat_l[i]);
335     }
336     }
337    
338    
339     /*
340     * ppc_cpu_register_match():
341     */
342     void ppc_cpu_register_match(struct machine *m, char *name,
343     int writeflag, uint64_t *valuep, int *match_register)
344     {
345     int cpunr = 0;
346    
347     /* CPU number: */
348    
349     /* TODO */
350    
351     /* Register name: */
352     if (strcasecmp(name, "pc") == 0) {
353     if (writeflag) {
354     m->cpus[cpunr]->pc = *valuep;
355     } else
356     *valuep = m->cpus[cpunr]->pc;
357     *match_register = 1;
358     } else if (strcasecmp(name, "msr") == 0) {
359     if (writeflag)
360     m->cpus[cpunr]->cd.ppc.msr = *valuep;
361     else
362     *valuep = m->cpus[cpunr]->cd.ppc.msr;
363     *match_register = 1;
364     } else if (strcasecmp(name, "lr") == 0) {
365     if (writeflag)
366     m->cpus[cpunr]->cd.ppc.lr = *valuep;
367     else
368     *valuep = m->cpus[cpunr]->cd.ppc.lr;
369     *match_register = 1;
370     } else if (strcasecmp(name, "cr") == 0) {
371     if (writeflag)
372     m->cpus[cpunr]->cd.ppc.cr = *valuep;
373     else
374     *valuep = m->cpus[cpunr]->cd.ppc.cr;
375     *match_register = 1;
376     } else if (strcasecmp(name, "dec") == 0) {
377     if (writeflag)
378     m->cpus[cpunr]->cd.ppc.dec = *valuep;
379     else
380     *valuep = m->cpus[cpunr]->cd.ppc.dec;
381     *match_register = 1;
382     } else if (strcasecmp(name, "hdec") == 0) {
383     if (writeflag)
384     m->cpus[cpunr]->cd.ppc.hdec = *valuep;
385     else
386     *valuep = m->cpus[cpunr]->cd.ppc.hdec;
387     *match_register = 1;
388     } else if (strcasecmp(name, "ctr") == 0) {
389     if (writeflag)
390     m->cpus[cpunr]->cd.ppc.ctr = *valuep;
391     else
392     *valuep = m->cpus[cpunr]->cd.ppc.ctr;
393     *match_register = 1;
394     } else if (name[0] == 'r' && isdigit((int)name[1])) {
395     int nr = atoi(name + 1);
396     if (nr >= 0 && nr < PPC_NGPRS) {
397     if (writeflag) {
398     m->cpus[cpunr]->cd.ppc.gpr[nr] = *valuep;
399     } else
400     *valuep = m->cpus[cpunr]->cd.ppc.gpr[nr];
401     *match_register = 1;
402     }
403     } else if (strcasecmp(name, "xer") == 0) {
404     if (writeflag)
405     m->cpus[cpunr]->cd.ppc.xer = *valuep;
406     else
407     *valuep = m->cpus[cpunr]->cd.ppc.xer;
408     *match_register = 1;
409     } else if (strcasecmp(name, "fpscr") == 0) {
410     if (writeflag)
411     m->cpus[cpunr]->cd.ppc.fpscr = *valuep;
412     else
413     *valuep = m->cpus[cpunr]->cd.ppc.fpscr;
414     *match_register = 1;
415     } else if (name[0] == 'f' && isdigit((int)name[1])) {
416     int nr = atoi(name + 1);
417     if (nr >= 0 && nr < PPC_NFPRS) {
418     if (writeflag) {
419     m->cpus[cpunr]->cd.ppc.fpr[nr] = *valuep;
420     } else
421     *valuep = m->cpus[cpunr]->cd.ppc.fpr[nr];
422     *match_register = 1;
423     }
424     }
425     }
426    
427    
428     /*
429     * ppc_cpu_show_full_statistics():
430     *
431     * Show detailed statistics on opcode usage on each cpu.
432     */
433     void ppc_cpu_show_full_statistics(struct machine *m)
434     {
435     fatal("ppc_cpu_show_full_statistics(): TODO\n");
436     }
437    
438    
439     /*
440     * ppc_cpu_tlbdump():
441     *
442     * Called from the debugger to dump the TLB in a readable format.
443     * x is the cpu number to dump, or -1 to dump all CPUs.
444     *
445     * If rawflag is nonzero, then the TLB contents isn't formated nicely,
446     * just dumped.
447     */
448     void ppc_cpu_tlbdump(struct machine *m, int x, int rawflag)
449     {
450     fatal("ppc_cpu_tlbdump(): TODO\n");
451     }
452    
453    
454     /*
455     * ppc_cpu_interrupt():
456     */
457     int ppc_cpu_interrupt(struct cpu *cpu, uint64_t irq_nr)
458     {
459     fatal("ppc_cpu_interrupt(): TODO\n");
460     return 0;
461     }
462    
463    
464     /*
465     * ppc_cpu_interrupt_ack():
466     */
467     int ppc_cpu_interrupt_ack(struct cpu *cpu, uint64_t irq_nr)
468     {
469     /* fatal("ppc_cpu_interrupt_ack(): TODO\n"); */
470     return 0;
471     }
472    
473    
474     /*
475     * ppc_cpu_disassemble_instr():
476     *
477     * Convert an instruction word into human readable format, for instruction
478     * tracing.
479     *
480     * If running is 1, cpu->pc should be the address of the instruction.
481     *
482     * If running is 0, things that depend on the runtime environment (eg.
483     * register contents) will not be shown, and addr will be used instead of
484     * cpu->pc for relative addresses.
485     */
486     int ppc_cpu_disassemble_instr(struct cpu *cpu, unsigned char *instr,
487     int running, uint64_t dumpaddr, int bintrans)
488     {
489     int hi6, xo, lev, rt, rs, ra, rb, imm, sh, me, rc, l_bit, oe_bit;
490     int spr, aa_bit, lk_bit, bf, bh, bi, bo, mb, nb, bt, ba, bb, fpreg;
491     int bfa, to, load, wlen, no_rb = 0;
492     uint64_t offset, addr;
493     uint32_t iword;
494     char *symbol, *mnem = "ERROR";
495     int power = cpu->cd.ppc.mode == MODE_POWER;
496    
497     if (running)
498     dumpaddr = cpu->pc;
499    
500     symbol = get_symbol_name(&cpu->machine->symbol_context,
501     dumpaddr, &offset);
502     if (symbol != NULL && offset==0)
503     debug("<%s>\n", symbol);
504    
505     if (cpu->machine->ncpus > 1 && running)
506     debug("cpu%i: ", cpu->cpu_id);
507    
508     if (cpu->cd.ppc.bits == 32)
509     debug("%08x", (int)dumpaddr);
510     else
511     debug("%016llx", (long long)dumpaddr);
512    
513     /* NOTE: Fixed to big-endian. */
514     iword = (instr[0] << 24) + (instr[1] << 16) + (instr[2] << 8)
515     + instr[3];
516    
517     debug(": %08x\t", iword);
518    
519     /*
520     * Decode the instruction:
521     */
522    
523     hi6 = iword >> 26;
524    
525     switch (hi6) {
526     case PPC_HI6_MULLI:
527     case PPC_HI6_SUBFIC:
528     rt = (iword >> 21) & 31;
529     ra = (iword >> 16) & 31;
530     imm = (int16_t)(iword & 0xffff);
531     switch (hi6) {
532     case PPC_HI6_MULLI:
533     mnem = power? "muli":"mulli";
534     break;
535     case PPC_HI6_SUBFIC:
536     mnem = power? "sfi":"subfic";
537     break;
538     }
539     debug("%s\tr%i,r%i,%i", mnem, rt, ra, imm);
540     break;
541     case PPC_HI6_CMPLI:
542     case PPC_HI6_CMPI:
543     bf = (iword >> 23) & 7;
544     l_bit = (iword >> 21) & 1;
545     ra = (iword >> 16) & 31;
546     if (hi6 == PPC_HI6_CMPLI) {
547     imm = iword & 0xffff;
548     mnem = "cmpl";
549     } else {
550     imm = (int16_t)(iword & 0xffff);
551     mnem = "cmp";
552     }
553     debug("%s%si\t", mnem, l_bit? "d" : "w");
554     if (bf != 0)
555     debug("cr%i,", bf);
556     debug("r%i,%i", ra, imm);
557     break;
558     case PPC_HI6_ADDIC:
559     case PPC_HI6_ADDIC_DOT:
560     rt = (iword >> 21) & 31;
561     ra = (iword >> 16) & 31;
562     rc = hi6 == PPC_HI6_ADDIC_DOT;
563     imm = (int16_t)(iword & 0xffff);
564     mnem = power? "ai":"addic";
565     if (imm < 0 && !power) {
566     mnem = "subic";
567     imm = -imm;
568     }
569     debug("%s%s\tr%i,r%i,%i", mnem, rc?".":"", rt, ra, imm);
570     break;
571     case PPC_HI6_ADDI:
572     rt = (iword >> 21) & 31;
573     ra = (iword >> 16) & 31;
574     imm = (int16_t)(iword & 0xffff);
575     if (ra == 0)
576     debug("li\tr%i,%i", rt, imm);
577     else {
578     mnem = power? "cal":"addi";
579     if (imm < 0 && !power) {
580     mnem = "subi";
581     imm = -imm;
582     }
583     debug("%s\tr%i,r%i,%i", mnem, rt, ra, imm);
584     }
585     break;
586     case PPC_HI6_ADDIS:
587     rt = (iword >> 21) & 31;
588     ra = (iword >> 16) & 31;
589     imm = (int16_t)(iword & 0xffff);
590     if (ra == 0)
591     debug("lis\tr%i,%i", rt, imm);
592     else
593     debug("%s\tr%i,r%i,%i",
594     power? "cau":"addis", rt, ra, imm);
595     break;
596     case PPC_HI6_BC:
597     aa_bit = (iword & 2) >> 1;
598     lk_bit = iword & 1;
599     bo = (iword >> 21) & 31;
600     bi = (iword >> 16) & 31;
601     /* Sign-extend addr: */
602     addr = (int64_t)(int16_t)(iword & 0xfffc);
603     debug("bc");
604     if (lk_bit)
605     debug("l");
606     if (aa_bit)
607     debug("a");
608     else
609     addr += dumpaddr;
610     debug("\t%i,%i,", bo, bi);
611     if (cpu->cd.ppc.bits == 32)
612     addr &= 0xffffffff;
613     if (cpu->cd.ppc.bits == 32)
614     debug("0x%x", (int)addr);
615     else
616     debug("0x%llx", (long long)addr);
617     symbol = get_symbol_name(&cpu->machine->symbol_context,
618     addr, &offset);
619     if (symbol != NULL)
620     debug("\t<%s>", symbol);
621     break;
622     case PPC_HI6_SC:
623     lev = (iword >> 5) & 0x7f;
624     debug("sc");
625     if (lev != 0) {
626     debug("\t%i", lev);
627     if (lev > 1)
628     debug(" (WARNING! reserved value)");
629     }
630     break;
631     case PPC_HI6_B:
632     aa_bit = (iword & 2) >> 1;
633     lk_bit = iword & 1;
634     /* Sign-extend addr: */
635     addr = (int64_t)(int32_t)((iword & 0x03fffffc) << 6);
636     addr = (int64_t)addr >> 6;
637     debug("b");
638     if (lk_bit)
639     debug("l");
640     if (aa_bit)
641     debug("a");
642     else
643     addr += dumpaddr;
644     if (cpu->cd.ppc.bits == 32)
645     addr &= 0xffffffff;
646     if (cpu->cd.ppc.bits == 32)
647     debug("\t0x%x", (int)addr);
648     else
649     debug("\t0x%llx", (long long)addr);
650     symbol = get_symbol_name(&cpu->machine->symbol_context,
651     addr, &offset);
652     if (symbol != NULL)
653     debug("\t<%s>", symbol);
654     break;
655     case PPC_HI6_19:
656     xo = (iword >> 1) & 1023;
657     switch (xo) {
658     case PPC_19_MCRF:
659     bf = (iword >> 23) & 7;
660     bfa = (iword >> 18) & 7;
661     debug("mcrf\tcr%i,cr%i", bf, bfa);
662     break;
663     case PPC_19_RFI:
664     debug("rfi");
665     break;
666     case PPC_19_RFID:
667     debug("rfid");
668     break;
669     case PPC_19_RFSVC:
670     debug("rfsvc%s", power?"":"\t(INVALID for PowerPC)");
671     break;
672     case PPC_19_BCLR:
673     case PPC_19_BCCTR:
674     bo = (iword >> 21) & 31;
675     bi = (iword >> 16) & 31;
676     bh = (iword >> 11) & 3;
677     lk_bit = iword & 1;
678     switch (xo) {
679     case PPC_19_BCLR:
680     mnem = power? "bcr" : "bclr"; break;
681     case PPC_19_BCCTR:
682     mnem = power? "bcc" : "bcctr"; break;
683     }
684     debug("%s%s%s\t%i,%i,%i", mnem, lk_bit? "l" : "",
685     bh? (bh==3? "+" : (bh==2? "-" : "?")) : "",
686     bo, bi, bh);
687     break;
688     case PPC_19_ISYNC:
689     debug("%s", power? "ics" : "isync");
690     break;
691     case PPC_19_CRAND:
692     case PPC_19_CRXOR:
693     case PPC_19_CROR:
694     case PPC_19_CRNAND:
695     case PPC_19_CRNOR:
696     case PPC_19_CRANDC:
697     case PPC_19_CREQV:
698     case PPC_19_CRORC:
699     bt = (iword >> 21) & 31;
700     ba = (iword >> 16) & 31;
701     bb = (iword >> 11) & 31;
702     switch (xo) {
703     case PPC_19_CRAND: mnem = "crand"; break;
704     case PPC_19_CRXOR: mnem = "crxor"; break;
705     case PPC_19_CROR: mnem = "cror"; break;
706     case PPC_19_CRNAND: mnem = "crnand"; break;
707     case PPC_19_CRNOR: mnem = "crnor"; break;
708     case PPC_19_CRANDC: mnem = "crandc"; break;
709     case PPC_19_CREQV: mnem = "creqv"; break;
710     case PPC_19_CRORC: mnem = "crorc"; break;
711     }
712     debug("%s\t%i,%i,%i", mnem, bt, ba, bb);
713     break;
714     default:
715     debug("unimplemented hi6_19, xo = 0x%x", xo);
716     }
717     break;
718     case PPC_HI6_RLWIMI:
719     case PPC_HI6_RLWINM:
720     rs = (iword >> 21) & 31;
721     ra = (iword >> 16) & 31;
722     sh = (iword >> 11) & 31;
723     mb = (iword >> 6) & 31;
724     me = (iword >> 1) & 31;
725     rc = iword & 1;
726     switch (hi6) {
727     case PPC_HI6_RLWIMI:
728     mnem = power? "rlimi" : "rlwimi"; break;
729     case PPC_HI6_RLWINM:
730     mnem = power? "rlinm" : "rlwinm"; break;
731     }
732     debug("%s%s\tr%i,r%i,%i,%i,%i",
733     mnem, rc?".":"", ra, rs, sh, mb, me);
734     break;
735     case PPC_HI6_ORI:
736     case PPC_HI6_ORIS:
737     case PPC_HI6_XORI:
738     case PPC_HI6_XORIS:
739     case PPC_HI6_ANDI_DOT:
740     case PPC_HI6_ANDIS_DOT:
741     rs = (iword >> 21) & 31;
742     ra = (iword >> 16) & 31;
743     imm = iword & 0xffff;
744     switch (hi6) {
745     case PPC_HI6_ORI:
746     mnem = power? "oril":"ori";
747     break;
748     case PPC_HI6_ORIS:
749     mnem = power? "oriu":"oris";
750     break;
751     case PPC_HI6_XORI:
752     mnem = power? "xoril":"xori";
753     break;
754     case PPC_HI6_XORIS:
755     mnem = power? "xoriu":"xoris";
756     break;
757     case PPC_HI6_ANDI_DOT:
758     mnem = power? "andil.":"andi.";
759     break;
760     case PPC_HI6_ANDIS_DOT:
761     mnem = power? "andiu.":"andis.";
762     break;
763     }
764     if (hi6 == PPC_HI6_ORI && rs == 0 && ra == 0 && imm == 0)
765     debug("nop");
766     else
767     debug("%s\tr%i,r%i,0x%04x", mnem, ra, rs, imm);
768     break;
769     case PPC_HI6_30:
770     xo = (iword >> 2) & 7;
771     switch (xo) {
772     case PPC_30_RLDICR:
773     rs = (iword >> 21) & 31;
774     ra = (iword >> 16) & 31;
775     sh = ((iword >> 11) & 31) | ((iword & 2) << 4);
776     me = ((iword >> 6) & 31) | (iword & 0x20);
777     rc = iword & 1;
778     debug("rldicr%s\tr%i,r%i,%i,%i",
779     rc?".":"", ra, rs, sh, me);
780     break;
781     default:
782     debug("unimplemented hi6_30, xo = 0x%x", xo);
783     }
784     break;
785     case PPC_HI6_31:
786     xo = (iword >> 1) & 1023;
787     switch (xo) {
788    
789     case PPC_31_CMP:
790     case PPC_31_CMPL:
791     bf = (iword >> 23) & 7;
792     l_bit = (iword >> 21) & 1;
793     ra = (iword >> 16) & 31;
794     rb = (iword >> 11) & 31;
795     if (xo == PPC_31_CMPL)
796     mnem = "cmpl";
797     else
798     mnem = "cmp";
799     debug("%s%s\t", mnem, l_bit? "d" : "w");
800     if (bf != 0)
801     debug("cr%i,", bf);
802     debug("r%i,r%i", ra, rb);
803     break;
804     case PPC_31_MFCR:
805     rt = (iword >> 21) & 31;
806     debug("mfcr\tr%i", rt);
807     break;
808     case PPC_31_MFMSR:
809     rt = (iword >> 21) & 31;
810     debug("mfmsr\tr%i", rt);
811     break;
812     case PPC_31_MTCRF:
813     rs = (iword >> 21) & 31;
814     mb = (iword >> 12) & 255; /* actually fxm, not mb */
815     debug("mtcrf\t%i,r%i", mb, rs);
816     break;
817     case PPC_31_MTMSR:
818     rs = (iword >> 21) & 31;
819     l_bit = (iword >> 16) & 1;
820     debug("mtmsr\tr%i", rs);
821     if (l_bit)
822     debug(",%i", l_bit);
823     break;
824     case PPC_31_TW:
825     case PPC_31_TD:
826     to = (iword >> 21) & 31;
827     ra = (iword >> 16) & 31;
828     rb = (iword >> 11) & 31;
829     switch (xo) {
830     case PPC_31_TW: mnem = power? "t" : "tw"; break;
831     case PPC_31_TD: mnem = "td"; break;
832     }
833     debug("%s\t%i,r%i,r%i", mnem, to, ra, rb);
834     break;
835     case PPC_31_LWARX:
836     case PPC_31_LDARX:
837     case PPC_31_LBZX:
838     case PPC_31_LBZUX:
839     case PPC_31_LHZX:
840     case PPC_31_LHZUX:
841     case PPC_31_LWZX:
842     case PPC_31_LWZUX:
843     case PPC_31_STWCX_DOT:
844     case PPC_31_STDCX_DOT:
845     case PPC_31_STBX:
846     case PPC_31_STBUX:
847     case PPC_31_STHX:
848     case PPC_31_STHUX:
849     case PPC_31_STWX:
850     case PPC_31_STWUX:
851     case PPC_31_STDX:
852     case PPC_31_STDUX:
853     /* rs for stores, rt for loads, actually */
854     load = 0; wlen = 0;
855     rs = (iword >> 21) & 31;
856     ra = (iword >> 16) & 31;
857     rb = (iword >> 11) & 31;
858     switch (xo) {
859     case PPC_31_LWARX: wlen=4;load=1; mnem = "lwarx"; break;
860     case PPC_31_LDARX: wlen=8;load=1; mnem = "ldarx"; break;
861     case PPC_31_LBZX: wlen=1;load=1; mnem = "lbzx"; break;
862     case PPC_31_LBZUX: wlen=1;load=1; mnem = "lbzux"; break;
863     case PPC_31_LHZX: wlen=2;load=1; mnem = "lhzx"; break;
864     case PPC_31_LHZUX: wlen=2;load=1; mnem = "lhzux"; break;
865     case PPC_31_LWZX: wlen = 4; load = 1;
866     mnem = power? "lx" : "lwzx";
867     break;
868     case PPC_31_LWZUX: wlen = 4; load = 1;
869     mnem = power? "lux":"lwzux";
870     break;
871     case PPC_31_STWCX_DOT: wlen=4; mnem = "stwcx."; break;
872     case PPC_31_STDCX_DOT: wlen=8; mnem = "stdcx."; break;
873     case PPC_31_STBX: wlen=1; mnem = "stbx"; break;
874     case PPC_31_STBUX: wlen=1; mnem = "stbux"; break;
875     case PPC_31_STHX: wlen=2; mnem = "sthx"; break;
876     case PPC_31_STHUX: wlen=2; mnem = "sthux"; break;
877     case PPC_31_STWX:
878     wlen = 4; mnem = power? "stx" : "stwx";
879     break;
880     case PPC_31_STWUX:
881     wlen = 4; mnem = power? "stux" : "stwux";
882     break;
883     case PPC_31_STDX: wlen = 8; mnem = "stdx"; break;
884     case PPC_31_STDUX: wlen = 8; mnem = "stdux"; break;
885     }
886     debug("%s\tr%i,r%i,r%i", mnem, rs, ra, rb);
887     if (!running)
888     break;
889     addr = (ra==0? 0 : cpu->cd.ppc.gpr[ra]) +
890     cpu->cd.ppc.gpr[rb];
891     symbol = get_symbol_name(&cpu->machine->symbol_context,
892     addr, &offset);
893     if (symbol != NULL)
894     debug(" \t<%s", symbol);
895     else
896     debug(" \t<0x%llx", (long long)addr);
897     if (wlen > 0) {
898     /* TODO */
899     }
900     debug(">");
901     break;
902     case PPC_31_NEG:
903     case PPC_31_NEGO:
904     rt = (iword >> 21) & 31;
905     ra = (iword >> 16) & 31;
906     oe_bit = (iword >> 10) & 1;
907     rc = iword & 1;
908     switch (xo) {
909     case PPC_31_NEG: mnem = "neg"; break;
910     case PPC_31_NEGO: mnem = "nego"; break;
911     }
912     debug("%s%s\tr%i,r%i", mnem, rc? "." : "", rt, ra);
913     break;
914     case PPC_31_ADDZE:
915     case PPC_31_ADDZEO:
916     rt = (iword >> 21) & 31;
917     ra = (iword >> 16) & 31;
918     oe_bit = (iword >> 10) & 1;
919     rc = iword & 1;
920     switch (xo) {
921     case PPC_31_ADDZE:
922     mnem = power? "aze" : "addze";
923     break;
924     case PPC_31_ADDZEO:
925     mnem = power? "azeo" : "addzeo";
926     break;
927     }
928     debug("%s%s\tr%i,r%i", mnem, rc? "." : "", rt, ra);
929     break;
930     case PPC_31_MTSR:
931     /* Move to segment register */
932     rt = (iword >> 21) & 31;
933     ra = (iword >> 16) & 15; /* actually: sr */
934     debug("mtsr\t%i,r%i", ra, rt);
935     break;
936     case PPC_31_MTSRIN:
937     case PPC_31_MFSRIN:
938     /* Move to/from segment register indirect */
939     rt = (iword >> 21) & 31;
940     rb = (iword >> 11) & 31;
941     switch (xo) {
942     case PPC_31_MTSRIN: mnem = "mtsrin"; break;
943     case PPC_31_MFSRIN: mnem = "mfsrin"; break;
944     }
945     debug("%s\tr%i,r%i", mnem, rt, rb);
946     break;
947     case PPC_31_ADDC:
948     case PPC_31_ADDCO:
949     case PPC_31_ADDE:
950     case PPC_31_ADDEO:
951     case PPC_31_ADDME:
952     case PPC_31_ADDMEO:
953     case PPC_31_ADD:
954     case PPC_31_ADDO:
955     case PPC_31_MULHW:
956     case PPC_31_MULHWU:
957     case PPC_31_MULLW:
958     case PPC_31_MULLWO:
959     case PPC_31_SUBF:
960     case PPC_31_SUBFO:
961     case PPC_31_SUBFC:
962     case PPC_31_SUBFCO:
963     case PPC_31_SUBFE:
964     case PPC_31_SUBFEO:
965     case PPC_31_SUBFZE:
966     case PPC_31_SUBFZEO:
967     rt = (iword >> 21) & 31;
968     ra = (iword >> 16) & 31;
969     rb = (iword >> 11) & 31;
970     oe_bit = (iword >> 10) & 1;
971     rc = iword & 1;
972     switch (xo) {
973     case PPC_31_ADDC:
974     mnem = power? "a" : "addc";
975     break;
976     case PPC_31_ADDCO:
977     mnem = power? "ao" : "addco";
978     break;
979     case PPC_31_ADDE:
980     mnem = power? "ae" : "adde";
981     break;
982     case PPC_31_ADDEO:
983     mnem = power? "aeo" : "addeo";
984     break;
985     case PPC_31_ADDME:
986     mnem = power? "ame" : "addme";
987     no_rb = 1;
988     break;
989     case PPC_31_ADDMEO:
990     mnem = power? "ameo" : "addmeo";
991     no_rb = 1;
992     break;
993     case PPC_31_ADD:
994     mnem = power? "cax" : "add";
995     break;
996     case PPC_31_ADDO:
997     mnem = power? "caxo" : "addo";
998     break;
999     case PPC_31_MULHW: mnem = "mulhw"; break;
1000     case PPC_31_MULHWU: mnem = "mulhwu"; break;
1001     case PPC_31_MULLW:
1002     mnem = power? "muls" : "mullw";
1003     break;
1004     case PPC_31_MULLWO:
1005     mnem = power? "mulso" : "mullwo";
1006     break;
1007     case PPC_31_SUBF: mnem = "subf"; break;
1008     case PPC_31_SUBFO: mnem = "subfo"; break;
1009     case PPC_31_SUBFC:
1010     mnem = power? "sf" : "subfc";
1011     break;
1012     case PPC_31_SUBFCO:
1013     mnem = power? "sfo" : "subfco";
1014     break;
1015     case PPC_31_SUBFE:
1016     mnem = power? "sfe" : "subfe";
1017     break;
1018     case PPC_31_SUBFEO:
1019     mnem = power? "sfeo" : "subfeo";
1020     break;
1021     case PPC_31_SUBFZE:
1022     mnem = power? "sfze" : "subfze";
1023     no_rb = 1;
1024     break;
1025     case PPC_31_SUBFZEO:
1026     mnem = power? "sfzeo" : "subfzeo";
1027     no_rb = 1;
1028     break;
1029     }
1030     debug("%s%s\tr%i,r%i", mnem, rc? "." : "", rt, ra);
1031     if (!no_rb)
1032     debug(",r%i", rb);
1033     break;
1034     case PPC_31_MFSPR:
1035     rt = (iword >> 21) & 31;
1036     spr = ((iword >> 6) & 0x3e0) + ((iword >> 16) & 31);
1037     switch (spr) {
1038     case 8: debug("mflr\tr%i", rt); break;
1039     case 9: debug("mfctr\tr%i", rt); break;
1040     case 26: debug("mfsrr0\tr%i", rt); break;
1041     case 27: debug("mfsrr1\tr%i", rt); break;
1042     case 272: debug("mfsprg\t0,r%i", rt); break;
1043     case 273: debug("mfsprg\t1,r%i", rt); break;
1044     case 274: debug("mfsprg\t2,r%i", rt); break;
1045     case 275: debug("mfsprg\t3,r%i", rt); break;
1046     case 287: debug("mfpvr\tr%i", rt); break;
1047     /* TODO: 1008 = hid0? */
1048     case 1008: debug("mfdbsr\tr%i", rt); break;
1049     case 1009: debug("mfhid1\tr%i", rt); break;
1050     case 1017: debug("mfl2cr\tr%i", rt); break;
1051     case 1018: debug("mfl3cr\tr%i", rt); break;
1052     default:debug("mfspr\tr%i,spr%i", rt, spr);
1053     }
1054     break;
1055     case PPC_31_TLBIE:
1056     /* TODO: what is ra? The IBM online docs didn't say */
1057     ra = 0;
1058     rb = (iword >> 11) & 31;
1059     if (power)
1060     debug("tlbi\tr%i,r%i", ra, rb);
1061     else
1062     debug("tlbie\tr%i", rb);
1063     break;
1064     case PPC_31_TLBSYNC:
1065     debug("tlbsync");
1066     break;
1067     case PPC_31_MFTB:
1068     rt = (iword >> 21) & 31;
1069     spr = ((iword >> 6) & 0x3e0) + ((iword >> 16) & 31);
1070     debug("mftb%s\tr%i", spr==268? "" :
1071     (spr==269? "u" : "?"), rt);
1072     break;
1073     case PPC_31_CNTLZW:
1074     rs = (iword >> 21) & 31;
1075     ra = (iword >> 16) & 31;
1076     rc = iword & 1;
1077     mnem = power? "cntlz" : "cntlzw";
1078     debug("%s%s\tr%i,r%i", mnem, rc? "." : "", ra, rs);
1079     break;
1080     case PPC_31_CLF: /* POWER only */
1081     case PPC_31_CLI: /* POWER only */
1082     case PPC_31_DCLST: /* POWER only */
1083     case PPC_31_DCBF: /* PowerPC only */
1084     case PPC_31_DCBI: /* PowerPC only */
1085     case PPC_31_DCBST: /* PowerPC only */
1086     case PPC_31_DCBTST: /* PowerPC only */
1087     case PPC_31_DCBT: /* PowerPC only */
1088     case PPC_31_ICBI: /* PowerPC only */
1089     case PPC_31_DCBZ: /* POWER/PowerPC */
1090     ra = (iword >> 16) & 31;
1091     rb = (iword >> 11) & 31;
1092     switch (xo) {
1093     case PPC_31_CLF: mnem = "clf"; break;
1094     case PPC_31_CLI: mnem = "cli"; break;
1095     case PPC_31_DCLST: mnem = "dclst"; break;
1096     case PPC_31_DCBF: mnem = "dcbf"; break;
1097     case PPC_31_DCBI: mnem = "dcbi"; break;
1098     case PPC_31_DCBST: mnem = "dcbst"; break;
1099     case PPC_31_DCBTST:mnem = "dcbtst"; break;
1100     case PPC_31_DCBT: mnem = "dcbt"; break;
1101     case PPC_31_ICBI: mnem = "icbi"; break;
1102     case PPC_31_DCBZ: mnem = power ?
1103     "dclz" : "dcbz"; break;
1104     }
1105     debug("%s\tr%i,r%i", mnem, ra, rb);
1106     break;
1107     case PPC_31_SLW:
1108     case PPC_31_SRAW:
1109     case PPC_31_SRW:
1110     case PPC_31_AND:
1111     case PPC_31_ANDC:
1112     case PPC_31_NOR:
1113     case PPC_31_OR:
1114     case PPC_31_ORC:
1115     case PPC_31_XOR:
1116     case PPC_31_NAND:
1117     rs = (iword >> 21) & 31;
1118     ra = (iword >> 16) & 31;
1119     rb = (iword >> 11) & 31;
1120     rc = iword & 1;
1121     if (rs == rb && xo == PPC_31_OR)
1122     debug("mr%s\tr%i,r%i", rc? "." : "", ra, rs);
1123     else {
1124     switch (xo) {
1125     case PPC_31_SLW: mnem =
1126     power? "sl" : "slw"; break;
1127     case PPC_31_SRAW: mnem =
1128     power? "sra" : "sraw"; break;
1129     case PPC_31_SRW: mnem =
1130     power? "sr" : "srw"; break;
1131     case PPC_31_AND: mnem = "and"; break;
1132     case PPC_31_NAND: mnem = "nand"; break;
1133     case PPC_31_ANDC: mnem = "andc"; break;
1134     case PPC_31_NOR: mnem = "nor"; break;
1135     case PPC_31_OR: mnem = "or"; break;
1136     case PPC_31_ORC: mnem = "orc"; break;
1137     case PPC_31_XOR: mnem = "xor"; break;
1138     }
1139     debug("%s%s\tr%i,r%i,r%i", mnem,
1140     rc? "." : "", ra, rs, rb);
1141     }
1142     break;
1143     case PPC_31_DCCCI:
1144     ra = (iword >> 16) & 31;
1145     rb = (iword >> 11) & 31;
1146     debug("dccci\tr%i,r%i", ra, rb);
1147     break;
1148     case PPC_31_ICCCI:
1149     ra = (iword >> 16) & 31;
1150     rb = (iword >> 11) & 31;
1151     debug("iccci\tr%i,r%i", ra, rb);
1152     break;
1153     case PPC_31_DIVW:
1154     case PPC_31_DIVWO:
1155     case PPC_31_DIVWU:
1156     case PPC_31_DIVWUO:
1157     rt = (iword >> 21) & 31;
1158     ra = (iword >> 16) & 31;
1159     rb = (iword >> 11) & 31;
1160     oe_bit = (iword >> 10) & 1;
1161     rc = iword & 1;
1162     switch (xo) {
1163     case PPC_31_DIVWU: mnem = "divwu"; break;
1164     case PPC_31_DIVWUO: mnem = "divwuo"; break;
1165     case PPC_31_DIVW: mnem = "divw"; break;
1166     case PPC_31_DIVWO: mnem = "divwo"; break;
1167     }
1168     debug("%s%s\tr%i,r%i,r%i", mnem, rc? "." : "",
1169     rt, ra, rb);
1170     break;
1171     case PPC_31_MTSPR:
1172     rs = (iword >> 21) & 31;
1173     spr = ((iword >> 6) & 0x3e0) + ((iword >> 16) & 31);
1174     switch (spr) {
1175     case 8: debug("mtlr\tr%i", rs); break;
1176     case 9: debug("mtctr\tr%i", rs); break;
1177     case 26: debug("mtsrr0\tr%i", rs); break;
1178     case 27: debug("mtsrr1\tr%i", rs); break;
1179     case 272: debug("mtsprg\t0,r%i", rs); break;
1180     case 273: debug("mtsprg\t1,r%i", rs); break;
1181     case 274: debug("mtsprg\t2,r%i", rs); break;
1182     case 275: debug("mtsprg\t3,r%i", rs); break;
1183     case 528: debug("mtibatu\t0,r%i", rs); break;
1184     case 529: debug("mtibatl\t0,r%i", rs); break;
1185     case 530: debug("mtibatu\t1,r%i", rs); break;
1186     case 531: debug("mtibatl\t1,r%i", rs); break;
1187     case 532: debug("mtibatu\t2,r%i", rs); break;
1188     case 533: debug("mtibatl\t2,r%i", rs); break;
1189     case 534: debug("mtibatu\t3,r%i", rs); break;
1190     case 535: debug("mtibatl\t3,r%i", rs); break;
1191     case 536: debug("mtdbatu\t0,r%i", rs); break;
1192     case 537: debug("mtdbatl\t0,r%i", rs); break;
1193     case 538: debug("mtdbatu\t1,r%i", rs); break;
1194     case 539: debug("mtdbatl\t1,r%i", rs); break;
1195     case 540: debug("mtdbatu\t2,r%i", rs); break;
1196     case 541: debug("mtdbatl\t2,r%i", rs); break;
1197     case 542: debug("mtdbatu\t3,r%i", rs); break;
1198     case 543: debug("mtdbatl\t3,r%i", rs); break;
1199     case 1008: debug("mtdbsr\tr%i", rs); break;
1200     default:debug("mtspr\tspr%i,r%i", spr, rs);
1201     }
1202     break;
1203     case PPC_31_SYNC:
1204     debug("%s", power? "dcs" : "sync");
1205     break;
1206     case PPC_31_LSWI:
1207     case PPC_31_STSWI:
1208     rs = (iword >> 21) & 31; /* lwsi uses rt */
1209     ra = (iword >> 16) & 31;
1210     nb = (iword >> 11) & 31;
1211     switch (xo) {
1212     case PPC_31_LSWI:
1213     mnem = power? "lsi" : "lswi"; break;
1214     case PPC_31_STSWI:
1215     mnem = power? "stsi" : "stswi"; break;
1216     }
1217     debug("%s\tr%i,r%i,%i", mnem, rs, ra, nb);
1218     break;
1219     case PPC_31_LHBRX:
1220     case PPC_31_LWBRX:
1221     case PPC_31_STHBRX:
1222     case PPC_31_STWBRX:
1223     rt = (iword >> 21) & 31; /* stores use rs */
1224     ra = (iword >> 16) & 31;
1225     rb = (iword >> 11) & 31;
1226     switch (xo) {
1227     case PPC_31_LHBRX: mnem = "lhbrx"; break;
1228     case PPC_31_LWBRX: mnem = power?
1229     "lbrx" : "lwbrx"; break;
1230     case PPC_31_STHBRX: mnem = "sthbrx"; break;
1231     case PPC_31_STWBRX: mnem = power?
1232     "stbrx" : "stwbrx"; break;
1233     }
1234     debug("%s\tr%i,r%i,r%i", mnem, rt, ra, rb);
1235     break;
1236     case PPC_31_SRAWI:
1237     rs = (iword >> 21) & 31;
1238     ra = (iword >> 16) & 31;
1239     sh = (iword >> 11) & 31;
1240     rc = iword & 1;
1241     mnem = power? "srai" : "srawi";
1242     debug("%s%s\tr%i,r%i,%i", mnem,
1243     rc? "." : "", ra, rs, sh);
1244     break;
1245     case PPC_31_EIEIO:
1246     debug("%s", power? "eieio?" : "eieio");
1247     break;
1248     case PPC_31_EXTSB:
1249     case PPC_31_EXTSH:
1250     case PPC_31_EXTSW:
1251     rs = (iword >> 21) & 31;
1252     ra = (iword >> 16) & 31;
1253     rc = iword & 1;
1254     switch (xo) {
1255     case PPC_31_EXTSB:
1256     mnem = power? "exts" : "extsb";
1257     break;
1258     case PPC_31_EXTSH:
1259     mnem = "extsh";
1260     break;
1261     case PPC_31_EXTSW:
1262     mnem = "extsw";
1263     break;
1264     }
1265     debug("%s%s\tr%i,r%i", mnem, rc? "." : "", ra, rs);
1266     break;
1267     default:
1268     debug("unimplemented hi6_31, xo = 0x%x", xo);
1269     }
1270     break;
1271     case PPC_HI6_LWZ:
1272     case PPC_HI6_LWZU:
1273     case PPC_HI6_LHZ:
1274     case PPC_HI6_LHZU:
1275     case PPC_HI6_LHA:
1276     case PPC_HI6_LHAU:
1277     case PPC_HI6_LBZ:
1278     case PPC_HI6_LBZU:
1279     case PPC_HI6_LMW:
1280     case PPC_HI6_STW:
1281     case PPC_HI6_STWU:
1282     case PPC_HI6_STH:
1283     case PPC_HI6_STHU:
1284     case PPC_HI6_STB:
1285     case PPC_HI6_STBU:
1286     case PPC_HI6_STMW:
1287     case PPC_HI6_LFD:
1288     case PPC_HI6_STFD:
1289     /* NOTE: Loads use rt, not rs, but are otherwise similar
1290     to stores */
1291     load = 0; wlen = 0;
1292     rs = (iword >> 21) & 31;
1293     ra = (iword >> 16) & 31;
1294     imm = (int16_t)(iword & 0xffff);
1295     fpreg = 0;
1296     switch (hi6) {
1297     case PPC_HI6_LWZ: load=1; wlen = 4;
1298     mnem = power? "l" : "lwz"; break;
1299     case PPC_HI6_LWZU: load=1; wlen = 4;
1300     mnem = power? "lu" : "lwzu"; break;
1301     case PPC_HI6_LHZ: load=1; wlen = 2;
1302     mnem = "lhz"; break;
1303     case PPC_HI6_LHZU: load=1; wlen = 2;
1304     mnem = "lhzu"; break;
1305     case PPC_HI6_LHA: load=2; wlen = 2;
1306     mnem = "lha"; break;
1307     case PPC_HI6_LHAU: load=2; wlen = 2;
1308     mnem = "lhau"; break;
1309     case PPC_HI6_LBZ: load=1; wlen = 1;
1310     mnem = "lbz"; break;
1311     case PPC_HI6_LBZU: load=1; wlen = 1;
1312     mnem = "lbzu"; break;
1313     case PPC_HI6_STW: wlen=4; mnem = power? "st" : "stw"; break;
1314     case PPC_HI6_STWU: wlen=4; mnem = power? "stu" : "stwu"; break;
1315     case PPC_HI6_STH: wlen=2; mnem = "sth"; break;
1316     case PPC_HI6_STHU: wlen=2; mnem = "sthu"; break;
1317     case PPC_HI6_STB: wlen=1; mnem = "stb"; break;
1318     case PPC_HI6_STBU: wlen=1; mnem = "stbu"; break;
1319     case PPC_HI6_LMW: load=1; mnem = power? "lm" : "lmw"; break;
1320     case PPC_HI6_STMW: mnem = power? "stm" : "stmw"; break;
1321     case PPC_HI6_LFD: load=1; fpreg = 1; mnem = "lfd"; break;
1322     case PPC_HI6_STFD: fpreg = 1; mnem = "stfd"; break;
1323     }
1324     debug("%s\t", mnem);
1325     if (fpreg)
1326     debug("f");
1327     else
1328     debug("r");
1329     debug("%i,%i(r%i)", rs, imm, ra);
1330     if (!running)
1331     break;
1332     addr = (ra==0? 0 : cpu->cd.ppc.gpr[ra]) + imm;
1333     symbol = get_symbol_name(&cpu->machine->symbol_context,
1334     addr, &offset);
1335     if (symbol != NULL)
1336     debug(" \t<%s", symbol);
1337     else
1338     debug(" \t<0x%llx", (long long)addr);
1339     if (wlen > 0 && load && wlen > 0) {
1340     unsigned char tw[8];
1341     uint64_t tdata = 0;
1342     int i, res = cpu->memory_rw(cpu, cpu->mem, addr, tw,
1343     wlen, MEM_READ, NO_EXCEPTIONS);
1344     if (res) {
1345     if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
1346     for (i=0; i<wlen; i++) {
1347     tdata <<= 8;
1348     tdata |= tw[wlen-1-i];
1349     }
1350     else
1351     for (i=0; i<wlen; i++) {
1352     tdata <<= 8;
1353     tdata |= tw[i];
1354     }
1355     debug(": ");
1356     if (wlen >= 4) {
1357     symbol = get_symbol_name(&cpu->machine->
1358     symbol_context, tdata, &offset);
1359     if (symbol != NULL)
1360     debug("%s", symbol);
1361     else
1362     debug("0x%llx",
1363     (long long)tdata);
1364     } else {
1365     /* TODO: if load==2, then this is
1366     a _signed_ load. */
1367     debug("0x%llx", (long long)tdata);
1368     }
1369     } else
1370     debug(": unreadable");
1371     }
1372     if (wlen > 0 && !load && wlen > 0) {
1373     int64_t tdata = 0;
1374     int i;
1375     for (i=0; i<wlen; i++)
1376     tdata |= (cpu->cd.ppc.gpr[rs] &
1377     ((uint64_t)0xff << i));
1378     debug(": ");
1379     if (wlen >= 4) {
1380     symbol = get_symbol_name(&cpu->machine->
1381     symbol_context, tdata, &offset);
1382     if (symbol != NULL)
1383     debug("%s", symbol);
1384     else
1385     debug("0x%llx",
1386     (long long)tdata);
1387     } else {
1388     if (tdata > -256 && tdata < 256)
1389     debug("%i", (int)tdata);
1390     else
1391     debug("0x%llx", (long long)tdata);
1392     }
1393     }
1394     debug(">");
1395     break;
1396     case PPC_HI6_63:
1397     xo = (iword >> 1) & 1023;
1398     switch (xo) {
1399     case PPC_63_FMR:
1400     rt = (iword >> 21) & 31;
1401     ra = (iword >> 16) & 31;
1402     rb = (iword >> 11) & 31;
1403     rc = iword & 1;
1404     switch (xo) {
1405     case PPC_63_FMR:
1406     debug("fmr%s\tf%i,f%i", rc? "." : "", rt, rb);
1407     break;
1408     }
1409     break;
1410     default:
1411     debug("unimplemented hi6_31, xo = 0x%x", xo);
1412     }
1413     break;
1414     default:
1415     /* TODO */
1416     debug("unimplemented hi6 = 0x%02x", hi6);
1417     }
1418    
1419     debug("\n");
1420     return sizeof(iword);
1421     }
1422    
1423    
1424     /*
1425     * update_cr0():
1426     *
1427     * Sets the top 4 bits of the CR register.
1428     */
1429     void update_cr0(struct cpu *cpu, uint64_t value)
1430     {
1431     int c;
1432    
1433     if (cpu->cd.ppc.bits == 64) {
1434     if ((int64_t)value < 0)
1435     c = 8;
1436     else if ((int64_t)value > 0)
1437     c = 4;
1438     else
1439     c = 2;
1440     } else {
1441     if ((int32_t)value < 0)
1442     c = 8;
1443     else if ((int32_t)value > 0)
1444     c = 4;
1445     else
1446     c = 2;
1447     }
1448    
1449     /* SO bit, copied from XER: */
1450     c |= ((cpu->cd.ppc.xer >> 31) & 1);
1451    
1452     cpu->cd.ppc.cr &= ~((uint32_t)0xf << 28);
1453     cpu->cd.ppc.cr |= ((uint32_t)c << 28);
1454     }
1455    
1456    
1457     #include "memory_ppc.c"
1458    
1459    
1460     #include "tmp_ppc_tail.c"
1461    

  ViewVC Help
Powered by ViewVC 1.1.26