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.71 2006/07/26 23:21:48 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 |
* |
* |
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) |
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: |
3720 |
case PPC_31_LVXL: |
case PPC_31_LVXL: |
3721 |
case PPC_31_STVX: |
case PPC_31_STVX: |
3722 |
case PPC_31_STVXL: |
case PPC_31_STVXL: |
|
fatal("[ TODO: altivec load/store ]\n"); |
|
3723 |
load = 0; |
load = 0; |
3724 |
switch (xo) { |
switch (xo) { |
3725 |
case PPC_31_LVX: |
case PPC_31_LVX: |
3729 |
rs = (iword >> 21) & 31; |
rs = (iword >> 21) & 31; |
3730 |
ra = (iword >> 16) & 31; |
ra = (iword >> 16) & 31; |
3731 |
rb = (iword >> 11) & 31; |
rb = (iword >> 11) & 31; |
3732 |
ic->arg[0] = (size_t)(&cpu->cd.ppc.vr_hi[rs]); |
ic->arg[0] = rs; |
3733 |
if (ra == 0) |
if (ra == 0) |
3734 |
ic->arg[1] = (size_t)(&cpu->cd.ppc.zero); |
ic->arg[1] = (size_t)(&cpu->cd.ppc.zero); |
3735 |
else |
else |
3736 |
ic->arg[1] = (size_t)(&cpu->cd.ppc.gpr[ra]); |
ic->arg[1] = (size_t)(&cpu->cd.ppc.gpr[ra]); |
3737 |
ic->arg[2] = (size_t)(&cpu->cd.ppc.gpr[rb]); |
ic->arg[2] = (size_t)(&cpu->cd.ppc.gpr[rb]); |
3738 |
ic->f = |
ic->f = load? instr(lvx) : instr(stvx); |
|
#ifdef MODE32 |
|
|
ppc32_loadstore_indexed |
|
|
#else |
|
|
ppc_loadstore_indexed |
|
|
#endif |
|
|
[3 + 4 * load]; |
|
3739 |
break; |
break; |
3740 |
|
|
3741 |
default:goto bad; |
default:goto bad; |