diff --git a/rpcs3/Emu/Cell/PPUAnalyser.cpp b/rpcs3/Emu/Cell/PPUAnalyser.cpp index 3fef5240dd..a936eb6853 100644 --- a/rpcs3/Emu/Cell/PPUAnalyser.cpp +++ b/rpcs3/Emu/Cell/PPUAnalyser.cpp @@ -3102,1962 +3102,3 @@ bool ppu_module::analyse(u32 lib_toc, u32 entry, const u32 sec_end, con ppu_log.notice("Block analysis: %zu blocks (%zu enqueued)", funcs.size(), block_queue.size()); return true; } - -// Temporarily -#ifndef _MSC_VER -#pragma GCC diagnostic ignored "-Wunused-parameter" -#endif - -void ppu_acontext::UNK(ppu_opcode_t op) -{ - std::fill_n(gpr, 32, spec_gpr{}); - ppu_log.error("Unknown/Illegal opcode: 0x%08x at 0x%x", op.opcode, cia); -} - -void ppu_acontext::MFVSCR(ppu_opcode_t op) -{ -} - -void ppu_acontext::MTVSCR(ppu_opcode_t op) -{ -} - -void ppu_acontext::VADDCUW(ppu_opcode_t op) -{ -} - -void ppu_acontext::VADDFP(ppu_opcode_t op) -{ -} - -void ppu_acontext::VADDSBS(ppu_opcode_t op) -{ -} - -void ppu_acontext::VADDSHS(ppu_opcode_t op) -{ -} - -void ppu_acontext::VADDSWS(ppu_opcode_t op) -{ -} - -void ppu_acontext::VADDUBM(ppu_opcode_t op) -{ -} - -void ppu_acontext::VADDUBS(ppu_opcode_t op) -{ -} - -void ppu_acontext::VADDUHM(ppu_opcode_t op) -{ -} - -void ppu_acontext::VADDUHS(ppu_opcode_t op) -{ -} - -void ppu_acontext::VADDUWM(ppu_opcode_t op) -{ -} - -void ppu_acontext::VADDUWS(ppu_opcode_t op) -{ -} - -void ppu_acontext::VAND(ppu_opcode_t op) -{ -} - -void ppu_acontext::VANDC(ppu_opcode_t op) -{ -} - -void ppu_acontext::VAVGSB(ppu_opcode_t op) -{ -} - -void ppu_acontext::VAVGSH(ppu_opcode_t op) -{ -} - -void ppu_acontext::VAVGSW(ppu_opcode_t op) -{ -} - -void ppu_acontext::VAVGUB(ppu_opcode_t op) -{ -} - -void ppu_acontext::VAVGUH(ppu_opcode_t op) -{ -} - -void ppu_acontext::VAVGUW(ppu_opcode_t op) -{ -} - -void ppu_acontext::VCFSX(ppu_opcode_t op) -{ -} - -void ppu_acontext::VCFUX(ppu_opcode_t op) -{ -} - -void ppu_acontext::VCMPBFP(ppu_opcode_t op) -{ -} - -void ppu_acontext::VCMPEQFP(ppu_opcode_t op) -{ -} - -void ppu_acontext::VCMPEQUB(ppu_opcode_t op) -{ -} - -void ppu_acontext::VCMPEQUH(ppu_opcode_t op) -{ -} - -void ppu_acontext::VCMPEQUW(ppu_opcode_t op) -{ -} - -void ppu_acontext::VCMPGEFP(ppu_opcode_t op) -{ -} - -void ppu_acontext::VCMPGTFP(ppu_opcode_t op) -{ -} - -void ppu_acontext::VCMPGTSB(ppu_opcode_t op) -{ -} - -void ppu_acontext::VCMPGTSH(ppu_opcode_t op) -{ -} - -void ppu_acontext::VCMPGTSW(ppu_opcode_t op) -{ -} - -void ppu_acontext::VCMPGTUB(ppu_opcode_t op) -{ -} - -void ppu_acontext::VCMPGTUH(ppu_opcode_t op) -{ -} - -void ppu_acontext::VCMPGTUW(ppu_opcode_t op) -{ -} - -void ppu_acontext::VCTSXS(ppu_opcode_t op) -{ -} - -void ppu_acontext::VCTUXS(ppu_opcode_t op) -{ -} - -void ppu_acontext::VEXPTEFP(ppu_opcode_t op) -{ -} - -void ppu_acontext::VLOGEFP(ppu_opcode_t op) -{ -} - -void ppu_acontext::VMADDFP(ppu_opcode_t op) -{ -} - -void ppu_acontext::VMAXFP(ppu_opcode_t op) -{ -} - -void ppu_acontext::VMAXSB(ppu_opcode_t op) -{ -} - -void ppu_acontext::VMAXSH(ppu_opcode_t op) -{ -} - -void ppu_acontext::VMAXSW(ppu_opcode_t op) -{ -} - -void ppu_acontext::VMAXUB(ppu_opcode_t op) -{ -} - -void ppu_acontext::VMAXUH(ppu_opcode_t op) -{ -} - -void ppu_acontext::VMAXUW(ppu_opcode_t op) -{ -} - -void ppu_acontext::VMHADDSHS(ppu_opcode_t op) -{ -} - -void ppu_acontext::VMHRADDSHS(ppu_opcode_t op) -{ -} - -void ppu_acontext::VMINFP(ppu_opcode_t op) -{ -} - -void ppu_acontext::VMINSB(ppu_opcode_t op) -{ -} - -void ppu_acontext::VMINSH(ppu_opcode_t op) -{ -} - -void ppu_acontext::VMINSW(ppu_opcode_t op) -{ -} - -void ppu_acontext::VMINUB(ppu_opcode_t op) -{ -} - -void ppu_acontext::VMINUH(ppu_opcode_t op) -{ -} - -void ppu_acontext::VMINUW(ppu_opcode_t op) -{ -} - -void ppu_acontext::VMLADDUHM(ppu_opcode_t op) -{ -} - -void ppu_acontext::VMRGHB(ppu_opcode_t op) -{ -} - -void ppu_acontext::VMRGHH(ppu_opcode_t op) -{ -} - -void ppu_acontext::VMRGHW(ppu_opcode_t op) -{ -} - -void ppu_acontext::VMRGLB(ppu_opcode_t op) -{ -} - -void ppu_acontext::VMRGLH(ppu_opcode_t op) -{ -} - -void ppu_acontext::VMRGLW(ppu_opcode_t op) -{ -} - -void ppu_acontext::VMSUMMBM(ppu_opcode_t op) -{ -} - -void ppu_acontext::VMSUMSHM(ppu_opcode_t op) -{ -} - -void ppu_acontext::VMSUMSHS(ppu_opcode_t op) -{ -} - -void ppu_acontext::VMSUMUBM(ppu_opcode_t op) -{ -} - -void ppu_acontext::VMSUMUHM(ppu_opcode_t op) -{ -} - -void ppu_acontext::VMSUMUHS(ppu_opcode_t op) -{ -} - -void ppu_acontext::VMULESB(ppu_opcode_t op) -{ -} - -void ppu_acontext::VMULESH(ppu_opcode_t op) -{ -} - -void ppu_acontext::VMULEUB(ppu_opcode_t op) -{ -} - -void ppu_acontext::VMULEUH(ppu_opcode_t op) -{ -} - -void ppu_acontext::VMULOSB(ppu_opcode_t op) -{ -} - -void ppu_acontext::VMULOSH(ppu_opcode_t op) -{ -} - -void ppu_acontext::VMULOUB(ppu_opcode_t op) -{ -} - -void ppu_acontext::VMULOUH(ppu_opcode_t op) -{ -} - -void ppu_acontext::VNMSUBFP(ppu_opcode_t op) -{ -} - -void ppu_acontext::VNOR(ppu_opcode_t op) -{ -} - -void ppu_acontext::VOR(ppu_opcode_t op) -{ -} - -void ppu_acontext::VPERM(ppu_opcode_t op) -{ -} - -void ppu_acontext::VPKPX(ppu_opcode_t op) -{ -} - -void ppu_acontext::VPKSHSS(ppu_opcode_t op) -{ -} - -void ppu_acontext::VPKSHUS(ppu_opcode_t op) -{ -} - -void ppu_acontext::VPKSWSS(ppu_opcode_t op) -{ -} - -void ppu_acontext::VPKSWUS(ppu_opcode_t op) -{ -} - -void ppu_acontext::VPKUHUM(ppu_opcode_t op) -{ -} - -void ppu_acontext::VPKUHUS(ppu_opcode_t op) -{ -} - -void ppu_acontext::VPKUWUM(ppu_opcode_t op) -{ -} - -void ppu_acontext::VPKUWUS(ppu_opcode_t op) -{ -} - -void ppu_acontext::VREFP(ppu_opcode_t op) -{ -} - -void ppu_acontext::VRFIM(ppu_opcode_t op) -{ -} - -void ppu_acontext::VRFIN(ppu_opcode_t op) -{ -} - -void ppu_acontext::VRFIP(ppu_opcode_t op) -{ -} - -void ppu_acontext::VRFIZ(ppu_opcode_t op) -{ -} - -void ppu_acontext::VRLB(ppu_opcode_t op) -{ -} - -void ppu_acontext::VRLH(ppu_opcode_t op) -{ -} - -void ppu_acontext::VRLW(ppu_opcode_t op) -{ -} - -void ppu_acontext::VRSQRTEFP(ppu_opcode_t op) -{ -} - -void ppu_acontext::VSEL(ppu_opcode_t op) -{ -} - -void ppu_acontext::VSL(ppu_opcode_t op) -{ -} - -void ppu_acontext::VSLB(ppu_opcode_t op) -{ -} - -void ppu_acontext::VSLDOI(ppu_opcode_t op) -{ -} - -void ppu_acontext::VSLH(ppu_opcode_t op) -{ -} - -void ppu_acontext::VSLO(ppu_opcode_t op) -{ -} - -void ppu_acontext::VSLW(ppu_opcode_t op) -{ -} - -void ppu_acontext::VSPLTB(ppu_opcode_t op) -{ -} - -void ppu_acontext::VSPLTH(ppu_opcode_t op) -{ -} - -void ppu_acontext::VSPLTISB(ppu_opcode_t op) -{ -} - -void ppu_acontext::VSPLTISH(ppu_opcode_t op) -{ -} - -void ppu_acontext::VSPLTISW(ppu_opcode_t op) -{ -} - -void ppu_acontext::VSPLTW(ppu_opcode_t op) -{ -} - -void ppu_acontext::VSR(ppu_opcode_t op) -{ -} - -void ppu_acontext::VSRAB(ppu_opcode_t op) -{ -} - -void ppu_acontext::VSRAH(ppu_opcode_t op) -{ -} - -void ppu_acontext::VSRAW(ppu_opcode_t op) -{ -} - -void ppu_acontext::VSRB(ppu_opcode_t op) -{ -} - -void ppu_acontext::VSRH(ppu_opcode_t op) -{ -} - -void ppu_acontext::VSRO(ppu_opcode_t op) -{ -} - -void ppu_acontext::VSRW(ppu_opcode_t op) -{ -} - -void ppu_acontext::VSUBCUW(ppu_opcode_t op) -{ -} - -void ppu_acontext::VSUBFP(ppu_opcode_t op) -{ -} - -void ppu_acontext::VSUBSBS(ppu_opcode_t op) -{ -} - -void ppu_acontext::VSUBSHS(ppu_opcode_t op) -{ -} - -void ppu_acontext::VSUBSWS(ppu_opcode_t op) -{ -} - -void ppu_acontext::VSUBUBM(ppu_opcode_t op) -{ -} - -void ppu_acontext::VSUBUBS(ppu_opcode_t op) -{ -} - -void ppu_acontext::VSUBUHM(ppu_opcode_t op) -{ -} - -void ppu_acontext::VSUBUHS(ppu_opcode_t op) -{ -} - -void ppu_acontext::VSUBUWM(ppu_opcode_t op) -{ -} - -void ppu_acontext::VSUBUWS(ppu_opcode_t op) -{ -} - -void ppu_acontext::VSUMSWS(ppu_opcode_t op) -{ -} - -void ppu_acontext::VSUM2SWS(ppu_opcode_t op) -{ -} - -void ppu_acontext::VSUM4SBS(ppu_opcode_t op) -{ -} - -void ppu_acontext::VSUM4SHS(ppu_opcode_t op) -{ -} - -void ppu_acontext::VSUM4UBS(ppu_opcode_t op) -{ -} - -void ppu_acontext::VUPKHPX(ppu_opcode_t op) -{ -} - -void ppu_acontext::VUPKHSB(ppu_opcode_t op) -{ -} - -void ppu_acontext::VUPKHSH(ppu_opcode_t op) -{ -} - -void ppu_acontext::VUPKLPX(ppu_opcode_t op) -{ -} - -void ppu_acontext::VUPKLSB(ppu_opcode_t op) -{ -} - -void ppu_acontext::VUPKLSH(ppu_opcode_t op) -{ -} - -void ppu_acontext::VXOR(ppu_opcode_t op) -{ -} - -void ppu_acontext::TDI(ppu_opcode_t op) -{ -} - -void ppu_acontext::TWI(ppu_opcode_t op) -{ -} - -void ppu_acontext::MULLI(ppu_opcode_t op) -{ - const s64 amin = gpr[op.ra].imin; - const s64 amax = gpr[op.ra].imax; - - // Undef or mixed range (default) - s64 min = 0; - s64 max = -1; - - // Special cases like powers of 2 and their negations are not handled - if (amin <= amax) - { - min = amin * op.simm16; - max = amax * op.simm16; - - // Check overflow - if (min >> 63 != utils::mulh64(amin, op.simm16) || max >> 63 != utils::mulh64(amax, op.simm16)) - { - min = 0; - max = -1; - } - else if (min > max) - { - std::swap(min, max); - } - } - - gpr[op.rd] = spec_gpr::range(min, max, gpr[op.ra].tz() + std::countr_zero(op.simm16)); -} - -void ppu_acontext::SUBFIC(ppu_opcode_t op) -{ - gpr[op.rd] = ~gpr[op.ra] + spec_gpr::fixed(op.simm16) + spec_gpr::fixed(1); -} - -void ppu_acontext::CMPLI(ppu_opcode_t op) -{ -} - -void ppu_acontext::CMPI(ppu_opcode_t op) -{ -} - -void ppu_acontext::ADDIC(ppu_opcode_t op) -{ - gpr[op.rd] = gpr[op.ra] + spec_gpr::fixed(op.simm16); -} - -void ppu_acontext::ADDI(ppu_opcode_t op) -{ - gpr[op.rd] = op.ra ? gpr[op.ra] + spec_gpr::fixed(op.simm16) : spec_gpr::fixed(op.simm16); -} - -void ppu_acontext::ADDIS(ppu_opcode_t op) -{ - gpr[op.rd] = op.ra ? gpr[op.ra] + spec_gpr::fixed(op.simm16 * 65536) : spec_gpr::fixed(op.simm16 * 65536); -} - -void ppu_acontext::BC(ppu_opcode_t op) -{ -} - -void ppu_acontext::SC(ppu_opcode_t op) -{ -} - -void ppu_acontext::B(ppu_opcode_t op) -{ -} - -void ppu_acontext::MCRF(ppu_opcode_t op) -{ -} - -void ppu_acontext::BCLR(ppu_opcode_t op) -{ -} - -void ppu_acontext::CRNOR(ppu_opcode_t op) -{ -} - -void ppu_acontext::CRANDC(ppu_opcode_t op) -{ -} - -void ppu_acontext::ISYNC(ppu_opcode_t op) -{ -} - -void ppu_acontext::CRXOR(ppu_opcode_t op) -{ -} - -void ppu_acontext::CRNAND(ppu_opcode_t op) -{ -} - -void ppu_acontext::CRAND(ppu_opcode_t op) -{ -} - -void ppu_acontext::CREQV(ppu_opcode_t op) -{ -} - -void ppu_acontext::CRORC(ppu_opcode_t op) -{ -} - -void ppu_acontext::CROR(ppu_opcode_t op) -{ -} - -void ppu_acontext::BCCTR(ppu_opcode_t op) -{ -} - -void ppu_acontext::RLWIMI(ppu_opcode_t op) -{ - const u64 mask = ppu_rotate_mask(32 + op.mb32, 32 + op.me32); - - u64 min = gpr[op.rs].bmin; - u64 max = gpr[op.rs].bmax; - - if (op.mb32 <= op.me32) - { - // 32-bit op, including mnemonics: INSLWI, INSRWI (TODO) - min = utils::rol32(static_cast(min), op.sh32) & mask; - max = utils::rol32(static_cast(max), op.sh32) & mask; - } - else - { - // Full 64-bit op with duplication - min = utils::rol64(static_cast(min) | min << 32, op.sh32) & mask; - max = utils::rol64(static_cast(max) | max << 32, op.sh32) & mask; - } - - if (mask != umax) - { - // Insertion - min |= gpr[op.ra].bmin & ~mask; - max |= gpr[op.ra].bmax & ~mask; - } - - gpr[op.rs] = spec_gpr::approx(min, max); -} - -void ppu_acontext::RLWINM(ppu_opcode_t op) -{ - const u64 mask = ppu_rotate_mask(32 + op.mb32, 32 + op.me32); - - u64 min = gpr[op.rs].bmin; - u64 max = gpr[op.rs].bmax; - - if (op.mb32 <= op.me32) - { - if (op.sh32 == 0) - { - // CLRLWI, CLRRWI mnemonics - gpr[op.ra] = gpr[op.ra] & spec_gpr::fixed(mask); - return; - } - else if (op.mb32 == 0 && op.me32 == 31) - { - // ROTLWI, ROTRWI mnemonics - } - else if (op.mb32 == 0 && op.sh32 == 31 - op.me32) - { - // SLWI mnemonic - } - else if (op.me32 == 31 && op.sh32 == 32 - op.mb32) - { - // SRWI mnemonic - } - else if (op.mb32 == 0 && op.sh32 < 31 - op.me32) - { - // EXTLWI and other possible mnemonics - } - else if (op.me32 == 31 && 32 - op.sh32 < op.mb32) - { - // EXTRWI and other possible mnemonics - } - - min = utils::rol32(static_cast(min), op.sh32) & mask; - max = utils::rol32(static_cast(max), op.sh32) & mask; - } - else - { - // Full 64-bit op with duplication - min = utils::rol64(static_cast(min) | min << 32, op.sh32) & mask; - max = utils::rol64(static_cast(max) | max << 32, op.sh32) & mask; - } - - gpr[op.ra] = spec_gpr::approx(min, max); -} - -void ppu_acontext::RLWNM(ppu_opcode_t op) -{ - const u64 mask = ppu_rotate_mask(32 + op.mb32, 32 + op.me32); - - u64 min = gpr[op.rs].bmin; - u64 max = gpr[op.rs].bmax; - - if (op.mb32 <= op.me32) - { - if (op.mb32 == 0 && op.me32 == 31) - { - // ROTLW mnemonic - } - - // TODO - min = 0; - max = mask; - } - else - { - // Full 64-bit op with duplication - min = 0; - max = mask; - } - - gpr[op.ra] = spec_gpr::approx(min, max); -} - -void ppu_acontext::ORI(ppu_opcode_t op) -{ - gpr[op.ra] = gpr[op.rs] | spec_gpr::fixed(op.uimm16); -} - -void ppu_acontext::ORIS(ppu_opcode_t op) -{ - gpr[op.ra] = gpr[op.rs] | spec_gpr::fixed(op.uimm16 << 16); -} - -void ppu_acontext::XORI(ppu_opcode_t op) -{ - gpr[op.ra] = gpr[op.rs] ^ spec_gpr::fixed(op.uimm16); -} - -void ppu_acontext::XORIS(ppu_opcode_t op) -{ - gpr[op.ra] = gpr[op.rs] ^ spec_gpr::fixed(op.uimm16 << 16); -} - -void ppu_acontext::ANDI(ppu_opcode_t op) -{ - gpr[op.ra] = gpr[op.rs] & spec_gpr::fixed(op.uimm16); -} - -void ppu_acontext::ANDIS(ppu_opcode_t op) -{ - gpr[op.ra] = gpr[op.rs] & spec_gpr::fixed(op.uimm16 << 16); -} - -void ppu_acontext::RLDICL(ppu_opcode_t op) -{ - const u32 sh = op.sh64; - const u32 mb = op.mbe64; - const u64 mask = ~0ull >> mb; - - u64 min = gpr[op.rs].bmin; - u64 max = gpr[op.rs].bmax; - - if (64 - sh < mb) - { - // EXTRDI mnemonic - } - else if (64 - sh == mb) - { - // SRDI mnemonic - } - else if (sh == 0) - { - // CLRLDI mnemonic - gpr[op.ra] = gpr[op.rs] & spec_gpr::fixed(mask); - return; - } - - min = utils::rol64(min, sh) & mask; - max = utils::rol64(max, sh) & mask; - gpr[op.ra] = spec_gpr::approx(min, max); -} - -void ppu_acontext::RLDICR(ppu_opcode_t op) -{ - const u32 sh = op.sh64; - const u32 me = op.mbe64; - const u64 mask = ~0ull << (63 - me); - - u64 min = gpr[op.rs].bmin; - u64 max = gpr[op.rs].bmax; - - if (sh < 63 - me) - { - // EXTLDI mnemonic - } - else if (sh == 63 - me) - { - // SLDI mnemonic - } - else if (sh == 0) - { - // CLRRDI mnemonic - gpr[op.ra] = gpr[op.rs] & spec_gpr::fixed(mask); - return; - } - - min = utils::rol64(min, sh) & mask; - max = utils::rol64(max, sh) & mask; - gpr[op.ra] = spec_gpr::approx(min, max); -} - -void ppu_acontext::RLDIC(ppu_opcode_t op) -{ - const u32 sh = op.sh64; - const u32 mb = op.mbe64; - const u64 mask = ppu_rotate_mask(mb, 63 - sh); - - u64 min = gpr[op.rs].bmin; - u64 max = gpr[op.rs].bmax; - - if (mb == 0 && sh == 0) - { - gpr[op.ra] = gpr[op.rs]; - return; - } - else if (mb <= 63 - sh) - { - // CLRLSLDI - //gpr[op.ra] = (gpr[op.rs] & spec_gpr::fixed(ppu_rotate_mask(0, sh + mb))) << spec_gpr::fixed(sh); - return; - } - - min = utils::rol64(min, sh) & mask; - max = utils::rol64(max, sh) & mask; - gpr[op.ra] = spec_gpr::approx(min, max); -} - -void ppu_acontext::RLDIMI(ppu_opcode_t op) -{ - const u32 sh = op.sh64; - const u32 mb = op.mbe64; - const u64 mask = ppu_rotate_mask(mb, 63 - sh); - - u64 min = gpr[op.rs].bmin; - u64 max = gpr[op.rs].bmax; - - if (mb == 0 && sh == 0) - { - // Copy - } - else if (mb <= 63 - sh) - { - // INSRDI mnemonic - } - - min = utils::rol64(min, sh) & mask; - max = utils::rol64(max, sh) & mask; - - if (mask != umax) - { - // Insertion - min |= gpr[op.ra].bmin & ~mask; - max |= gpr[op.ra].bmax & ~mask; - } - - gpr[op.ra] = spec_gpr::approx(min, max); -} - -void ppu_acontext::RLDCL(ppu_opcode_t op) -{ - const u32 mb = op.mbe64; - const u64 mask = ~0ull >> mb; - - u64 min = gpr[op.rs].bmin; - u64 max = gpr[op.rs].bmax; - - // TODO - min = 0; - max = mask; - gpr[op.ra] = spec_gpr::approx(min, max); -} - -void ppu_acontext::RLDCR(ppu_opcode_t op) -{ - const u32 me = op.mbe64; - const u64 mask = ~0ull << (63 - me); - - u64 min = gpr[op.rs].bmin; - u64 max = gpr[op.rs].bmax; - - // TODO - min = 0; - max = mask; - gpr[op.ra] = spec_gpr::approx(min, max); -} - -void ppu_acontext::CMP(ppu_opcode_t op) -{ -} - -void ppu_acontext::TW(ppu_opcode_t op) -{ -} - -void ppu_acontext::LVSL(ppu_opcode_t op) -{ -} - -void ppu_acontext::LVEBX(ppu_opcode_t op) -{ -} - -void ppu_acontext::SUBFC(ppu_opcode_t op) -{ - gpr[op.rd] = ~gpr[op.ra] + gpr[op.rb] + spec_gpr::fixed(1); -} - -void ppu_acontext::ADDC(ppu_opcode_t op) -{ - gpr[op.rd] = gpr[op.ra] + gpr[op.rb]; -} - -void ppu_acontext::MULHDU(ppu_opcode_t op) -{ - gpr[op.rd].set_undef(); -} - -void ppu_acontext::MULHWU(ppu_opcode_t op) -{ - gpr[op.rd].set_undef(); -} - -void ppu_acontext::MFOCRF(ppu_opcode_t op) -{ - gpr[op.rd].set_undef(); -} - -void ppu_acontext::LWARX(ppu_opcode_t op) -{ - gpr[op.rd] = spec_gpr::range(0, u32{umax}); -} - -void ppu_acontext::LDX(ppu_opcode_t op) -{ - gpr[op.rd].set_undef(); -} - -void ppu_acontext::LWZX(ppu_opcode_t op) -{ - gpr[op.rd].set_undef(); -} - -void ppu_acontext::SLW(ppu_opcode_t op) -{ - gpr[op.ra].set_undef(); -} - -void ppu_acontext::CNTLZW(ppu_opcode_t op) -{ - gpr[op.ra].set_undef(); -} - -void ppu_acontext::SLD(ppu_opcode_t op) -{ - gpr[op.ra].set_undef(); -} - -void ppu_acontext::AND(ppu_opcode_t op) -{ - gpr[op.ra] = gpr[op.rs] & gpr[op.rb]; -} - -void ppu_acontext::CMPL(ppu_opcode_t op) -{ -} - -void ppu_acontext::LVSR(ppu_opcode_t op) -{ -} - -void ppu_acontext::LVEHX(ppu_opcode_t op) -{ -} - -void ppu_acontext::SUBF(ppu_opcode_t op) -{ - gpr[op.rd] = ~gpr[op.ra] + gpr[op.rb] + spec_gpr::fixed(1); -} - -void ppu_acontext::LDUX(ppu_opcode_t op) -{ - const auto addr = gpr[op.ra] + gpr[op.rb]; - gpr[op.rd].set_undef(); - gpr[op.ra] = addr; -} - -void ppu_acontext::DCBST(ppu_opcode_t op) -{ -} - -void ppu_acontext::LWZUX(ppu_opcode_t op) -{ - const auto addr = gpr[op.ra] + gpr[op.rb]; - gpr[op.rd].set_undef(); - gpr[op.ra] = addr; -} - -void ppu_acontext::CNTLZD(ppu_opcode_t op) -{ - gpr[op.ra].set_undef(); -} - -void ppu_acontext::ANDC(ppu_opcode_t op) -{ - gpr[op.ra] = gpr[op.rs] & ~gpr[op.rb]; -} - -void ppu_acontext::TD(ppu_opcode_t op) -{ -} - -void ppu_acontext::LVEWX(ppu_opcode_t op) -{ -} - -void ppu_acontext::MULHD(ppu_opcode_t op) -{ - gpr[op.rd].set_undef(); -} - -void ppu_acontext::MULHW(ppu_opcode_t op) -{ - gpr[op.rd].set_undef(); -} - -void ppu_acontext::LDARX(ppu_opcode_t op) -{ - gpr[op.rd] = {}; -} - -void ppu_acontext::DCBF(ppu_opcode_t op) -{ -} - -void ppu_acontext::LBZX(ppu_opcode_t op) -{ - gpr[op.rd].set_undef(); -} - -void ppu_acontext::LVX(ppu_opcode_t op) -{ -} - -void ppu_acontext::NEG(ppu_opcode_t op) -{ - gpr[op.rd] = ~gpr[op.ra] + spec_gpr::fixed(1); -} - -void ppu_acontext::LBZUX(ppu_opcode_t op) -{ - const auto addr = gpr[op.ra] + gpr[op.rb]; - gpr[op.rd].set_undef(); - gpr[op.ra] = addr; -} - -void ppu_acontext::NOR(ppu_opcode_t op) -{ - gpr[op.ra] = ~(gpr[op.rs] | gpr[op.rb]); -} - -void ppu_acontext::STVEBX(ppu_opcode_t op) -{ -} - -void ppu_acontext::SUBFE(ppu_opcode_t op) -{ - gpr[op.rd] = ~gpr[op.ra] + gpr[op.rb] + spec_gpr::range(0, 1); -} - -void ppu_acontext::ADDE(ppu_opcode_t op) -{ - gpr[op.rd] = gpr[op.ra] + gpr[op.rb] + spec_gpr::range(0, 1); -} - -void ppu_acontext::MTOCRF(ppu_opcode_t op) -{ -} - -void ppu_acontext::STDX(ppu_opcode_t op) -{ -} - -void ppu_acontext::STWCX(ppu_opcode_t op) -{ -} - -void ppu_acontext::STWX(ppu_opcode_t op) -{ -} - -void ppu_acontext::STVEHX(ppu_opcode_t op) -{ -} - -void ppu_acontext::STDUX(ppu_opcode_t op) -{ - const auto addr = gpr[op.ra] + gpr[op.rb]; - gpr[op.ra] = addr; -} - -void ppu_acontext::STWUX(ppu_opcode_t op) -{ - const auto addr = gpr[op.ra] + gpr[op.rb]; - gpr[op.ra] = addr; -} - -void ppu_acontext::STVEWX(ppu_opcode_t op) -{ -} - -void ppu_acontext::SUBFZE(ppu_opcode_t op) -{ - gpr[op.rd] = ~gpr[op.ra] + spec_gpr::range(0, 1); -} - -void ppu_acontext::ADDZE(ppu_opcode_t op) -{ - gpr[op.rd] = gpr[op.ra] + spec_gpr::range(0, 1); -} - -void ppu_acontext::STDCX(ppu_opcode_t op) -{ -} - -void ppu_acontext::STBX(ppu_opcode_t op) -{ -} - -void ppu_acontext::STVX(ppu_opcode_t op) -{ -} - -void ppu_acontext::SUBFME(ppu_opcode_t op) -{ - gpr[op.rd] = ~gpr[op.ra] + spec_gpr::fixed(-1) + spec_gpr::range(0, 1); -} - -void ppu_acontext::MULLD(ppu_opcode_t op) -{ - gpr[op.rd].set_undef(); -} - -void ppu_acontext::ADDME(ppu_opcode_t op) -{ - gpr[op.rd] = gpr[op.ra] + spec_gpr::fixed(-1) + spec_gpr::range(0, 1); -} - -void ppu_acontext::MULLW(ppu_opcode_t op) -{ - gpr[op.rd].set_undef(); -} - -void ppu_acontext::DCBTST(ppu_opcode_t op) -{ -} - -void ppu_acontext::STBUX(ppu_opcode_t op) -{ - const auto addr = gpr[op.ra] + gpr[op.rb]; - gpr[op.ra] = addr; -} - -void ppu_acontext::ADD(ppu_opcode_t op) -{ - gpr[op.rd] = gpr[op.ra] + gpr[op.rd]; -} - -void ppu_acontext::DCBT(ppu_opcode_t op) -{ -} - -void ppu_acontext::LHZX(ppu_opcode_t op) -{ - gpr[op.rd].set_undef(); -} - -void ppu_acontext::EQV(ppu_opcode_t op) -{ - gpr[op.ra] = ~(gpr[op.rs] ^ gpr[op.rb]); -} - -void ppu_acontext::ECIWX(ppu_opcode_t op) -{ - gpr[op.rd].set_undef(); -} - -void ppu_acontext::LHZUX(ppu_opcode_t op) -{ - const auto addr = gpr[op.ra] + gpr[op.rb]; - gpr[op.rd].set_undef(); - gpr[op.ra] = addr; -} - -void ppu_acontext::XOR(ppu_opcode_t op) -{ - gpr[op.ra] = gpr[op.rs] ^ gpr[op.rb]; -} - -void ppu_acontext::MFSPR(ppu_opcode_t op) -{ - gpr[op.rd].set_undef(); -} - -void ppu_acontext::LWAX(ppu_opcode_t op) -{ - gpr[op.rd].set_undef(); -} - -void ppu_acontext::DST(ppu_opcode_t op) -{ -} - -void ppu_acontext::LHAX(ppu_opcode_t op) -{ - gpr[op.rd].set_undef(); -} - -void ppu_acontext::LVXL(ppu_opcode_t op) -{ -} - -void ppu_acontext::MFTB(ppu_opcode_t op) -{ - gpr[op.rd].set_undef(); -} - -void ppu_acontext::LWAUX(ppu_opcode_t op) -{ - const auto addr = gpr[op.ra] + gpr[op.rb]; - gpr[op.rd].set_undef(); - gpr[op.ra] = addr; -} - -void ppu_acontext::DSTST(ppu_opcode_t op) -{ -} - -void ppu_acontext::LHAUX(ppu_opcode_t op) -{ - const auto addr = gpr[op.ra] + gpr[op.rb]; - gpr[op.rd].set_undef(); - gpr[op.ra] = addr; -} - -void ppu_acontext::STHX(ppu_opcode_t op) -{ -} - -void ppu_acontext::ORC(ppu_opcode_t op) -{ - gpr[op.ra] = gpr[op.rs] | ~gpr[op.rb]; -} - -void ppu_acontext::ECOWX(ppu_opcode_t op) -{ -} - -void ppu_acontext::STHUX(ppu_opcode_t op) -{ - const auto addr = gpr[op.ra] + gpr[op.rb]; - gpr[op.ra] = addr; -} - -void ppu_acontext::OR(ppu_opcode_t op) -{ - gpr[op.ra] = gpr[op.rs] | gpr[op.rb]; -} - -void ppu_acontext::DIVDU(ppu_opcode_t op) -{ - gpr[op.rd].set_undef(); -} - -void ppu_acontext::DIVWU(ppu_opcode_t op) -{ - gpr[op.rd].set_undef(); -} - -void ppu_acontext::MTSPR(ppu_opcode_t op) -{ -} - -void ppu_acontext::DCBI(ppu_opcode_t op) -{ -} - -void ppu_acontext::NAND(ppu_opcode_t op) -{ - gpr[op.ra] = ~(gpr[op.rs] & gpr[op.rb]); -} - -void ppu_acontext::STVXL(ppu_opcode_t op) -{ -} - -void ppu_acontext::DIVD(ppu_opcode_t op) -{ - gpr[op.rd].set_undef(); -} - -void ppu_acontext::DIVW(ppu_opcode_t op) -{ - gpr[op.rd].set_undef(); -} - -void ppu_acontext::LVLX(ppu_opcode_t op) -{ -} - -void ppu_acontext::LDBRX(ppu_opcode_t op) -{ - gpr[op.rd].set_undef(); -} - -void ppu_acontext::LSWX(ppu_opcode_t op) -{ -} - -void ppu_acontext::LWBRX(ppu_opcode_t op) -{ - gpr[op.rd].set_undef(); -} - -void ppu_acontext::LFSX(ppu_opcode_t op) -{ -} - -void ppu_acontext::SRW(ppu_opcode_t op) -{ - gpr[op.ra].set_undef(); -} - -void ppu_acontext::SRD(ppu_opcode_t op) -{ - gpr[op.ra].set_undef(); -} - -void ppu_acontext::LVRX(ppu_opcode_t op) -{ -} - -void ppu_acontext::LSWI(ppu_opcode_t op) -{ - std::fill_n(gpr, 32, spec_gpr{}); -} - -void ppu_acontext::LFSUX(ppu_opcode_t op) -{ - const auto addr = gpr[op.ra] + gpr[op.rb]; - gpr[op.ra] = addr; -} - -void ppu_acontext::SYNC(ppu_opcode_t op) -{ -} - -void ppu_acontext::LFDX(ppu_opcode_t op) -{ -} - -void ppu_acontext::LFDUX(ppu_opcode_t op) -{ - const auto addr = gpr[op.ra] + gpr[op.rb]; - gpr[op.ra] = addr; -} - -void ppu_acontext::STVLX(ppu_opcode_t op) -{ -} - -void ppu_acontext::STDBRX(ppu_opcode_t op) -{ -} - -void ppu_acontext::STSWX(ppu_opcode_t op) -{ -} - -void ppu_acontext::STWBRX(ppu_opcode_t op) -{ -} - -void ppu_acontext::STFSX(ppu_opcode_t op) -{ -} - -void ppu_acontext::STVRX(ppu_opcode_t op) -{ -} - -void ppu_acontext::STFSUX(ppu_opcode_t op) -{ - const auto addr = gpr[op.ra] + gpr[op.rb]; - gpr[op.ra] = addr; -} - -void ppu_acontext::STSWI(ppu_opcode_t op) -{ -} - -void ppu_acontext::STFDX(ppu_opcode_t op) -{ -} - -void ppu_acontext::STFDUX(ppu_opcode_t op) -{ - const auto addr = gpr[op.ra] + gpr[op.rb]; - gpr[op.ra] = addr; -} - -void ppu_acontext::LVLXL(ppu_opcode_t op) -{ -} - -void ppu_acontext::LHBRX(ppu_opcode_t op) -{ - gpr[op.rd].set_undef(); -} - -void ppu_acontext::SRAW(ppu_opcode_t op) -{ - gpr[op.ra].set_undef(); -} - -void ppu_acontext::SRAD(ppu_opcode_t op) -{ - gpr[op.ra].set_undef(); -} - -void ppu_acontext::LVRXL(ppu_opcode_t op) -{ -} - -void ppu_acontext::DSS(ppu_opcode_t op) -{ -} - -void ppu_acontext::SRAWI(ppu_opcode_t op) -{ - gpr[op.ra].set_undef(); -} - -void ppu_acontext::SRADI(ppu_opcode_t op) -{ - gpr[op.ra].set_undef(); -} - -void ppu_acontext::EIEIO(ppu_opcode_t op) -{ -} - -void ppu_acontext::STVLXL(ppu_opcode_t op) -{ -} - -void ppu_acontext::STHBRX(ppu_opcode_t op) -{ -} - -void ppu_acontext::EXTSH(ppu_opcode_t op) -{ - gpr[op.ra].set_undef(); -} - -void ppu_acontext::STVRXL(ppu_opcode_t op) -{ -} - -void ppu_acontext::EXTSB(ppu_opcode_t op) -{ - gpr[op.ra].set_undef(); -} - -void ppu_acontext::STFIWX(ppu_opcode_t op) -{ -} - -void ppu_acontext::EXTSW(ppu_opcode_t op) -{ - gpr[op.ra].set_undef(); -} - -void ppu_acontext::ICBI(ppu_opcode_t op) -{ -} - -void ppu_acontext::DCBZ(ppu_opcode_t op) -{ -} - -void ppu_acontext::LWZ(ppu_opcode_t op) -{ - gpr[op.rd].set_undef(); -} - -void ppu_acontext::LWZU(ppu_opcode_t op) -{ - const auto addr = gpr[op.ra] + gpr[op.rb]; - gpr[op.rd].set_undef(); - gpr[op.ra] = addr; -} - -void ppu_acontext::LBZ(ppu_opcode_t op) -{ - gpr[op.rd].set_undef(); -} - -void ppu_acontext::LBZU(ppu_opcode_t op) -{ - const auto addr = gpr[op.ra] + gpr[op.rb]; - gpr[op.rd].set_undef(); - gpr[op.ra] = addr; -} - -void ppu_acontext::STW(ppu_opcode_t op) -{ -} - -void ppu_acontext::STWU(ppu_opcode_t op) -{ - const auto addr = gpr[op.ra] + gpr[op.rb]; - gpr[op.ra] = addr; -} - -void ppu_acontext::STB(ppu_opcode_t op) -{ -} - -void ppu_acontext::STBU(ppu_opcode_t op) -{ - const auto addr = gpr[op.ra] + gpr[op.rb]; - gpr[op.ra] = addr; -} - -void ppu_acontext::LHZ(ppu_opcode_t op) -{ - gpr[op.rd].set_undef(); -} - -void ppu_acontext::LHZU(ppu_opcode_t op) -{ - const auto addr = gpr[op.ra] + gpr[op.rb]; - gpr[op.rd].set_undef(); - gpr[op.ra] = addr; -} - -void ppu_acontext::LHA(ppu_opcode_t op) -{ - gpr[op.rd].set_undef(); -} - -void ppu_acontext::LHAU(ppu_opcode_t op) -{ - const auto addr = gpr[op.ra] + gpr[op.rb]; - gpr[op.rd].set_undef(); - gpr[op.ra] = addr; -} - -void ppu_acontext::STH(ppu_opcode_t op) -{ -} - -void ppu_acontext::STHU(ppu_opcode_t op) -{ - const auto addr = gpr[op.ra] + gpr[op.rb]; - gpr[op.ra] = addr; -} - -void ppu_acontext::LMW(ppu_opcode_t op) -{ - std::fill_n(gpr, 32, spec_gpr{}); -} - -void ppu_acontext::STMW(ppu_opcode_t op) -{ -} - -void ppu_acontext::LFS(ppu_opcode_t op) -{ -} - -void ppu_acontext::LFSU(ppu_opcode_t op) -{ - const auto addr = gpr[op.ra] + gpr[op.rb]; - gpr[op.ra] = addr; -} - -void ppu_acontext::LFD(ppu_opcode_t op) -{ -} - -void ppu_acontext::LFDU(ppu_opcode_t op) -{ - const auto addr = gpr[op.ra] + gpr[op.rb]; - gpr[op.ra] = addr; -} - -void ppu_acontext::STFS(ppu_opcode_t op) -{ -} - -void ppu_acontext::STFSU(ppu_opcode_t op) -{ - const auto addr = gpr[op.ra] + gpr[op.rb]; - gpr[op.ra] = addr; -} - -void ppu_acontext::STFD(ppu_opcode_t op) -{ -} - -void ppu_acontext::STFDU(ppu_opcode_t op) -{ - const auto addr = gpr[op.ra] + gpr[op.rb]; - gpr[op.ra] = addr; -} - -void ppu_acontext::LD(ppu_opcode_t op) -{ - gpr[op.rd].set_undef(); -} - -void ppu_acontext::LDU(ppu_opcode_t op) -{ - const auto addr = gpr[op.ra] + gpr[op.rb]; - gpr[op.rd].set_undef(); - gpr[op.ra] = addr; -} - -void ppu_acontext::LWA(ppu_opcode_t op) -{ - gpr[op.rd].set_undef(); -} - -void ppu_acontext::STD(ppu_opcode_t op) -{ -} - -void ppu_acontext::STDU(ppu_opcode_t op) -{ - const auto addr = gpr[op.ra] + gpr[op.rb]; - gpr[op.ra] = addr; -} - -void ppu_acontext::FDIVS(ppu_opcode_t op) -{ -} - -void ppu_acontext::FSUBS(ppu_opcode_t op) -{ -} - -void ppu_acontext::FADDS(ppu_opcode_t op) -{ -} - -void ppu_acontext::FSQRTS(ppu_opcode_t op) -{ -} - -void ppu_acontext::FRES(ppu_opcode_t op) -{ -} - -void ppu_acontext::FMULS(ppu_opcode_t op) -{ -} - -void ppu_acontext::FMADDS(ppu_opcode_t op) -{ -} - -void ppu_acontext::FMSUBS(ppu_opcode_t op) -{ -} - -void ppu_acontext::FNMSUBS(ppu_opcode_t op) -{ -} - -void ppu_acontext::FNMADDS(ppu_opcode_t op) -{ -} - -void ppu_acontext::MTFSB1(ppu_opcode_t op) -{ -} - -void ppu_acontext::MCRFS(ppu_opcode_t op) -{ -} - -void ppu_acontext::MTFSB0(ppu_opcode_t op) -{ -} - -void ppu_acontext::MTFSFI(ppu_opcode_t op) -{ -} - -void ppu_acontext::MFFS(ppu_opcode_t op) -{ -} - -void ppu_acontext::MTFSF(ppu_opcode_t op) -{ -} - -void ppu_acontext::FCMPU(ppu_opcode_t op) -{ -} - -void ppu_acontext::FRSP(ppu_opcode_t op) -{ -} - -void ppu_acontext::FCTIW(ppu_opcode_t op) -{ -} - -void ppu_acontext::FCTIWZ(ppu_opcode_t op) -{ -} - -void ppu_acontext::FDIV(ppu_opcode_t op) -{ -} - -void ppu_acontext::FSUB(ppu_opcode_t op) -{ -} - -void ppu_acontext::FADD(ppu_opcode_t op) -{ -} - -void ppu_acontext::FSQRT(ppu_opcode_t op) -{ -} - -void ppu_acontext::FSEL(ppu_opcode_t op) -{ -} - -void ppu_acontext::FMUL(ppu_opcode_t op) -{ -} - -void ppu_acontext::FRSQRTE(ppu_opcode_t op) -{ -} - -void ppu_acontext::FMSUB(ppu_opcode_t op) -{ -} - -void ppu_acontext::FMADD(ppu_opcode_t op) -{ -} - -void ppu_acontext::FNMSUB(ppu_opcode_t op) -{ -} - -void ppu_acontext::FNMADD(ppu_opcode_t op) -{ -} - -void ppu_acontext::FCMPO(ppu_opcode_t op) -{ -} - -void ppu_acontext::FNEG(ppu_opcode_t op) -{ -} - -void ppu_acontext::FMR(ppu_opcode_t op) -{ -} - -void ppu_acontext::FNABS(ppu_opcode_t op) -{ -} - -void ppu_acontext::FABS(ppu_opcode_t op) -{ -} - -void ppu_acontext::FCTID(ppu_opcode_t op) -{ -} - -void ppu_acontext::FCTIDZ(ppu_opcode_t op) -{ -} - -void ppu_acontext::FCFID(ppu_opcode_t op) -{ -} - -#include - -const bool s_tes = []() -{ - return true; - - std::mt19937_64 rnd{123}; - - for (u32 i = 0; i < 10000; i++) - { - ppu_acontext::spec_gpr r1, r2, r3; - r1 = ppu_acontext::spec_gpr::approx(rnd(), rnd()); - r2 = ppu_acontext::spec_gpr::range(rnd(), rnd()); - r3 = r1 | r2; - - for (u32 j = 0; j < 10000; j++) - { - u64 v1 = rnd(), v2 = rnd(); - v1 &= r1.mask(); - v1 |= r1.ones(); - if (!r2.test(v2)) - { - v2 = r2.imin; - } - - if (r1.test(v1) && r2.test(v2)) - { - if (!r3.test(v1 | v2)) - { - auto exp = ppu_acontext::spec_gpr::approx(r1.ones() & r2.ones(), r1.mask() & r2.mask()); - - ppu_log.error("ppu_acontext failure:" - "\n\tr1 = 0x%016x..0x%016x, 0x%016x:0x%016x" - "\n\tr2 = 0x%016x..0x%016x, 0x%016x:0x%016x" - "\n\tr3 = 0x%016x..0x%016x, 0x%016x:0x%016x" - "\n\tex = 0x%016x..0x%016x" - "\n\tv1 = 0x%016x, v2 = 0x%016x, v3 = 0x%016x", - r1.imin, r1.imax, r1.bmin, r1.bmax, r2.imin, r2.imax, r2.bmin, r2.bmax, r3.imin, r3.imax, r3.bmin, r3.bmax, exp.imin, exp.imax, v1, v2, v1 | v2); - break; - } - } - } - } - - ppu_acontext::spec_gpr r1; - r1 = ppu_acontext::spec_gpr::range(0x13311, 0x1fe22); - r1 = r1 ^ ppu_acontext::spec_gpr::approx(0x000, 0xf00); - ppu_log.success("0x%x..0x%x", r1.imin, r1.imax); - - return true; -}(); diff --git a/rpcs3/Emu/Cell/PPUAnalyser.h b/rpcs3/Emu/Cell/PPUAnalyser.h index 31571bdf93..9282ac1ba8 100644 --- a/rpcs3/Emu/Cell/PPUAnalyser.h +++ b/rpcs3/Emu/Cell/PPUAnalyser.h @@ -1419,738 +1419,3 @@ struct ppu_iname #undef NAME #undef NAME_ }; - -// PPU Analyser Context -struct ppu_acontext -{ - // General-purpose register range - struct spec_gpr - { - // Integral range: normalized undef = (0;UINT64_MAX), unnormalized undefs are possible (when max = min - 1) - // Bit range: constant 0 = (0;0), constant 1 = (1;1), normalized undef = (0;1), unnormalized undef = (1;0) - - u64 imin = 0ull; // Integral range begin - u64 imax = ~0ull; // Integral range end - u64 bmin = 0ull; // Bit range begin - u64 bmax = ~0ull; // Bit range end - - void set_undef() - { - imin = 0; - imax = -1; - bmin = 0; - bmax = -1; - } - - // (Number of possible values - 1), 0 = const - u64 div() const - { - return imax - imin; - } - - // Return zero bits for zeros, ones for ones or undefs - u64 mask() const - { - return bmin | bmax; - } - - // Return one bits for ones, zeros for zeros or undefs - u64 ones() const - { - return bmin & bmax; - } - - // Return one bits for undefs - u64 undefs() const - { - return bmin ^ bmax; - } - - // Return number of trailing zero bits - u64 tz() const - { - return std::countr_zero(mask()); - } - - // Range NOT - spec_gpr operator ~() const - { - spec_gpr r; - r.imin = ~imax; - r.imax = ~imin; - r.bmin = ~bmax; - r.bmax = ~bmin; - return r; - } - - // Range ADD - spec_gpr operator +(const spec_gpr& rhs) const - { - spec_gpr r{}; - - const u64 adiv = div(); - const u64 bdiv = rhs.div(); - - // Check overflow, generate normalized range - if (adiv != umax && bdiv != umax && adiv <= adiv + bdiv) - { - r = range(imin + rhs.imin, imax + rhs.imax); - } - - // Carry for bitrange computation - u64 cmin = 0; - u64 cmax = 0; - - const u64 amask = mask(); - const u64 bmask = rhs.mask(); - const u64 aones = ones(); - const u64 bones = rhs.ones(); - - for (u32 i = 0; i < 64; i++) - { - cmin += ((amask >> i) & 1) + ((bmask >> i) & 1); - cmax += ((aones >> i) & 1) + ((bones >> i) & 1); - - // Discover some constant bits - if (cmin == cmax) - { - r.bmin |= (cmin & 1) << i; - r.bmax &= ~((~cmin & 1) << i); - } - - cmin >>= 1; - cmax >>= 1; - } - - return r; - } - - // Range AND - spec_gpr operator &(const spec_gpr& rhs) const - { - // Ignore inverted ranges (TODO) - if (imin > imax || rhs.imin > rhs.imax) - { - return approx(ones() & rhs.ones(), mask() & rhs.mask()); - } - - // Const (TODO: remove when unnecessary) - if (imin == imax && rhs.imin == rhs.imax) - { - return fixed(imin & rhs.imin); - } - - // Swap (TODO: remove when unnecessary) - if (imin == imax || rhs.undefs() > undefs()) - { - return rhs & *this; - } - - // Copy and attempt to partially preserve integral range - spec_gpr r = *this; - - for (u32 i = 63; ~i; i--) - { - const u64 m = 1ull << i; - - if (!(rhs.mask() & m)) - { - if (r.undefs() & m) - { - // undef -> 0 - r.imin &= ~(m - 1); - r.imax |= (m - 1); - r.imin &= ~m; - r.imax &= ~m; - } - else if (r.ones() & m) - { - // 1 -> 0 - if ((r.imin ^ r.imax) > (m - 1)) - { - r.imin &= ~(m - 1); - r.imax |= (m - 1); - } - - r.imin &= ~m; - r.imax &= ~m; - } - } - else if (rhs.undefs() & m) - { - // -> undef - r.imin &= ~(m - 1); - r.imax |= (m - 1); - r.imin &= ~m; - r.imax |= m; - } - } - - r.bmin = ones() & rhs.ones(); - r.bmax = mask() & rhs.mask(); - return r; - } - - // Range OR - spec_gpr operator |(const spec_gpr& rhs) const - { - // Ignore inverted ranges (TODO) - if (imin > imax || rhs.imin > rhs.imax) - { - return approx(ones() | rhs.ones(), mask() | rhs.mask()); - } - - // Const (TODO: remove when unnecessary) - if (imin == imax && rhs.imin == rhs.imax) - { - return fixed(imin | rhs.imin); - } - - // Swap (TODO: remove when unnecessary) - if (imin == imax || rhs.undefs() > undefs()) - { - return rhs | *this; - } - - // Copy and attempt to partially preserve integral range - spec_gpr r = *this; - - for (u32 i = 63; ~i; i--) - { - const u64 m = 1ull << i; - - if (rhs.ones() & m) - { - if (r.undefs() & m) - { - // undef -> 1 - r.imin &= ~(m - 1); - r.imax |= (m - 1); - r.imin |= m; - r.imax |= m; - } - else if (!(r.mask() & m)) - { - // 0 -> 1 - if ((r.imin ^ r.imax) > (m - 1)) - { - r.imin &= ~(m - 1); - r.imax |= (m - 1); - } - - r.imin |= m; - r.imax |= m; - } - } - else if (rhs.undefs() & m) - { - // -> undef - r.imin &= ~(m - 1); - r.imax |= (m - 1); - r.imin &= ~m; - r.imax |= m; - } - } - - r.bmin = ones() | rhs.ones(); - r.bmax = mask() | rhs.mask(); - return r; - } - - // Range XOR - spec_gpr operator ^(const spec_gpr& rhs) const - { - return (~*this & rhs) | (*this & ~rhs); - } - - // Check whether the value is in range - bool test(u64 value) const - { - if (imin <= imax) - { - if (value < imin || value > imax) - { - return false; - } - } - else - { - if (value < imin && value > imax) - { - return false; - } - } - - if ((value & mask()) != value) - { - return false; - } - - if ((value | ones()) != value) - { - return false; - } - - return true; - } - - // Constant value - static spec_gpr fixed(u64 value) - { - spec_gpr r; - r.imin = value; - r.imax = value; - r.bmin = value; - r.bmax = value; - return r; - } - - // Range (tz = number of constant trailing zeros) - static spec_gpr range(u64 min, u64 max, u64 tz = 0) - { - const u64 mask = tz < 64 ? ~0ull << tz : 0ull; - - spec_gpr r; - r.bmin = 0; - r.bmax = mask; - - // Normalize min/max for tz (TODO) - if (min < max) - { - // Inverted constant MSB mask - const u64 mix = ~0ull >> std::countl_zero(min ^ max); - r.bmin |= min & ~mix; - r.bmax &= max | mix; - - r.imin = (min + ~mask) & mask; - r.imax = max & mask; - ensure(r.imin <= r.imax); // "Impossible range" - } - else - { - r.imin = min & mask; - r.imax = (max + ~mask) & mask; - ensure(r.imin >= r.imax); // "Impossible range" - } - - // Fix const values - if (r.imin == r.imax) - { - r.bmin = r.imin; - r.bmax = r.imax; - } - - return r; - } - - // Make from bitrange (normalize, approximate range values) - static spec_gpr approx(u64 bmin, u64 bmax) - { - spec_gpr r; - r.imin = bmin & ~(bmin ^ bmax); - r.imax = bmax | (bmin ^ bmax); - r.bmin = bmin & ~(bmin ^ bmax); - r.bmax = bmax | (bmin ^ bmax); - return r; - } - } gpr[32]{}; - - // Vector registers (draft) - struct spec_vec - { - u8 imin8[16]{}; - u8 imax8[16]{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}; - u16 imin16[8]{}; - u16 imax16[8]{0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff}; - u32 imin32[4]{}; - u32 imax32[4]{0xffffffffu, 0xffffffffu, 0xffffffffu, 0xffffffffu}; - u64 bmin64[2]{}; - u64 bmax64[2]{0xffffffffffffffffull, 0xffffffffffffffffull}; - }; - - // Info - u32 cia; - - // Analyser step - void UNK(ppu_opcode_t); - - void MFVSCR(ppu_opcode_t); - void MTVSCR(ppu_opcode_t); - void VADDCUW(ppu_opcode_t); - void VADDFP(ppu_opcode_t); - void VADDSBS(ppu_opcode_t); - void VADDSHS(ppu_opcode_t); - void VADDSWS(ppu_opcode_t); - void VADDUBM(ppu_opcode_t); - void VADDUBS(ppu_opcode_t); - void VADDUHM(ppu_opcode_t); - void VADDUHS(ppu_opcode_t); - void VADDUWM(ppu_opcode_t); - void VADDUWS(ppu_opcode_t); - void VAND(ppu_opcode_t); - void VANDC(ppu_opcode_t); - void VAVGSB(ppu_opcode_t); - void VAVGSH(ppu_opcode_t); - void VAVGSW(ppu_opcode_t); - void VAVGUB(ppu_opcode_t); - void VAVGUH(ppu_opcode_t); - void VAVGUW(ppu_opcode_t); - void VCFSX(ppu_opcode_t); - void VCFUX(ppu_opcode_t); - void VCMPBFP(ppu_opcode_t); - void VCMPEQFP(ppu_opcode_t); - void VCMPEQUB(ppu_opcode_t); - void VCMPEQUH(ppu_opcode_t); - void VCMPEQUW(ppu_opcode_t); - void VCMPGEFP(ppu_opcode_t); - void VCMPGTFP(ppu_opcode_t); - void VCMPGTSB(ppu_opcode_t); - void VCMPGTSH(ppu_opcode_t); - void VCMPGTSW(ppu_opcode_t); - void VCMPGTUB(ppu_opcode_t); - void VCMPGTUH(ppu_opcode_t); - void VCMPGTUW(ppu_opcode_t); - void VCTSXS(ppu_opcode_t); - void VCTUXS(ppu_opcode_t); - void VEXPTEFP(ppu_opcode_t); - void VLOGEFP(ppu_opcode_t); - void VMADDFP(ppu_opcode_t); - void VMAXFP(ppu_opcode_t); - void VMAXSB(ppu_opcode_t); - void VMAXSH(ppu_opcode_t); - void VMAXSW(ppu_opcode_t); - void VMAXUB(ppu_opcode_t); - void VMAXUH(ppu_opcode_t); - void VMAXUW(ppu_opcode_t); - void VMHADDSHS(ppu_opcode_t); - void VMHRADDSHS(ppu_opcode_t); - void VMINFP(ppu_opcode_t); - void VMINSB(ppu_opcode_t); - void VMINSH(ppu_opcode_t); - void VMINSW(ppu_opcode_t); - void VMINUB(ppu_opcode_t); - void VMINUH(ppu_opcode_t); - void VMINUW(ppu_opcode_t); - void VMLADDUHM(ppu_opcode_t); - void VMRGHB(ppu_opcode_t); - void VMRGHH(ppu_opcode_t); - void VMRGHW(ppu_opcode_t); - void VMRGLB(ppu_opcode_t); - void VMRGLH(ppu_opcode_t); - void VMRGLW(ppu_opcode_t); - void VMSUMMBM(ppu_opcode_t); - void VMSUMSHM(ppu_opcode_t); - void VMSUMSHS(ppu_opcode_t); - void VMSUMUBM(ppu_opcode_t); - void VMSUMUHM(ppu_opcode_t); - void VMSUMUHS(ppu_opcode_t); - void VMULESB(ppu_opcode_t); - void VMULESH(ppu_opcode_t); - void VMULEUB(ppu_opcode_t); - void VMULEUH(ppu_opcode_t); - void VMULOSB(ppu_opcode_t); - void VMULOSH(ppu_opcode_t); - void VMULOUB(ppu_opcode_t); - void VMULOUH(ppu_opcode_t); - void VNMSUBFP(ppu_opcode_t); - void VNOR(ppu_opcode_t); - void VOR(ppu_opcode_t); - void VPERM(ppu_opcode_t); - void VPKPX(ppu_opcode_t); - void VPKSHSS(ppu_opcode_t); - void VPKSHUS(ppu_opcode_t); - void VPKSWSS(ppu_opcode_t); - void VPKSWUS(ppu_opcode_t); - void VPKUHUM(ppu_opcode_t); - void VPKUHUS(ppu_opcode_t); - void VPKUWUM(ppu_opcode_t); - void VPKUWUS(ppu_opcode_t); - void VREFP(ppu_opcode_t); - void VRFIM(ppu_opcode_t); - void VRFIN(ppu_opcode_t); - void VRFIP(ppu_opcode_t); - void VRFIZ(ppu_opcode_t); - void VRLB(ppu_opcode_t); - void VRLH(ppu_opcode_t); - void VRLW(ppu_opcode_t); - void VRSQRTEFP(ppu_opcode_t); - void VSEL(ppu_opcode_t); - void VSL(ppu_opcode_t); - void VSLB(ppu_opcode_t); - void VSLDOI(ppu_opcode_t); - void VSLH(ppu_opcode_t); - void VSLO(ppu_opcode_t); - void VSLW(ppu_opcode_t); - void VSPLTB(ppu_opcode_t); - void VSPLTH(ppu_opcode_t); - void VSPLTISB(ppu_opcode_t); - void VSPLTISH(ppu_opcode_t); - void VSPLTISW(ppu_opcode_t); - void VSPLTW(ppu_opcode_t); - void VSR(ppu_opcode_t); - void VSRAB(ppu_opcode_t); - void VSRAH(ppu_opcode_t); - void VSRAW(ppu_opcode_t); - void VSRB(ppu_opcode_t); - void VSRH(ppu_opcode_t); - void VSRO(ppu_opcode_t); - void VSRW(ppu_opcode_t); - void VSUBCUW(ppu_opcode_t); - void VSUBFP(ppu_opcode_t); - void VSUBSBS(ppu_opcode_t); - void VSUBSHS(ppu_opcode_t); - void VSUBSWS(ppu_opcode_t); - void VSUBUBM(ppu_opcode_t); - void VSUBUBS(ppu_opcode_t); - void VSUBUHM(ppu_opcode_t); - void VSUBUHS(ppu_opcode_t); - void VSUBUWM(ppu_opcode_t); - void VSUBUWS(ppu_opcode_t); - void VSUMSWS(ppu_opcode_t); - void VSUM2SWS(ppu_opcode_t); - void VSUM4SBS(ppu_opcode_t); - void VSUM4SHS(ppu_opcode_t); - void VSUM4UBS(ppu_opcode_t); - void VUPKHPX(ppu_opcode_t); - void VUPKHSB(ppu_opcode_t); - void VUPKHSH(ppu_opcode_t); - void VUPKLPX(ppu_opcode_t); - void VUPKLSB(ppu_opcode_t); - void VUPKLSH(ppu_opcode_t); - void VXOR(ppu_opcode_t); - void TDI(ppu_opcode_t); - void TWI(ppu_opcode_t); - void MULLI(ppu_opcode_t); - void SUBFIC(ppu_opcode_t); - void CMPLI(ppu_opcode_t); - void CMPI(ppu_opcode_t); - void ADDIC(ppu_opcode_t); - void ADDI(ppu_opcode_t); - void ADDIS(ppu_opcode_t); - void BC(ppu_opcode_t); - void SC(ppu_opcode_t); - void B(ppu_opcode_t); - void MCRF(ppu_opcode_t); - void BCLR(ppu_opcode_t); - void CRNOR(ppu_opcode_t); - void CRANDC(ppu_opcode_t); - void ISYNC(ppu_opcode_t); - void CRXOR(ppu_opcode_t); - void CRNAND(ppu_opcode_t); - void CRAND(ppu_opcode_t); - void CREQV(ppu_opcode_t); - void CRORC(ppu_opcode_t); - void CROR(ppu_opcode_t); - void BCCTR(ppu_opcode_t); - void RLWIMI(ppu_opcode_t); - void RLWINM(ppu_opcode_t); - void RLWNM(ppu_opcode_t); - void ORI(ppu_opcode_t); - void ORIS(ppu_opcode_t); - void XORI(ppu_opcode_t); - void XORIS(ppu_opcode_t); - void ANDI(ppu_opcode_t); - void ANDIS(ppu_opcode_t); - void RLDICL(ppu_opcode_t); - void RLDICR(ppu_opcode_t); - void RLDIC(ppu_opcode_t); - void RLDIMI(ppu_opcode_t); - void RLDCL(ppu_opcode_t); - void RLDCR(ppu_opcode_t); - void CMP(ppu_opcode_t); - void TW(ppu_opcode_t); - void LVSL(ppu_opcode_t); - void LVEBX(ppu_opcode_t); - void SUBFC(ppu_opcode_t); - void ADDC(ppu_opcode_t); - void MULHDU(ppu_opcode_t); - void MULHWU(ppu_opcode_t); - void MFOCRF(ppu_opcode_t); - void LWARX(ppu_opcode_t); - void LDX(ppu_opcode_t); - void LWZX(ppu_opcode_t); - void SLW(ppu_opcode_t); - void CNTLZW(ppu_opcode_t); - void SLD(ppu_opcode_t); - void AND(ppu_opcode_t); - void CMPL(ppu_opcode_t); - void LVSR(ppu_opcode_t); - void LVEHX(ppu_opcode_t); - void SUBF(ppu_opcode_t); - void LDUX(ppu_opcode_t); - void DCBST(ppu_opcode_t); - void LWZUX(ppu_opcode_t); - void CNTLZD(ppu_opcode_t); - void ANDC(ppu_opcode_t); - void TD(ppu_opcode_t); - void LVEWX(ppu_opcode_t); - void MULHD(ppu_opcode_t); - void MULHW(ppu_opcode_t); - void LDARX(ppu_opcode_t); - void DCBF(ppu_opcode_t); - void LBZX(ppu_opcode_t); - void LVX(ppu_opcode_t); - void NEG(ppu_opcode_t); - void LBZUX(ppu_opcode_t); - void NOR(ppu_opcode_t); - void STVEBX(ppu_opcode_t); - void SUBFE(ppu_opcode_t); - void ADDE(ppu_opcode_t); - void MTOCRF(ppu_opcode_t); - void STDX(ppu_opcode_t); - void STWCX(ppu_opcode_t); - void STWX(ppu_opcode_t); - void STVEHX(ppu_opcode_t); - void STDUX(ppu_opcode_t); - void STWUX(ppu_opcode_t); - void STVEWX(ppu_opcode_t); - void SUBFZE(ppu_opcode_t); - void ADDZE(ppu_opcode_t); - void STDCX(ppu_opcode_t); - void STBX(ppu_opcode_t); - void STVX(ppu_opcode_t); - void SUBFME(ppu_opcode_t); - void MULLD(ppu_opcode_t); - void ADDME(ppu_opcode_t); - void MULLW(ppu_opcode_t); - void DCBTST(ppu_opcode_t); - void STBUX(ppu_opcode_t); - void ADD(ppu_opcode_t); - void DCBT(ppu_opcode_t); - void LHZX(ppu_opcode_t); - void EQV(ppu_opcode_t); - void ECIWX(ppu_opcode_t); - void LHZUX(ppu_opcode_t); - void XOR(ppu_opcode_t); - void MFSPR(ppu_opcode_t); - void LWAX(ppu_opcode_t); - void DST(ppu_opcode_t); - void LHAX(ppu_opcode_t); - void LVXL(ppu_opcode_t); - void MFTB(ppu_opcode_t); - void LWAUX(ppu_opcode_t); - void DSTST(ppu_opcode_t); - void LHAUX(ppu_opcode_t); - void STHX(ppu_opcode_t); - void ORC(ppu_opcode_t); - void ECOWX(ppu_opcode_t); - void STHUX(ppu_opcode_t); - void OR(ppu_opcode_t); - void DIVDU(ppu_opcode_t); - void DIVWU(ppu_opcode_t); - void MTSPR(ppu_opcode_t); - void DCBI(ppu_opcode_t); - void NAND(ppu_opcode_t); - void STVXL(ppu_opcode_t); - void DIVD(ppu_opcode_t); - void DIVW(ppu_opcode_t); - void LVLX(ppu_opcode_t); - void LDBRX(ppu_opcode_t); - void LSWX(ppu_opcode_t); - void LWBRX(ppu_opcode_t); - void LFSX(ppu_opcode_t); - void SRW(ppu_opcode_t); - void SRD(ppu_opcode_t); - void LVRX(ppu_opcode_t); - void LSWI(ppu_opcode_t); - void LFSUX(ppu_opcode_t); - void SYNC(ppu_opcode_t); - void LFDX(ppu_opcode_t); - void LFDUX(ppu_opcode_t); - void STVLX(ppu_opcode_t); - void STDBRX(ppu_opcode_t); - void STSWX(ppu_opcode_t); - void STWBRX(ppu_opcode_t); - void STFSX(ppu_opcode_t); - void STVRX(ppu_opcode_t); - void STFSUX(ppu_opcode_t); - void STSWI(ppu_opcode_t); - void STFDX(ppu_opcode_t); - void STFDUX(ppu_opcode_t); - void LVLXL(ppu_opcode_t); - void LHBRX(ppu_opcode_t); - void SRAW(ppu_opcode_t); - void SRAD(ppu_opcode_t); - void LVRXL(ppu_opcode_t); - void DSS(ppu_opcode_t); - void SRAWI(ppu_opcode_t); - void SRADI(ppu_opcode_t); - void EIEIO(ppu_opcode_t); - void STVLXL(ppu_opcode_t); - void STHBRX(ppu_opcode_t); - void EXTSH(ppu_opcode_t); - void STVRXL(ppu_opcode_t); - void EXTSB(ppu_opcode_t); - void STFIWX(ppu_opcode_t); - void EXTSW(ppu_opcode_t); - void ICBI(ppu_opcode_t); - void DCBZ(ppu_opcode_t); - void LWZ(ppu_opcode_t); - void LWZU(ppu_opcode_t); - void LBZ(ppu_opcode_t); - void LBZU(ppu_opcode_t); - void STW(ppu_opcode_t); - void STWU(ppu_opcode_t); - void STB(ppu_opcode_t); - void STBU(ppu_opcode_t); - void LHZ(ppu_opcode_t); - void LHZU(ppu_opcode_t); - void LHA(ppu_opcode_t); - void LHAU(ppu_opcode_t); - void STH(ppu_opcode_t); - void STHU(ppu_opcode_t); - void LMW(ppu_opcode_t); - void STMW(ppu_opcode_t); - void LFS(ppu_opcode_t); - void LFSU(ppu_opcode_t); - void LFD(ppu_opcode_t); - void LFDU(ppu_opcode_t); - void STFS(ppu_opcode_t); - void STFSU(ppu_opcode_t); - void STFD(ppu_opcode_t); - void STFDU(ppu_opcode_t); - void LD(ppu_opcode_t); - void LDU(ppu_opcode_t); - void LWA(ppu_opcode_t); - void STD(ppu_opcode_t); - void STDU(ppu_opcode_t); - void FDIVS(ppu_opcode_t); - void FSUBS(ppu_opcode_t); - void FADDS(ppu_opcode_t); - void FSQRTS(ppu_opcode_t); - void FRES(ppu_opcode_t); - void FMULS(ppu_opcode_t); - void FMADDS(ppu_opcode_t); - void FMSUBS(ppu_opcode_t); - void FNMSUBS(ppu_opcode_t); - void FNMADDS(ppu_opcode_t); - void MTFSB1(ppu_opcode_t); - void MCRFS(ppu_opcode_t); - void MTFSB0(ppu_opcode_t); - void MTFSFI(ppu_opcode_t); - void MFFS(ppu_opcode_t); - void MTFSF(ppu_opcode_t); - void FCMPU(ppu_opcode_t); - void FRSP(ppu_opcode_t); - void FCTIW(ppu_opcode_t); - void FCTIWZ(ppu_opcode_t); - void FDIV(ppu_opcode_t); - void FSUB(ppu_opcode_t); - void FADD(ppu_opcode_t); - void FSQRT(ppu_opcode_t); - void FSEL(ppu_opcode_t); - void FMUL(ppu_opcode_t); - void FRSQRTE(ppu_opcode_t); - void FMSUB(ppu_opcode_t); - void FMADD(ppu_opcode_t); - void FNMSUB(ppu_opcode_t); - void FNMADD(ppu_opcode_t); - void FCMPO(ppu_opcode_t); - void FNEG(ppu_opcode_t); - void FMR(ppu_opcode_t); - void FNABS(ppu_opcode_t); - void FABS(ppu_opcode_t); - void FCTID(ppu_opcode_t); - void FCTIDZ(ppu_opcode_t); - void FCFID(ppu_opcode_t); -};