/[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 28 - (hide annotations)
Mon Oct 8 16:20:26 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 51717 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1298 2006/07/22 11:27:46 debug Exp $
20060626	Continuing on SPARC emulation (beginning on the 'save'
		instruction, register windows, etc).
20060629	Planning statistics gathering (new -s command line option),
		and renaming speed_tricks to allow_instruction_combinations.
20060630	Some minor manual page updates.
		Various cleanups.
		Implementing the -s command line option.
20060701	FINALLY found the bug which prevented Linux and Ultrix from
		running without the ugly hack in the R2000/R3000 cache isol
		code; it was the phystranslation hint array which was buggy.
		Removing the phystranslation hint code completely, for now.
20060702	Minor dyntrans cleanups; invalidation of physpages now only
		invalidate those parts of a page that have actually been
		translated. (32 parts per page.)
		Some MIPS non-R3000 speed fixes.
		Experimenting with MIPS instruction combination for some
		addiu+bne+sw loops, and sw+sw+sw.
		Adding support (again) for larger-than-4KB pages in MIPS tlbw*.
		Continuing on SPARC emulation: adding load/store instructions.
20060704	Fixing a virtual vs physical page shift bug in the new tlbw*
		implementation. Problem noticed by Jakub Jermar. (Many thanks.)
		Moving rfe and eret to cpu_mips_instr.c, since that is the
		only place that uses them nowadays.
20060705	Removing the BSD license from the "testmachine" include files,
		placing them in the public domain instead; this enables the
		testmachine stuff to be used from projects which are
		incompatible with the BSD license for some reason.
20060707	Adding instruction combinations for the R2000/R3000 L1
		I-cache invalidation code used by NetBSD/pmax 3.0, lui+addiu,
		various branches followed by addiu or nop, and jr ra followed
		by addiu. The time it takes to perform a full NetBSD/pmax R3000
		install on the laptop has dropped from 573 seconds to 539. :-)
20060708	Adding a framebuffer controller device (dev_fbctrl), which so
		far can be used to change the fb resolution during runtime, but
		in the future will also be useful for accelerated block fill/
		copy, and possibly also simplified character output.
		Adding an instruction combination for NetBSD/pmax' strlen.
20060709	Minor fixes: reading raw files in src/file.c wasn't memblock
		aligned, removing buggy multi_sw MIPS instruction combination,
		etc.
20060711	Adding a machine_qemu.c, which contains a "qemu_mips" machine.
		(It mimics QEMU's MIPS machine mode, so that a test kernel
		made for QEMU_MIPS also can run in GXemul... at least to some
		extent.)  Adding a short section about how to run this mode to
		doc/guestoses.html.
20060714	Misc. minor code cleanups.
20060715	Applying a patch which adds getchar() to promemul/yamon.c
		(from Oleksandr Tymoshenko).
		Adding yamon.h from NetBSD, and rewriting yamon.c to use it
		(instead of ugly hardcoded numbers) + some cleanup.
20060716	Found and fixed the bug which broke single-stepping of 64-bit
		programs between 0.4.0 and 0.4.0.1 (caused by too quick
		refactoring and no testing). Hopefully this fix will not
		break too many other things.
20060718	Continuing on the 8253 PIT; it now works with Linux/QEMU_MIPS.
		Re-adding the sw+sw+sw instr comb (the problem was that I had
		ignored endian issues); however, it doesn't seem to give any
		big performance gain.
20060720	Adding a dummy Transputer mode (T414, T800 etc) skeleton (only
		the 'j' and 'ldc' instructions are implemented so far). :-}
20060721	Adding gtreg.h from NetBSD, updating dev_gt.c to use it, plus
		misc. other updates to get Linux 2.6 for evbmips/malta working
		(thanks to Alec Voropay for the details).
		FINALLY found and fixed the bug which made tlbw* for non-R3000
		buggy; it was a reference count problem in the dyntrans core.
20060722	Testing stuff; things seem stable enough for a new release.

==============  RELEASE 0.4.1  ==============


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

  ViewVC Help
Powered by ViewVC 1.1.26