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

Parent Directory Parent Directory | Revision Log Revision Log


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

  ViewVC Help
Powered by ViewVC 1.1.26