/[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 44 - (hide annotations)
Mon Oct 8 16:22:56 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 49821 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1632 2007/09/11 21:46:35 debug Exp $
20070616	Implementing the MIPS32/64 revision 2 "ror" instruction.
20070617	Adding a struct for each physpage which keeps track of which
		ranges within that page (base offset, length) that are
		continuously translatable. When running with native code
		generation enabled (-b), a range is added after each read-
		ahead loop.
		Experimenting with using the physical program counter sample
		data (implemented 20070608) together with the "translatable
		range" information, to figure out which physical address ranges
		would be worth translating to native code (if the number of
		samples falling within a range is above a certain threshold).
20070618	Adding automagic building of .index comment files for
		src/file/, src/promemul/, src src/useremul/ as well.
		Adding a "has been translated" bit to the ranges, so that only
		not-yet-translated ranges will be sampled.
20070619	Moving src/cpu.c and src/memory_rw.c into src/cpus/,
		src/device.c into src/devices/, and src/machine.c into
		src/machines/.
		Creating a skeleton cc/ld native backend module; beginning on
		the function which will detect cc command line, etc.
20070620	Continuing on the native code generation infrastructure.
20070621	Moving src/x11.c and src/console.c into a new src/console/
		subdir (for everything that is console or framebuffer related).
		Moving src/symbol*.c into a new src/symbol/, which should
		contain anything that is symbol handling related.
20070624	Making the program counter sampling threshold a "settings
		variable" (sampling_threshold), i.e. it can now be changed
		during runtime.
		Switching the RELEASE notes format from plain text to HTML.
		If the TMPDIR environment variable is set, it is used instead
		of "/tmp" for temporary files.
		Continuing on the cc/ld backend: simple .c code is generated,
		the compiler and linker are called, etc.
		Adding detection of host architecture to the configure script
		(again), and adding icache invalidation support (only
		implemented for Alpha hosts so far).
20070625	Simplifying the program counter sampling mechanism.
20070626	Removing the cc/ld native code generation stuff, program
		counter sampling, etc; it would not have worked well in the
		general case.
20070627	Removing everything related to native code generation.
20070629	Removing the (practically unusable) support for multiple
		emulations. (The single emulation allowed now still supports
		multiple simultaneous machines, as before.)
		Beginning on PCCTWO and M88K interrupts.
20070723	Adding a dummy skeleton for emulation of M32R processors.
20070901	Fixing a warning found by "gcc version 4.3.0 20070817
		(experimental)" on amd64.
20070905	Removing some more traces of the old "multiple emulations"
		code.
		Also looking in /usr/local/include and /usr/local/lib for
		X11 libs, when running configure.
20070909	Minor updates to the guest OS install instructions, in
		preparation for the NetBSD 4.0 release.
20070918	More testing of NetBSD 4.0 RC1.

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

  ViewVC Help
Powered by ViewVC 1.1.26