/[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 18 - (show annotations)
Mon Oct 8 16:19:11 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 37964 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1004 2005/10/27 14:01:10 debug Exp $
20051011        Passing -A as the default boot arg for CATS (works fine with
                OpenBSD/cats).
20051012	Fixing the VGA cursor offset bug, and speeding up framebuffer
		redraws if character cells contain the same thing as during
		the last redraw.
20051013	Adding a slow strd ARM instruction hack.
20051017	Minor updates: Adding a dummy i80321 Verde controller (for
		XScale emulation), fixing the disassembly of the ARM "ldrd"
		instruction, adding "support" for less-than-4KB pages for ARM
		(by not adding them to translation tables).
20051020	Continuing on some HPCarm stuff. A NetBSD/hpcarm kernel prints
		some boot messages on an emulated Jornada 720.
		Making dev_ram work better with dyntrans (speeds up some things
		quite a bit).
20051021	Automatically generating some of the most common ARM load/store
		multiple instructions.
20051022	Better statistics gathering for the ARM load/store multiple.
		Various other dyntrans and device updates.
20051023	Various minor updates.
20051024	Continuing; minor device and dyntrans fine-tuning. Adding the
		first "reasonable" instruction combination hacks for ARM (the
		cores of NetBSD/cats' memset and memcpy).
20051025	Fixing a dyntrans-related bug in dev_vga. Also changing the
		dyntrans low/high access notification to only be updated on
		writes, not reads. Hopefully it will be enough. (dev_vga in
		charcell mode now seems to work correctly with both reads and
		writes.)
		Experimenting with gathering dyntrans statistics (which parts
		of emulated RAM that are actually executed), and adding
		instruction combination hacks for cache cleaning and a part of
		NetBSD's scanc() function.
20051026	Adding a bitmap for ARM emulation which indicates if a page is
		(specifically) user accessible; loads and stores with the t-
		flag set can now use the translation arrays, which results in
		a measurable speedup.
20051027	Dyntrans updates; adding an extra bitmap array for 32-bit
		emulation modes, speeding up the check whether a physical page
		has any code translations or not (O(n) -> O(1)). Doing a
		similar reduction of O(n) to O(1) by avoiding the scan through
		the translation entries on a translation update (32-bit mode
		only).
		Various other minor hacks.
20051029	Quick release, without any testing at all.

==============  RELEASE 0.3.6.2  ==============


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

  ViewVC Help
Powered by ViewVC 1.1.26