#pragma once #include #include #include #include #include "util/types.hpp" #include "util/asm.hpp" #include "util/to_endian.hpp" #include "Utilities/bit_set.h" #include "PPUOpcodes.h" // PPU Function Attributes enum class ppu_attr : u8 { known_size, no_return, no_size, has_mfvscr, __bitset_enum_max }; // PPU Function Information struct ppu_function { u32 addr = 0; u32 toc = 0; u32 size = 0; std::map blocks{}; // Basic blocks: addr -> size struct iterator { const ppu_function* _this; typename std::map::const_iterator it; usz index = 0; std::pair operator*() const { return _this->blocks.empty() ? std::pair(_this->addr, _this->size) : *it; } iterator& operator++() { index++; if (it != _this->blocks.end()) { it++; } return *this; } bool operator==(const iterator& rhs) const noexcept { return it == rhs.it || (rhs.index == index && _this->blocks.empty()); } bool operator!=(const iterator& rhs) const noexcept { return !operator==(rhs); } }; iterator begin() const { return iterator{this, blocks.begin()}; } iterator end() const { return iterator{this, blocks.end(), 1}; } }; // PPU Relocation Information struct ppu_reloc { u32 addr; u32 type; u64 data; // Operator for sorting bool operator <(const ppu_reloc& rhs) const { return addr < rhs.addr; } bool operator <(u32 rhs) const { return addr < rhs; } }; // PPU Segment Information struct ppu_segment { u32 addr; u32 size; u32 type; u32 flags; u32 filesz; void* ptr{}; }; // PPU Module Information template struct ppu_module : public Type { using Type::Type; ppu_module() noexcept = default; ppu_module(const ppu_module&) = delete; ppu_module(ppu_module&&) noexcept = default; ppu_module& operator=(const ppu_module&) = delete; ppu_module& operator=(ppu_module&&) noexcept = default; uchar sha1[20]{}; // Hash std::string name{}; // Filename std::string path{}; // Filepath s64 offset = 0; // Offset of file mutable bs_t attr{}; // Shared module attributes std::string cache{}; // Cache file path std::vector relocs{}; // Relocations std::vector segs{}; // Segments std::vector secs{}; // Segment sections std::vector funcs{}; // Function list std::vector applied_patches; // Patch addresses std::deque> allocations; // Segment memory allocations std::map addr_to_seg_index; // address->segment ordered translator map ppu_module* parent = nullptr; // For compilation: refers to original structure (is whole, not partitioned) std::pair local_bounds{0, u32{umax}}; // Module addresses range std::shared_ptr> jit_bounds; // JIT instance modules addresses range bool is_relocatable = false; // Is code relocatable(?) template auto as_span(T&& arg, bool bound_local, bool bound_jit) const { using unref = std::remove_reference_t; using type = std::conditional_t, std::add_const_t, typename unref::value_type>; if (bound_local || bound_jit) { // Return span bound to specified bounds const auto [min_addr, max_addr] = bound_jit ? *jit_bounds : local_bounds; constexpr auto compare = [](const type& a, u32 addr) { return a.addr < addr; }; const auto end = arg.data() + arg.size(); const auto start = std::lower_bound(arg.data(), end, min_addr, compare); return std::span{ start, std::lower_bound(start, end, max_addr, compare) }; } return std::span(arg.data(), arg.size()); } auto get_funcs(bool bound_local = true, bool bound_jit = false) { return as_span(parent ? parent->funcs : funcs, bound_local, bound_jit); } auto get_funcs(bool bound_local = true, bool bound_jit = false) const { return as_span(parent ? parent->funcs : funcs, bound_local, bound_jit); } auto get_relocs(bool bound_local = false) const { return as_span(parent ? parent->relocs : relocs, bound_local, false); } // Copy info without functions void copy_part(const ppu_module& info) { std::memcpy(sha1, info.sha1, sizeof(sha1)); name = info.name; path = info.path; segs = info.segs; allocations = info.allocations; addr_to_seg_index = info.addr_to_seg_index; parent = const_cast(&info); attr = info.attr; is_relocatable = info.is_relocatable; local_bounds = {u32{umax}, 0}; // Initially empty range } bool analyse(u32 lib_toc, u32 entry, u32 end, const std::vector& applied, const std::vector& exported_funcs = std::vector{}, std::function check_aborted = {}); void validate(u32 reloc); template to_be_t* get_ptr(u32 addr, u32 size_bytes) const { auto it = addr_to_seg_index.upper_bound(addr); if (it == addr_to_seg_index.begin()) { return nullptr; } it--; const auto& seg = segs[it->second]; const u32 seg_size = seg.size; const u32 seg_addr = seg.addr; if (seg_size >= std::max(size_bytes, 1) && addr <= utils::align(seg_addr + seg_size, 0x10000) - size_bytes) { return reinterpret_cast*>(static_cast(seg.ptr) + (addr - seg_addr)); } return nullptr; } template to_be_t* get_ptr(u32 addr) const { constexpr usz size_element = std::is_void_v ? 0 : sizeof(std::conditional_t, char, T>); return get_ptr(addr, u32{size_element}); } template requires requires (const U& obj) { obj.get_ptr(); } to_be_t* get_ptr(U&& addr) const { constexpr usz size_element = std::is_void_v ? 0 : sizeof(std::conditional_t, char, T>); return get_ptr(addr.addr(), u32{size_element}); } template to_be_t& get_ref(u32 addr, std::source_location src_loc = std::source_location::current()) const { constexpr usz size_element = std::is_void_v ? 0 : sizeof(std::conditional_t, char, T>); if (auto ptr = get_ptr(addr, u32{size_element})) { return *ptr; } fmt::throw_exception("get_ref(): Failure! (addr=0x%x)%s", addr, src_loc); return *std::add_pointer_t>{}; } template requires requires (const U& obj) { obj.get_ptr(); } to_be_t& get_ref(U&& addr, u32 index = 0, std::source_location src_loc = std::source_location::current()) const { constexpr usz size_element = std::is_void_v ? 0 : sizeof(std::conditional_t, char, T>); if (auto ptr = get_ptr((addr + index).addr(), u32{size_element})) { return *ptr; } fmt::throw_exception("get_ref(): Failure! (addr=0x%x)%s", (addr + index).addr(), src_loc); return *std::add_pointer_t>{}; } }; template struct main_ppu_module : public ppu_module { u32 elf_entry{}; u32 seg0_code_end{}; // Disable inherited savestate ordering void save(utils::serial&) = delete; static constexpr double savestate_init_pos = double{}; }; // Aux struct ppu_pattern { be_t opcode; be_t mask; ppu_pattern() = default; ppu_pattern(u32 op) : opcode(op) , mask(0xffffffff) { } ppu_pattern(u32 op, u32 ign) : opcode(op & ~ign) , mask(~ign) { } }; struct ppu_pattern_array { const ppu_pattern* ptr; usz count; template constexpr ppu_pattern_array(const ppu_pattern(&array)[N]) : ptr(array) , count(N) { } constexpr const ppu_pattern* begin() const { return ptr; } constexpr const ppu_pattern* end() const { return ptr + count; } }; struct ppu_pattern_matrix { const ppu_pattern_array* ptr; usz count; template constexpr ppu_pattern_matrix(const ppu_pattern_array(&array)[N]) : ptr(array) , count(N) { } constexpr const ppu_pattern_array* begin() const { return ptr; } constexpr const ppu_pattern_array* end() const { return ptr + count; } }; // PPU Instruction Type struct ppu_itype { static constexpr struct branch_tag{} branch{}; // Branch Instructions static constexpr struct trap_tag{} trap{}; // Trap Instructions static constexpr struct store_tag{} store{}; // Memory store Instructions static constexpr struct load_tag{} load{}; // Memory load Instructions (TODO: Fill it) static constexpr struct memory_tag{} memory{}; // Memory Instructions enum class type { UNK = 0, MFVSCR, MTVSCR, VADDCUW, VADDFP, VADDSBS, VADDSHS, VADDSWS, VADDUBM, VADDUBS, VADDUHM, VADDUHS, VADDUWM, VADDUWS, VAND, VANDC, VAVGSB, VAVGSH, VAVGSW, VAVGUB, VAVGUH, VAVGUW, VCFSX, VCFUX, VCMPBFP, VCMPBFP_, VCMPEQFP, VCMPEQFP_, VCMPEQUB, VCMPEQUB_, VCMPEQUH, VCMPEQUH_, VCMPEQUW, VCMPEQUW_, VCMPGEFP, VCMPGEFP_, VCMPGTFP, VCMPGTFP_, VCMPGTSB, VCMPGTSB_, VCMPGTSH, VCMPGTSH_, VCMPGTSW, VCMPGTSW_, VCMPGTUB, VCMPGTUB_, VCMPGTUH, VCMPGTUH_, VCMPGTUW, VCMPGTUW_, VCTSXS, VCTUXS, VEXPTEFP, VLOGEFP, VMADDFP, VMAXFP, VMAXSB, VMAXSH, VMAXSW, VMAXUB, VMAXUH, VMAXUW, VMHADDSHS, VMHRADDSHS, VMINFP, VMINSB, VMINSH, VMINSW, VMINUB, VMINUH, VMINUW, VMLADDUHM, VMRGHB, VMRGHH, VMRGHW, VMRGLB, VMRGLH, VMRGLW, VMSUMMBM, VMSUMSHM, VMSUMSHS, VMSUMUBM, VMSUMUHM, VMSUMUHS, VMULESB, VMULESH, VMULEUB, VMULEUH, VMULOSB, VMULOSH, VMULOUB, VMULOUH, VNMSUBFP, VNOR, VOR, VPERM, VPKPX, VPKSHSS, VPKSHUS, VPKSWSS, VPKSWUS, VPKUHUM, VPKUHUS, VPKUWUM, VPKUWUS, VREFP, VRFIM, VRFIN, VRFIP, VRFIZ, VRLB, VRLH, VRLW, VRSQRTEFP, VSEL, VSL, VSLB, VSLDOI, VSLH, VSLO, VSLW, VSPLTB, VSPLTH, VSPLTISB, VSPLTISH, VSPLTISW, VSPLTW, VSR, VSRAB, VSRAH, VSRAW, VSRB, VSRH, VSRO, VSRW, VSUBCUW, VSUBFP, VSUBSBS, VSUBSHS, VSUBSWS, VSUBUBM, VSUBUBS, VSUBUHM, VSUBUHS, VSUBUWM, VSUBUWS, VSUMSWS, VSUM2SWS, VSUM4SBS, VSUM4SHS, VSUM4UBS, VUPKHPX, VUPKHSB, VUPKHSH, VUPKLPX, VUPKLSB, VUPKLSH, VXOR, MULLI, SUBFIC, ADDIC, ADDI, ADDIS, SC, MCRF, CRNOR, CRANDC, ISYNC, CRXOR, CRNAND, CRAND, CREQV, CRORC, CROR, RLWIMI, RLWINM, RLWNM, ORI, ORIS, XORI, XORIS, ANDI, ANDIS, RLDICL, RLDICR, RLDIC, RLDIMI, RLDCL, RLDCR, LVSL, LVEBX, SUBFC, SUBFCO, ADDC, ADDCO, MULHDU, MULHWU, MFOCRF, LWARX, LDX, LWZX, SLW, CNTLZW, SLD, AND, LVSR, LVEHX, SUBF, SUBFO, LDUX, LWZUX, CNTLZD, ANDC, LVEWX, MULHD, MULHW, LDARX, DCBF, LBZX, LVX, NEG, NEGO, LBZUX, NOR, SUBFE, SUBFEO, ADDE, ADDEO, MTOCRF, SUBFZE, SUBFZEO, ADDZE, ADDZEO, SUBFME, SUBFMEO, MULLD, MULLDO, ADDME, ADDMEO, MULLW, MULLWO, ADD, ADDO, LHZX, EQV, ECIWX, LHZUX, XOR, MFSPR, LWAX, LHAX, LVXL, MFTB, LWAUX, LHAUX, ORC, ECOWX, OR, DIVDU, DIVDUO, DIVWU, DIVWUO, MTSPR, NAND, DIVD, DIVDO, DIVW, DIVWO, LVLX, LDBRX, LSWX, LWBRX, LFSX, SRW, SRD, LVRX, LSWI, LFSUX, LFDX, LFDUX, LVLXL, LHBRX, SRAW, SRAD, LVRXL, SRAWI, SRADI, EXTSH, EXTSB, EXTSW, LWZ, LWZU, LBZ, LBZU, LHZ, LHZU, LHA, LHAU, LMW, LFS, LFSU, LFD, LFDU, LD, LDU, LWA, FDIVS, FSUBS, FADDS, FSQRTS, FRES, FMULS, FMADDS, FMSUBS, FNMSUBS, FNMADDS, MTFSB1, MCRFS, MTFSB0, MTFSFI, MFFS, MTFSF, FCMPU, FRSP, FCTIW, FCTIWZ, FDIV, FSUB, FADD, FSQRT, FSEL, FMUL, FRSQRTE, FMSUB, FMADD, FNMSUB, FNMADD, FCMPO, FNEG, FMR, FNABS, FABS, FCTID, FCTIDZ, FCFID, SUBFCO_, ADDCO_, SUBFO_, NEGO_, SUBFEO_, ADDEO_, SUBFZEO_, ADDZEO_, SUBFMEO_, MULLDO_, ADDMEO_, MULLWO_, ADDO_, DIVDUO_, DIVWUO_, DIVDO_, DIVWO_, RLWIMI_, RLWINM_, RLWNM_, RLDICL_, RLDICR_, RLDIC_, RLDIMI_, RLDCL_, RLDCR_, SUBFC_, MULHDU_, ADDC_, MULHWU_, SLW_, CNTLZW_, SLD_, AND_, SUBF_, CNTLZD_, ANDC_, MULHD_, MULHW_, NEG_, NOR_, SUBFE_, ADDE_, SUBFZE_, ADDZE_, MULLD_, SUBFME_, ADDME_, MULLW_, ADD_, EQV_, XOR_, ORC_, OR_, DIVDU_, DIVWU_, NAND_, DIVD_, DIVW_, SRW_, SRD_, SRAW_, SRAD_, SRAWI_, SRADI_, EXTSH_, EXTSB_, EXTSW_, FDIVS_, FSUBS_, FADDS_, FSQRTS_, FRES_, FMULS_, FMADDS_, FMSUBS_, FNMSUBS_, FNMADDS_, MTFSB1_, MTFSB0_, MTFSFI_, MFFS_, MTFSF_, FRSP_, FCTIW_, FCTIWZ_, FDIV_, FSUB_, FADD_, FSQRT_, FSEL_, FMUL_, FRSQRTE_, FMSUB_, FMADD_, FNMSUB_, FNMADD_, FNEG_, FMR_, FNABS_, FABS_, FCTID_, FCTIDZ_, FCFID_, CMPLI, CMPI, CMP, CMPL, STMW, // store_tag first STSWX, STSWI, STVXL, STVLX, STVRX, STVEBX, STVEHX, STVEWX, STVX, STVLXL, STVRXL, STDX, STDUX, STDCX, STDBRX, STD, STDU, STFDUX, STFDX, STFDU, STFD, STFS, STFSU, STFSX, STFSUX, STFIWX, STWCX, STWX, STWUX, STWBRX, STWU, STW, STHBRX, STHX, STHUX, STH, STBX, STBU, STB, STHU, STBUX, DCBZ, DCBI, // Perceive memory barrier or flag instructions as stores DCBTST, DCBT, DCBST, DST, DSS, ICBI, SYNC, EIEIO, DSTST, // store_tag last B, // branch_tag first BC, BCLR, BCCTR, // branch_tag last TD, // trap_tag first TW, TDI, TWI, // trap_tag last }; using enum type; // Enable address-of operator for ppu_decoder<> friend constexpr type operator &(type value) { return value; } friend constexpr bool operator &(type value, branch_tag) { return value >= B && value <= BCCTR; } friend constexpr bool operator &(type value, trap_tag) { return value >= TD && value <= TWI; } friend constexpr bool operator &(type value, store_tag) { return value >= STMW && value <= DSTST; } }; struct ppu_iname { #define NAME(x) static constexpr const char& x = *#x; #define NAME_(x) static constexpr const char& x##_ = *#x "."; NAME(UNK) NAME(MFVSCR) NAME(MTVSCR) NAME(VADDCUW) NAME(VADDFP) NAME(VADDSBS) NAME(VADDSHS) NAME(VADDSWS) NAME(VADDUBM) NAME(VADDUBS) NAME(VADDUHM) NAME(VADDUHS) NAME(VADDUWM) NAME(VADDUWS) NAME(VAND) NAME(VANDC) NAME(VAVGSB) NAME(VAVGSH) NAME(VAVGSW) NAME(VAVGUB) NAME(VAVGUH) NAME(VAVGUW) NAME(VCFSX) NAME(VCFUX) NAME(VCMPBFP) NAME_(VCMPBFP) NAME(VCMPEQFP) NAME_(VCMPEQFP) NAME(VCMPEQUB) NAME_(VCMPEQUB) NAME(VCMPEQUH) NAME_(VCMPEQUH) NAME(VCMPEQUW) NAME_(VCMPEQUW) NAME(VCMPGEFP) NAME_(VCMPGEFP) NAME(VCMPGTFP) NAME_(VCMPGTFP) NAME(VCMPGTSB) NAME_(VCMPGTSB) NAME(VCMPGTSH) NAME_(VCMPGTSH) NAME(VCMPGTSW) NAME_(VCMPGTSW) NAME(VCMPGTUB) NAME_(VCMPGTUB) NAME(VCMPGTUH) NAME_(VCMPGTUH) NAME(VCMPGTUW) NAME_(VCMPGTUW) NAME(VCTSXS) NAME(VCTUXS) NAME(VEXPTEFP) NAME(VLOGEFP) NAME(VMADDFP) NAME(VMAXFP) NAME(VMAXSB) NAME(VMAXSH) NAME(VMAXSW) NAME(VMAXUB) NAME(VMAXUH) NAME(VMAXUW) NAME(VMHADDSHS) NAME(VMHRADDSHS) NAME(VMINFP) NAME(VMINSB) NAME(VMINSH) NAME(VMINSW) NAME(VMINUB) NAME(VMINUH) NAME(VMINUW) NAME(VMLADDUHM) NAME(VMRGHB) NAME(VMRGHH) NAME(VMRGHW) NAME(VMRGLB) NAME(VMRGLH) NAME(VMRGLW) NAME(VMSUMMBM) NAME(VMSUMSHM) NAME(VMSUMSHS) NAME(VMSUMUBM) NAME(VMSUMUHM) NAME(VMSUMUHS) NAME(VMULESB) NAME(VMULESH) NAME(VMULEUB) NAME(VMULEUH) NAME(VMULOSB) NAME(VMULOSH) NAME(VMULOUB) NAME(VMULOUH) NAME(VNMSUBFP) NAME(VNOR) NAME(VOR) NAME(VPERM) NAME(VPKPX) NAME(VPKSHSS) NAME(VPKSHUS) NAME(VPKSWSS) NAME(VPKSWUS) NAME(VPKUHUM) NAME(VPKUHUS) NAME(VPKUWUM) NAME(VPKUWUS) NAME(VREFP) NAME(VRFIM) NAME(VRFIN) NAME(VRFIP) NAME(VRFIZ) NAME(VRLB) NAME(VRLH) NAME(VRLW) NAME(VRSQRTEFP) NAME(VSEL) NAME(VSL) NAME(VSLB) NAME(VSLDOI) NAME(VSLH) NAME(VSLO) NAME(VSLW) NAME(VSPLTB) NAME(VSPLTH) NAME(VSPLTISB) NAME(VSPLTISH) NAME(VSPLTISW) NAME(VSPLTW) NAME(VSR) NAME(VSRAB) NAME(VSRAH) NAME(VSRAW) NAME(VSRB) NAME(VSRH) NAME(VSRO) NAME(VSRW) NAME(VSUBCUW) NAME(VSUBFP) NAME(VSUBSBS) NAME(VSUBSHS) NAME(VSUBSWS) NAME(VSUBUBM) NAME(VSUBUBS) NAME(VSUBUHM) NAME(VSUBUHS) NAME(VSUBUWM) NAME(VSUBUWS) NAME(VSUMSWS) NAME(VSUM2SWS) NAME(VSUM4SBS) NAME(VSUM4SHS) NAME(VSUM4UBS) NAME(VUPKHPX) NAME(VUPKHSB) NAME(VUPKHSH) NAME(VUPKLPX) NAME(VUPKLSB) NAME(VUPKLSH) NAME(VXOR) NAME(TDI) NAME(TWI) NAME(MULLI) NAME(SUBFIC) NAME(CMPLI) NAME(CMPI) NAME(ADDIC) NAME(ADDI) NAME(ADDIS) NAME(BC) NAME(SC) NAME(B) NAME(MCRF) NAME(BCLR) NAME(CRNOR) NAME(CRANDC) NAME(ISYNC) NAME(CRXOR) NAME(CRNAND) NAME(CRAND) NAME(CREQV) NAME(CRORC) NAME(CROR) NAME(BCCTR) NAME(RLWIMI) NAME(RLWINM) NAME(RLWNM) NAME(ORI) NAME(ORIS) NAME(XORI) NAME(XORIS) NAME(ANDI) NAME(ANDIS) NAME(RLDICL) NAME(RLDICR) NAME(RLDIC) NAME(RLDIMI) NAME(RLDCL) NAME(RLDCR) NAME(CMP) NAME(TW) NAME(LVSL) NAME(LVEBX) NAME(SUBFC) NAME(ADDC) NAME(MULHDU) NAME(MULHWU) NAME(MFOCRF) NAME(LWARX) NAME(LDX) NAME(LWZX) NAME(SLW) NAME(CNTLZW) NAME(SLD) NAME(AND) NAME(CMPL) NAME(LVSR) NAME(LVEHX) NAME(SUBF) NAME(LDUX) NAME(DCBST) NAME(LWZUX) NAME(CNTLZD) NAME(ANDC) NAME(TD) NAME(LVEWX) NAME(MULHD) NAME(MULHW) NAME(LDARX) NAME(DCBF) NAME(LBZX) NAME(LVX) NAME(NEG) NAME(LBZUX) NAME(NOR) NAME(STVEBX) NAME(SUBFE) NAME(ADDE) NAME(MTOCRF) NAME(STDX) NAME(STWCX) NAME(STWX) NAME(STVEHX) NAME(STDUX) NAME(STWUX) NAME(STVEWX) NAME(SUBFZE) NAME(ADDZE) NAME(STDCX) NAME(STBX) NAME(STVX) NAME(SUBFME) NAME(MULLD) NAME(ADDME) NAME(MULLW) NAME(DCBTST) NAME(STBUX) NAME(ADD) NAME(DCBT) NAME(LHZX) NAME(EQV) NAME(ECIWX) NAME(LHZUX) NAME(XOR) NAME(MFSPR) NAME(LWAX) NAME(DST) NAME(LHAX) NAME(LVXL) NAME(MFTB) NAME(LWAUX) NAME(DSTST) NAME(LHAUX) NAME(STHX) NAME(ORC) NAME(ECOWX) NAME(STHUX) NAME(OR) NAME(DIVDU) NAME(DIVWU) NAME(MTSPR) NAME(DCBI) NAME(NAND) NAME(STVXL) NAME(DIVD) NAME(DIVW) NAME(LVLX) NAME(LDBRX) NAME(LSWX) NAME(LWBRX) NAME(LFSX) NAME(SRW) NAME(SRD) NAME(LVRX) NAME(LSWI) NAME(LFSUX) NAME(SYNC) NAME(LFDX) NAME(LFDUX) NAME(STVLX) NAME(STDBRX) NAME(STSWX) NAME(STWBRX) NAME(STFSX) NAME(STVRX) NAME(STFSUX) NAME(STSWI) NAME(STFDX) NAME(STFDUX) NAME(LVLXL) NAME(LHBRX) NAME(SRAW) NAME(SRAD) NAME(LVRXL) NAME(DSS) NAME(SRAWI) NAME(SRADI) NAME(EIEIO) NAME(STVLXL) NAME(STHBRX) NAME(EXTSH) NAME(STVRXL) NAME(EXTSB) NAME(STFIWX) NAME(EXTSW) NAME(ICBI) NAME(DCBZ) NAME(LWZ) NAME(LWZU) NAME(LBZ) NAME(LBZU) NAME(STW) NAME(STWU) NAME(STB) NAME(STBU) NAME(LHZ) NAME(LHZU) NAME(LHA) NAME(LHAU) NAME(STH) NAME(STHU) NAME(LMW) NAME(STMW) NAME(LFS) NAME(LFSU) NAME(LFD) NAME(LFDU) NAME(STFS) NAME(STFSU) NAME(STFD) NAME(STFDU) NAME(LD) NAME(LDU) NAME(LWA) NAME(STD) NAME(STDU) NAME(FDIVS) NAME(FSUBS) NAME(FADDS) NAME(FSQRTS) NAME(FRES) NAME(FMULS) NAME(FMADDS) NAME(FMSUBS) NAME(FNMSUBS) NAME(FNMADDS) NAME(MTFSB1) NAME(MCRFS) NAME(MTFSB0) NAME(MTFSFI) NAME(MFFS) NAME(MTFSF) NAME(FCMPU) NAME(FRSP) NAME(FCTIW) NAME(FCTIWZ) NAME(FDIV) NAME(FSUB) NAME(FADD) NAME(FSQRT) NAME(FSEL) NAME(FMUL) NAME(FRSQRTE) NAME(FMSUB) NAME(FMADD) NAME(FNMSUB) NAME(FNMADD) NAME(FCMPO) NAME(FNEG) NAME(FMR) NAME(FNABS) NAME(FABS) NAME(FCTID) NAME(FCTIDZ) NAME(FCFID) NAME(SUBFCO) NAME(ADDCO) NAME(SUBFO) NAME(NEGO) NAME(SUBFEO) NAME(ADDEO) NAME(SUBFZEO) NAME(ADDZEO) NAME(SUBFMEO) NAME(MULLDO) NAME(ADDMEO) NAME(MULLWO) NAME(ADDO) NAME(DIVDUO) NAME(DIVWUO) NAME(DIVDO) NAME(DIVWO) NAME_(SUBFCO) NAME_(ADDCO) NAME_(SUBFO) NAME_(NEGO) NAME_(SUBFEO) NAME_(ADDEO) NAME_(SUBFZEO) NAME_(ADDZEO) NAME_(SUBFMEO) NAME_(MULLDO) NAME_(ADDMEO) NAME_(MULLWO) NAME_(ADDO) NAME_(DIVDUO) NAME_(DIVWUO) NAME_(DIVDO) NAME_(DIVWO) NAME_(RLWIMI) NAME_(RLWINM) NAME_(RLWNM) NAME_(RLDICL) NAME_(RLDICR) NAME_(RLDIC) NAME_(RLDIMI) NAME_(RLDCL) NAME_(RLDCR) NAME_(SUBFC) NAME_(MULHDU) NAME_(ADDC) NAME_(MULHWU) NAME_(SLW) NAME_(CNTLZW) NAME_(SLD) NAME_(AND) NAME_(SUBF) NAME_(CNTLZD) NAME_(ANDC) NAME_(MULHD) NAME_(MULHW) NAME_(NEG) NAME_(NOR) NAME_(SUBFE) NAME_(ADDE) NAME_(SUBFZE) NAME_(ADDZE) NAME_(MULLD) NAME_(SUBFME) NAME_(ADDME) NAME_(MULLW) NAME_(ADD) NAME_(EQV) NAME_(XOR) NAME_(ORC) NAME_(OR) NAME_(DIVDU) NAME_(DIVWU) NAME_(NAND) NAME_(DIVD) NAME_(DIVW) NAME_(SRW) NAME_(SRD) NAME_(SRAW) NAME_(SRAD) NAME_(SRAWI) NAME_(SRADI) NAME_(EXTSH) NAME_(EXTSB) NAME_(EXTSW) NAME_(FDIVS) NAME_(FSUBS) NAME_(FADDS) NAME_(FSQRTS) NAME_(FRES) NAME_(FMULS) NAME_(FMADDS) NAME_(FMSUBS) NAME_(FNMSUBS) NAME_(FNMADDS) NAME_(MTFSB1) NAME_(MTFSB0) NAME_(MTFSFI) NAME_(MFFS) NAME_(MTFSF) NAME_(FRSP) NAME_(FCTIW) NAME_(FCTIWZ) NAME_(FDIV) NAME_(FSUB) NAME_(FADD) NAME_(FSQRT) NAME_(FSEL) NAME_(FMUL) NAME_(FRSQRTE) NAME_(FMSUB) NAME_(FMADD) NAME_(FNMSUB) NAME_(FNMADD) NAME_(FNEG) NAME_(FMR) NAME_(FNABS) NAME_(FABS) NAME_(FCTID) NAME_(FCTIDZ) NAME_(FCFID) #undef NAME #undef NAME_ };