1 |
/* |
/* |
2 |
* Copyright (C) 2005-2006 Anders Gavare. All rights reserved. |
* Copyright (C) 2005-2007 Anders Gavare. All rights reserved. |
3 |
* |
* |
4 |
* Redistribution and use in source and binary forms, with or without |
* Redistribution and use in source and binary forms, with or without |
5 |
* modification, are permitted provided that the following conditions are met: |
* modification, are permitted provided that the following conditions are met: |
25 |
* SUCH DAMAGE. |
* SUCH DAMAGE. |
26 |
* |
* |
27 |
* |
* |
28 |
* $Id: cpu_ppc_instr.c,v 1.59 2006/02/09 22:40:27 debug Exp $ |
* $Id: cpu_ppc_instr.c,v 1.73 2007/02/17 10:06:19 debug Exp $ |
29 |
* |
* |
30 |
* POWER/PowerPC instructions. |
* POWER/PowerPC instructions. |
31 |
* |
* |
987 |
X(fctiwz) |
X(fctiwz) |
988 |
{ |
{ |
989 |
struct ieee_float_value frb; |
struct ieee_float_value frb; |
990 |
int32_t res = 0; |
uint32_t res = 0; |
991 |
|
|
992 |
CHECK_FOR_FPU_EXCEPTION; |
CHECK_FOR_FPU_EXCEPTION; |
993 |
|
|
1411 |
|
|
1412 |
|
|
1413 |
/* |
/* |
1414 |
|
* rldicl: |
1415 |
|
* |
1416 |
|
* arg[0] = copy of the instruction word |
1417 |
|
*/ |
1418 |
|
X(rldicl) |
1419 |
|
{ |
1420 |
|
int rs = (ic->arg[0] >> 21) & 31; |
1421 |
|
int ra = (ic->arg[0] >> 16) & 31; |
1422 |
|
int sh = ((ic->arg[0] >> 11) & 31) | ((ic->arg[0] & 2) << 4); |
1423 |
|
int mb = ((ic->arg[0] >> 6) & 31) | (ic->arg[0] & 0x20); |
1424 |
|
int rc = ic->arg[0] & 1; |
1425 |
|
uint64_t tmp = cpu->cd.ppc.gpr[rs], tmp2; |
1426 |
|
/* TODO: Fix this, its performance is awful: */ |
1427 |
|
while (sh-- != 0) { |
1428 |
|
int b = (tmp >> 63) & 1; |
1429 |
|
tmp = (tmp << 1) | b; |
1430 |
|
} |
1431 |
|
tmp2 = 0; |
1432 |
|
while (mb <= 63) { |
1433 |
|
tmp |= ((uint64_t)1 << (63-mb)); |
1434 |
|
mb ++; |
1435 |
|
} |
1436 |
|
cpu->cd.ppc.gpr[ra] = tmp & tmp2; |
1437 |
|
if (rc) |
1438 |
|
update_cr0(cpu, cpu->cd.ppc.gpr[ra]); |
1439 |
|
} |
1440 |
|
|
1441 |
|
|
1442 |
|
/* |
1443 |
* rldicr: |
* rldicr: |
1444 |
* |
* |
1445 |
* arg[0] = copy of the instruction word |
* arg[0] = copy of the instruction word |
1466 |
|
|
1467 |
|
|
1468 |
/* |
/* |
1469 |
|
* rldimi: |
1470 |
|
* |
1471 |
|
* arg[0] = copy of the instruction word |
1472 |
|
*/ |
1473 |
|
X(rldimi) |
1474 |
|
{ |
1475 |
|
uint32_t iw = ic->arg[0]; |
1476 |
|
int rs = (iw >> 21) & 31, ra = (iw >> 16) & 31; |
1477 |
|
int sh = ((iw >> 11) & 31) | ((iw & 2) << 4); |
1478 |
|
int mb = ((iw >> 6) & 31) | (iw & 0x20); |
1479 |
|
int rc = ic->arg[0] & 1; |
1480 |
|
int m; |
1481 |
|
uint64_t tmp, s = cpu->cd.ppc.gpr[rs]; |
1482 |
|
/* TODO: Fix this, its performance is awful: */ |
1483 |
|
while (sh-- != 0) { |
1484 |
|
int b = (s >> 63) & 1; |
1485 |
|
s = (s << 1) | b; |
1486 |
|
} |
1487 |
|
m = mb; tmp = 0; |
1488 |
|
do { |
1489 |
|
tmp |= ((uint64_t)1 << (63-m)); |
1490 |
|
m ++; |
1491 |
|
} while (m != 63 - sh); |
1492 |
|
cpu->cd.ppc.gpr[ra] &= ~tmp; |
1493 |
|
cpu->cd.ppc.gpr[ra] |= (tmp & s); |
1494 |
|
if (rc) |
1495 |
|
update_cr0(cpu, cpu->cd.ppc.gpr[ra]); |
1496 |
|
} |
1497 |
|
|
1498 |
|
|
1499 |
|
/* |
1500 |
* rlwnm: |
* rlwnm: |
1501 |
* |
* |
1502 |
* arg[0] = ptr to ra |
* arg[0] = ptr to ra |
1733 |
|
|
1734 |
|
|
1735 |
/* |
/* |
1736 |
* rfi: Return from Interrupt |
* rfi[d]: Return from Interrupt |
1737 |
*/ |
*/ |
1738 |
X(rfi) |
X(rfi) |
1739 |
{ |
{ |
1747 |
cpu->pc = cpu->cd.ppc.spr[SPR_SRR0]; |
cpu->pc = cpu->cd.ppc.spr[SPR_SRR0]; |
1748 |
quick_pc_to_pointers(cpu); |
quick_pc_to_pointers(cpu); |
1749 |
} |
} |
1750 |
|
X(rfid) |
1751 |
|
{ |
1752 |
|
uint64_t tmp, mask = 0x800000000000ff73ULL; |
1753 |
|
|
1754 |
|
reg_access_msr(cpu, &tmp, 0, 0); |
1755 |
|
tmp &= ~mask; |
1756 |
|
tmp |= (cpu->cd.ppc.spr[SPR_SRR1] & mask); |
1757 |
|
reg_access_msr(cpu, &tmp, 1, 0); |
1758 |
|
|
1759 |
|
cpu->pc = cpu->cd.ppc.spr[SPR_SRR0]; |
1760 |
|
if (!(tmp & PPC_MSR_SF)) |
1761 |
|
cpu->pc = (uint32_t)cpu->pc; |
1762 |
|
quick_pc_to_pointers(cpu); |
1763 |
|
} |
1764 |
|
|
1765 |
|
|
1766 |
/* |
/* |
1789 |
* mtmsr: Move To MSR |
* mtmsr: Move To MSR |
1790 |
* |
* |
1791 |
* arg[0] = pointer to source register |
* arg[0] = pointer to source register |
1792 |
|
* arg[1] = page offset of the next instruction |
1793 |
|
* arg[2] = 0 for 32-bit (mtmsr), 1 for 64-bit (mtmsrd) |
1794 |
*/ |
*/ |
1795 |
X(mtmsr) |
X(mtmsr) |
1796 |
{ |
{ |
1797 |
MODE_uint_t old_pc; |
MODE_uint_t old_pc; |
1798 |
|
uint64_t x = reg(ic->arg[0]); |
1799 |
|
|
1800 |
/* TODO: check permission! */ |
/* TODO: check permission! */ |
1801 |
|
|
1803 |
cpu->pc = (cpu->pc & ~0xfff) + ic->arg[1]; |
cpu->pc = (cpu->pc & ~0xfff) + ic->arg[1]; |
1804 |
old_pc = cpu->pc; |
old_pc = cpu->pc; |
1805 |
|
|
1806 |
reg_access_msr(cpu, (uint64_t*)ic->arg[0], 1, 1); |
if (!ic->arg[2]) { |
1807 |
|
uint64_t y; |
1808 |
|
reg_access_msr(cpu, &y, 0, 0); |
1809 |
|
x = (y & 0xffffffff00000000ULL) | (x & 0xffffffffULL); |
1810 |
|
} |
1811 |
|
|
1812 |
|
reg_access_msr(cpu, &x, 1, 1); |
1813 |
|
|
1814 |
/* |
/* |
1815 |
* Super-ugly hack: If the pc wasn't changed (i.e. if there was no |
* Super-ugly hack: If the pc wasn't changed (i.e. if there was no |
2031 |
DOT2(extsh) |
DOT2(extsh) |
2032 |
X(extsw) { |
X(extsw) { |
2033 |
#ifdef MODE32 |
#ifdef MODE32 |
2034 |
fatal("TODO: extsw: invalid instruction\n"); exit(1); |
fatal("TODO: extsw: invalid instruction\n"); |
2035 |
#else |
#else |
2036 |
reg(ic->arg[2]) = (int64_t)(int32_t)reg(ic->arg[0]); |
reg(ic->arg[2]) = (int64_t)(int32_t)reg(ic->arg[0]); |
2037 |
#endif |
#endif |
2040 |
X(slw) { reg(ic->arg[2]) = (uint64_t)reg(ic->arg[0]) |
X(slw) { reg(ic->arg[2]) = (uint64_t)reg(ic->arg[0]) |
2041 |
<< (reg(ic->arg[1]) & 31); } |
<< (reg(ic->arg[1]) & 31); } |
2042 |
DOT2(slw) |
DOT2(slw) |
2043 |
|
X(sld) {int sa = reg(ic->arg[1]) & 127; |
2044 |
|
if (sa >= 64) reg(ic->arg[2]) = 0; |
2045 |
|
else reg(ic->arg[2]) = (uint64_t)reg(ic->arg[0]) << (sa & 63); } |
2046 |
|
DOT2(sld) |
2047 |
X(sraw) |
X(sraw) |
2048 |
{ |
{ |
2049 |
uint32_t tmp = reg(ic->arg[0]); |
uint32_t tmp = reg(ic->arg[0]); |
2082 |
DOT2(orc) |
DOT2(orc) |
2083 |
X(xor) { reg(ic->arg[2]) = reg(ic->arg[0]) ^ reg(ic->arg[1]); } |
X(xor) { reg(ic->arg[2]) = reg(ic->arg[0]) ^ reg(ic->arg[1]); } |
2084 |
DOT2(xor) |
DOT2(xor) |
2085 |
|
X(eqv) { reg(ic->arg[2]) = ~(reg(ic->arg[0]) ^ reg(ic->arg[1])); } |
2086 |
|
DOT2(eqv) |
2087 |
|
|
2088 |
|
|
2089 |
/* |
/* |
2473 |
|
|
2474 |
|
|
2475 |
/* |
/* |
2476 |
|
* lvx, stvx: Vector (16-byte) load/store (slow implementation) |
2477 |
|
* |
2478 |
|
* arg[0] = v-register nr of rs |
2479 |
|
* arg[1] = pointer to ra |
2480 |
|
* arg[2] = pointer to rb |
2481 |
|
*/ |
2482 |
|
X(lvx) |
2483 |
|
{ |
2484 |
|
MODE_uint_t addr = reg(ic->arg[1]) + reg(ic->arg[2]); |
2485 |
|
uint8_t data[16]; |
2486 |
|
uint64_t hi, lo; |
2487 |
|
int rs = ic->arg[0]; |
2488 |
|
|
2489 |
|
if (cpu->memory_rw(cpu, cpu->mem, addr, data, sizeof(data), |
2490 |
|
MEM_READ, CACHE_DATA) != MEMORY_ACCESS_OK) { |
2491 |
|
/* exception */ |
2492 |
|
return; |
2493 |
|
} |
2494 |
|
|
2495 |
|
hi = ((uint64_t)data[0] << 56) + |
2496 |
|
((uint64_t)data[1] << 48) + |
2497 |
|
((uint64_t)data[2] << 40) + |
2498 |
|
((uint64_t)data[3] << 32) + |
2499 |
|
((uint64_t)data[4] << 24) + |
2500 |
|
((uint64_t)data[5] << 16) + |
2501 |
|
((uint64_t)data[6] << 8) + |
2502 |
|
((uint64_t)data[7]); |
2503 |
|
lo = ((uint64_t)data[8] << 56) + |
2504 |
|
((uint64_t)data[9] << 48) + |
2505 |
|
((uint64_t)data[10] << 40) + |
2506 |
|
((uint64_t)data[11] << 32) + |
2507 |
|
((uint64_t)data[12] << 24) + |
2508 |
|
((uint64_t)data[13] << 16) + |
2509 |
|
((uint64_t)data[14] << 8) + |
2510 |
|
((uint64_t)data[15]); |
2511 |
|
|
2512 |
|
cpu->cd.ppc.vr_hi[rs] = hi; cpu->cd.ppc.vr_lo[rs] = lo; |
2513 |
|
} |
2514 |
|
X(stvx) |
2515 |
|
{ |
2516 |
|
uint8_t data[16]; |
2517 |
|
MODE_uint_t addr = reg(ic->arg[1]) + reg(ic->arg[2]); |
2518 |
|
int rs = ic->arg[0]; |
2519 |
|
uint64_t hi = cpu->cd.ppc.vr_hi[rs], lo = cpu->cd.ppc.vr_lo[rs]; |
2520 |
|
|
2521 |
|
data[0] = hi >> 56; |
2522 |
|
data[1] = hi >> 48; |
2523 |
|
data[2] = hi >> 40; |
2524 |
|
data[3] = hi >> 32; |
2525 |
|
data[4] = hi >> 24; |
2526 |
|
data[5] = hi >> 16; |
2527 |
|
data[6] = hi >> 8; |
2528 |
|
data[7] = hi; |
2529 |
|
data[8] = lo >> 56; |
2530 |
|
data[9] = lo >> 48; |
2531 |
|
data[10] = lo >> 40; |
2532 |
|
data[11] = lo >> 32; |
2533 |
|
data[12] = lo >> 24; |
2534 |
|
data[13] = lo >> 16; |
2535 |
|
data[14] = lo >> 8; |
2536 |
|
data[15] = lo; |
2537 |
|
|
2538 |
|
cpu->memory_rw(cpu, cpu->mem, addr, data, |
2539 |
|
sizeof(data), MEM_WRITE, CACHE_DATA); |
2540 |
|
} |
2541 |
|
|
2542 |
|
|
2543 |
|
/* |
2544 |
|
* vxor: Vector (16-byte) XOR |
2545 |
|
* |
2546 |
|
* arg[0] = v-register nr of source 1 |
2547 |
|
* arg[1] = v-register nr of source 2 |
2548 |
|
* arg[2] = v-register nr of destination |
2549 |
|
*/ |
2550 |
|
X(vxor) |
2551 |
|
{ |
2552 |
|
cpu->cd.ppc.vr_hi[ic->arg[2]] = |
2553 |
|
cpu->cd.ppc.vr_hi[ic->arg[0]] ^ cpu->cd.ppc.vr_hi[ic->arg[1]]; |
2554 |
|
cpu->cd.ppc.vr_lo[ic->arg[2]] = |
2555 |
|
cpu->cd.ppc.vr_lo[ic->arg[0]] ^ cpu->cd.ppc.vr_lo[ic->arg[1]]; |
2556 |
|
} |
2557 |
|
|
2558 |
|
|
2559 |
|
/* |
2560 |
* tlbia: TLB invalidate all |
* tlbia: TLB invalidate all |
2561 |
*/ |
*/ |
2562 |
X(tlbia) |
X(tlbia) |
2563 |
{ |
{ |
2564 |
printf("[ tlbia ]\n"); |
fatal("[ tlbia ]\n"); |
2565 |
cpu->invalidate_translation_caches(cpu, 0, INVALIDATE_ALL); |
cpu->invalidate_translation_caches(cpu, 0, INVALIDATE_ALL); |
2566 |
} |
} |
2567 |
|
|
2571 |
*/ |
*/ |
2572 |
X(tlbie) |
X(tlbie) |
2573 |
{ |
{ |
2574 |
|
/* fatal("[ tlbie ]\n"); */ |
2575 |
cpu->invalidate_translation_caches(cpu, reg(ic->arg[0]), |
cpu->invalidate_translation_caches(cpu, reg(ic->arg[0]), |
2576 |
INVALIDATE_VADDR); |
INVALIDATE_VADDR); |
2577 |
} |
} |
2600 |
X(user_syscall) |
X(user_syscall) |
2601 |
{ |
{ |
2602 |
useremul_syscall(cpu, ic->arg[0]); |
useremul_syscall(cpu, ic->arg[0]); |
2603 |
|
|
2604 |
|
if (!cpu->running) { |
2605 |
|
cpu->n_translated_instrs --; |
2606 |
|
cpu->cd.ppc.next_ic = ¬hing_call; |
2607 |
|
} |
2608 |
} |
} |
2609 |
|
|
2610 |
|
|
2615 |
{ |
{ |
2616 |
of_emul(cpu); |
of_emul(cpu); |
2617 |
if (cpu->running == 0) { |
if (cpu->running == 0) { |
2618 |
cpu->running_translated = 0; |
cpu->n_translated_instrs --; |
2619 |
|
cpu->cd.ppc.next_ic = ¬hing_call; |
2620 |
} |
} |
2621 |
cpu->pc = cpu->cd.ppc.spr[SPR_LR]; |
cpu->pc = cpu->cd.ppc.spr[SPR_LR]; |
2622 |
if (cpu->machine->show_trace_tree) |
if (cpu->machine->show_trace_tree) |
2683 |
/* |
/* |
2684 |
* ppc_instr_to_be_translated(): |
* ppc_instr_to_be_translated(): |
2685 |
* |
* |
2686 |
* Translate an instruction word into an ppc_instr_call. ic is filled in with |
* Translate an instruction word into a ppc_instr_call. ic is filled in with |
2687 |
* valid data for the translated instruction, or a "nothing" instruction if |
* valid data for the translated instruction, or a "nothing" instruction if |
2688 |
* there was a translation failure. The newly translated instruction is then |
* there was a translation failure. The newly translated instruction is then |
2689 |
* executed. |
* executed. |
2694 |
uint32_t iword, mask; |
uint32_t iword, mask; |
2695 |
unsigned char *page; |
unsigned char *page; |
2696 |
unsigned char ib[4]; |
unsigned char ib[4]; |
|
#ifdef DYNTRANS_BACKEND |
|
|
int simple = 0; |
|
|
#endif |
|
2697 |
int main_opcode, rt, rs, ra, rb, rc, aa_bit, l_bit, lk_bit, spr, sh, |
int main_opcode, rt, rs, ra, rb, rc, aa_bit, l_bit, lk_bit, spr, sh, |
2698 |
xo, imm, load, size, update, zero, bf, bo, bi, bh, oe_bit, n64=0, |
xo, imm, load, size, update, zero, bf, bo, bi, bh, oe_bit, n64=0, |
2699 |
bfa, fp, byterev, nb, mb, me; |
bfa, fp, byterev, nb, mb, me; |
2710 |
addr &= ~((1 << PPC_INSTR_ALIGNMENT_SHIFT) - 1); |
addr &= ~((1 << PPC_INSTR_ALIGNMENT_SHIFT) - 1); |
2711 |
|
|
2712 |
/* Read the instruction word from memory: */ |
/* Read the instruction word from memory: */ |
2713 |
page = cpu->cd.ppc.host_load[addr >> 12]; |
#ifdef MODE32 |
2714 |
|
page = cpu->cd.ppc.host_load[((uint32_t)addr) >> 12]; |
2715 |
|
#else |
2716 |
|
{ |
2717 |
|
const uint32_t mask1 = (1 << DYNTRANS_L1N) - 1; |
2718 |
|
const uint32_t mask2 = (1 << DYNTRANS_L2N) - 1; |
2719 |
|
const uint32_t mask3 = (1 << DYNTRANS_L3N) - 1; |
2720 |
|
uint32_t x1 = (addr >> (64-DYNTRANS_L1N)) & mask1; |
2721 |
|
uint32_t x2 = (addr >> (64-DYNTRANS_L1N-DYNTRANS_L2N)) & mask2; |
2722 |
|
uint32_t x3 = (addr >> (64-DYNTRANS_L1N-DYNTRANS_L2N- |
2723 |
|
DYNTRANS_L3N)) & mask3; |
2724 |
|
struct DYNTRANS_L2_64_TABLE *l2 = cpu->cd.ppc.l1_64[x1]; |
2725 |
|
struct DYNTRANS_L3_64_TABLE *l3 = l2->l3[x2]; |
2726 |
|
page = l3->host_load[x3]; |
2727 |
|
} |
2728 |
|
#endif |
2729 |
|
|
2730 |
if (page != NULL) { |
if (page != NULL) { |
2731 |
/* fatal("TRANSLATION HIT!\n"); */ |
/* fatal("TRANSLATION HIT!\n"); */ |
2759 |
switch (main_opcode) { |
switch (main_opcode) { |
2760 |
|
|
2761 |
case 0x04: |
case 0x04: |
2762 |
fatal("[ TODO: ALTIVEC ]\n"); |
if (iword == 0x12739cc4) { |
2763 |
ic->f = instr(nop); |
/* vxor v19,v19,v19 */ |
2764 |
|
ic->f = instr(vxor); |
2765 |
|
ic->arg[0] = 19; |
2766 |
|
ic->arg[1] = 19; |
2767 |
|
ic->arg[2] = 19; |
2768 |
|
} else { |
2769 |
|
fatal("[ TODO: Unimplemented ALTIVEC, iword" |
2770 |
|
" = 0x%08"PRIx32"x ]\n", iword); |
2771 |
|
goto bad; |
2772 |
|
} |
2773 |
break; |
break; |
2774 |
|
|
2775 |
case PPC_HI6_MULLI: |
case PPC_HI6_MULLI: |
2890 |
case PPC_HI6_LHAU: |
case PPC_HI6_LHAU: |
2891 |
case PPC_HI6_LWZ: |
case PPC_HI6_LWZ: |
2892 |
case PPC_HI6_LWZU: |
case PPC_HI6_LWZU: |
2893 |
|
case PPC_HI6_LD: |
2894 |
case PPC_HI6_LFD: |
case PPC_HI6_LFD: |
2895 |
case PPC_HI6_LFS: |
case PPC_HI6_LFS: |
2896 |
case PPC_HI6_STB: |
case PPC_HI6_STB: |
2899 |
case PPC_HI6_STHU: |
case PPC_HI6_STHU: |
2900 |
case PPC_HI6_STW: |
case PPC_HI6_STW: |
2901 |
case PPC_HI6_STWU: |
case PPC_HI6_STWU: |
2902 |
|
case PPC_HI6_STD: |
2903 |
case PPC_HI6_STFD: |
case PPC_HI6_STFD: |
2904 |
case PPC_HI6_STFS: |
case PPC_HI6_STFS: |
2905 |
rs = (iword >> 21) & 31; |
rs = (iword >> 21) & 31; |
2916 |
case PPC_HI6_LHZU: load=1; size=1; update=1; break; |
case PPC_HI6_LHZU: load=1; size=1; update=1; break; |
2917 |
case PPC_HI6_LWZ: load=1; size=2; break; |
case PPC_HI6_LWZ: load=1; size=2; break; |
2918 |
case PPC_HI6_LWZU: load=1; size=2; update=1; break; |
case PPC_HI6_LWZU: load=1; size=2; update=1; break; |
2919 |
|
case PPC_HI6_LD: load=1; size=3; break; |
2920 |
case PPC_HI6_LFD: load=1; size=3; fp=1;ic->f=instr(lfd);break; |
case PPC_HI6_LFD: load=1; size=3; fp=1;ic->f=instr(lfd);break; |
2921 |
case PPC_HI6_LFS: load=1; size=2; fp=1;ic->f=instr(lfs);break; |
case PPC_HI6_LFS: load=1; size=2; fp=1;ic->f=instr(lfs);break; |
2922 |
case PPC_HI6_STB: break; |
case PPC_HI6_STB: break; |
2925 |
case PPC_HI6_STHU: size=1; update=1; break; |
case PPC_HI6_STHU: size=1; update=1; break; |
2926 |
case PPC_HI6_STW: size=2; break; |
case PPC_HI6_STW: size=2; break; |
2927 |
case PPC_HI6_STWU: size=2; update=1; break; |
case PPC_HI6_STWU: size=2; update=1; break; |
2928 |
|
case PPC_HI6_STD: size=3; break; |
2929 |
case PPC_HI6_STFD: size=3; fp=1; ic->f = instr(stfd); break; |
case PPC_HI6_STFD: size=3; fp=1; ic->f = instr(stfd); break; |
2930 |
case PPC_HI6_STFS: size=2; fp=1; ic->f = instr(stfs); break; |
case PPC_HI6_STFS: size=2; fp=1; ic->f = instr(stfs); break; |
2931 |
} |
} |
3095 |
ic->f = instr(rfi); |
ic->f = instr(rfi); |
3096 |
break; |
break; |
3097 |
|
|
3098 |
|
case PPC_19_RFID: |
3099 |
|
ic->f = instr(rfid); |
3100 |
|
break; |
3101 |
|
|
3102 |
case PPC_19_MCRF: |
case PPC_19_MCRF: |
3103 |
bf = (iword >> 23) & 7; |
bf = (iword >> 23) & 7; |
3104 |
bfa = (iword >> 18) & 7; |
bfa = (iword >> 18) & 7; |
3188 |
xo = (iword >> 2) & 7; |
xo = (iword >> 2) & 7; |
3189 |
switch (xo) { |
switch (xo) { |
3190 |
|
|
3191 |
|
case PPC_30_RLDICL: |
3192 |
case PPC_30_RLDICR: |
case PPC_30_RLDICR: |
3193 |
ic->f = instr(rldicr); |
case PPC_30_RLDIMI: |
3194 |
|
switch (xo) { |
3195 |
|
case PPC_30_RLDICL: ic->f = instr(rldicl); break; |
3196 |
|
case PPC_30_RLDICR: ic->f = instr(rldicr); break; |
3197 |
|
case PPC_30_RLDIMI: ic->f = instr(rldimi); break; |
3198 |
|
} |
3199 |
ic->arg[0] = iword; |
ic->arg[0] = iword; |
3200 |
if (cpu->cd.ppc.bits == 32) { |
if (cpu->cd.ppc.bits == 32) { |
3201 |
fatal("TODO: rldicr in 32-bit mode?\n"); |
fatal("TODO: rld* in 32-bit mode?\n"); |
3202 |
goto bad; |
goto bad; |
3203 |
} |
} |
3204 |
break; |
break; |
3292 |
break; |
break; |
3293 |
|
|
3294 |
case PPC_31_MTMSR: |
case PPC_31_MTMSR: |
3295 |
|
case PPC_31_MTMSRD: |
3296 |
rs = (iword >> 21) & 31; |
rs = (iword >> 21) & 31; |
3297 |
l_bit = (iword >> 16) & 1; |
l_bit = (iword >> 16) & 1; |
3298 |
if (l_bit) { |
if (l_bit) { |
3301 |
} |
} |
3302 |
ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[rs]); |
ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[rs]); |
3303 |
ic->arg[1] = (addr & 0xfff) + 4; |
ic->arg[1] = (addr & 0xfff) + 4; |
3304 |
|
ic->arg[2] = xo == PPC_31_MTMSRD; |
3305 |
ic->f = instr(mtmsr); |
ic->f = instr(mtmsr); |
3306 |
break; |
break; |
3307 |
|
|
3367 |
break; |
break; |
3368 |
|
|
3369 |
case PPC_31_SYNC: |
case PPC_31_SYNC: |
3370 |
|
case PPC_31_DSSALL: |
3371 |
case PPC_31_EIEIO: |
case PPC_31_EIEIO: |
3372 |
case PPC_31_DCBST: |
case PPC_31_DCBST: |
3373 |
case PPC_31_DCBTST: |
case PPC_31_DCBTST: |
3576 |
case PPC_31_EXTSH: |
case PPC_31_EXTSH: |
3577 |
case PPC_31_EXTSW: |
case PPC_31_EXTSW: |
3578 |
case PPC_31_SLW: |
case PPC_31_SLW: |
3579 |
|
case PPC_31_SLD: |
3580 |
case PPC_31_SRAW: |
case PPC_31_SRAW: |
3581 |
case PPC_31_SRW: |
case PPC_31_SRW: |
3582 |
case PPC_31_AND: |
case PPC_31_AND: |
3586 |
case PPC_31_OR: |
case PPC_31_OR: |
3587 |
case PPC_31_ORC: |
case PPC_31_ORC: |
3588 |
case PPC_31_XOR: |
case PPC_31_XOR: |
3589 |
|
case PPC_31_EQV: |
3590 |
rs = (iword >> 21) & 31; |
rs = (iword >> 21) & 31; |
3591 |
ra = (iword >> 16) & 31; |
ra = (iword >> 16) & 31; |
3592 |
rb = (iword >> 11) & 31; |
rb = (iword >> 11) & 31; |
3601 |
rc_f = instr(extsw_dot); break; |
rc_f = instr(extsw_dot); break; |
3602 |
case PPC_31_SLW: ic->f = instr(slw); |
case PPC_31_SLW: ic->f = instr(slw); |
3603 |
rc_f = instr(slw_dot); break; |
rc_f = instr(slw_dot); break; |
3604 |
|
case PPC_31_SLD: ic->f = instr(sld); |
3605 |
|
rc_f = instr(sld_dot); break; |
3606 |
case PPC_31_SRAW: ic->f = instr(sraw); |
case PPC_31_SRAW: ic->f = instr(sraw); |
3607 |
rc_f = instr(sraw_dot); break; |
rc_f = instr(sraw_dot); break; |
3608 |
case PPC_31_SRW: ic->f = instr(srw); |
case PPC_31_SRW: ic->f = instr(srw); |
3622 |
rc_f = instr(orc_dot); break; |
rc_f = instr(orc_dot); break; |
3623 |
case PPC_31_XOR: ic->f = instr(xor); |
case PPC_31_XOR: ic->f = instr(xor); |
3624 |
rc_f = instr(xor_dot); break; |
rc_f = instr(xor_dot); break; |
3625 |
|
case PPC_31_EQV: ic->f = instr(eqv); |
3626 |
|
rc_f = instr(eqv_dot); break; |
3627 |
} |
} |
3628 |
ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[rs]); |
ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[rs]); |
3629 |
ic->arg[1] = (size_t)(&cpu->cd.ppc.gpr[rb]); |
ic->arg[1] = (size_t)(&cpu->cd.ppc.gpr[rb]); |
3716 |
} |
} |
3717 |
break; |
break; |
3718 |
|
|
|
case 359: |
|
|
fatal("[ TODO: 359 ]\n"); |
|
|
ic->f = instr(nop); |
|
|
break; |
|
3719 |
case PPC_31_LVX: |
case PPC_31_LVX: |
3720 |
fatal("[ TODO: lvx ]\n"); |
case PPC_31_LVXL: |
|
ic->f = instr(nop); |
|
|
break; |
|
3721 |
case PPC_31_STVX: |
case PPC_31_STVX: |
|
fatal("[ TODO: stvx ]\n"); |
|
|
ic->f = instr(nop); |
|
|
break; |
|
3722 |
case PPC_31_STVXL: |
case PPC_31_STVXL: |
3723 |
fatal("[ TODO: stvxl ]\n"); |
load = 0; |
3724 |
ic->f = instr(nop); |
switch (xo) { |
3725 |
|
case PPC_31_LVX: |
3726 |
|
case PPC_31_LVXL: |
3727 |
|
load = 1; break; |
3728 |
|
} |
3729 |
|
rs = (iword >> 21) & 31; |
3730 |
|
ra = (iword >> 16) & 31; |
3731 |
|
rb = (iword >> 11) & 31; |
3732 |
|
ic->arg[0] = rs; |
3733 |
|
if (ra == 0) |
3734 |
|
ic->arg[1] = (size_t)(&cpu->cd.ppc.zero); |
3735 |
|
else |
3736 |
|
ic->arg[1] = (size_t)(&cpu->cd.ppc.gpr[ra]); |
3737 |
|
ic->arg[2] = (size_t)(&cpu->cd.ppc.gpr[rb]); |
3738 |
|
ic->f = load? instr(lvx) : instr(stvx); |
3739 |
break; |
break; |
3740 |
|
|
3741 |
default:goto bad; |
default:goto bad; |