// main opcode 63 static inline ppc_opc_func_t* ppc_opc_group_f2(uint32 instr) { uint32 ext = PPC_OPC_EXT(instr); uint32_t index = ext & 0x1f; debug(DEBUG_DEC, "In %s, ext=%d\n", __FUNCTION__, ext); return ppc_opc_table_group_f2[index]; }
static void ppc_opc_invalid() { #if 0 if (gCPU.pc == gPromOSIEntry && gCPU.current_opc == PROM_MAGIC_OPCODE) { call_prom_osi(); return; } if (gCPU.current_opc == 0x00333301) { // memset(r3, r4, r5) uint32 dest = gCPU.gpr[3]; uint32 c = gCPU.gpr[4]; uint32 size = gCPU.gpr[5]; if (dest & 0xfff) { byte *dst; ppc_direct_effective_memory_handle(dest, dst); uint32 a = 4096 - (dest & 0xfff); memset(dst, c, a); size -= a; dest += a; } while (size >= 4096) { byte *dst; ppc_direct_effective_memory_handle(dest, dst); memset(dst, c, 4096); dest += 4096; size -= 4096; } if (size) { byte *dst; ppc_direct_effective_memory_handle(dest, dst); memset(dst, c, size); } gCPU.pc = gCPU.npc; return; } if (gCPU.current_opc == 0x00333302) { // memcpy uint32 dest = gCPU.gpr[3]; uint32 src = gCPU.gpr[4]; uint32 size = gCPU.gpr[5]; byte *d, *s; ppc_direct_effective_memory_handle(dest, d); ppc_direct_effective_memory_handle(src, s); while (size--) { if (!(dest & 0xfff)) ppc_direct_effective_memory_handle(dest, d); if (!(src & 0xfff)) ppc_direct_effective_memory_handle(src, s); *d = *s; src++; dest++; d++; s++; } gCPU.pc = gCPU.npc; return; } #endif ht_printf("[PPC/DEC] Bad opcode: %08x (%u:%u) PC=%08x\n", gCPU.current_opc, PPC_OPC_MAIN(gCPU.current_opc), PPC_OPC_EXT(gCPU.current_opc), gCPU.pc); SINGLESTEP("unknown instruction\n"); }
// main opcode 31 inline static void ppc_opc_group_2() { uint32 ext = PPC_OPC_EXT(gCPU.current_opc); if (ext >= (sizeof ppc_opc_table_group2 / sizeof ppc_opc_table_group2[0])) { ppc_opc_invalid(); } ppc_opc_table_group2[ext](); }
// main opcode 31 static inline ppc_opc_func_t* ppc_opc_group_2(uint32 opc) { uint32 ext = PPC_OPC_EXT(opc); debug(DEBUG_DEC, "In %s, ext=%d\n", __FUNCTION__, ext); if (ext >= (sizeof ppc_opc_table_group_2 / sizeof ppc_opc_table_group_2[0])) { return &ppc_opc_invalid; } return ppc_opc_table_group_2[ext]; }
// main opcode 63 static void ppc_opc_group_f2() { if ((gCPU.msr & MSR_FP) == 0) { ppc_exception(PPC_EXC_NO_FPU); return; } uint32 ext = PPC_OPC_EXT(gCPU.current_opc); if (ext & 16) { switch (ext & 0x1f) { case 18: ppc_opc_fdivx(); return; case 20: ppc_opc_fsubx(); return; case 21: ppc_opc_faddx(); return; case 22: ppc_opc_fsqrtx(); return; case 23: ppc_opc_fselx(); return; case 25: ppc_opc_fmulx(); return; case 26: ppc_opc_frsqrtex(); return; case 28: ppc_opc_fmsubx(); return; case 29: ppc_opc_fmaddx(); return; case 30: ppc_opc_fnmsubx(); return; case 31: ppc_opc_fnmaddx(); return; } } else { switch (ext) { case 0: ppc_opc_fcmpu(); return; case 12: ppc_opc_frspx(); return; case 14: ppc_opc_fctiwx(); return; case 15: ppc_opc_fctiwzx(); return; //-- case 32: ppc_opc_fcmpo(); return; case 38: ppc_opc_mtfsb1x(); return; case 40: ppc_opc_fnegx(); return; case 64: ppc_opc_mcrfs(); return; case 70: ppc_opc_mtfsb0x(); return; case 72: ppc_opc_fmrx(); return; case 134: ppc_opc_mtfsfix(); return; case 136: ppc_opc_fnabsx(); return; case 264: ppc_opc_fabsx(); return; case 583: ppc_opc_mffsx(); return; case 711: ppc_opc_mtfsfx(); return; } } ppc_opc_invalid(); }
// main opcode 59 static void ppc_opc_group_f1() { if ((gCPU.msr & MSR_FP) == 0) { ppc_exception(PPC_EXC_NO_FPU); return; } uint32 ext = PPC_OPC_EXT(gCPU.current_opc); switch (ext & 0x1f) { case 18: ppc_opc_fdivsx(); return; case 20: ppc_opc_fsubsx(); return; case 21: ppc_opc_faddsx(); return; case 22: ppc_opc_fsqrtsx(); return; case 24: ppc_opc_fresx(); return; case 25: ppc_opc_fmulsx(); return; case 28: ppc_opc_fmsubsx(); return; case 29: ppc_opc_fmaddsx(); return; case 30: ppc_opc_fnmsubsx(); return; case 31: ppc_opc_fnmaddsx(); return; } ppc_opc_invalid(); }
// main opcode 19 static void ppc_opc_group_1() { uint32 ext = PPC_OPC_EXT(gCPU.current_opc); if (ext & 1) { // crxxx if (ext <= 225) { switch (ext) { case 33: ppc_opc_crnor(); return; case 129: ppc_opc_crandc(); return; case 193: ppc_opc_crxor(); return; case 225: ppc_opc_crnand(); return; } } else { switch (ext) { case 257: ppc_opc_crand(); return; case 289: ppc_opc_creqv(); return; case 417: ppc_opc_crorc(); return; case 449: ppc_opc_cror(); return; } } } else if (ext & (1<<9)) { // bcctrx if (ext == 528) { ppc_opc_bcctrx(); return; } } else { switch (ext) { case 16: ppc_opc_bclrx(); return; case 0: ppc_opc_mcrf(); return; case 50: ppc_opc_rfi(); return; case 150: ppc_opc_isync(); return; } } ppc_opc_invalid(); }
// main opcode 04 static void ppc_opc_group_v() { uint32 ext = PPC_OPC_EXT(gCPU.current_opc); #ifndef __VEC_EXC_OFF__ if ((gCPU.msr & MSR_VEC) == 0) { ppc_exception(PPC_EXC_NO_VEC); return; } #endif switch(ext & 0x1f) { case 16: if (gCPU.current_opc & PPC_OPC_Rc) return ppc_opc_vmhraddshs(); else return ppc_opc_vmhaddshs(); case 17: return ppc_opc_vmladduhm(); case 18: if (gCPU.current_opc & PPC_OPC_Rc) return ppc_opc_vmsummbm(); else return ppc_opc_vmsumubm(); case 19: if (gCPU.current_opc & PPC_OPC_Rc) return ppc_opc_vmsumuhs(); else return ppc_opc_vmsumuhm(); case 20: if (gCPU.current_opc & PPC_OPC_Rc) return ppc_opc_vmsumshs(); else return ppc_opc_vmsumshm(); case 21: if (gCPU.current_opc & PPC_OPC_Rc) return ppc_opc_vperm(); else return ppc_opc_vsel(); case 22: return ppc_opc_vsldoi(); case 23: if (gCPU.current_opc & PPC_OPC_Rc) return ppc_opc_vnmsubfp(); else return ppc_opc_vmaddfp(); } switch(ext & 0x1ff) { case 3: return ppc_opc_vcmpequbx(); case 35: return ppc_opc_vcmpequhx(); case 67: return ppc_opc_vcmpequwx(); case 99: return ppc_opc_vcmpeqfpx(); case 227: return ppc_opc_vcmpgefpx(); case 259: return ppc_opc_vcmpgtubx(); case 291: return ppc_opc_vcmpgtuhx(); case 323: return ppc_opc_vcmpgtuwx(); case 355: return ppc_opc_vcmpgtfpx(); case 387: return ppc_opc_vcmpgtsbx(); case 419: return ppc_opc_vcmpgtshx(); case 451: return ppc_opc_vcmpgtswx(); case 483: return ppc_opc_vcmpbfpx(); } if (ext >= (sizeof ppc_opc_table_groupv / sizeof ppc_opc_table_groupv[0])) { return ppc_opc_invalid(); } return ppc_opc_table_groupv[ext](); }