/[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

Contents of /trunk/src/cpus/cpu_ppc.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 30 - (show 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 /*
2 * Copyright (C) 2005-2006 Anders Gavare. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * 3. The name of the author may not be used to endorse or promote products
13 * derived from this software without specific prior written permission.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 *
27 *
28 * $Id: cpu_ppc.c,v 1.61 2006/07/24 21:14:52 debug Exp $
29 *
30 * PowerPC/POWER CPU emulation.
31 */
32
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <ctype.h>
37
38 #include "cpu.h"
39 #include "devices.h"
40 #include "machine.h"
41 #include "memory.h"
42 #include "misc.h"
43 #include "of.h"
44 #include "opcodes_ppc.h"
45 #include "ppc_bat.h"
46 #include "ppc_pte.h"
47 #include "ppc_spr.h"
48 #include "ppc_spr_strings.h"
49 #include "symbol.h"
50
51 #define DYNTRANS_DUALMODE_32
52 #include "tmp_ppc_head.c"
53
54
55 void ppc_pc_to_pointers(struct cpu *);
56 void ppc32_pc_to_pointers(struct cpu *);
57
58
59 /*
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 cpu->cd.ppc.spr[SPR_PVR] = cpu->cd.ppc.cpu_type.pvr;
97
98 /* cpu->cd.ppc.msr = PPC_MSR_IR | PPC_MSR_DR |
99 PPC_MSR_SF | PPC_MSR_FP; */
100
101 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 cpu->is_32bit = (cpu->cd.ppc.bits == 32)? 1 : 0;
117
118 if (cpu->is_32bit) {
119 cpu->run_instr = ppc32_run_instr;
120 cpu->update_translation_table = ppc32_update_translation_table;
121 cpu->invalidate_translation_caches =
122 ppc32_invalidate_translation_caches;
123 cpu->invalidate_code_translation =
124 ppc32_invalidate_code_translation;
125 } else {
126 cpu->run_instr = ppc_run_instr;
127 cpu->update_translation_table = ppc_update_translation_table;
128 cpu->invalidate_translation_caches =
129 ppc_invalidate_translation_caches;
130 cpu->invalidate_code_translation =
131 ppc_invalidate_code_translation;
132 }
133
134 cpu->translate_v2p = ppc_translate_v2p;
135
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 cpu->cd.ppc.spr[SPR_PIR] = cpu_id;
161
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 void reg_access_msr(struct cpu *cpu, uint64_t *valuep, int writeflag,
236 int check_for_interrupts)
237 {
238 uint64_t old = cpu->cd.ppc.msr;
239
240 if (valuep == NULL) {
241 fatal("reg_access_msr(): NULL\n");
242 return;
243 }
244
245 if (writeflag) {
246 cpu->cd.ppc.msr = *valuep;
247
248 /* 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 /* 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
274 if (check_for_interrupts && cpu->cd.ppc.msr & PPC_MSR_EE) {
275 if (cpu->cd.ppc.dec_intr_pending &&
276 !(cpu->cd.ppc.cpu_type.flags & PPC_NO_DEC)) {
277 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 }
283
284
285 /*
286 * 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 fatal("[ PPC Exception 0x%x; pc=0x%"PRIx64" ]\n", exception_nr,
301 (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 cpu->pc += 0xfff00000ULL;
310
311 if (cpu->is_32bit)
312 ppc32_pc_to_pointers(cpu);
313 else
314 ppc_pc_to_pointers(cpu);
315 }
316
317
318 /*
319 * 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 debug("%08"PRIx32, (uint32_t)cpu->pc);
341 else
342 debug("%016"PRIx64, (uint64_t)cpu->pc);
343 debug(" <%s>\n", symbol != NULL? symbol : " no symbol ");
344
345 debug("cpu%i: lr = 0x", x);
346 if (bits32)
347 debug("%08"PRIx32, (uint32_t)cpu->cd.ppc.spr[SPR_LR]);
348 else
349 debug("%016"PRIx64, (uint64_t)cpu->cd.ppc.spr[SPR_LR]);
350 debug(" cr = 0x%08"PRIx32, (uint32_t)cpu->cd.ppc.cr);
351
352 if (bits32)
353 debug(" ");
354 else
355 debug("\ncpu%i: ", x);
356 debug("ctr = 0x", x);
357 if (bits32)
358 debug("%08"PRIx32, (uint32_t)cpu->cd.ppc.spr[SPR_CTR]);
359 else
360 debug("%016"PRIx64, (uint64_t)cpu->cd.ppc.spr[SPR_CTR]);
361
362 debug(" xer = 0x", x);
363 if (bits32)
364 debug("%08"PRIx32, (uint32_t)cpu->cd.ppc.spr[SPR_XER]);
365 else
366 debug("%016"PRIx64, (uint64_t)cpu->cd.ppc.spr[SPR_XER]);
367
368 debug("\n");
369
370 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 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 reg_access_msr(cpu, &tmp, 0, 0);
405 if (bits32)
406 debug("0x%08x ", (int)tmp);
407 else
408 debug("0x%016llx ", (long long)tmp);
409 debug("tb = 0x%08x%08x\n", (int)cpu->cd.ppc.spr[SPR_TBU],
410 (int)cpu->cd.ppc.spr[SPR_TBL]);
411 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 }
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 (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 }
478
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 }
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 m->cpus[cpunr]->cd.ppc.spr[SPR_LR] = *valuep;
543 else
544 *valuep = m->cpus[cpunr]->cd.ppc.spr[SPR_LR];
545 *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 m->cpus[cpunr]->cd.ppc.spr[SPR_DEC] = *valuep;
555 else
556 *valuep = m->cpus[cpunr]->cd.ppc.spr[SPR_DEC];
557 *match_register = 1;
558 } else if (strcasecmp(name, "hdec") == 0) {
559 if (writeflag)
560 m->cpus[cpunr]->cd.ppc.spr[SPR_HDEC] = *valuep;
561 else
562 *valuep = m->cpus[cpunr]->cd.ppc.spr[SPR_HDEC];
563 *match_register = 1;
564 } else if (strcasecmp(name, "ctr") == 0) {
565 if (writeflag)
566 m->cpus[cpunr]->cd.ppc.spr[SPR_CTR] = *valuep;
567 else
568 *valuep = m->cpus[cpunr]->cd.ppc.spr[SPR_CTR];
569 *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 m->cpus[cpunr]->cd.ppc.spr[SPR_XER] = *valuep;
582 else
583 *valuep = m->cpus[cpunr]->cd.ppc.spr[SPR_XER];
584 *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 * 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 * ppc_cpu_interrupt():
703 *
704 * 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 *
707 * TODO: don't hardcode to BeBox!
708 */
709 int ppc_cpu_interrupt(struct cpu *cpu, uint64_t irq_nr)
710 {
711 /* 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 }
724
725
726 /*
727 * ppc_cpu_interrupt_ack():
728 */
729 int ppc_cpu_interrupt_ack(struct cpu *cpu, uint64_t irq_nr)
730 {
731 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 }
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 int running, uint64_t dumpaddr)
757 {
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 case 0x4:
796 debug("ALTIVEC TODO");
797 /* vxor etc */
798 break;
799 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 case PPC_HI6_RLWNM:
992 case PPC_HI6_RLWIMI:
993 case PPC_HI6_RLWINM:
994 rs = (iword >> 21) & 31;
995 ra = (iword >> 16) & 31;
996 sh = (iword >> 11) & 31; /* actually rb for rlwnm */
997 mb = (iword >> 6) & 31;
998 me = (iword >> 1) & 31;
999 rc = iword & 1;
1000 switch (hi6) {
1001 case PPC_HI6_RLWNM:
1002 mnem = power? "rlnm" : "rlwnm"; break;
1003 case PPC_HI6_RLWIMI:
1004 mnem = power? "rlimi" : "rlwimi"; break;
1005 case PPC_HI6_RLWINM:
1006 mnem = power? "rlinm" : "rlwinm"; break;
1007 }
1008 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 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 case PPC_30_RLDICL:
1051 case PPC_30_RLDICR:
1052 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 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 debug("%s%s\tr%i,r%i,%i,%i",
1065 mnem, rc?".":"", ra, rs, sh, me);
1066 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 case PPC_31_LHAX:
1126 case PPC_31_LHAUX:
1127 case PPC_31_LHZX:
1128 case PPC_31_LHZUX:
1129 case PPC_31_LWZX:
1130 case PPC_31_LWZUX:
1131 case PPC_31_LHBRX:
1132 case PPC_31_LWBRX:
1133 case PPC_31_LFDX:
1134 case PPC_31_LFSX:
1135 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 case PPC_31_STHBRX:
1146 case PPC_31_STWBRX:
1147 case PPC_31_STFDX:
1148 case PPC_31_STFSX:
1149 /* rs for stores, rt for loads, actually */
1150 load = 0; wlen = 0; fpreg = 0;
1151 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 case PPC_31_LHAX: wlen=2;load=1; mnem = "lhax"; break;
1160 case PPC_31_LHAUX: wlen=2;load=1; mnem = "lhaux"; break;
1161 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 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 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 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 }
1198 debug("%s\t%s%i,r%i,r%i", mnem,
1199 fpreg? "f" : "r", rs, ra, rb);
1200 if (!running)
1201 break;
1202 addr = (ra==0? 0 : cpu->cd.ppc.gpr[ra]) +
1203 cpu->cd.ppc.gpr[rb];
1204 if (cpu->cd.ppc.bits == 32)
1205 addr &= 0xffffffff;
1206 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 if (wlen > 0 && !fpreg /* && !reverse */) {
1213 /* 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 case PPC_31_WRTEEI:
1230 debug("wrteei\t%i", iword & 0x8000? 1 : 0);
1231 break;
1232 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 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 case PPC_31_MFSR:
1258 /* Move to/from segment register */
1259 rt = (iword >> 21) & 31;
1260 ra = (iword >> 16) & 15; /* actually: sr */
1261 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 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 case PPC_31_SUBFME:
1297 case PPC_31_SUBFMEO:
1298 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 mnem = power? "sf" : "subfc"; break;
1344 case PPC_31_SUBFCO:
1345 mnem = power? "sfo" : "subfco"; break;
1346 case PPC_31_SUBFE:
1347 mnem = power? "sfe" : "subfe"; break;
1348 case PPC_31_SUBFEO:
1349 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 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 /* Some very common ones: */
1372 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 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 break;
1390 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 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 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 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 case PPC_31_SLD:
1461 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 case PPC_31_EQV:
1467 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 case PPC_31_SLD: mnem = "sld"; break;
1482 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 case PPC_31_EQV: mnem = "eqv"; break;
1491 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 /* Some very common ones: */
1532 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 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 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 case PPC_31_DSSALL:
1576 debug("dssall");
1577 break;
1578 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 case PPC_31_LVX:
1601 case PPC_31_LVXL:
1602 case PPC_31_STVX:
1603 case PPC_31_STVXL:
1604 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 break;
1617 default:
1618 debug("unimplemented hi6_31, xo = 0x%x", xo);
1619 }
1620 break;
1621 case PPC_HI6_LD:
1622 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 case PPC_HI6_LFD:
1631 case PPC_HI6_LFS:
1632 case PPC_HI6_LMW:
1633 case PPC_HI6_STD:
1634 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 case PPC_HI6_STFS:
1643 /* 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 case PPC_HI6_LD: load=1; wlen = 8; mnem = "ld"; break;
1652 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 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 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 case PPC_HI6_STFD: fpreg=1; wlen=8; mnem = "stfd"; break;
1680 case PPC_HI6_STFS: fpreg=1; wlen=4; mnem = "stfs"; break;
1681 }
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 if (cpu->cd.ppc.bits == 32)
1692 addr &= 0xffffffff;
1693 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 ((uint64_t)0xff << (i*8)));
1738 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 debug("0x%llx", (long long)tdata);
1746 } 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 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 case PPC_HI6_63:
1793 xo = (iword >> 1) & 1023;
1794 /* 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 rt = (iword >> 21) & 31;
1804 ra = (iword >> 16) & 31;
1805 rb = (iword >> 11) & 31;
1806 rs = (iword >> 6) & 31; /* actually frc */
1807 rc = iword & 1;
1808 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 switch (xo) {
1838 case PPC_63_FCMPU:
1839 case PPC_63_FRSP:
1840 case PPC_63_FCTIWZ:
1841 case PPC_63_FNEG:
1842 case PPC_63_FMR:
1843 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 break;
1871 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 }
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 * 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 * 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 c |= ((cpu->cd.ppc.spr[SPR_XER] >> 31) & 1);
1977
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

  ViewVC Help
Powered by ViewVC 1.1.26