/[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 30 - (hide annotations)
Mon Oct 8 16:20:40 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 51769 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1325 2006/08/15 15:38:37 debug Exp $
20060723	More Transputer instructions (pfix, nfix, opr, mint, ldl, ldlp,
		eqc, rev, ajw, stl, stlf, sthf, sub, ldnl, ldnlp, ldpi, move,
		wcnt, add, bcnt).
		Adding more SPARC instructions (andcc, addcc, bl, rdpr).
		Progress on the igsfb framebuffer used by NetBSD/netwinder.
		Enabling 8-bit fills in dev_fb.
		NetBSD/netwinder 3.0.1 can now run from a disk image :-)
20060724	Cleanup/performance fix for 64-bit virtual translation table
		updates (by removing the "timestamp" stuff). A full NetBSD/pmax
		3.0.1 install for R4400 has dropped from 667 seconds to 584 :)
		Fixing the igsfb "almost vga" color (it is 24-bit, not 18-bit).
		Adding some MIPS instruction combinations (3*lw, and 3*addu).
		The 8048 keyboard now turns off interrupt enable between the
		KBR_ACK and the KBR_RSTDONE, to work better with Linux 2.6.
		Not causing PPC DEC interrupts if PPC_NO_DEC is set for a
		specific CPU; NetBSD/bebox gets slightly further than before.
		Adding some more SPARC instructions: branches, udiv.
20060725	Refreshing dev_pckbc.c a little.
		Cleanups for the SH emulation mode, and adding the first
		"compact" (16-bit) instructions: various simple movs, nop,
		shll, stc, or, ldc.
20060726	Adding dummy "pcn" (AMD PCnet NIC) PCI glue.
20060727	Various cleanups; removing stuff from cpu.h, such as
		running_translated (not really meaningful anymore), and
		page flags (breaking into the debugger clears all translations
		anyway).
		Minor MIPS instruction combination updates.
20060807	Expanding the 3*sw and 3*lw MIPS instruction combinations to
		work with 2* and 4* too, resulting in a minor performance gain.
		Implementing a usleep hack for the RM52xx/MIPS32/MIPS64 "wait"
		instruction (when emulating 1 cpu).
20060808	Experimenting with some more MIPS instruction combinations.
		Implementing support for showing a (hardcoded 12x22) text
		cursor in igsfb.
20060809	Simplifying the NetBSD/evbmips (Malta) install instructions
		somewhat (by using a NetBSD/pmax ramdisk install kernel).
20060812	Experimenting more with the MIPS 'wait' instruction.
		PCI configuration register writes can now be handled, which
		allow PCI IDE controllers to work with NetBSD/Malta 3.0.1 and
		NetBSD/cobalt 3.0.1. (Previously only NetBSD 2.1 worked.)
20060813	Updating dev_gt.c based on numbers from Alec Voropay, to enable
		Linux 2.6 to use PCI on Malta.
		Continuing on Algor interrupt stuff.
20060814	Adding support for routing ISA interrupts to two different
		interrupts, making it possible to run NetBSD/algor :-)
20060814-15	Testing for the release.

==============  RELEASE 0.4.2  ==============


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

  ViewVC Help
Powered by ViewVC 1.1.26