/[gxemul]/trunk/src/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/cpu_ppc.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 10 - (show annotations)
Mon Oct 8 16:18:27 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 69237 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.815 2005/06/27 23:04:35 debug Exp $
20050617	Experimenting some more with netbooting OpenBSD/sgi. Adding
		a hack which allows emulated ethernet networks to be
		distributed across multiple emulator processes.
20050618	Minor updates (documentation, dummy YAMON emulation, etc).
20050620	strcpy/strcat -> strlcpy/strlcat updates.
		Some more progress on evbmips (Malta).
20050621	Adding a section to doc/configfiles.html about ethernet
		emulation across multiple hosts.
		Beginning the work on the ARM translation engine (using the
		dynamic-but-not-binary translation method).
		Fixing a bintrans bug: 0x9fc00000 should always be treated as
		PROM area, just as 0xbfc00000 is.
		Minor progress on Malta emulation (the PCI-ISA bus).
20050622	NetBSD/evbmips can now be installed (using another emulated
		machine) and run (including userland and so on). :-)
		Spliting up the bintrans haddr_entry field into two (one for
		read, one for write). Probably not much of a speed increase,
		though.
		Updating some NetBSD 2.0 -> 2.0.2 in the documentation.
20050623	Minor updates (documentation, the TODO file, etc).
		gzipped kernels are now always automagically gunzipped when
		loaded.
20050624	Adding a dummy Playstation Portable (PSP) mode, just barely
		enough to run Hello World (in weird colors :-).
		Removing the -b command line option; old bintrans is enabled
		by default instead. It makes more sense.
		Trying to finally fix the non-working performance measurement
		thing (instr/second etc).
20050625	Continuing on the essential basics for ARM emulation. Two
		instructions seem to work, a branch and a simple "mov". (The
		mov arguments are not correct yet.) Performance is definitely
		reasonable.
		Various other minor updates.
		Adding the ARM "bl" instruction.
		Adding support for combining multiple ARM instructions into one
		function call. ("mov" + "mov" is the only one implemented so
		far, but it seems to work.)
		Cleaning up some IP32 interrupt things (crime/mace); disabling
		the PS/2 keyboard controller on IP32, so that NetBSD/sgimips
		boots into userland again.
20050626	Finally! NetBSD/sgimips netboots. Adding instructions to
		doc/guestoses.html on how to set up an nfs server etc.
		Various other minor fixes.
		Playstation Portable ".pbp" files can now be used directly.
		(The ELF part of the .pbp is extracted transparently.)
		Converting some sprintf -> snprintf.
		Adding some more instructions to the ARM disassembler.
20050627	More ARM updates. Adding some simple ldr(b), str(b),
		cmps, and conditional branch instructions, enough to run
		a simple Hello World program.
		All ARM instructions are now inlined/generated for all possible
		condition codes.
		Adding add and sub, and more load/store instructions.
		Removing dummy files: cpu_alpha.c, cpu_hppa.c, and cpu_sparc.c.
		Some minor documentation updates; preparing for a 0.3.4
		release. Updating some URLs.

==============  RELEASE 0.3.4  ==============


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.63 2005/06/26 22:23:42 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 "misc.h"
39
40
41 #ifndef ENABLE_PPC
42
43
44 #include "cpu_ppc.h"
45
46
47 /*
48 * ppc_cpu_family_init():
49 *
50 * Bogus function.
51 */
52 int ppc_cpu_family_init(struct cpu_family *fp)
53 {
54 return 0;
55 }
56
57
58 #else /* ENABLE_PPC */
59
60
61 #include "cpu.h"
62 #include "cpu_ppc.h"
63 #include "machine.h"
64 #include "memory.h"
65 #include "opcodes_ppc.h"
66 #include "symbol.h"
67
68
69 extern volatile int single_step;
70 extern int old_show_trace_tree;
71 extern int old_instruction_trace;
72 extern int old_quiet_mode;
73 extern int quiet_mode;
74
75
76 /*
77 * ppc_cpu_new():
78 *
79 * Create a new PPC cpu object.
80 *
81 * Returns 1 on success, 0 if there was no matching PPC processor with
82 * this cpu_type_name.
83 */
84 int ppc_cpu_new(struct cpu *cpu, struct memory *mem, struct machine *machine,
85 int cpu_id, char *cpu_type_name)
86 {
87 int any_cache = 0;
88 int i, found;
89 struct ppc_cpu_type_def cpu_type_defs[] = PPC_CPU_TYPE_DEFS;
90
91 /* Scan the cpu_type_defs list for this cpu type: */
92 i = 0;
93 found = -1;
94 while (i >= 0 && cpu_type_defs[i].name != NULL) {
95 if (strcasecmp(cpu_type_defs[i].name, cpu_type_name) == 0) {
96 found = i;
97 break;
98 }
99 i++;
100 }
101 if (found == -1)
102 return 0;
103
104 cpu->memory_rw = ppc_memory_rw;
105 cpu->cd.ppc.cpu_type = cpu_type_defs[found];
106 cpu->name = cpu->cd.ppc.cpu_type.name;
107 cpu->byte_order = EMUL_BIG_ENDIAN;
108 cpu->cd.ppc.mode = MODE_PPC; /* TODO */
109 cpu->cd.ppc.of_emul_addr = 0xff000000; /* TODO */
110
111 /* Current operating mode: */
112 cpu->cd.ppc.bits = cpu->cd.ppc.cpu_type.bits;
113
114 /* Only show name and caches etc for CPU nr 0 (in SMP machines): */
115 if (cpu_id == 0) {
116 debug("%s", cpu->cd.ppc.cpu_type.name);
117
118 if (cpu->cd.ppc.cpu_type.icache_shift != 0)
119 any_cache = 1;
120 if (cpu->cd.ppc.cpu_type.dcache_shift != 0)
121 any_cache = 1;
122 if (cpu->cd.ppc.cpu_type.l2cache_shift != 0)
123 any_cache = 1;
124
125 if (any_cache) {
126 debug(" (I+D = %i+%i KB",
127 (int)(1 << (cpu->cd.ppc.cpu_type.icache_shift-10)),
128 (int)(1 << (cpu->cd.ppc.cpu_type.dcache_shift-10)));
129 if (cpu->cd.ppc.cpu_type.l2cache_shift != 0) {
130 debug(", L2 = %i KB",
131 (int)(1 << (cpu->cd.ppc.cpu_type.
132 l2cache_shift-10)));
133 }
134 debug(")");
135 }
136 }
137
138 cpu->cd.ppc.pir = cpu_id;
139
140 /* Some default stack pointer value. TODO: move this? */
141 cpu->cd.ppc.gpr[1] = machine->physical_ram_in_mb * 1048576 - 4096;
142
143 return 1;
144 }
145
146
147 /*
148 * ppc_cpu_list_available_types():
149 *
150 * Print a list of available PPC CPU types.
151 */
152 void ppc_cpu_list_available_types(void)
153 {
154 int i, j;
155 struct ppc_cpu_type_def tdefs[] = PPC_CPU_TYPE_DEFS;
156
157 i = 0;
158 while (tdefs[i].name != NULL) {
159 debug("%s", tdefs[i].name);
160 for (j=10 - strlen(tdefs[i].name); j>0; j--)
161 debug(" ");
162 i++;
163 if ((i % 6) == 0 || tdefs[i].name == NULL)
164 debug("\n");
165 }
166 }
167
168
169 /*
170 * ppc_cpu_dumpinfo():
171 */
172 void ppc_cpu_dumpinfo(struct cpu *cpu)
173 {
174 struct ppc_cpu_type_def *ct = &cpu->cd.ppc.cpu_type;
175
176 debug(" (%i-bit ", cpu->cd.ppc.bits);
177
178 switch (cpu->cd.ppc.mode) {
179 case MODE_PPC:
180 debug("PPC");
181 break;
182 case MODE_POWER:
183 debug("POWER");
184 break;
185 default:
186 debug("_INTERNAL ERROR_");
187 }
188
189 debug(", I+D = %i+%i KB",
190 (1 << ct->icache_shift) / 1024,
191 (1 << ct->dcache_shift) / 1024);
192
193 if (ct->l2cache_shift) {
194 int kb = (1 << ct->l2cache_shift) / 1024;
195 debug(", L2 = %i %cB",
196 kb >= 1024? kb / 1024 : kb,
197 kb >= 1024? 'M' : 'K');
198 }
199
200 debug(")\n");
201 }
202
203
204 /*
205 * reg_access_msr():
206 */
207 static void reg_access_msr(struct cpu *cpu, uint64_t *valuep, int writeflag)
208 {
209 if (valuep == NULL) {
210 fatal("reg_access_msr(): NULL\n");
211 return;
212 }
213
214 if (writeflag)
215 cpu->cd.ppc.msr = *valuep;
216
217 /* TODO: Is the little-endian bit writable? */
218
219 cpu->cd.ppc.msr &= ~PPC_MSR_LE;
220 if (cpu->byte_order != EMUL_BIG_ENDIAN)
221 cpu->cd.ppc.msr |= PPC_MSR_LE;
222
223 if (!writeflag)
224 *valuep = cpu->cd.ppc.msr;
225 }
226
227
228 /*
229 * ppc_cpu_register_dump():
230 *
231 * Dump cpu registers in a relatively readable format.
232 *
233 * gprs: set to non-zero to dump GPRs and some special-purpose registers.
234 * coprocs: set bit 0..3 to dump registers in coproc 0..3.
235 */
236 void ppc_cpu_register_dump(struct cpu *cpu, int gprs, int coprocs)
237 {
238 char *symbol;
239 uint64_t offset, tmp;
240 int i, x = cpu->cpu_id;
241 int bits32 = cpu->cd.ppc.bits == 32;
242
243 if (gprs) {
244 /* Special registers (pc, ...) first: */
245 symbol = get_symbol_name(&cpu->machine->symbol_context,
246 cpu->pc, &offset);
247
248 debug("cpu%i: pc = 0x", x);
249 if (bits32)
250 debug("%08x", (int)cpu->pc);
251 else
252 debug("%016llx", (long long)cpu->pc);
253 debug(" <%s>\n", symbol != NULL? symbol : " no symbol ");
254
255 debug("cpu%i: lr = 0x", x);
256 if (bits32)
257 debug("%08x", (int)cpu->cd.ppc.lr);
258 else
259 debug("%016llx", (long long)cpu->cd.ppc.lr);
260 debug(" cr = 0x%08x\n", (int)cpu->cd.ppc.cr);
261
262 debug("cpu%i: ctr = 0x", x);
263 if (bits32)
264 debug("%08x", (int)cpu->cd.ppc.ctr);
265 else
266 debug("%016llx", (long long)cpu->cd.ppc.ctr);
267
268 debug(" xer = 0x", x);
269 if (bits32)
270 debug("%08x\n", (int)cpu->cd.ppc.xer);
271 else
272 debug("%016llx\n", (long long)cpu->cd.ppc.xer);
273
274 if (bits32) {
275 /* 32-bit: */
276 for (i=0; i<PPC_NGPRS; i++) {
277 if ((i % 4) == 0)
278 debug("cpu%i:", x);
279 debug(" r%02i = 0x%08x ", i,
280 (int)cpu->cd.ppc.gpr[i]);
281 if ((i % 4) == 3)
282 debug("\n");
283 }
284 } else {
285 /* 64-bit: */
286 for (i=0; i<PPC_NGPRS; i++) {
287 if ((i % 2) == 0)
288 debug("cpu%i:", x);
289 debug(" r%02i = 0x%016llx ", i,
290 (long long)cpu->cd.ppc.gpr[i]);
291 if ((i % 2) == 1)
292 debug("\n");
293 }
294 }
295
296 /* Other special registers: */
297 reg_access_msr(cpu, &tmp, 0);
298 debug("cpu%i: msr = 0x%016llx ", x, (long long)tmp);
299 debug("tb = 0x%08x%08x\n",
300 (int)cpu->cd.ppc.tbu, (int)cpu->cd.ppc.tbl);
301 debug("cpu%i: dec = 0x%08x hdec = 0x%08x\n",
302 x, (int)cpu->cd.ppc.dec, (int)cpu->cd.ppc.hdec);
303 }
304
305 if (coprocs) {
306 debug("cpu%i: fpscr = 0x%08x\n", x, (int)cpu->cd.ppc.fpscr);
307
308 /* TODO: show floating-point values :-) */
309
310 /* TODO: 32-bit fprs on 32-bit PPC cpus? */
311
312 for (i=0; i<PPC_NFPRS; i++) {
313 if ((i % 2) == 0)
314 debug("cpu%i:", x);
315 debug(" f%02i = 0x%016llx ", i,
316 (long long)cpu->cd.ppc.fpr[i]);
317 if ((i % 2) == 1)
318 debug("\n");
319 }
320 }
321 }
322
323
324 /*
325 * ppc_cpu_register_match():
326 */
327 void ppc_cpu_register_match(struct machine *m, char *name,
328 int writeflag, uint64_t *valuep, int *match_register)
329 {
330 int cpunr = 0;
331
332 /* CPU number: */
333
334 /* TODO */
335
336 /* Register name: */
337 if (strcasecmp(name, "pc") == 0) {
338 if (writeflag) {
339 m->cpus[cpunr]->pc = *valuep;
340 } else
341 *valuep = m->cpus[cpunr]->pc;
342 *match_register = 1;
343 } else if (strcasecmp(name, "msr") == 0) {
344 if (writeflag)
345 m->cpus[cpunr]->cd.ppc.msr = *valuep;
346 else
347 *valuep = m->cpus[cpunr]->cd.ppc.msr;
348 *match_register = 1;
349 } else if (strcasecmp(name, "lr") == 0) {
350 if (writeflag)
351 m->cpus[cpunr]->cd.ppc.lr = *valuep;
352 else
353 *valuep = m->cpus[cpunr]->cd.ppc.lr;
354 *match_register = 1;
355 } else if (strcasecmp(name, "cr") == 0) {
356 if (writeflag)
357 m->cpus[cpunr]->cd.ppc.cr = *valuep;
358 else
359 *valuep = m->cpus[cpunr]->cd.ppc.cr;
360 *match_register = 1;
361 } else if (strcasecmp(name, "dec") == 0) {
362 if (writeflag)
363 m->cpus[cpunr]->cd.ppc.dec = *valuep;
364 else
365 *valuep = m->cpus[cpunr]->cd.ppc.dec;
366 *match_register = 1;
367 } else if (strcasecmp(name, "hdec") == 0) {
368 if (writeflag)
369 m->cpus[cpunr]->cd.ppc.hdec = *valuep;
370 else
371 *valuep = m->cpus[cpunr]->cd.ppc.hdec;
372 *match_register = 1;
373 } else if (strcasecmp(name, "ctr") == 0) {
374 if (writeflag)
375 m->cpus[cpunr]->cd.ppc.ctr = *valuep;
376 else
377 *valuep = m->cpus[cpunr]->cd.ppc.ctr;
378 *match_register = 1;
379 } else if (name[0] == 'r' && isdigit((int)name[1])) {
380 int nr = atoi(name + 1);
381 if (nr >= 0 && nr < PPC_NGPRS) {
382 if (writeflag) {
383 m->cpus[cpunr]->cd.ppc.gpr[nr] = *valuep;
384 } else
385 *valuep = m->cpus[cpunr]->cd.ppc.gpr[nr];
386 *match_register = 1;
387 }
388 } else if (strcasecmp(name, "xer") == 0) {
389 if (writeflag)
390 m->cpus[cpunr]->cd.ppc.xer = *valuep;
391 else
392 *valuep = m->cpus[cpunr]->cd.ppc.xer;
393 *match_register = 1;
394 } else if (strcasecmp(name, "fpscr") == 0) {
395 if (writeflag)
396 m->cpus[cpunr]->cd.ppc.fpscr = *valuep;
397 else
398 *valuep = m->cpus[cpunr]->cd.ppc.fpscr;
399 *match_register = 1;
400 } else if (name[0] == 'f' && isdigit((int)name[1])) {
401 int nr = atoi(name + 1);
402 if (nr >= 0 && nr < PPC_NFPRS) {
403 if (writeflag) {
404 m->cpus[cpunr]->cd.ppc.fpr[nr] = *valuep;
405 } else
406 *valuep = m->cpus[cpunr]->cd.ppc.fpr[nr];
407 *match_register = 1;
408 }
409 }
410 }
411
412
413 /*
414 * ppc_cpu_disassemble_instr():
415 *
416 * Convert an instruction word into human readable format, for instruction
417 * tracing.
418 *
419 * If running is 1, cpu->pc should be the address of the instruction.
420 *
421 * If running is 0, things that depend on the runtime environment (eg.
422 * register contents) will not be shown, and addr will be used instead of
423 * cpu->pc for relative addresses.
424 */
425 int ppc_cpu_disassemble_instr(struct cpu *cpu, unsigned char *instr,
426 int running, uint64_t dumpaddr, int bintrans)
427 {
428 int hi6, xo, lev, rt, rs, ra, rb, imm, sh, me, rc, l_bit, oe_bit;
429 int spr, aa_bit, lk_bit, bf, bh, bi, bo, mb, nb, bt, ba, bb, fpreg;
430 int bfa;
431 uint64_t offset, addr;
432 uint32_t iword;
433 char *symbol, *mnem = "ERROR";
434 int power = cpu->cd.ppc.mode == MODE_POWER;
435
436 if (running)
437 dumpaddr = cpu->pc;
438
439 symbol = get_symbol_name(&cpu->machine->symbol_context,
440 dumpaddr, &offset);
441 if (symbol != NULL && offset==0)
442 debug("<%s>\n", symbol);
443
444 if (cpu->machine->ncpus > 1 && running)
445 debug("cpu%i: ", cpu->cpu_id);
446
447 if (cpu->cd.ppc.bits == 32)
448 debug("%08x", (int)dumpaddr);
449 else
450 debug("%016llx", (long long)dumpaddr);
451
452 /* NOTE: Fixed to big-endian. */
453 iword = (instr[0] << 24) + (instr[1] << 16) + (instr[2] << 8)
454 + instr[3];
455
456 debug(": %08x\t", iword);
457
458 if (bintrans && !running) {
459 debug("(bintrans)");
460 goto disasm_ret;
461 }
462
463 /*
464 * Decode the instruction:
465 */
466
467 hi6 = iword >> 26;
468
469 switch (hi6) {
470 case PPC_HI6_MULLI:
471 case PPC_HI6_SUBFIC:
472 rt = (iword >> 21) & 31;
473 ra = (iword >> 16) & 31;
474 imm = (int16_t)(iword & 0xffff);
475 switch (hi6) {
476 case PPC_HI6_MULLI:
477 mnem = power? "muli":"mulli";
478 break;
479 case PPC_HI6_SUBFIC:
480 mnem = power? "sfi":"subfic";
481 break;
482 }
483 debug("%s\tr%i,r%i,%i", mnem, rt, ra, imm);
484 break;
485 case PPC_HI6_CMPLI:
486 case PPC_HI6_CMPI:
487 bf = (iword >> 23) & 7;
488 l_bit = (iword >> 21) & 1;
489 ra = (iword >> 16) & 31;
490 if (hi6 == PPC_HI6_CMPLI) {
491 imm = iword & 0xffff;
492 mnem = "cmpl";
493 } else {
494 imm = (int16_t)(iword & 0xffff);
495 mnem = "cmp";
496 }
497 debug("%s%si\t", mnem, l_bit? "d" : "w");
498 if (bf != 0)
499 debug("cr%i,", bf);
500 debug("r%i,%i", ra, imm);
501 break;
502 case PPC_HI6_ADDIC:
503 case PPC_HI6_ADDIC_DOT:
504 rt = (iword >> 21) & 31;
505 ra = (iword >> 16) & 31;
506 rc = hi6 == PPC_HI6_ADDIC_DOT;
507 imm = (int16_t)(iword & 0xffff);
508 mnem = power? "ai":"addic";
509 if (imm < 0 && !power) {
510 mnem = "subic";
511 imm = -imm;
512 }
513 debug("%s%s\tr%i,r%i,%i", mnem, rc?".":"", rt, ra, imm);
514 break;
515 case PPC_HI6_ADDI:
516 rt = (iword >> 21) & 31;
517 ra = (iword >> 16) & 31;
518 imm = (int16_t)(iword & 0xffff);
519 if (ra == 0)
520 debug("li\tr%i,%i", rt, imm);
521 else {
522 mnem = power? "cal":"addi";
523 if (imm < 0 && !power) {
524 mnem = "subi";
525 imm = -imm;
526 }
527 debug("%s\tr%i,r%i,%i", mnem, rt, ra, imm);
528 }
529 break;
530 case PPC_HI6_ADDIS:
531 rt = (iword >> 21) & 31;
532 ra = (iword >> 16) & 31;
533 imm = (int16_t)(iword & 0xffff);
534 if (ra == 0)
535 debug("lis\tr%i,%i", rt, imm);
536 else
537 debug("%s\tr%i,r%i,%i",
538 power? "cau":"addis", rt, ra, imm);
539 break;
540 case PPC_HI6_BC:
541 aa_bit = (iword & 2) >> 1;
542 lk_bit = iword & 1;
543 bo = (iword >> 21) & 31;
544 bi = (iword >> 16) & 31;
545 /* Sign-extend addr: */
546 addr = (int64_t)(int16_t)(iword & 0xfffc);
547 debug("bc");
548 if (lk_bit)
549 debug("l");
550 if (aa_bit)
551 debug("a");
552 else
553 addr += dumpaddr;
554 debug("\t%i,%i,", bo, bi);
555 if (cpu->cd.ppc.bits == 32)
556 addr &= 0xffffffff;
557 if (cpu->cd.ppc.bits == 32)
558 debug("0x%x", (int)addr);
559 else
560 debug("0x%llx", (long long)addr);
561 symbol = get_symbol_name(&cpu->machine->symbol_context,
562 addr, &offset);
563 if (symbol != NULL)
564 debug("\t<%s>", symbol);
565 break;
566 case PPC_HI6_SC:
567 lev = (iword >> 5) & 0x7f;
568 debug("sc");
569 if (lev != 0) {
570 debug("\t%i", lev);
571 if (lev > 1)
572 debug(" (WARNING! reserved value)");
573 }
574 break;
575 case PPC_HI6_B:
576 aa_bit = (iword & 2) >> 1;
577 lk_bit = iword & 1;
578 /* Sign-extend addr: */
579 addr = (int64_t)(int32_t)((iword & 0x03fffffc) << 6);
580 addr = (int64_t)addr >> 6;
581 debug("b");
582 if (lk_bit)
583 debug("l");
584 if (aa_bit)
585 debug("a");
586 else
587 addr += dumpaddr;
588 if (cpu->cd.ppc.bits == 32)
589 addr &= 0xffffffff;
590 if (cpu->cd.ppc.bits == 32)
591 debug("\t0x%x", (int)addr);
592 else
593 debug("\t0x%llx", (long long)addr);
594 symbol = get_symbol_name(&cpu->machine->symbol_context,
595 addr, &offset);
596 if (symbol != NULL)
597 debug("\t<%s>", symbol);
598 break;
599 case PPC_HI6_19:
600 xo = (iword >> 1) & 1023;
601 switch (xo) {
602 case PPC_19_MCRF:
603 bf = (iword >> 23) & 7;
604 bfa = (iword >> 18) & 7;
605 debug("mcrf\tcr%i,cr%i", bf, bfa);
606 break;
607 case PPC_19_BCLR:
608 case PPC_19_BCCTR:
609 bo = (iword >> 21) & 31;
610 bi = (iword >> 16) & 31;
611 bh = (iword >> 11) & 3;
612 lk_bit = iword & 1;
613 switch (xo) {
614 case PPC_19_BCLR:
615 mnem = power? "bcr" : "bclr"; break;
616 case PPC_19_BCCTR:
617 mnem = power? "bcc" : "bcctr"; break;
618 }
619 debug("%s%s%s\t%i,%i,%i", mnem, lk_bit? "l" : "",
620 bh? (bh==3? "+" : (bh==2? "-" : "?")) : "",
621 bo, bi, bh);
622 break;
623 case PPC_19_ISYNC:
624 debug("%s", power? "ics" : "isync");
625 break;
626 case PPC_19_CRAND:
627 case PPC_19_CRXOR:
628 case PPC_19_CROR:
629 case PPC_19_CRNAND:
630 case PPC_19_CRNOR:
631 case PPC_19_CRANDC:
632 case PPC_19_CREQV:
633 case PPC_19_CRORC:
634 bt = (iword >> 21) & 31;
635 ba = (iword >> 16) & 31;
636 bb = (iword >> 11) & 31;
637 switch (xo) {
638 case PPC_19_CRAND: mnem = "crand"; break;
639 case PPC_19_CRXOR: mnem = "crxor"; break;
640 case PPC_19_CROR: mnem = "cror"; break;
641 case PPC_19_CRNAND: mnem = "crnand"; break;
642 case PPC_19_CRNOR: mnem = "crnor"; break;
643 case PPC_19_CRANDC: mnem = "crandc"; break;
644 case PPC_19_CREQV: mnem = "creqv"; break;
645 case PPC_19_CRORC: mnem = "crorc"; break;
646 }
647 debug("%s\t%i,%i,%i", mnem, bt, ba, bb);
648 break;
649 default:
650 debug("unimplemented hi6_19, xo = 0x%x", xo);
651 }
652 break;
653 case PPC_HI6_RLWIMI:
654 case PPC_HI6_RLWINM:
655 rs = (iword >> 21) & 31;
656 ra = (iword >> 16) & 31;
657 sh = (iword >> 11) & 31;
658 mb = (iword >> 6) & 31;
659 me = (iword >> 1) & 31;
660 rc = iword & 1;
661 switch (hi6) {
662 case PPC_HI6_RLWIMI:
663 mnem = power? "rlimi" : "rlwimi"; break;
664 case PPC_HI6_RLWINM:
665 mnem = power? "rlinm" : "rlwinm"; break;
666 }
667 debug("%s%s\tr%i,r%i,%i,%i,%i",
668 mnem, rc?".":"", ra, rs, sh, mb, me);
669 break;
670 case PPC_HI6_ORI:
671 case PPC_HI6_ORIS:
672 case PPC_HI6_XORI:
673 case PPC_HI6_XORIS:
674 case PPC_HI6_ANDI_DOT:
675 case PPC_HI6_ANDIS_DOT:
676 rs = (iword >> 21) & 31;
677 ra = (iword >> 16) & 31;
678 imm = iword & 0xffff;
679 switch (hi6) {
680 case PPC_HI6_ORI:
681 mnem = power? "oril":"ori";
682 break;
683 case PPC_HI6_ORIS:
684 mnem = power? "oriu":"oris";
685 break;
686 case PPC_HI6_XORI:
687 mnem = power? "xoril":"xori";
688 break;
689 case PPC_HI6_XORIS:
690 mnem = power? "xoriu":"xoris";
691 break;
692 case PPC_HI6_ANDI_DOT:
693 mnem = power? "andil.":"andi.";
694 break;
695 case PPC_HI6_ANDIS_DOT:
696 mnem = power? "andiu.":"andis.";
697 break;
698 }
699 if (hi6 == PPC_HI6_ORI && rs == 0 && ra == 0 && imm == 0)
700 debug("nop");
701 else
702 debug("%s\tr%i,r%i,0x%04x", mnem, ra, rs, imm);
703 break;
704 case PPC_HI6_30:
705 xo = (iword >> 2) & 7;
706 switch (xo) {
707 case PPC_30_RLDICR:
708 rs = (iword >> 21) & 31;
709 ra = (iword >> 16) & 31;
710 sh = ((iword >> 11) & 31) | ((iword & 2) << 4);
711 me = ((iword >> 6) & 31) | (iword & 0x20);
712 rc = iword & 1;
713 debug("rldicr%s\tr%i,r%i,%i,%i",
714 rc?".":"", ra, rs, sh, me);
715 break;
716 default:
717 debug("unimplemented hi6_30, xo = 0x%x", xo);
718 }
719 break;
720 case PPC_HI6_31:
721 xo = (iword >> 1) & 1023;
722 switch (xo) {
723
724 case PPC_31_CMP:
725 case PPC_31_CMPL:
726 bf = (iword >> 23) & 7;
727 l_bit = (iword >> 21) & 1;
728 ra = (iword >> 16) & 31;
729 rb = (iword >> 11) & 31;
730 if (xo == PPC_31_CMPL)
731 mnem = "cmpl";
732 else
733 mnem = "cmp";
734 debug("%s%s\t", mnem, l_bit? "d" : "w");
735 if (bf != 0)
736 debug("cr%i,", bf);
737 debug("r%i,r%i", ra, rb);
738 break;
739 case PPC_31_MFCR:
740 rt = (iword >> 21) & 31;
741 debug("mfcr\tr%i", rt);
742 break;
743 case PPC_31_DCBST:
744 case PPC_31_ICBI:
745 ra = (iword >> 16) & 31;
746 rb = (iword >> 11) & 31;
747 switch (xo) {
748 case PPC_31_DCBST: mnem = "dcbst"; break;
749 case PPC_31_ICBI: mnem = "icbi"; break;
750 }
751 debug("%s\tr%i,r%i", mnem, ra, rb);
752 break;
753 case PPC_31_MFMSR:
754 rt = (iword >> 21) & 31;
755 debug("mfmsr\tr%i", rt);
756 break;
757 case PPC_31_MTCRF:
758 rs = (iword >> 21) & 31;
759 mb = (iword >> 12) & 255; /* actually fxm, not mb */
760 debug("mtcrf\t%i,r%i", mb, rs);
761 break;
762 case PPC_31_MTMSR:
763 rs = (iword >> 21) & 31;
764 l_bit = (iword >> 16) & 1;
765 debug("mtmsr\tr%i", rs);
766 if (l_bit)
767 debug(",%i", l_bit);
768 break;
769 case PPC_31_LBZX:
770 case PPC_31_LBZUX:
771 case PPC_31_LHZX:
772 case PPC_31_LHZUX:
773 case PPC_31_LWZX:
774 case PPC_31_LWZUX:
775 case PPC_31_STBX:
776 case PPC_31_STBUX:
777 case PPC_31_STHX:
778 case PPC_31_STHUX:
779 case PPC_31_STWX:
780 case PPC_31_STWUX:
781 /* rs for stores, rt for loads, actually */
782 rs = (iword >> 21) & 31;
783 ra = (iword >> 16) & 31;
784 rb = (iword >> 11) & 31;
785 switch (xo) {
786 case PPC_31_LBZX: mnem = "lbzx"; break;
787 case PPC_31_LBZUX: mnem = "lbzux"; break;
788 case PPC_31_LHZX: mnem = "lhzx"; break;
789 case PPC_31_LHZUX: mnem = "lhzux"; break;
790 case PPC_31_LWZX:
791 mnem = power? "lx" : "lwzx";
792 break;
793 case PPC_31_LWZUX:
794 mnem = power? "lux" : "lwzux";
795 break;
796 case PPC_31_STBX: mnem = "stbx"; break;
797 case PPC_31_STBUX: mnem = "stbux"; break;
798 case PPC_31_STHX: mnem = "sthx"; break;
799 case PPC_31_STHUX: mnem = "sthux"; break;
800 case PPC_31_STWX:
801 mnem = power? "stx" : "stwx";
802 break;
803 case PPC_31_STWUX:
804 mnem = power? "stux" : "stwux";
805 break;
806 }
807 debug("%s\tr%i,r%i,r%i", mnem, rs, ra, rb);
808 if (running)
809 goto disasm_ret_nonewline;
810 break;
811 case PPC_31_NEG:
812 case PPC_31_NEGO:
813 rt = (iword >> 21) & 31;
814 ra = (iword >> 16) & 31;
815 oe_bit = (iword >> 10) & 1;
816 rc = iword & 1;
817 switch (xo) {
818 case PPC_31_NEG: mnem = "neg"; break;
819 case PPC_31_NEGO: mnem = "nego"; break;
820 }
821 debug("%s%s\tr%i,r%i", mnem, rc? "." : "", rt, ra);
822 break;
823 case PPC_31_ADDZE:
824 case PPC_31_ADDZEO:
825 rt = (iword >> 21) & 31;
826 ra = (iword >> 16) & 31;
827 oe_bit = (iword >> 10) & 1;
828 rc = iword & 1;
829 switch (xo) {
830 case PPC_31_ADDZE:
831 mnem = power? "aze" : "addze";
832 break;
833 case PPC_31_ADDZEO:
834 mnem = power? "azeo" : "addzeo";
835 break;
836 }
837 debug("%s%s\tr%i,r%i", mnem, rc? "." : "", rt, ra);
838 break;
839 case PPC_31_MTSR:
840 /* Move to segment register (?) */
841 /* TODO */
842 debug("mtsr\tTODO");
843 break;
844 case PPC_31_MTSRIN:
845 case PPC_31_MFSRIN:
846 /* Move to/from segment register indirect */
847 rt = (iword >> 21) & 31;
848 rb = (iword >> 11) & 31;
849 switch (xo) {
850 case PPC_31_MTSRIN: mnem = "mtsrin"; break;
851 case PPC_31_MFSRIN: mnem = "mfsrin"; break;
852 }
853 debug("%s\tr%i,r%i", mnem, rt, rb);
854 break;
855 case PPC_31_ADDC:
856 case PPC_31_ADDCO:
857 case PPC_31_ADDE:
858 case PPC_31_ADDEO:
859 case PPC_31_ADD:
860 case PPC_31_ADDO:
861 case PPC_31_MULHW:
862 case PPC_31_MULHWU:
863 case PPC_31_MULLW:
864 case PPC_31_MULLWO:
865 case PPC_31_SUBF:
866 case PPC_31_SUBFO:
867 case PPC_31_SUBFC:
868 case PPC_31_SUBFCO:
869 case PPC_31_SUBFE:
870 case PPC_31_SUBFEO:
871 case PPC_31_SUBFZE:
872 case PPC_31_SUBFZEO:
873 rt = (iword >> 21) & 31;
874 ra = (iword >> 16) & 31;
875 rb = (iword >> 11) & 31;
876 oe_bit = (iword >> 10) & 1;
877 rc = iword & 1;
878 switch (xo) {
879 case PPC_31_ADDC:
880 mnem = power? "a" : "addc";
881 break;
882 case PPC_31_ADDCO:
883 mnem = power? "ao" : "addco";
884 break;
885 case PPC_31_ADDE:
886 mnem = power? "ae" : "adde";
887 break;
888 case PPC_31_ADDEO:
889 mnem = power? "aeo" : "addeo";
890 break;
891 case PPC_31_ADD:
892 mnem = power? "cax" : "add";
893 break;
894 case PPC_31_ADDO:
895 mnem = power? "caxo" : "addo";
896 break;
897 case PPC_31_MULHW: mnem = "mulhw"; break;
898 case PPC_31_MULHWU: mnem = "mulhwu"; break;
899 case PPC_31_MULLW:
900 mnem = power? "muls" : "mullw";
901 break;
902 case PPC_31_MULLWO:
903 mnem = power? "mulso" : "mullwo";
904 break;
905 case PPC_31_SUBF: mnem = "subf"; break;
906 case PPC_31_SUBFO: mnem = "subfo"; break;
907 case PPC_31_SUBFC:
908 mnem = power? "sf" : "subfc";
909 break;
910 case PPC_31_SUBFCO:
911 mnem = power? "sfo" : "subfco";
912 break;
913 case PPC_31_SUBFE:
914 mnem = power? "sfe" : "subfe";
915 break;
916 case PPC_31_SUBFEO:
917 mnem = power? "sfeo" : "subfeo";
918 break;
919 case PPC_31_SUBFZE:
920 mnem = power? "sfze" : "subfze";
921 break;
922 case PPC_31_SUBFZEO:
923 mnem = power? "sfzeo" : "subfzeo";
924 break;
925 }
926 debug("%s%s\tr%i,r%i,r%i", mnem, rc? "." : "",
927 rt, ra, rb);
928 break;
929 case PPC_31_MFSPR:
930 rt = (iword >> 21) & 31;
931 spr = ((iword >> 6) & 0x3e0) + ((iword >> 16) & 31);
932 debug("mfspr\tr%i,spr%i", rt, spr);
933 break;
934 case PPC_31_TLBIE:
935 /* TODO: what is ra? The IBM online docs didn't say */
936 ra = 0;
937 rb = (iword >> 11) & 31;
938 if (power)
939 debug("tlbi\tr%i,r%i", ra, rb);
940 else
941 debug("tlbie\tr%i", rb);
942 break;
943 case PPC_31_TLBSYNC:
944 debug("tlbsync");
945 break;
946 case PPC_31_MFTB:
947 rt = (iword >> 21) & 31;
948 spr = ((iword >> 6) & 0x3e0) + ((iword >> 16) & 31);
949 debug("mftb%s\tr%i", spr==268? "" :
950 (spr==269? "u" : "?"), rt);
951 break;
952 case PPC_31_CNTLZW:
953 rs = (iword >> 21) & 31;
954 ra = (iword >> 16) & 31;
955 rc = iword & 1;
956 mnem = power? "cntlz" : "cntlzw";
957 debug("%s\tr%i,r%i", mnem, rc? "." : "", ra, rs);
958 break;
959 case PPC_31_SLW:
960 case PPC_31_SRAW:
961 case PPC_31_SRW:
962 case PPC_31_AND:
963 case PPC_31_ANDC:
964 case PPC_31_NOR:
965 case PPC_31_OR:
966 case PPC_31_ORC:
967 case PPC_31_XOR:
968 case PPC_31_NAND:
969 rs = (iword >> 21) & 31;
970 ra = (iword >> 16) & 31;
971 rb = (iword >> 11) & 31;
972 rc = iword & 1;
973 if (rs == rb && xo == PPC_31_OR)
974 debug("mr%s\tr%i,r%i", rc? "." : "", ra, rs);
975 else {
976 switch (xo) {
977 case PPC_31_SLW: mnem =
978 power? "sl" : "slw"; break;
979 case PPC_31_SRAW: mnem =
980 power? "sra" : "sraw"; break;
981 case PPC_31_SRW: mnem =
982 power? "sr" : "srw"; break;
983 case PPC_31_AND: mnem = "and"; break;
984 case PPC_31_NAND: mnem = "nand"; break;
985 case PPC_31_ANDC: mnem = "andc"; break;
986 case PPC_31_NOR: mnem = "nor"; break;
987 case PPC_31_OR: mnem = "or"; break;
988 case PPC_31_ORC: mnem = "orc"; break;
989 case PPC_31_XOR: mnem = "xor"; break;
990 }
991 debug("%s%s\tr%i,r%i,r%i", mnem,
992 rc? "." : "", ra, rs, rb);
993 }
994 break;
995 case PPC_31_DCCCI:
996 ra = (iword >> 16) & 31;
997 rb = (iword >> 11) & 31;
998 debug("dccci\tr%i,r%i", ra, rb);
999 break;
1000 case PPC_31_ICCCI:
1001 ra = (iword >> 16) & 31;
1002 rb = (iword >> 11) & 31;
1003 debug("iccci\tr%i,r%i", ra, rb);
1004 break;
1005 case PPC_31_DIVW:
1006 case PPC_31_DIVWO:
1007 case PPC_31_DIVWU:
1008 case PPC_31_DIVWUO:
1009 rt = (iword >> 21) & 31;
1010 ra = (iword >> 16) & 31;
1011 rb = (iword >> 11) & 31;
1012 oe_bit = (iword >> 10) & 1;
1013 rc = iword & 1;
1014 switch (xo) {
1015 case PPC_31_DIVWU: mnem = "divwu"; break;
1016 case PPC_31_DIVWUO: mnem = "divwuo"; break;
1017 case PPC_31_DIVW: mnem = "divw"; break;
1018 case PPC_31_DIVWO: mnem = "divwo"; break;
1019 }
1020 debug("%s%s\tr%i,r%i,r%i", mnem, rc? "." : "",
1021 rt, ra, rb);
1022 break;
1023 case PPC_31_MTSPR:
1024 rs = (iword >> 21) & 31;
1025 spr = ((iword >> 6) & 0x3e0) + ((iword >> 16) & 31);
1026 debug("mtspr\tspr%i,r%i", spr, rs);
1027 break;
1028 case PPC_31_SYNC:
1029 debug("%s", power? "dcs" : "sync");
1030 break;
1031 case PPC_31_LSWI:
1032 case PPC_31_STSWI:
1033 rs = (iword >> 21) & 31; /* lwsi uses rt */
1034 ra = (iword >> 16) & 31;
1035 nb = (iword >> 11) & 31;
1036 switch (xo) {
1037 case PPC_31_LSWI:
1038 mnem = power? "lsi" : "lswi"; break;
1039 case PPC_31_STSWI:
1040 mnem = power? "stsi" : "stswi"; break;
1041 }
1042 debug("%s\tr%i,r%i,%i", mnem, rs, ra, nb);
1043 if (running)
1044 goto disasm_ret_nonewline;
1045 break;
1046 case PPC_31_SRAWI:
1047 rs = (iword >> 21) & 31;
1048 ra = (iword >> 16) & 31;
1049 sh = (iword >> 11) & 31;
1050 rc = iword & 1;
1051 mnem = power? "srai" : "srawi";
1052 debug("%s%s\tr%i,r%i,%i", mnem,
1053 rc? "." : "", ra, rs, sh);
1054 break;
1055 case PPC_31_EIEIO:
1056 debug("%s", power? "eieio?" : "eieio");
1057 break;
1058 case PPC_31_EXTSB:
1059 case PPC_31_EXTSH:
1060 case PPC_31_EXTSW:
1061 rs = (iword >> 21) & 31;
1062 ra = (iword >> 16) & 31;
1063 rc = iword & 1;
1064 switch (xo) {
1065 case PPC_31_EXTSB:
1066 mnem = power? "exts" : "extsb";
1067 break;
1068 case PPC_31_EXTSH:
1069 mnem = "extsh";
1070 break;
1071 case PPC_31_EXTSW:
1072 mnem = "extsw";
1073 break;
1074 }
1075 debug("%s%s\tr%i,r%i", mnem, rc? "." : "", ra, rs);
1076 break;
1077 default:
1078 debug("unimplemented hi6_31, xo = 0x%x", xo);
1079 }
1080 break;
1081 case PPC_HI6_LWZ:
1082 case PPC_HI6_LWZU:
1083 case PPC_HI6_LHZ:
1084 case PPC_HI6_LHZU:
1085 case PPC_HI6_LHA:
1086 case PPC_HI6_LHAU:
1087 case PPC_HI6_LBZ:
1088 case PPC_HI6_LBZU:
1089 case PPC_HI6_STW:
1090 case PPC_HI6_STWU:
1091 case PPC_HI6_STH:
1092 case PPC_HI6_STHU:
1093 case PPC_HI6_STB:
1094 case PPC_HI6_STBU:
1095 case PPC_HI6_STMW:
1096 case PPC_HI6_LFD:
1097 case PPC_HI6_STFD:
1098 /* NOTE: Loads use rt, not rs, but are otherwise similar
1099 to stores */
1100 rs = (iword >> 21) & 31;
1101 ra = (iword >> 16) & 31;
1102 imm = (int16_t)(iword & 0xffff);
1103 fpreg = 0;
1104 switch (hi6) {
1105 case PPC_HI6_LWZ: mnem = power? "l" : "lwz"; break;
1106 case PPC_HI6_LWZU: mnem = power? "lu" : "lwzu"; break;
1107 case PPC_HI6_LHZ: mnem = "lhz"; break;
1108 case PPC_HI6_LHZU: mnem = "lhzu"; break;
1109 case PPC_HI6_LHA: mnem = "lha"; break;
1110 case PPC_HI6_LHAU: mnem = "lhau"; break;
1111 case PPC_HI6_LBZ: mnem = "lbz"; break;
1112 case PPC_HI6_LBZU: mnem = "lbzu"; break;
1113 case PPC_HI6_STW: mnem = power? "st" : "stw"; break;
1114 case PPC_HI6_STWU: mnem = power? "stu" : "stwu"; break;
1115 case PPC_HI6_STH: mnem = "sth"; break;
1116 case PPC_HI6_STHU: mnem = "sthu"; break;
1117 case PPC_HI6_STB: mnem = "stb"; break;
1118 case PPC_HI6_STBU: mnem = "stbu"; break;
1119 case PPC_HI6_LMW: mnem = power? "lm" : "lmw"; break;
1120 case PPC_HI6_STMW: mnem = power? "stm" : "stmw"; break;
1121 case PPC_HI6_LFD: fpreg = 1; mnem = "lfd"; break;
1122 case PPC_HI6_STFD: fpreg = 1; mnem = "stfd"; break;
1123 }
1124 debug("%s\t", mnem);
1125 if (fpreg)
1126 debug("f");
1127 else
1128 debug("r");
1129 debug("%i,%i(r%i)", rs, imm, ra);
1130 if (running)
1131 goto disasm_ret_nonewline;
1132 break;
1133 default:
1134 /* TODO */
1135 debug("unimplemented hi6 = 0x%02x", hi6);
1136 }
1137
1138 disasm_ret:
1139 debug("\n");
1140 disasm_ret_nonewline:
1141 return sizeof(iword);
1142 }
1143
1144
1145 /*
1146 * show_trace():
1147 *
1148 * Show trace tree. This function should be called every time
1149 * a function is called. cpu->cd.ppc.trace_tree_depth is increased here
1150 * and should not be increased by the caller.
1151 *
1152 * Note: This function should not be called if show_trace_tree == 0.
1153 */
1154 static void show_trace(struct cpu *cpu)
1155 {
1156 uint64_t offset, addr = cpu->pc;
1157 int x, n_args_to_print;
1158 char strbuf[60];
1159 char *symbol;
1160
1161 cpu->cd.ppc.trace_tree_depth ++;
1162
1163 if (cpu->machine->ncpus > 1)
1164 debug("cpu%i:", cpu->cpu_id);
1165
1166 symbol = get_symbol_name(&cpu->machine->symbol_context, addr, &offset);
1167
1168 for (x=0; x<cpu->cd.ppc.trace_tree_depth; x++)
1169 debug(" ");
1170
1171 /* debug("<%s>\n", symbol!=NULL? symbol : "no symbol"); */
1172
1173 if (symbol != NULL)
1174 debug("<%s(", symbol);
1175 else {
1176 debug("<0x");
1177 if (cpu->cd.ppc.bits == 32)
1178 debug("%08x", (int)addr);
1179 else
1180 debug("%016llx", (long long)addr);
1181 debug("(");
1182 }
1183
1184 /*
1185 * TODO: The number of arguments and the symbol type of each
1186 * argument should be taken from the symbol table, in some way.
1187 */
1188 n_args_to_print = 5;
1189
1190 for (x=0; x<n_args_to_print; x++) {
1191 int64_t d = cpu->cd.ppc.gpr[x + 3];
1192
1193 if (d > -256 && d < 256)
1194 debug("%i", (int)d);
1195 else if (memory_points_to_string(cpu, cpu->mem, d, 1)) {
1196 debug("\"%s\"", memory_conv_to_string(cpu,
1197 cpu->mem, d, strbuf, sizeof(strbuf)));
1198 if (strlen(strbuf) >= sizeof(strbuf)-1)
1199 debug("..");
1200 } else {
1201 if (cpu->cd.ppc.bits == 32)
1202 debug("0x%x", (int)d);
1203 else
1204 debug("0x%llx", (long long)d);
1205 }
1206
1207 if (x < n_args_to_print - 1)
1208 debug(",");
1209
1210 if (x == n_args_to_print - 1)
1211 break;
1212 }
1213
1214 if (n_args_to_print > 9)
1215 debug("..");
1216
1217 debug(")>\n");
1218 }
1219
1220
1221 /*
1222 * update_cr0():
1223 *
1224 * Sets the top 4 bits of the CR register.
1225 */
1226 static void update_cr0(struct cpu *cpu, uint64_t value)
1227 {
1228 int c;
1229
1230 if (cpu->cd.ppc.bits == 64) {
1231 if ((int64_t)value < 0)
1232 c = 8;
1233 else if ((int64_t)value > 0)
1234 c = 4;
1235 else
1236 c = 2;
1237 } else {
1238 if ((int32_t)value < 0)
1239 c = 8;
1240 else if ((int32_t)value > 0)
1241 c = 4;
1242 else
1243 c = 2;
1244 }
1245
1246 /* SO bit, copied from XER: */
1247 c |= ((cpu->cd.ppc.xer >> 31) & 1);
1248
1249 cpu->cd.ppc.cr &= ~((uint32_t)0xf << 28);
1250 cpu->cd.ppc.cr |= ((uint32_t)c << 28);
1251 }
1252
1253
1254 /*
1255 * ppc_cpu_run_instr():
1256 *
1257 * Execute one instruction on a specific CPU.
1258 *
1259 * Return value is the number of instructions executed during this call,
1260 * 0 if no instruction was executed.
1261 */
1262 int ppc_cpu_run_instr(struct emul *emul, struct cpu *cpu)
1263 {
1264 uint32_t iword;
1265 unsigned char buf[4];
1266 unsigned char tmp_data[8];
1267 size_t tmp_data_len;
1268 char *mnem = NULL;
1269 int r, hi6, rt, rs, ra, rb, xo, lev, sh, me, rc, imm, l_bit, oe_bit;
1270 int c, i, spr, aa_bit, bo, bi, bh, lk_bit, bf, ctr_ok, cond_ok;
1271 int update, load, mb, nb, bt, ba, bb, fpreg, arithflag, old_ca, bfa;
1272 uint64_t tmp=0, tmp2, addr;
1273 uint64_t cached_pc;
1274
1275 cached_pc = cpu->cd.ppc.pc_last = cpu->pc & ~3;
1276
1277 /* Check PC against breakpoints: */
1278 if (!single_step)
1279 for (i=0; i<cpu->machine->n_breakpoints; i++)
1280 if (cached_pc == cpu->machine->breakpoint_addr[i]) {
1281 fatal("Breakpoint reached, pc=0x");
1282 if (cpu->cd.ppc.bits == 32)
1283 fatal("%08x", (int)cached_pc);
1284 else
1285 fatal("%016llx", (long long)cached_pc);
1286 fatal("\n");
1287 single_step = 1;
1288 return 0;
1289 }
1290
1291 /* Update the Time Base and Decrementer: */
1292 if ((++ cpu->cd.ppc.tbl) == 0)
1293 cpu->cd.ppc.tbu ++;
1294
1295 cpu->cd.ppc.dec --;
1296 /* TODO: dec interrupt! */
1297
1298 /* TODO: hdec for POWER4+ */
1299
1300 /* ROM emulation: (TODO: non-OF-emuls) */
1301 if (cpu->pc == cpu->cd.ppc.of_emul_addr &&
1302 cpu->machine->prom_emulation) {
1303 int res = of_emul(cpu);
1304 if (res) {
1305 cpu->pc = cpu->cd.ppc.lr;
1306 }
1307 return 100;
1308 }
1309
1310 r = cpu->memory_rw(cpu, cpu->mem, cached_pc, &buf[0], sizeof(buf),
1311 MEM_READ, CACHE_INSTRUCTION | PHYSICAL);
1312 if (!r)
1313 return 0;
1314
1315 iword = (buf[0] << 24) + (buf[1] << 16) + (buf[2] << 8) + buf[3];
1316
1317 if (cpu->machine->instruction_trace)
1318 ppc_cpu_disassemble_instr(cpu, buf, 1, 0, 0);
1319
1320 cpu->pc += sizeof(iword);
1321 cached_pc += sizeof(iword);
1322
1323 hi6 = iword >> 26;
1324
1325 switch (hi6) {
1326
1327 case PPC_HI6_MULLI:
1328 rt = (iword >> 21) & 31;
1329 ra = (iword >> 16) & 31;
1330 imm = (int16_t)(iword & 0xffff);
1331 cpu->cd.ppc.gpr[rt] = (int64_t)cpu->cd.ppc.gpr[ra]
1332 * (int64_t)imm;
1333 break;
1334
1335 case PPC_HI6_SUBFIC:
1336 rt = (iword >> 21) & 31;
1337 ra = (iword >> 16) & 31;
1338 imm = (int16_t)(iword & 0xffff);
1339 cpu->cd.ppc.xer &= ~PPC_XER_CA;
1340 if (cpu->cd.ppc.bits == 32) {
1341 tmp = (~cpu->cd.ppc.gpr[ra]) & 0xffffffff;
1342 cpu->cd.ppc.gpr[rt] = tmp + imm + 1;
1343 /* TODO: is this CA correct? */
1344 /* printf("subfic: tmp = %016llx\n", (long long)tmp);
1345 printf("subfic: rt = %016llx\n\n",
1346 (long long)cpu->cd.ppc.gpr[rt]); */
1347 if ((tmp >> 32) != (cpu->cd.ppc.gpr[rt] >> 32))
1348 cpu->cd.ppc.xer |= PPC_XER_CA;
1349 /* High 32 bits are probably undefined in
1350 32-bit mode (I hope) */
1351 } else {
1352 /*
1353 * Ugly, but I can't figure out a way right now how
1354 * to get the carry bit out of a 64-bit addition,
1355 * without access to more-than-64-bit operations in C.
1356 */
1357 tmp = ~cpu->cd.ppc.gpr[ra];
1358 tmp2 = (tmp >> 32); /* High 32 bits */
1359 tmp &= 0xffffffff; /* Low 32 bits */
1360
1361 tmp += imm + 1;
1362 if ((tmp >> 32) == 0) {
1363 /* No change to upper 32 bits */
1364 } else if ((tmp >> 32) == 1) {
1365 /* Positive change: */
1366 tmp2 ++;
1367 } else {
1368 /* Negative change: */
1369 tmp2 --;
1370 }
1371
1372 tmp &= 0xffffffff;
1373
1374 /* TODO: is this CA calculation correct? */
1375 if ((tmp2 >> 32) != 0)
1376 cpu->cd.ppc.xer |= PPC_XER_CA;
1377
1378 cpu->cd.ppc.gpr[rt] = (tmp2 << 32) + tmp;
1379 }
1380 break;
1381
1382 case PPC_HI6_CMPLI:
1383 case PPC_HI6_CMPI:
1384 bf = (iword >> 23) & 7;
1385 l_bit = (iword >> 21) & 1;
1386 ra = (iword >> 16) & 31;
1387 if (hi6 == PPC_HI6_CMPLI)
1388 imm = iword & 0xffff;
1389 else
1390 imm = (int16_t)(iword & 0xffff);
1391 tmp = cpu->cd.ppc.gpr[ra];
1392
1393 if (hi6 == PPC_HI6_CMPI) {
1394 if (!l_bit)
1395 tmp = (int64_t)(int32_t)tmp;
1396 if ((int64_t)tmp < (int64_t)imm)
1397 c = 8;
1398 else if ((int64_t)tmp > (int64_t)imm)
1399 c = 4;
1400 else
1401 c = 2;
1402 } else {
1403 if (!l_bit)
1404 tmp &= 0xffffffff;
1405 if ((uint64_t)tmp < (uint64_t)imm)
1406 c = 8;
1407 else if ((uint64_t)tmp > (uint64_t)imm)
1408 c = 4;
1409 else
1410 c = 2;
1411 }
1412
1413 /* SO bit, copied from XER: */
1414 c |= ((cpu->cd.ppc.xer >> 31) & 1);
1415
1416 cpu->cd.ppc.cr &= ~(0xf << (28 - 4*bf));
1417 cpu->cd.ppc.cr |= (c << (28 - 4*bf));
1418 break;
1419
1420 case PPC_HI6_ADDIC:
1421 case PPC_HI6_ADDIC_DOT:
1422 rt = (iword >> 21) & 31;
1423 ra = (iword >> 16) & 31;
1424 rc = hi6 == PPC_HI6_ADDIC_DOT;
1425 imm = (int16_t)(iword & 0xffff);
1426 /* NOTE: Addic doesn't clear CA! */
1427 if (cpu->cd.ppc.bits == 32) {
1428 tmp = cpu->cd.ppc.gpr[ra] & 0xffffffff;
1429 cpu->cd.ppc.gpr[rt] = tmp + (uint32_t)imm;
1430 /* TODO: is this CA correct? */
1431 /* printf("addic: tmp = %016llx\n", (long long)tmp);
1432 printf("addic: rt = %016llx\n\n",
1433 (long long)cpu->cd.ppc.gpr[rt]); */
1434 if ((tmp >> 32) != (cpu->cd.ppc.gpr[rt] >> 32))
1435 cpu->cd.ppc.xer |= PPC_XER_CA;
1436 /* High 32 bits are probably undefined in
1437 32-bit mode (I hope) */
1438 } else {
1439 /* See comment about ugliness regarding SUBFIC */
1440 tmp = cpu->cd.ppc.gpr[ra];
1441 tmp2 = (tmp >> 32); /* High 32 bits */
1442 tmp &= 0xffffffff; /* Low 32 bits */
1443
1444 tmp += (int64_t)imm;
1445 if ((tmp >> 32) == 0) {
1446 /* No change to upper 32 bits */
1447 } else if ((tmp >> 32) == 1) {
1448 /* Positive change: */
1449 tmp2 ++;
1450 } else {
1451 /* Negative change: */
1452 tmp2 --;
1453 }
1454
1455 tmp &= 0xffffffff;
1456
1457 /* TODO: is this CA calculation correct? */
1458 if ((tmp2 >> 32) != 0)
1459 cpu->cd.ppc.xer |= PPC_XER_CA;
1460
1461 cpu->cd.ppc.gpr[rt] = (tmp2 << 32) + tmp;
1462 }
1463 if (rc)
1464 update_cr0(cpu, cpu->cd.ppc.gpr[rt]);
1465 break;
1466
1467 case PPC_HI6_ADDI:
1468 case PPC_HI6_ADDIS:
1469 rt = (iword >> 21) & 31;
1470 ra = (iword >> 16) & 31;
1471 if (hi6 == PPC_HI6_ADDI)
1472 imm = (int16_t)(iword & 0xffff);
1473 else
1474 imm = (int32_t)((iword & 0xffff) << 16);
1475 if (ra == 0)
1476 tmp = 0;
1477 else
1478 tmp = cpu->cd.ppc.gpr[ra];
1479 cpu->cd.ppc.gpr[rt] = tmp + imm;
1480 break;
1481
1482 case PPC_HI6_BC:
1483 aa_bit = (iword >> 1) & 1;
1484 lk_bit = iword & 1;
1485 bo = (iword >> 21) & 31;
1486 bi = (iword >> 16) & 31;
1487 /* Sign-extend addr: */
1488 addr = (int64_t)(int16_t)(iword & 0xfffc);
1489
1490 if (!aa_bit)
1491 addr += cpu->cd.ppc.pc_last;
1492
1493 if (cpu->cd.ppc.bits == 32)
1494 addr &= 0xffffffff;
1495
1496 if (!(bo & 4))
1497 cpu->cd.ppc.ctr --;
1498 ctr_ok = (bo >> 2) & 1;
1499 tmp = cpu->cd.ppc.ctr;
1500 if (cpu->cd.ppc.bits == 32)
1501 tmp &= 0xffffffff;
1502 ctr_ok |= ( (tmp != 0) ^ ((bo >> 1) & 1) );
1503
1504 cond_ok = (bo >> 4) & 1;
1505 cond_ok |= ( ((bo >> 3) & 1) ==
1506 ((cpu->cd.ppc.cr >> (31-bi)) & 1) );
1507
1508 if (lk_bit)
1509 cpu->cd.ppc.lr = cpu->pc;
1510 if (ctr_ok && cond_ok)
1511 cpu->pc = addr & ~3;
1512 if (lk_bit && cpu->machine->show_trace_tree)
1513 show_trace(cpu);
1514 break;
1515
1516 case PPC_HI6_SC:
1517 lev = (iword >> 5) & 0x7f;
1518 if (cpu->machine->userland_emul != NULL) {
1519 useremul_syscall(cpu, lev);
1520 } else {
1521 fatal("[ PPC: pc = 0x%016llx, sc not yet "
1522 "implemented ]\n", (long long)cached_pc);
1523 cpu->running = 0;
1524 return 0;
1525 }
1526 break;
1527
1528 case PPC_HI6_B:
1529 aa_bit = (iword & 2) >> 1;
1530 lk_bit = iword & 1;
1531 /* Sign-extend addr: */
1532 addr = (int64_t)(int32_t)((iword & 0x03fffffc) << 6);
1533 addr = (int64_t)addr >> 6;
1534
1535 if (!aa_bit)
1536 addr += cpu->cd.ppc.pc_last;
1537
1538 if (cpu->cd.ppc.bits == 32)
1539 addr &= 0xffffffff;
1540
1541 if (lk_bit)
1542 cpu->cd.ppc.lr = cpu->pc;
1543
1544 cpu->pc = addr;
1545
1546 if (lk_bit && cpu->machine->show_trace_tree)
1547 show_trace(cpu);
1548 break;
1549
1550 case PPC_HI6_19:
1551 xo = (iword >> 1) & 1023;
1552 switch (xo) {
1553
1554 case PPC_19_MCRF:
1555 bf = (iword >> 23) & 7;
1556 bfa = (iword >> 18) & 7;
1557 tmp = cpu->cd.ppc.cr >> (28 - bfa*4);
1558 tmp &= 0xf;
1559 cpu->cd.ppc.cr &= ~(0xf << (28 - bf*4));
1560 cpu->cd.ppc.cr |= (tmp << (28 - bf*4));
1561 break;
1562
1563 case PPC_19_BCLR:
1564 case PPC_19_BCCTR:
1565 bo = (iword >> 21) & 31;
1566 bi = (iword >> 16) & 31;
1567 bh = (iword >> 11) & 3;
1568 lk_bit = iword & 1;
1569 if (xo == PPC_19_BCLR) {
1570 addr = cpu->cd.ppc.lr;
1571 if (!(bo & 4))
1572 cpu->cd.ppc.ctr --;
1573 ctr_ok = (bo >> 2) & 1;
1574 tmp = cpu->cd.ppc.ctr;
1575 if (cpu->cd.ppc.bits == 32)
1576 tmp &= 0xffffffff;
1577 ctr_ok |= ( (tmp != 0) ^ ((bo >> 1) & 1) );
1578 if (!quiet_mode && !lk_bit &&
1579 cpu->machine->show_trace_tree) {
1580 cpu->cd.ppc.trace_tree_depth --;
1581 /* TODO: show return value? */
1582 }
1583 } else {
1584 addr = cpu->cd.ppc.ctr;
1585 ctr_ok = 1;
1586 }
1587 cond_ok = (bo >> 4) & 1;
1588 cond_ok |= ( ((bo >> 3) & 1) ==
1589 ((cpu->cd.ppc.cr >> (31-bi)) & 1) );
1590 if (lk_bit)
1591 cpu->cd.ppc.lr = cpu->pc;
1592 if (ctr_ok && cond_ok) {
1593 cpu->pc = addr & ~3;
1594 if (cpu->cd.ppc.bits == 32)
1595 cpu->pc &= 0xffffffff;
1596 }
1597 if (lk_bit && cpu->machine->show_trace_tree)
1598 show_trace(cpu);
1599 break;
1600
1601 case PPC_19_ISYNC:
1602 /* TODO: actually sync */
1603 break;
1604
1605 case PPC_19_CRAND:
1606 case PPC_19_CRXOR:
1607 case PPC_19_CROR:
1608 case PPC_19_CRNAND:
1609 case PPC_19_CRNOR:
1610 case PPC_19_CRANDC:
1611 case PPC_19_CREQV:
1612 case PPC_19_CRORC:
1613 bt = (iword >> 21) & 31;
1614 ba = (iword >> 16) & 31;
1615 bb = (iword >> 11) & 31;
1616 ba = (cpu->cd.ppc.cr >> (31-ba)) & 1;
1617 bb = (cpu->cd.ppc.cr >> (31-bb)) & 1;
1618 cpu->cd.ppc.cr &= ~(1 << (31-bt));
1619 switch (xo) {
1620 case PPC_19_CRXOR:
1621 if (ba ^ bb)
1622 cpu->cd.ppc.cr |= (1 << (31-bt));
1623 break;
1624 case PPC_19_CROR:
1625 if (ba | bb)
1626 cpu->cd.ppc.cr |= (1 << (31-bt));
1627 break;
1628 default:
1629 fatal("[ TODO: crXXX, xo = %i, "
1630 "pc = 0x%016llx ]\n",
1631 xo, (long long) (cpu->cd.ppc.pc_last));
1632 cpu->running = 0;
1633 return 0;
1634 }
1635 break;
1636
1637 default:
1638 fatal("[ unimplemented PPC hi6_19, xo = 0x%04x, "
1639 "pc = 0x%016llx ]\n",
1640 xo, (long long) (cpu->cd.ppc.pc_last));
1641 cpu->running = 0;
1642 return 0;
1643 }
1644 break;
1645
1646 case PPC_HI6_RLWIMI:
1647 case PPC_HI6_RLWINM:
1648 rs = (iword >> 21) & 31;
1649 ra = (iword >> 16) & 31;
1650 sh = (iword >> 11) & 31;
1651 mb = (iword >> 6) & 31;
1652 me = (iword >> 1) & 31;
1653 rc = iword & 1;
1654 tmp = cpu->cd.ppc.gpr[rs];
1655 /* TODO: Fix this, its performance is awful: */
1656 while (sh-- != 0) {
1657 int b = (tmp >> 31) & 1;
1658 tmp = (tmp << 1) | b;
1659 }
1660
1661 switch (hi6) {
1662 case PPC_HI6_RLWIMI:
1663 for (;;) {
1664 uint64_t mask;
1665 mask = (uint64_t)1 << (31-mb);
1666 cpu->cd.ppc.gpr[ra] &= ~mask;
1667 cpu->cd.ppc.gpr[ra] |= (tmp & mask);
1668 if (mb == me)
1669 break;
1670 mb ++;
1671 if (mb == 32)
1672 mb = 0;
1673 }
1674 break;
1675 case PPC_HI6_RLWINM:
1676 cpu->cd.ppc.gpr[ra] = 0;
1677 for (;;) {
1678 uint64_t mask;
1679 mask = (uint64_t)1 << (31-mb);
1680 cpu->cd.ppc.gpr[ra] |= (tmp & mask);
1681 if (mb == me)
1682 break;
1683 mb ++;
1684 if (mb == 32)
1685 mb = 0;
1686 }
1687 break;
1688 }
1689 if (rc)
1690 update_cr0(cpu, cpu->cd.ppc.gpr[ra]);
1691 break;
1692
1693 case PPC_HI6_ORI:
1694 case PPC_HI6_ORIS:
1695 rs = (iword >> 21) & 31;
1696 ra = (iword >> 16) & 31;
1697 if (hi6 == PPC_HI6_ORI)
1698 imm = (iword & 0xffff);
1699 else
1700 imm = (iword & 0xffff) << 16;
1701 tmp = cpu->cd.ppc.gpr[rs];
1702 cpu->cd.ppc.gpr[ra] = tmp | (uint32_t)imm;
1703 break;
1704
1705 case PPC_HI6_XORI:
1706 case PPC_HI6_XORIS:
1707 rs = (iword >> 21) & 31;
1708 ra = (iword >> 16) & 31;
1709 if (hi6 == PPC_HI6_XORI)
1710 imm = (iword & 0xffff);
1711 else
1712 imm = (iword & 0xffff) << 16;
1713 tmp = cpu->cd.ppc.gpr[rs];
1714 cpu->cd.ppc.gpr[ra] = tmp ^ (uint32_t)imm;
1715 break;
1716
1717 case PPC_HI6_ANDI_DOT:
1718 case PPC_HI6_ANDIS_DOT:
1719 rs = (iword >> 21) & 31;
1720 ra = (iword >> 16) & 31;
1721 if (hi6 == PPC_HI6_ANDI_DOT)
1722 imm = (iword & 0xffff);
1723 else
1724 imm = (iword & 0xffff) << 16;
1725 tmp = cpu->cd.ppc.gpr[rs];
1726 cpu->cd.ppc.gpr[ra] = tmp & (uint32_t)imm;
1727 update_cr0(cpu, cpu->cd.ppc.gpr[ra]);
1728 break;
1729
1730 case PPC_HI6_30:
1731 xo = (iword >> 2) & 7;
1732 switch (xo) {
1733 case PPC_30_RLDICR:
1734 if (cpu->cd.ppc.bits == 32) {
1735 /* TODO: Illegal instruction. */
1736 break;
1737 }
1738 rs = (iword >> 21) & 31;
1739 ra = (iword >> 16) & 31;
1740 sh = ((iword >> 11) & 31) | ((iword & 2) << 4);
1741 me = ((iword >> 6) & 31) | (iword & 0x20);
1742 rc = iword & 1;
1743 tmp = cpu->cd.ppc.gpr[rs];
1744 /* TODO: Fix this, its performance is awful: */
1745 while (sh-- != 0) {
1746 int b = (tmp >> 63) & 1;
1747 tmp = (tmp << 1) | b;
1748 }
1749 while (me++ < 63)
1750 tmp &= ~((uint64_t)1 << (63-me));
1751 cpu->cd.ppc.gpr[ra] = tmp;
1752 if (rc)
1753 update_cr0(cpu, cpu->cd.ppc.gpr[ra]);
1754 break;
1755 default:
1756 fatal("[ unimplemented PPC hi6_30, xo = 0x%04x, "
1757 "pc = 0x%016llx ]\n",
1758 xo, (long long) (cpu->cd.ppc.pc_last));
1759 cpu->running = 0;
1760 return 0;
1761 }
1762 break;
1763
1764 case PPC_HI6_31:
1765 xo = (iword >> 1) & 1023;
1766 switch (xo) {
1767
1768 case PPC_31_CMPL:
1769 case PPC_31_CMP:
1770 bf = (iword >> 23) & 7;
1771 l_bit = (iword >> 21) & 1;
1772 ra = (iword >> 16) & 31;
1773 rb = (iword >> 11) & 31;
1774
1775 tmp = cpu->cd.ppc.gpr[ra];
1776 tmp2 = cpu->cd.ppc.gpr[rb];
1777
1778 if (hi6 == PPC_31_CMP) {
1779 if (!l_bit) {
1780 tmp = (int64_t)(int32_t)tmp;
1781 tmp2 = (int64_t)(int32_t)tmp2;
1782 }
1783 if ((int64_t)tmp < (int64_t)tmp2)
1784 c = 8;
1785 else if ((int64_t)tmp > (int64_t)tmp2)
1786 c = 4;
1787 else
1788 c = 2;
1789 } else {
1790 if (!l_bit) {
1791 tmp &= 0xffffffff;
1792 tmp2 &= 0xffffffff;
1793 }
1794 if ((uint64_t)tmp < (uint64_t)tmp2)
1795 c = 8;
1796 else if ((uint64_t)tmp > (uint64_t)tmp2)
1797 c = 4;
1798 else
1799 c = 2;
1800 }
1801
1802 /* SO bit, copied from XER: */
1803 c |= ((cpu->cd.ppc.xer >> 31) & 1);
1804
1805 cpu->cd.ppc.cr &= ~(0xf << (28 - 4*bf));
1806 cpu->cd.ppc.cr |= (c << (28 - 4*bf));
1807 break;
1808
1809 case PPC_31_MFCR:
1810 rt = (iword >> 21) & 31;
1811 cpu->cd.ppc.gpr[rt] = cpu->cd.ppc.cr;
1812 break;
1813
1814 case PPC_31_DCBST:
1815 case PPC_31_ICBI:
1816 ra = (iword >> 16) & 31;
1817 rb = (iword >> 11) & 31;
1818 switch (xo) {
1819 case PPC_31_DCBST: mnem = "dcbst"; break;
1820 case PPC_31_ICBI: mnem = "icbi"; break;
1821 }
1822 /* debug("[ %s r%i,r%i: TODO ]\n", mnem, ra, rb); */
1823 break;
1824
1825 case PPC_31_MFMSR:
1826 rt = (iword >> 21) & 31;
1827 /* TODO: check pr */
1828 reg_access_msr(cpu, &cpu->cd.ppc.gpr[rt], 0);
1829 break;
1830
1831 case PPC_31_MTCRF:
1832 rs = (iword >> 21) & 31;
1833 mb = (iword >> 12) & 255; /* actually fxm, not mb */
1834 tmp = 0;
1835 for (i=0; i<8; i++, mb <<= 1, tmp <<= 4)
1836 if (mb & 128)
1837 tmp |= 0xf;
1838 cpu->cd.ppc.cr &= ~tmp;
1839 cpu->cd.ppc.cr |= (cpu->cd.ppc.gpr[rs] & tmp);
1840 break;
1841
1842 case PPC_31_MTMSR:
1843 rs = (iword >> 21) & 31;
1844 l_bit = (iword >> 16) & 1;
1845 /* TODO: the l_bit */
1846 reg_access_msr(cpu, &cpu->cd.ppc.gpr[rs], 1);
1847 break;
1848
1849 case PPC_31_LBZX:
1850 case PPC_31_LBZUX:
1851 case PPC_31_LHZX:
1852 case PPC_31_LHZUX:
1853 case PPC_31_LWZX:
1854 case PPC_31_LWZUX:
1855 case PPC_31_STBX:
1856 case PPC_31_STBUX:
1857 case PPC_31_STHX:
1858 case PPC_31_STHUX:
1859 case PPC_31_STWX:
1860 case PPC_31_STWUX:
1861 rs = (iword >> 21) & 31;
1862 ra = (iword >> 16) & 31;
1863 rb = (iword >> 11) & 31;
1864 update = 0;
1865 switch (xo) {
1866 case PPC_31_LBZUX:
1867 case PPC_31_LHZUX:
1868 case PPC_31_LWZUX:
1869 case PPC_31_STBUX:
1870 case PPC_31_STHUX:
1871 case PPC_31_STWUX:
1872 update = 1;
1873 }
1874 if (ra == 0)
1875 addr = 0;
1876 else
1877 addr = cpu->cd.ppc.gpr[ra];
1878 addr += cpu->cd.ppc.gpr[rb];
1879 load = 0;
1880 switch (xo) {
1881 case PPC_31_LBZX:
1882 case PPC_31_LBZUX:
1883 case PPC_31_LHZX:
1884 case PPC_31_LHZUX:
1885 case PPC_31_LWZX:
1886 case PPC_31_LWZUX:
1887 load = 1;
1888 }
1889
1890 if (cpu->machine->instruction_trace) {
1891 if (cpu->cd.ppc.bits == 32)
1892 debug("\t[0x%08llx", (long long)addr);
1893 else
1894 debug("\t[0x%016llx", (long long)addr);
1895 }
1896
1897 tmp_data_len = 4;
1898 switch (xo) {
1899 case PPC_31_LBZX:
1900 case PPC_31_LBZUX:
1901 case PPC_31_STBX:
1902 case PPC_31_STBUX:
1903 tmp_data_len = 1;
1904 break;
1905 case PPC_31_LHZX:
1906 case PPC_31_LHZUX:
1907 case PPC_31_STHX:
1908 case PPC_31_STHUX:
1909 tmp_data_len = 2;
1910 break;
1911 }
1912
1913 tmp = 0;
1914
1915 if (load) {
1916 r = cpu->memory_rw(cpu, cpu->mem, addr,
1917 tmp_data, tmp_data_len, MEM_READ,
1918 CACHE_DATA);
1919 if (r == MEMORY_ACCESS_OK) {
1920 if (cpu->byte_order ==
1921 EMUL_BIG_ENDIAN) {
1922 for (i=0; i<tmp_data_len; i++) {
1923 tmp <<= 8;
1924 tmp += tmp_data[i];
1925 }
1926 } else {
1927 for (i=0; i<tmp_data_len; i++) {
1928 tmp <<= 8;
1929 tmp += tmp_data[
1930 tmp_data_len - 1
1931 - i];
1932 }
1933 }
1934 cpu->cd.ppc.gpr[rs] = tmp;
1935 }
1936 } else {
1937 tmp = cpu->cd.ppc.gpr[rs];
1938 if (cpu->byte_order == EMUL_BIG_ENDIAN) {
1939 for (i=0; i<tmp_data_len; i++)
1940 tmp_data[tmp_data_len-1-i] =
1941 tmp >> (8*i);
1942 } else {
1943 for (i=0; i<tmp_data_len; i++)
1944 tmp_data[i] = tmp >> (8*i);
1945 }
1946
1947 r = cpu->memory_rw(cpu, cpu->mem, addr,
1948 tmp_data, tmp_data_len, MEM_WRITE,
1949 CACHE_DATA);
1950 }
1951
1952 if (cpu->machine->instruction_trace) {
1953 if (r == MEMORY_ACCESS_OK) {
1954 switch (tmp_data_len) {
1955 case 1: debug(", data = 0x%02x]\n",
1956 (int)tmp);
1957 break;
1958 case 2: debug(", data = 0x%04x]\n",
1959 (int)tmp);
1960 break;
1961 case 4: debug(", data = 0x%08x]\n",
1962 (int)tmp);
1963 break;
1964 default:debug(", data = 0x%016llx]\n",
1965 (long long)tmp);
1966 }
1967 } else
1968 debug(", FAILED]\n");
1969 }
1970
1971 if (r != MEMORY_ACCESS_OK) {
1972 /* TODO: exception? */
1973 return 0;
1974 }
1975
1976 if (update && ra != 0)
1977 cpu->cd.ppc.gpr[ra] = addr;
1978 break;
1979
1980 case PPC_31_NEG:
1981 case PPC_31_NEGO:
1982 rt = (iword >> 21) & 31;
1983 ra = (iword >> 16) & 31;
1984 oe_bit = (iword >> 10) & 1;
1985 rc = iword & 1;
1986 if (oe_bit) {
1987 fatal("[ neg: PPC oe not yet implemeted ]\n");
1988 cpu->running = 0;
1989 return 0;
1990 }
1991 cpu->cd.ppc.gpr[rt] = ~cpu->cd.ppc.gpr[ra] + 1;
1992 if (rc)
1993 update_cr0(cpu, cpu->cd.ppc.gpr[rt]);
1994 break;
1995
1996 case PPC_31_ADDZE:
1997 case PPC_31_ADDZEO:
1998 rt = (iword >> 21) & 31;
1999 ra = (iword >> 16) & 31;
2000 oe_bit = (iword >> 10) & 1;
2001 rc = iword & 1;
2002 if (oe_bit) {
2003 fatal("[ addz: PPC oe not yet implemeted ]\n");
2004 cpu->running = 0;
2005 return 0;
2006 }
2007 old_ca = cpu->cd.ppc.xer & PPC_XER_CA;
2008 cpu->cd.ppc.xer &= PPC_XER_CA;
2009 if (cpu->cd.ppc.bits == 32) {
2010 tmp = (uint32_t)cpu->cd.ppc.gpr[ra];
2011 tmp2 = tmp;
2012 /* printf("addze: tmp2 = %016llx\n",
2013 (long long)tmp2); */
2014 if (old_ca)
2015 tmp ++;
2016 /* printf("addze: tmp = %016llx\n\n",
2017 (long long)tmp); */
2018 /* TODO: is this CA correct? */
2019 if ((tmp >> 32) != (tmp2 >> 32))
2020 cpu->cd.ppc.xer |= PPC_XER_CA;
2021 /* High 32 bits are probably undefined
2022 in 32-bit mode (I hope) */
2023 cpu->cd.ppc.gpr[rt] = tmp;
2024 } else {
2025 fatal("ADDZE 64-bit, TODO\n");
2026 }
2027 if (rc)
2028 update_cr0(cpu, cpu->cd.ppc.gpr[rt]);
2029 break;
2030
2031 case PPC_31_MTSR:
2032 /* Move to segment register (?) */
2033 /* TODO */
2034 break;
2035
2036 case PPC_31_MFSRIN:
2037 case PPC_31_MTSRIN:
2038 /* mfsrin: Move to segment register indirect (?) */
2039 /* mtsrin: Move to segment register indirect (?) */
2040 rt = (iword >> 21) & 31;
2041 rb = (iword >> 11) & 31;
2042
2043 /* TODO */
2044
2045 if (xo == PPC_31_MFSRIN)
2046 cpu->cd.ppc.gpr[rt] = 0;
2047 break;
2048
2049 case PPC_31_ADDC:
2050 case PPC_31_ADDCO:
2051 case PPC_31_ADDE:
2052 case PPC_31_ADDEO:
2053 case PPC_31_ADD:
2054 case PPC_31_ADDO:
2055 case PPC_31_MULHW:
2056 case PPC_31_MULHWU:
2057 case PPC_31_MULLW:
2058 case PPC_31_MULLWO:
2059 case PPC_31_SUBFE:
2060 case PPC_31_SUBFEO:
2061 case PPC_31_SUBFZE:
2062 case PPC_31_SUBFZEO:
2063 case PPC_31_SUBFC:
2064 case PPC_31_SUBFCO:
2065 case PPC_31_SUBF:
2066 case PPC_31_SUBFO:
2067 rt = (iword >> 21) & 31;
2068 ra = (iword >> 16) & 31;
2069 rb = (iword >> 11) & 31;
2070 oe_bit = (iword >> 10) & 1;
2071 rc = iword & 1;
2072 if (oe_bit) {
2073 fatal("[ add: PPC oe not yet implemeted ]\n");
2074 cpu->running = 0;
2075 return 0;
2076 }
2077 switch (xo) {
2078 case PPC_31_ADD:
2079 case PPC_31_ADDO:
2080 cpu->cd.ppc.gpr[rt] = cpu->cd.ppc.gpr[ra] +
2081 cpu->cd.ppc.gpr[rb];
2082 break;
2083 case PPC_31_ADDC:
2084 case PPC_31_ADDCO:
2085 case PPC_31_ADDE:
2086 case PPC_31_ADDEO:
2087 old_ca = cpu->cd.ppc.xer & PPC_XER_CA;
2088 cpu->cd.ppc.xer &= PPC_XER_CA;
2089 if (cpu->cd.ppc.bits == 32) {
2090 tmp = (uint32_t)cpu->cd.ppc.gpr[ra];
2091 tmp2 = tmp;
2092 /* printf("adde: tmp2 = %016llx\n",
2093 (long long)tmp2); */
2094 tmp += (uint32_t)cpu->cd.ppc.gpr[rb];
2095 if ((xo == PPC_31_ADDE ||
2096 xo == PPC_31_ADDEO) && old_ca)
2097 tmp ++;
2098 /* printf("adde: tmp = %016llx\n\n",
2099 (long long)tmp); */
2100 /* TODO: is this CA correct? */
2101 if ((tmp >> 32) != (tmp2 >> 32))
2102 cpu->cd.ppc.xer |= PPC_XER_CA;
2103 /* High 32 bits are probably undefined
2104 in 32-bit mode (I hope) */
2105 cpu->cd.ppc.gpr[rt] = tmp;
2106 } else {
2107 fatal("ADDE 64-bit, TODO\n");
2108 }
2109 break;
2110 case PPC_31_MULHW:
2111 cpu->cd.ppc.gpr[rt] = (int64_t) (
2112 (int64_t)(int32_t)cpu->cd.ppc.gpr[ra] *
2113 (int64_t)(int32_t)cpu->cd.ppc.gpr[rb]);
2114 cpu->cd.ppc.gpr[rt] >>= 32;
2115 break;
2116 case PPC_31_MULHWU:
2117 cpu->cd.ppc.gpr[rt] = (uint64_t) (
2118 (uint64_t)(uint32_t)cpu->cd.ppc.gpr[ra] *
2119 (uint64_t)(uint32_t)cpu->cd.ppc.gpr[rb]);
2120 cpu->cd.ppc.gpr[rt] >>= 32;
2121 break;
2122 case PPC_31_MULLW:
2123 case PPC_31_MULLWO:
2124 cpu->cd.ppc.gpr[rt] = (int64_t) (
2125 (int32_t)cpu->cd.ppc.gpr[ra] *
2126 (int32_t)cpu->cd.ppc.gpr[rb]);
2127 break;
2128 case PPC_31_SUBF:
2129 case PPC_31_SUBFO:
2130 cpu->cd.ppc.gpr[rt] = ~cpu->cd.ppc.gpr[ra] +
2131 cpu->cd.ppc.gpr[rb] + 1;
2132 break;
2133 case PPC_31_SUBFC:
2134 case PPC_31_SUBFCO:
2135 case PPC_31_SUBFE:
2136 case PPC_31_SUBFEO:
2137 case PPC_31_SUBFZE:
2138 case PPC_31_SUBFZEO:
2139 old_ca = cpu->cd.ppc.xer & PPC_XER_CA;
2140 if (xo == PPC_31_SUBFC || xo == PPC_31_SUBFCO)
2141 old_ca = 1;
2142 cpu->cd.ppc.xer &= PPC_XER_CA;
2143 if (cpu->cd.ppc.bits == 32) {
2144 tmp = (~cpu->cd.ppc.gpr[ra])
2145 & 0xffffffff;
2146 tmp2 = tmp;
2147 if (xo != PPC_31_SUBFZE &&
2148 xo != PPC_31_SUBFZEO)
2149 tmp += (cpu->cd.ppc.gpr[rb] &
2150 0xffffffff);
2151 if (old_ca)
2152 tmp ++;
2153 /* printf("subfe: tmp2 = %016llx\n",
2154 (long long)tmp2);
2155 printf("subfe: tmp = %016llx\n\n",
2156 (long long)tmp); */
2157 /* TODO: is this CA correct? */
2158 if ((tmp >> 32) != (tmp2 >> 32))
2159 cpu->cd.ppc.xer |= PPC_XER_CA;
2160 /* High 32 bits are probably undefined
2161 in 32-bit mode (I hope) */
2162 cpu->cd.ppc.gpr[rt] = tmp;
2163 } else {
2164 fatal("SUBFE 64-bit, TODO\n");
2165 }
2166 break;
2167 }
2168 if (rc)
2169 update_cr0(cpu, cpu->cd.ppc.gpr[rt]);
2170 break;
2171
2172 case PPC_31_MFSPR:
2173 case PPC_31_MFTB:
2174 rt = (iword >> 21) & 31;
2175 spr = ((iword >> 6) & 0x3e0) + ((iword >> 16) & 31);
2176 switch (spr) {
2177 case 1: cpu->cd.ppc.gpr[rt] = cpu->cd.ppc.xer;
2178 break;
2179 case 8: cpu->cd.ppc.gpr[rt] = cpu->cd.ppc.lr;
2180 break;
2181 case 9: cpu->cd.ppc.gpr[rt] = cpu->cd.ppc.ctr;
2182 break;
2183 case 22:/* TODO: check pr */
2184 cpu->cd.ppc.gpr[rt] = cpu->cd.ppc.dec;
2185 break;
2186 case 259: /* NOTE: no pr check */
2187 cpu->cd.ppc.gpr[rt] = cpu->cd.ppc.sprg3;
2188 break;
2189 case 268: /* MFTB, NOTE: no pr check */
2190 cpu->cd.ppc.gpr[rt] = cpu->cd.ppc.tbl;
2191 break;
2192 case 269: /* MFTBU, NOTE: no pr check */
2193 cpu->cd.ppc.gpr[rt] = cpu->cd.ppc.tbu;
2194 break;
2195 case 272:
2196 /* TODO: check pr */
2197 cpu->cd.ppc.gpr[rt] = cpu->cd.ppc.sprg0;
2198 break;
2199 case 273:
2200 /* TODO: check pr */
2201 cpu->cd.ppc.gpr[rt] = cpu->cd.ppc.sprg1;
2202 break;
2203 case 274:
2204 /* TODO: check pr */
2205 cpu->cd.ppc.gpr[rt] = cpu->cd.ppc.sprg2;
2206 break;
2207 case 275:
2208 /* TODO: check pr */
2209 cpu->cd.ppc.gpr[rt] = cpu->cd.ppc.sprg3;
2210 break;
2211 case 287:
2212 /* TODO: check pr */
2213 cpu->cd.ppc.gpr[rt] = cpu->cd.ppc.pvr;
2214 break;
2215 case 310:/* TODO: check pr */
2216 cpu->cd.ppc.gpr[rt] = cpu->cd.ppc.hdec;
2217 break;
2218 case 1023:
2219 /* TODO: check pr */
2220 cpu->cd.ppc.gpr[rt] = cpu->cd.ppc.pir;
2221 break;
2222 default:
2223 fatal("[ unimplemented PPC spr 0x%04x, "
2224 "pc = 0x%016llx ]\n",
2225 spr, (long long) (cpu->cd.ppc.pc_last));
2226 /* cpu->running = 0;
2227 return 0; */
2228 break;
2229 }
2230
2231 /* TODO: is this correct? */
2232 if (cpu->cd.ppc.bits == 32)
2233 cpu->cd.ppc.gpr[rt] &= 0xffffffff;
2234 break;
2235
2236 case PPC_31_CNTLZW:
2237 rs = (iword >> 21) & 31;
2238 ra = (iword >> 16) & 31;
2239 rc = iword & 1;
2240 cpu->cd.ppc.gpr[ra] = 0;
2241 for (i=0; i<32; i++) {
2242 if (cpu->cd.ppc.gpr[rs] &
2243 ((uint64_t)1 << (31-i)))
2244 break;
2245 cpu->cd.ppc.gpr[ra] ++;
2246 }
2247 if (rc)
2248 update_cr0(cpu, cpu->cd.ppc.gpr[ra]);
2249 break;
2250
2251 case PPC_31_SLW:
2252 case PPC_31_SRAW:
2253 case PPC_31_SRW:
2254 case PPC_31_AND:
2255 case PPC_31_ANDC:
2256 case PPC_31_NOR:
2257 case PPC_31_OR:
2258 case PPC_31_ORC:
2259 case PPC_31_XOR:
2260 case PPC_31_NAND:
2261 rs = (iword >> 21) & 31;
2262 ra = (iword >> 16) & 31;
2263 rb = (iword >> 11) & 31;
2264 rc = iword & 1;
2265 switch (xo) {
2266 case PPC_31_SLW:
2267 sh = cpu->cd.ppc.gpr[rb] & 0x3f;
2268 cpu->cd.ppc.gpr[ra] = cpu->cd.ppc.gpr[rs];
2269 while (sh-- > 0)
2270 cpu->cd.ppc.gpr[ra] <<= 1;
2271 cpu->cd.ppc.gpr[ra] &= 0xffffffff;
2272 break;
2273 case PPC_31_SRAW:
2274 tmp = cpu->cd.ppc.gpr[rs] & 0xffffffff;
2275 cpu->cd.ppc.xer &= ~PPC_XER_CA;
2276 i = 0;
2277 sh = cpu->cd.ppc.gpr[rb] & 0x3f;
2278 if (tmp & 0x80000000)
2279 i = 1;
2280 while (sh-- > 0) {
2281 if (tmp & 1)
2282 i++;
2283 tmp >>= 1;
2284 if (tmp & 0x40000000)
2285 tmp |= 0x80000000;
2286 }
2287 cpu->cd.ppc.gpr[ra] = (int64_t)(int32_t)tmp;
2288 /* Set the CA bit if rs contained a negative
2289 number to begin with, and any 1-bits were
2290 shifted out: */
2291 if (i > 1)
2292 cpu->cd.ppc.xer |= PPC_XER_CA;
2293 break;
2294 case PPC_31_SRW:
2295 sh = cpu->cd.ppc.gpr[rb] & 0x3f;
2296 cpu->cd.ppc.gpr[ra] = cpu->cd.ppc.gpr[rs]
2297 & 0xffffffff;
2298 while (sh-- > 0)
2299 cpu->cd.ppc.gpr[ra] >>= 1;
2300 break;
2301 case PPC_31_AND:
2302 cpu->cd.ppc.gpr[ra] = cpu->cd.ppc.gpr[rs] &
2303 cpu->cd.ppc.gpr[rb];
2304 break;
2305 case PPC_31_ANDC:
2306 cpu->cd.ppc.gpr[ra] = cpu->cd.ppc.gpr[rs] &
2307 (~cpu->cd.ppc.gpr[rb]);
2308 break;
2309 case PPC_31_NOR:
2310 cpu->cd.ppc.gpr[ra] = ~(cpu->cd.ppc.gpr[rs] |
2311 cpu->cd.ppc.gpr[rb]);
2312 break;
2313 case PPC_31_OR:
2314 cpu->cd.ppc.gpr[ra] = cpu->cd.ppc.gpr[rs] |
2315 cpu->cd.ppc.gpr[rb];
2316 break;
2317 case PPC_31_ORC:
2318 cpu->cd.ppc.gpr[ra] = cpu->cd.ppc.gpr[rs] |
2319 (~cpu->cd.ppc.gpr[rb]);
2320 break;
2321 case PPC_31_XOR:
2322 cpu->cd.ppc.gpr[ra] = cpu->cd.ppc.gpr[rs] ^
2323 cpu->cd.ppc.gpr[rb];
2324 break;
2325 case PPC_31_NAND:
2326 cpu->cd.ppc.gpr[ra] = ~(cpu->cd.ppc.gpr[rs]
2327 & cpu->cd.ppc.gpr[rb]);
2328 break;
2329 }
2330 if (rc)
2331 update_cr0(cpu, cpu->cd.ppc.gpr[ra]);
2332 break;
2333
2334 case PPC_31_TLBIE:
2335 rb = (iword >> 11) & 31;
2336 /* TODO */
2337 break;
2338
2339 case PPC_31_TLBSYNC:
2340 /* Only on 603 and 604 (?) */
2341
2342 /* TODO */
2343 break;
2344
2345 case PPC_31_DCCCI:
2346 case PPC_31_ICCCI:
2347 /* Supervisor IBM 4xx Data Cache Congruence Class
2348 Invalidate, see www.xilinx.com/publications/
2349 xcellonline/partners/xc_pdf/xc_ibm_pwrpc42.pdf
2350 or similar */
2351 /* ICCCI is probably Instruction... blah blah */
2352 /* TODO */
2353 break;
2354
2355 case PPC_31_DIVWU:
2356 case PPC_31_DIVWUO:
2357 case PPC_31_DIVW:
2358 case PPC_31_DIVWO:
2359 rt = (iword >> 21) & 31;
2360 ra = (iword >> 16) & 31;
2361 rb = (iword >> 11) & 31;
2362 oe_bit = (iword >> 10) & 1;
2363 rc = iword & 1;
2364 switch (xo) {
2365 case PPC_31_DIVWU:
2366 case PPC_31_DIVWUO:
2367 tmp = cpu->cd.ppc.gpr[ra] & 0xffffffff;
2368 tmp2 = cpu->cd.ppc.gpr[rb] & 0xffffffff;
2369 if (tmp2 == 0) {
2370 /* Undefined: */
2371 tmp = 0;
2372 } else {
2373 tmp = tmp / tmp2;
2374 }
2375 cpu->cd.ppc.gpr[rt] = (int64_t)(int32_t)tmp;
2376 break;
2377 case PPC_31_DIVW:
2378 case PPC_31_DIVWO:
2379 tmp = (int64_t)(int32_t)cpu->cd.ppc.gpr[ra];
2380 tmp2 = (int64_t)(int32_t)cpu->cd.ppc.gpr[rb];
2381 if (tmp2 == 0) {
2382 /* Undefined: */
2383 tmp = 0;
2384 } else {
2385 tmp = (int64_t)tmp / (int64_t)tmp2;
2386 }
2387 cpu->cd.ppc.gpr[rt] = (int64_t)(int32_t)tmp;
2388 break;
2389 }
2390 if (rc)
2391 update_cr0(cpu, cpu->cd.ppc.gpr[rt]);
2392 if (oe_bit) {
2393 fatal("[ divwu: PPC oe not yet implemeted ]\n");
2394 cpu->running = 0;
2395 return 0;
2396 }
2397 break;
2398
2399 case PPC_31_MTSPR:
2400 rs = (iword >> 21) & 31;
2401 spr = ((iword >> 6) & 0x3e0) + ((iword >> 16) & 31);
2402 switch (spr) {
2403 case 1: cpu->cd.ppc.xer = cpu->cd.ppc.gpr[rs];
2404 break;
2405 case 8: cpu->cd.ppc.lr = cpu->cd.ppc.gpr[rs];
2406 break;
2407 case 9: cpu->cd.ppc.ctr = cpu->cd.ppc.gpr[rs];
2408 break;
2409 case 22: /* TODO: check pr */
2410 cpu->cd.ppc.dec = cpu->cd.ppc.gpr[rs];
2411 break;
2412 case 272:
2413 /* TODO: check hypv */
2414 cpu->cd.ppc.sprg0 = cpu->cd.ppc.gpr[rs];
2415 break;
2416 case 273:
2417 /* TODO: check pr */
2418 cpu->cd.ppc.sprg1 = cpu->cd.ppc.gpr[rs];
2419 break;
2420 case 274:
2421 /* TODO: check pr */
2422 cpu->cd.ppc.sprg2 = cpu->cd.ppc.gpr[rs];
2423 break;
2424 case 275:
2425 /* TODO: check pr */
2426 cpu->cd.ppc.sprg3 = cpu->cd.ppc.gpr[rs];
2427 break;
2428 case 284:
2429 /* TODO: check pr */
2430 cpu->cd.ppc.tbl = cpu->cd.ppc.gpr[rs];
2431 break;
2432 case 285:
2433 /* TODO: check pr */
2434 cpu->cd.ppc.tbu = cpu->cd.ppc.gpr[rs];
2435 break;
2436 case 287:
2437 fatal("[ PPC: attempt to write to PVR ]\n");
2438 break;
2439 case 310: /* TODO: check hypv */
2440 cpu->cd.ppc.hdec = cpu->cd.ppc.gpr[rs];
2441 break;
2442 case 1023:
2443 /* TODO: check pr */
2444 cpu->cd.ppc.pir = cpu->cd.ppc.gpr[rs];
2445 break;
2446 default:
2447 fatal("[ unimplemented PPC spr 0x%04x, "
2448 "pc = 0x%016llx ]\n",
2449 spr, (long long) (cpu->cd.ppc.pc_last));
2450 /* cpu->running = 0;
2451 return 0; */
2452 break;
2453 }
2454 break;
2455
2456 case PPC_31_SYNC:
2457 /* TODO: actually sync */
2458 break;
2459
2460 case PPC_31_LSWI:
2461 case PPC_31_STSWI:
2462 rs = (iword >> 21) & 31;
2463 ra = (iword >> 16) & 31;
2464 nb = (iword >> 11) & 31;
2465 if (nb == 0)
2466 nb = 32;
2467 if (ra == 0)
2468 addr = 0;
2469 else
2470 addr = cpu->cd.ppc.gpr[ra];
2471
2472 load = 0;
2473 if (xo == PPC_31_LSWI)
2474 load = 1;
2475
2476 if (cpu->machine->instruction_trace) {
2477 if (cpu->cd.ppc.bits == 32)
2478 debug("\t[0x%08llx", (long long)addr);
2479 else
2480 debug("\t[0x%016llx", (long long)addr);
2481 }
2482
2483 i = 24;
2484 r = 0; /* Error count. */
2485 while (nb-- > 0) {
2486 if (load) {
2487 /* (Actually rt should be used.) */
2488 if (cpu->memory_rw(cpu, cpu->mem, addr,
2489 tmp_data, 1, MEM_READ, CACHE_DATA)
2490 != MEMORY_ACCESS_OK) {
2491 r++;
2492 break;
2493 }
2494 if (i == 24)
2495 cpu->cd.ppc.gpr[rs] = 0;
2496 cpu->cd.ppc.gpr[rs] |=
2497 (tmp_data[0] << i);
2498 } else {
2499 tmp_data[0] = cpu->cd.ppc.gpr[rs] >> i;
2500 if (cpu->memory_rw(cpu, cpu->mem, addr,
2501 tmp_data, 1, MEM_WRITE, CACHE_DATA)
2502 != MEMORY_ACCESS_OK) {
2503 r++;
2504 break;
2505 }
2506 }
2507 addr++; i-=8;
2508 if (i < 0) {
2509 i = 24;
2510 rs = (rs + 1) % 32;
2511 }
2512 }
2513
2514 if (cpu->machine->instruction_trace) {
2515 if (r == 0)
2516 debug(", ...]\n");
2517 else
2518 debug(", FAILED]\n");
2519 }
2520
2521 if (r > 0) {
2522 /* TODO: exception */
2523 fatal("TODO: exception.\n");
2524 return 0;
2525 }
2526 break;
2527
2528 case PPC_31_SRAWI:
2529 rs = (iword >> 21) & 31;
2530 ra = (iword >> 16) & 31;
2531 sh = (iword >> 11) & 31;
2532 rc = iword & 1;
2533 tmp = cpu->cd.ppc.gpr[rs] & 0xffffffff;
2534 cpu->cd.ppc.xer &= ~PPC_XER_CA;
2535 i = 0;
2536 if (tmp & 0x80000000)
2537 i = 1;
2538 while (sh-- > 0) {
2539 if (tmp & 1)
2540 i++;
2541 tmp >>= 1;
2542 if (tmp & 0x40000000)
2543 tmp |= 0x80000000;
2544 }
2545 cpu->cd.ppc.gpr[ra] = (int64_t)(int32_t)tmp;
2546 /* Set the CA bit if rs contained a negative
2547 number to begin with, and any 1-bits were
2548 shifted out: */
2549 if (i > 1)
2550 cpu->cd.ppc.xer |= PPC_XER_CA;
2551 if (rc)
2552 update_cr0(cpu, cpu->cd.ppc.gpr[ra]);
2553 break;
2554
2555 case PPC_31_EIEIO:
2556 /* TODO: actually eieio */
2557 break;
2558
2559 case PPC_31_EXTSB:
2560 case PPC_31_EXTSH:
2561 case PPC_31_EXTSW:
2562 rs = (iword >> 21) & 31;
2563 ra = (iword >> 16) & 31;
2564 rc = iword & 1;
2565 switch (xo) {
2566 case PPC_31_EXTSB:
2567 cpu->cd.ppc.gpr[ra] = (int64_t)
2568 (int8_t)cpu->cd.ppc.gpr[rs];
2569 break;
2570 case PPC_31_EXTSH:
2571 cpu->cd.ppc.gpr[ra] = (int64_t)
2572 (int16_t)cpu->cd.ppc.gpr[rs];
2573 break;
2574 case PPC_31_EXTSW:
2575 cpu->cd.ppc.gpr[ra] = (int64_t)
2576 (int32_t)cpu->cd.ppc.gpr[rs];
2577 break;
2578 }
2579 if (rc)
2580 update_cr0(cpu, cpu->cd.ppc.gpr[ra]);
2581 break;
2582
2583 default:
2584 fatal("[ unimplemented PPC hi6_31, xo = 0x%04x, "
2585 "pc = 0x%016llx ]\n",
2586 xo, (long long) (cpu->cd.ppc.pc_last));
2587 cpu->running = 0;
2588 return 0;
2589 }
2590 break;
2591
2592 case PPC_HI6_LWZ:
2593 case PPC_HI6_LWZU:
2594 case PPC_HI6_LHZ:
2595 case PPC_HI6_LHZU:
2596 case PPC_HI6_LHA:
2597 case PPC_HI6_LHAU:
2598 case PPC_HI6_LBZ:
2599 case PPC_HI6_LBZU:
2600 case PPC_HI6_STW:
2601 case PPC_HI6_STWU:
2602 case PPC_HI6_STH:
2603 case PPC_HI6_STHU:
2604 case PPC_HI6_STB:
2605 case PPC_HI6_STBU:
2606 case PPC_HI6_LFD:
2607 case PPC_HI6_STFD:
2608 /* NOTE: Loads use rt, not rs, but are otherwise similar
2609 to stores. This code uses rs for both. */
2610 rs = (iword >> 21) & 31;
2611 ra = (iword >> 16) & 31;
2612 imm = (int16_t)(iword & 0xffff);
2613
2614 fpreg = 0; load = 1; update = 0; tmp_data_len = 4;
2615 arithflag = 0;
2616
2617 switch (hi6) {
2618 case PPC_HI6_LWZU:
2619 case PPC_HI6_LHZU:
2620 case PPC_HI6_LHAU:
2621 case PPC_HI6_LBZU:
2622 case PPC_HI6_STBU:
2623 case PPC_HI6_STHU:
2624 case PPC_HI6_STWU:
2625 update = 1;
2626 }
2627
2628 switch (hi6) {
2629 case PPC_HI6_STW:
2630 case PPC_HI6_STWU:
2631 case PPC_HI6_STH:
2632 case PPC_HI6_STHU:
2633 case PPC_HI6_STB:
2634 case PPC_HI6_STBU:
2635 case PPC_HI6_STFD:
2636 load = 0;
2637 }
2638
2639 switch (hi6) {
2640 case PPC_HI6_LFD:
2641 case PPC_HI6_STFD:
2642 tmp_data_len = 8;
2643 break;
2644 case PPC_HI6_LBZ:
2645 case PPC_HI6_LBZU:
2646 case PPC_HI6_STB:
2647 case PPC_HI6_STBU:
2648 tmp_data_len = 1;
2649 break;
2650 case PPC_HI6_LHZ:
2651 case PPC_HI6_LHZU:
2652 case PPC_HI6_LHA:
2653 case PPC_HI6_LHAU:
2654 case PPC_HI6_STH:
2655 case PPC_HI6_STHU:
2656 tmp_data_len = 2;
2657 break;
2658 }
2659
2660 switch (hi6) {
2661 case PPC_HI6_LFD:
2662 case PPC_HI6_STFD:
2663 fpreg = 1;
2664 }
2665
2666 switch (hi6) {
2667 case PPC_HI6_LHA:
2668 case PPC_HI6_LHAU:
2669 arithflag = 1;
2670 }
2671
2672 if (ra == 0) {
2673 if (update)
2674 fatal("[ PPC WARNING: invalid Update form ]\n");
2675 addr = 0;
2676 } else
2677 addr = cpu->cd.ppc.gpr[ra];
2678
2679 if (load && update && ra == rs)
2680 fatal("[ PPC WARNING: invalid Update load form ]\n");
2681
2682 addr += imm;
2683
2684 /* TODO: alignment check? */
2685
2686 if (cpu->machine->instruction_trace) {
2687 if (cpu->cd.ppc.bits == 32)
2688 debug("\t[0x%08llx", (long long)addr);
2689 else
2690 debug("\t[0x%016llx", (long long)addr);
2691 }
2692
2693 if (load) {
2694 r = cpu->memory_rw(cpu, cpu->mem, addr, tmp_data,
2695 tmp_data_len, MEM_READ, CACHE_DATA);
2696
2697 if (r == MEMORY_ACCESS_OK) {
2698 tmp = 0;
2699 if (arithflag) {
2700 if (cpu->byte_order ==
2701 EMUL_BIG_ENDIAN) {
2702 if (tmp_data[0] & 0x80)
2703 tmp --;
2704 } else {
2705 if (tmp_data[tmp_data_len-1]
2706 & 0x80)
2707 tmp --;
2708 }
2709 }
2710 if (cpu->byte_order == EMUL_BIG_ENDIAN) {
2711 for (i=0; i<tmp_data_len; i++) {
2712 tmp <<= 8;
2713 tmp += tmp_data[i];
2714 }
2715 } else {
2716 for (i=0; i<tmp_data_len; i++) {
2717 tmp <<= 8;
2718 tmp += tmp_data[
2719 tmp_data_len - 1 -i];
2720 }
2721 }
2722
2723 if (!fpreg)
2724 cpu->cd.ppc.gpr[rs] = tmp;
2725 else
2726 cpu->cd.ppc.fpr[rs] = tmp;
2727 }
2728 } else {
2729 if (!fpreg)
2730 tmp = cpu->cd.ppc.gpr[rs];
2731 else
2732 tmp = cpu->cd.ppc.fpr[rs];
2733
2734 if (cpu->byte_order == EMUL_BIG_ENDIAN) {
2735 for (i=0; i<tmp_data_len; i++)
2736 tmp_data[tmp_data_len-1-i] =
2737 tmp >> (8*i);
2738 } else {
2739 for (i=0; i<tmp_data_len; i++)
2740 tmp_data[i] = tmp >> (8*i);
2741 }
2742
2743 r = cpu->memory_rw(cpu, cpu->mem, addr, tmp_data,
2744 tmp_data_len, MEM_WRITE, CACHE_DATA);
2745 }
2746
2747 if (cpu->machine->instruction_trace) {
2748 if (r == MEMORY_ACCESS_OK) {
2749 switch (tmp_data_len) {
2750 case 1: debug(", data = 0x%02x]\n", (int)tmp);
2751 break;
2752 case 2: debug(", data = 0x%04x]\n", (int)tmp);
2753 break;
2754 case 4: debug(", data = 0x%08x]\n", (int)tmp);
2755 break;
2756 default:debug(", data = 0x%016llx]\n",
2757 (long long)tmp);
2758 }
2759 } else
2760 debug(", FAILED]\n");
2761 }
2762
2763 if (r != MEMORY_ACCESS_OK) {
2764 /* TODO: exception? */
2765 return 0;
2766 }
2767
2768 if (update && ra != 0)
2769 cpu->cd.ppc.gpr[ra] = addr;
2770 break;
2771
2772 case PPC_HI6_LMW:
2773 case PPC_HI6_STMW:
2774 /* NOTE: Loads use rt, not rs, but are otherwise similar
2775 to stores. This code uses rs for both. */
2776 rs = (iword >> 21) & 31;
2777 ra = (iword >> 16) & 31;
2778 imm = (int16_t)(iword & 0xffff);
2779
2780 load = 1; tmp_data_len = 4;
2781
2782 switch (hi6) {
2783 case PPC_HI6_STMW:
2784 load = 0;
2785 }
2786
2787 if (ra == 0) {
2788 addr = 0;
2789 } else
2790 addr = cpu->cd.ppc.gpr[ra];
2791
2792 if (load && rs == 0)
2793 fatal("[ PPC WARNING: invalid LMW form ]\n");
2794
2795 addr += imm;
2796
2797 /* TODO: alignment check? */
2798
2799 if (cpu->machine->instruction_trace) {
2800 if (cpu->cd.ppc.bits == 32)
2801 debug("\t[0x%08llx", (long long)addr);
2802 else
2803 debug("\t[0x%016llx", (long long)addr);
2804 }
2805
2806 /* There can be multiple errors! */
2807 r = 0;
2808
2809 while (rs <= 31) {
2810 if (load) {
2811 if (cpu->memory_rw(cpu, cpu->mem, addr,
2812 tmp_data, tmp_data_len, MEM_READ,
2813 CACHE_DATA) != MEMORY_ACCESS_OK)
2814 r++;
2815
2816 if (r == 0) {
2817 tmp = 0;
2818 if (cpu->byte_order ==
2819 EMUL_BIG_ENDIAN) {
2820 for (i=0; i<tmp_data_len; i++) {
2821 tmp <<= 8;
2822 tmp += tmp_data[i];
2823 }
2824 } else {
2825 for (i=0; i<tmp_data_len; i++) {
2826 tmp <<= 8;
2827 tmp += tmp_data[
2828 tmp_data_len - 1
2829 - i];
2830 }
2831 }
2832
2833 cpu->cd.ppc.gpr[rs] = tmp;
2834 }
2835 } else {
2836 tmp = cpu->cd.ppc.gpr[rs];
2837
2838 if (cpu->byte_order == EMUL_BIG_ENDIAN) {
2839 for (i=0; i<tmp_data_len; i++)
2840 tmp_data[tmp_data_len-1-i] =
2841 tmp >> (8*i);
2842 } else {
2843 for (i=0; i<tmp_data_len; i++)
2844 tmp_data[i] = tmp >> (8*i);
2845 }
2846
2847 if (cpu->memory_rw(cpu, cpu->mem, addr,
2848 tmp_data, tmp_data_len, MEM_WRITE,
2849 CACHE_DATA) != MEMORY_ACCESS_OK)
2850 r ++;
2851 }
2852
2853 /* TODO: Exception! */
2854
2855 /* Go to next register, multiword... */
2856 rs ++;
2857 addr += tmp_data_len;
2858 }
2859
2860 if (cpu->machine->instruction_trace) {
2861 if (r == 0) {
2862 debug(", data = ...]\n");
2863 } else
2864 debug(", FAILED]\n");
2865 }
2866
2867 if (r > 0)
2868 return 0;
2869 break;
2870
2871 default:
2872 fatal("[ unimplemented PPC hi6 = 0x%02x, pc = 0x%016llx ]\n",
2873 hi6, (long long) (cpu->cd.ppc.pc_last));
2874 cpu->running = 0;
2875 return 0;
2876 }
2877
2878 return 1;
2879 }
2880
2881
2882 #define CPU_RUN ppc_cpu_run
2883 #define CPU_RINSTR ppc_cpu_run_instr
2884 #define CPU_RUN_PPC
2885 #include "cpu_run.c"
2886 #undef CPU_RINSTR
2887 #undef CPU_RUN_PPC
2888 #undef CPU_RUN
2889
2890
2891 #define MEMORY_RW ppc_memory_rw
2892 #define MEM_PPC
2893 #include "memory_rw.c"
2894 #undef MEM_PPC
2895 #undef MEMORY_RW
2896
2897
2898 /*
2899 * ppc_cpu_family_init():
2900 *
2901 * Fill in the cpu_family struct for PPC.
2902 */
2903 int ppc_cpu_family_init(struct cpu_family *fp)
2904 {
2905 fp->name = "PPC";
2906 fp->cpu_new = ppc_cpu_new;
2907 fp->list_available_types = ppc_cpu_list_available_types;
2908 fp->register_match = ppc_cpu_register_match;
2909 fp->disassemble_instr = ppc_cpu_disassemble_instr;
2910 fp->register_dump = ppc_cpu_register_dump;
2911 fp->run = ppc_cpu_run;
2912 fp->dumpinfo = ppc_cpu_dumpinfo;
2913 /* fp->show_full_statistics = ppc_cpu_show_full_statistics; */
2914 /* fp->tlbdump = ppc_cpu_tlbdump; */
2915 /* fp->interrupt = ppc_cpu_interrupt; */
2916 /* fp->interrupt_ack = ppc_cpu_interrupt_ack; */
2917 return 1;
2918 }
2919
2920
2921 #endif /* ENABLE_PPC */

  ViewVC Help
Powered by ViewVC 1.1.26