dolphin/Source/Core/Core/PowerPC/PPCTables.cpp
mitaclaw 76a998ecf9 TypeUtils: Remove Common::Fill
This temporary solution is no longer needed.
2024-08-22 17:29:26 -07:00

746 lines
32 KiB
C++

// Copyright 2008 Dolphin Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "Core/PowerPC/PPCTables.h"
#include <algorithm>
#include <array>
#include <cstddef>
#include <cstdio>
#include <vector>
#include <fmt/format.h>
#include "Common/Assert.h"
#include "Common/CommonTypes.h"
#include "Common/FileUtil.h"
#include "Common/IOFile.h"
#include "Common/Logging/Log.h"
#include "Common/StringUtil.h"
#include "Core/PowerPC/PowerPC.h"
namespace PPCTables
{
namespace
{
struct GekkoOPTemplate
{
u32 opcode;
const char* opname;
OpType type;
u32 num_cycles;
u64 flags;
};
constexpr GekkoOPTemplate s_unknown_op_info = {0, "unknown_instruction", OpType::Unknown, 0,
FL_ENDBLOCK};
constexpr std::array<GekkoOPTemplate, 54> s_primary_table{{
{4, "RunTable4", OpType::Subtable, 0, 0},
{19, "RunTable19", OpType::Subtable, 0, 0},
{31, "RunTable31", OpType::Subtable, 0, 0},
{59, "RunTable59", OpType::Subtable, 0, 0},
{63, "RunTable63", OpType::Subtable, 0, 0},
{16, "bcx", OpType::Branch, 1, FL_ENDBLOCK | FL_READ_CR_BI},
{18, "bx", OpType::Branch, 1, FL_ENDBLOCK},
{3, "twi", OpType::System, 1, FL_IN_A | FL_ENDBLOCK},
{17, "sc", OpType::System, 2, FL_ENDBLOCK},
{7, "mulli", OpType::Integer, 3, FL_OUT_D | FL_IN_A},
{8, "subfic", OpType::Integer, 1, FL_OUT_D | FL_IN_A | FL_SET_CA},
{10, "cmpli", OpType::Integer, 1, FL_IN_A | FL_SET_CRn},
{11, "cmpi", OpType::Integer, 1, FL_IN_A | FL_SET_CRn},
{12, "addic", OpType::Integer, 1, FL_OUT_D | FL_IN_A | FL_SET_CA},
{13, "addic_rc", OpType::Integer, 1, FL_OUT_D | FL_IN_A | FL_SET_CA | FL_SET_CR0},
{14, "addi", OpType::Integer, 1, FL_OUT_D | FL_IN_A0},
{15, "addis", OpType::Integer, 1, FL_OUT_D | FL_IN_A0},
{20, "rlwimix", OpType::Integer, 1, FL_OUT_A | FL_IN_A | FL_IN_S | FL_RC_BIT},
{21, "rlwinmx", OpType::Integer, 1, FL_OUT_A | FL_IN_S | FL_RC_BIT},
{23, "rlwnmx", OpType::Integer, 1, FL_OUT_A | FL_IN_SB | FL_RC_BIT},
{24, "ori", OpType::Integer, 1, FL_OUT_A | FL_IN_S},
{25, "oris", OpType::Integer, 1, FL_OUT_A | FL_IN_S},
{26, "xori", OpType::Integer, 1, FL_OUT_A | FL_IN_S},
{27, "xoris", OpType::Integer, 1, FL_OUT_A | FL_IN_S},
{28, "andi_rc", OpType::Integer, 1, FL_OUT_A | FL_IN_S | FL_SET_CR0},
{29, "andis_rc", OpType::Integer, 1, FL_OUT_A | FL_IN_S | FL_SET_CR0},
{32, "lwz", OpType::Load, 1, FL_OUT_D | FL_IN_A0 | FL_LOADSTORE},
{33, "lwzu", OpType::Load, 1, FL_OUT_D | FL_OUT_A | FL_IN_A | FL_LOADSTORE},
{34, "lbz", OpType::Load, 1, FL_OUT_D | FL_IN_A0 | FL_LOADSTORE},
{35, "lbzu", OpType::Load, 1, FL_OUT_D | FL_OUT_A | FL_IN_A | FL_LOADSTORE},
{40, "lhz", OpType::Load, 1, FL_OUT_D | FL_IN_A0 | FL_LOADSTORE},
{41, "lhzu", OpType::Load, 1, FL_OUT_D | FL_OUT_A | FL_IN_A | FL_LOADSTORE},
{42, "lha", OpType::Load, 1, FL_OUT_D | FL_IN_A0 | FL_LOADSTORE},
{43, "lhau", OpType::Load, 1, FL_OUT_D | FL_OUT_A | FL_IN_A | FL_LOADSTORE},
{44, "sth", OpType::Store, 1, FL_IN_A0 | FL_IN_S | FL_LOADSTORE},
{45, "sthu", OpType::Store, 1, FL_OUT_A | FL_IN_A | FL_IN_S | FL_LOADSTORE},
{36, "stw", OpType::Store, 1, FL_IN_A0 | FL_IN_S | FL_LOADSTORE},
{37, "stwu", OpType::Store, 1, FL_OUT_A | FL_IN_A | FL_IN_S | FL_LOADSTORE},
{38, "stb", OpType::Store, 1, FL_IN_A0 | FL_IN_S | FL_LOADSTORE},
{39, "stbu", OpType::Store, 1, FL_OUT_A | FL_IN_A | FL_IN_S | FL_LOADSTORE},
{46, "lmw", OpType::System, 11, FL_IN_A0 | FL_LOADSTORE},
{47, "stmw", OpType::System, 11, FL_IN_A0 | FL_LOADSTORE},
{48, "lfs", OpType::LoadFP, 1, FL_OUT_FLOAT_D | FL_IN_A | FL_USE_FPU | FL_LOADSTORE},
{49, "lfsu", OpType::LoadFP, 1,
FL_OUT_FLOAT_D | FL_OUT_A | FL_IN_A | FL_USE_FPU | FL_LOADSTORE},
{50, "lfd", OpType::LoadFP, 1, FL_INOUT_FLOAT_D | FL_IN_A | FL_USE_FPU | FL_LOADSTORE},
{51, "lfdu", OpType::LoadFP, 1,
FL_INOUT_FLOAT_D | FL_OUT_A | FL_IN_A | FL_USE_FPU | FL_LOADSTORE},
{52, "stfs", OpType::StoreFP, 1, FL_IN_FLOAT_S | FL_IN_A0 | FL_USE_FPU | FL_LOADSTORE},
{53, "stfsu", OpType::StoreFP, 1,
FL_IN_FLOAT_S | FL_OUT_A | FL_IN_A | FL_USE_FPU | FL_LOADSTORE},
{54, "stfd", OpType::StoreFP, 1, FL_IN_FLOAT_S | FL_IN_A0 | FL_USE_FPU | FL_LOADSTORE},
{55, "stfdu", OpType::StoreFP, 1,
FL_IN_FLOAT_S | FL_OUT_A | FL_IN_A | FL_USE_FPU | FL_LOADSTORE},
{56, "psq_l", OpType::LoadPS, 1,
FL_OUT_FLOAT_D | FL_IN_A0 | FL_USE_FPU | FL_LOADSTORE | FL_PROGRAMEXCEPTION},
{57, "psq_lu", OpType::LoadPS, 1,
FL_OUT_FLOAT_D | FL_OUT_A | FL_IN_A | FL_USE_FPU | FL_LOADSTORE | FL_PROGRAMEXCEPTION},
{60, "psq_st", OpType::StorePS, 1,
FL_IN_FLOAT_S | FL_IN_A0 | FL_USE_FPU | FL_LOADSTORE | FL_PROGRAMEXCEPTION},
{61, "psq_stu", OpType::StorePS, 1,
FL_IN_FLOAT_S | FL_OUT_A | FL_IN_A | FL_USE_FPU | FL_LOADSTORE | FL_PROGRAMEXCEPTION},
// missing: 0, 1, 2, 5, 6, 9, 22, 30, 62, 58
}};
constexpr std::array<GekkoOPTemplate, 13> s_table4{{
// SUBOP10
{0, "ps_cmpu0", OpType::PS, 1,
FL_IN_FLOAT_AB | FL_SET_CRn | FL_USE_FPU | FL_READ_FPRF | FL_SET_FPRF | FL_PROGRAMEXCEPTION |
FL_FLOAT_EXCEPTION},
{32, "ps_cmpo0", OpType::PS, 1,
FL_IN_FLOAT_AB | FL_SET_CRn | FL_USE_FPU | FL_READ_FPRF | FL_SET_FPRF | FL_PROGRAMEXCEPTION |
FL_FLOAT_EXCEPTION},
{40, "ps_neg", OpType::PS, 1,
FL_OUT_FLOAT_D | FL_IN_FLOAT_B | FL_IN_FLOAT_B_BITEXACT | FL_RC_BIT_F | FL_USE_FPU |
FL_PROGRAMEXCEPTION},
{136, "ps_nabs", OpType::PS, 1,
FL_OUT_FLOAT_D | FL_IN_FLOAT_B | FL_IN_FLOAT_B_BITEXACT | FL_RC_BIT_F | FL_USE_FPU |
FL_PROGRAMEXCEPTION},
{264, "ps_abs", OpType::PS, 1,
FL_OUT_FLOAT_D | FL_IN_FLOAT_B | FL_IN_FLOAT_B_BITEXACT | FL_RC_BIT_F | FL_USE_FPU |
FL_PROGRAMEXCEPTION},
{64, "ps_cmpu1", OpType::PS, 1,
FL_IN_FLOAT_AB | FL_SET_CRn | FL_USE_FPU | FL_READ_FPRF | FL_SET_FPRF | FL_PROGRAMEXCEPTION |
FL_FLOAT_EXCEPTION},
{72, "ps_mr", OpType::PS, 1,
FL_OUT_FLOAT_D | FL_IN_FLOAT_B | FL_IN_FLOAT_B_BITEXACT | FL_RC_BIT_F | FL_USE_FPU |
FL_PROGRAMEXCEPTION},
{96, "ps_cmpo1", OpType::PS, 1,
FL_IN_FLOAT_AB | FL_SET_CRn | FL_USE_FPU | FL_READ_FPRF | FL_SET_FPRF | FL_PROGRAMEXCEPTION |
FL_FLOAT_EXCEPTION},
{528, "ps_merge00", OpType::PS, 1,
FL_OUT_FLOAT_D | FL_IN_FLOAT_AB | FL_IN_FLOAT_AB_BITEXACT | FL_RC_BIT_F | FL_USE_FPU |
FL_PROGRAMEXCEPTION},
{560, "ps_merge01", OpType::PS, 1,
FL_OUT_FLOAT_D | FL_IN_FLOAT_AB | FL_IN_FLOAT_AB_BITEXACT | FL_RC_BIT_F | FL_USE_FPU |
FL_PROGRAMEXCEPTION},
{592, "ps_merge10", OpType::PS, 1,
FL_OUT_FLOAT_D | FL_IN_FLOAT_AB | FL_IN_FLOAT_AB_BITEXACT | FL_RC_BIT_F | FL_USE_FPU |
FL_PROGRAMEXCEPTION},
{624, "ps_merge11", OpType::PS, 1,
FL_OUT_FLOAT_D | FL_IN_FLOAT_AB | FL_IN_FLOAT_AB_BITEXACT | FL_RC_BIT_F | FL_USE_FPU |
FL_PROGRAMEXCEPTION},
{1014, "dcbz_l", OpType::System, 1, FL_IN_A0B | FL_LOADSTORE | FL_PROGRAMEXCEPTION},
}};
constexpr std::array<GekkoOPTemplate, 17> s_table4_2{{
{10, "ps_sum0", OpType::PS, 1,
FL_OUT_FLOAT_D | FL_IN_FLOAT_ABC | FL_RC_BIT_F | FL_USE_FPU | FL_SET_FPRF |
FL_PROGRAMEXCEPTION | FL_FLOAT_EXCEPTION},
{11, "ps_sum1", OpType::PS, 1,
FL_OUT_FLOAT_D | FL_IN_FLOAT_ABC | FL_RC_BIT_F | FL_USE_FPU | FL_SET_FPRF |
FL_PROGRAMEXCEPTION | FL_FLOAT_EXCEPTION},
{12, "ps_muls0", OpType::PS, 1,
FL_OUT_FLOAT_D | FL_IN_FLOAT_AC | FL_RC_BIT_F | FL_USE_FPU | FL_SET_FPRF |
FL_PROGRAMEXCEPTION | FL_FLOAT_EXCEPTION},
{13, "ps_muls1", OpType::PS, 1,
FL_OUT_FLOAT_D | FL_IN_FLOAT_AC | FL_RC_BIT_F | FL_USE_FPU | FL_SET_FPRF |
FL_PROGRAMEXCEPTION | FL_FLOAT_EXCEPTION},
{14, "ps_madds0", OpType::PS, 1,
FL_OUT_FLOAT_D | FL_IN_FLOAT_ABC | FL_RC_BIT_F | FL_USE_FPU | FL_SET_FPRF |
FL_PROGRAMEXCEPTION | FL_FLOAT_EXCEPTION},
{15, "ps_madds1", OpType::PS, 1,
FL_OUT_FLOAT_D | FL_IN_FLOAT_ABC | FL_RC_BIT_F | FL_USE_FPU | FL_SET_FPRF |
FL_PROGRAMEXCEPTION | FL_FLOAT_EXCEPTION},
{18, "ps_div", OpType::PS, 17,
FL_OUT_FLOAT_D | FL_IN_FLOAT_AB | FL_RC_BIT_F | FL_USE_FPU | FL_SET_FPRF |
FL_PROGRAMEXCEPTION | FL_FLOAT_EXCEPTION | FL_FLOAT_DIV},
{20, "ps_sub", OpType::PS, 1,
FL_OUT_FLOAT_D | FL_IN_FLOAT_AB | FL_RC_BIT_F | FL_USE_FPU | FL_SET_FPRF |
FL_PROGRAMEXCEPTION | FL_FLOAT_EXCEPTION},
{21, "ps_add", OpType::PS, 1,
FL_OUT_FLOAT_D | FL_IN_FLOAT_AB | FL_RC_BIT_F | FL_USE_FPU | FL_SET_FPRF |
FL_PROGRAMEXCEPTION | FL_FLOAT_EXCEPTION},
{23, "ps_sel", OpType::PS, 1,
FL_OUT_FLOAT_D | FL_IN_FLOAT_ABC | FL_IN_FLOAT_BC_BITEXACT | FL_RC_BIT_F | FL_USE_FPU |
FL_PROGRAMEXCEPTION},
{24, "ps_res", OpType::PS, 1,
FL_OUT_FLOAT_D | FL_IN_FLOAT_B | FL_RC_BIT_F | FL_USE_FPU | FL_SET_FPRF | FL_PROGRAMEXCEPTION |
FL_FLOAT_EXCEPTION | FL_FLOAT_DIV},
{25, "ps_mul", OpType::PS, 1,
FL_OUT_FLOAT_D | FL_IN_FLOAT_AC | FL_RC_BIT_F | FL_USE_FPU | FL_SET_FPRF |
FL_PROGRAMEXCEPTION | FL_FLOAT_EXCEPTION},
{26, "ps_rsqrte", OpType::PS, 2,
FL_OUT_FLOAT_D | FL_IN_FLOAT_B | FL_RC_BIT_F | FL_USE_FPU | FL_SET_FPRF | FL_PROGRAMEXCEPTION |
FL_FLOAT_EXCEPTION | FL_FLOAT_DIV},
{28, "ps_msub", OpType::PS, 1,
FL_OUT_FLOAT_D | FL_IN_FLOAT_ABC | FL_RC_BIT_F | FL_USE_FPU | FL_SET_FPRF |
FL_PROGRAMEXCEPTION | FL_FLOAT_EXCEPTION},
{29, "ps_madd", OpType::PS, 1,
FL_OUT_FLOAT_D | FL_IN_FLOAT_ABC | FL_RC_BIT_F | FL_USE_FPU | FL_SET_FPRF |
FL_PROGRAMEXCEPTION | FL_FLOAT_EXCEPTION},
{30, "ps_nmsub", OpType::PS, 1,
FL_OUT_FLOAT_D | FL_IN_FLOAT_ABC | FL_RC_BIT_F | FL_USE_FPU | FL_SET_FPRF |
FL_PROGRAMEXCEPTION | FL_FLOAT_EXCEPTION},
{31, "ps_nmadd", OpType::PS, 1,
FL_OUT_FLOAT_D | FL_IN_FLOAT_ABC | FL_RC_BIT_F | FL_USE_FPU | FL_SET_FPRF |
FL_PROGRAMEXCEPTION | FL_FLOAT_EXCEPTION},
}};
constexpr std::array<GekkoOPTemplate, 4> s_table4_3{{
{6, "psq_lx", OpType::LoadPS, 1, FL_OUT_FLOAT_D | FL_IN_A0B | FL_USE_FPU | FL_LOADSTORE},
{7, "psq_stx", OpType::StorePS, 1, FL_IN_FLOAT_S | FL_IN_A0B | FL_USE_FPU | FL_LOADSTORE},
{38, "psq_lux", OpType::LoadPS, 1,
FL_OUT_FLOAT_D | FL_OUT_A | FL_IN_AB | FL_USE_FPU | FL_LOADSTORE},
{39, "psq_stux", OpType::StorePS, 1,
FL_IN_FLOAT_S | FL_OUT_A | FL_IN_AB | FL_USE_FPU | FL_LOADSTORE},
}};
constexpr std::array<GekkoOPTemplate, 13> s_table19{{
{528, "bcctrx", OpType::Branch, 1, FL_ENDBLOCK | FL_READ_CR_BI},
{16, "bclrx", OpType::Branch, 1, FL_ENDBLOCK | FL_READ_CR_BI},
{257, "crand", OpType::CR, 1, 0},
{129, "crandc", OpType::CR, 1, 0},
{289, "creqv", OpType::CR, 1, 0},
{225, "crnand", OpType::CR, 1, 0},
{33, "crnor", OpType::CR, 1, 0},
{449, "cror", OpType::CR, 1, 0},
{417, "crorc", OpType::CR, 1, 0},
{193, "crxor", OpType::CR, 1, 0},
{150, "isync", OpType::InstructionCache, 1, FL_NO_REORDER},
{0, "mcrf", OpType::System, 1, FL_SET_CRn | FL_READ_CRn},
{50, "rfi", OpType::System, 2, FL_ENDBLOCK | FL_CHECKEXCEPTIONS | FL_PROGRAMEXCEPTION},
}};
constexpr std::array<GekkoOPTemplate, 107> s_table31{{
{266, "addx", OpType::Integer, 1, FL_OUT_D | FL_IN_AB | FL_RC_BIT},
{778, "addox", OpType::Integer, 1, FL_OUT_D | FL_IN_AB | FL_RC_BIT | FL_SET_OE},
{10, "addcx", OpType::Integer, 1, FL_OUT_D | FL_IN_AB | FL_SET_CA | FL_RC_BIT},
{522, "addcox", OpType::Integer, 1, FL_OUT_D | FL_IN_AB | FL_SET_CA | FL_RC_BIT | FL_SET_OE},
{138, "addex", OpType::Integer, 1, FL_OUT_D | FL_IN_AB | FL_READ_CA | FL_SET_CA | FL_RC_BIT},
{650, "addeox", OpType::Integer, 1,
FL_OUT_D | FL_IN_AB | FL_READ_CA | FL_SET_CA | FL_RC_BIT | FL_SET_OE},
{234, "addmex", OpType::Integer, 1, FL_OUT_D | FL_IN_A | FL_READ_CA | FL_SET_CA | FL_RC_BIT},
{746, "addmeox", OpType::Integer, 1,
FL_OUT_D | FL_IN_A | FL_READ_CA | FL_SET_CA | FL_RC_BIT | FL_SET_OE},
{202, "addzex", OpType::Integer, 1, FL_OUT_D | FL_IN_A | FL_READ_CA | FL_SET_CA | FL_RC_BIT},
{714, "addzeox", OpType::Integer, 1,
FL_OUT_D | FL_IN_A | FL_READ_CA | FL_SET_CA | FL_RC_BIT | FL_SET_OE},
{491, "divwx", OpType::Integer, 40, FL_OUT_D | FL_IN_AB | FL_RC_BIT},
{1003, "divwox", OpType::Integer, 40, FL_OUT_D | FL_IN_AB | FL_RC_BIT | FL_SET_OE},
{459, "divwux", OpType::Integer, 40, FL_OUT_D | FL_IN_AB | FL_RC_BIT},
{971, "divwuox", OpType::Integer, 40, FL_OUT_D | FL_IN_AB | FL_RC_BIT | FL_SET_OE},
{75, "mulhwx", OpType::Integer, 5, FL_OUT_D | FL_IN_AB | FL_RC_BIT},
{11, "mulhwux", OpType::Integer, 5, FL_OUT_D | FL_IN_AB | FL_RC_BIT},
{235, "mullwx", OpType::Integer, 5, FL_OUT_D | FL_IN_AB | FL_RC_BIT},
{747, "mullwox", OpType::Integer, 5, FL_OUT_D | FL_IN_AB | FL_RC_BIT | FL_SET_OE},
{104, "negx", OpType::Integer, 1, FL_OUT_D | FL_IN_A | FL_RC_BIT},
{616, "negox", OpType::Integer, 1, FL_OUT_D | FL_IN_A | FL_RC_BIT | FL_SET_OE},
{40, "subfx", OpType::Integer, 1, FL_OUT_D | FL_IN_AB | FL_RC_BIT},
{552, "subfox", OpType::Integer, 1, FL_OUT_D | FL_IN_AB | FL_RC_BIT | FL_SET_OE},
{8, "subfcx", OpType::Integer, 1, FL_OUT_D | FL_IN_AB | FL_SET_CA | FL_RC_BIT},
{520, "subfcox", OpType::Integer, 1, FL_OUT_D | FL_IN_AB | FL_SET_CA | FL_RC_BIT | FL_SET_OE},
{136, "subfex", OpType::Integer, 1, FL_OUT_D | FL_IN_AB | FL_READ_CA | FL_SET_CA | FL_RC_BIT},
{648, "subfeox", OpType::Integer, 1,
FL_OUT_D | FL_IN_AB | FL_READ_CA | FL_SET_CA | FL_RC_BIT | FL_SET_OE},
{232, "subfmex", OpType::Integer, 1, FL_OUT_D | FL_IN_A | FL_READ_CA | FL_SET_CA | FL_RC_BIT},
{744, "subfmeox", OpType::Integer, 1,
FL_OUT_D | FL_IN_A | FL_READ_CA | FL_SET_CA | FL_RC_BIT | FL_SET_OE},
{200, "subfzex", OpType::Integer, 1, FL_OUT_D | FL_IN_A | FL_READ_CA | FL_SET_CA | FL_RC_BIT},
{712, "subfzeox", OpType::Integer, 1,
FL_OUT_D | FL_IN_A | FL_READ_CA | FL_SET_CA | FL_RC_BIT | FL_SET_OE},
{28, "andx", OpType::Integer, 1, FL_OUT_A | FL_IN_SB | FL_RC_BIT},
{60, "andcx", OpType::Integer, 1, FL_OUT_A | FL_IN_SB | FL_RC_BIT},
{444, "orx", OpType::Integer, 1, FL_OUT_A | FL_IN_SB | FL_RC_BIT},
{124, "norx", OpType::Integer, 1, FL_OUT_A | FL_IN_SB | FL_RC_BIT},
{316, "xorx", OpType::Integer, 1, FL_OUT_A | FL_IN_SB | FL_RC_BIT},
{412, "orcx", OpType::Integer, 1, FL_OUT_A | FL_IN_SB | FL_RC_BIT},
{476, "nandx", OpType::Integer, 1, FL_OUT_A | FL_IN_SB | FL_RC_BIT},
{284, "eqvx", OpType::Integer, 1, FL_OUT_A | FL_IN_SB | FL_RC_BIT},
{0, "cmp", OpType::Integer, 1, FL_IN_AB | FL_SET_CRn},
{32, "cmpl", OpType::Integer, 1, FL_IN_AB | FL_SET_CRn},
{26, "cntlzwx", OpType::Integer, 1, FL_OUT_A | FL_IN_S | FL_RC_BIT},
{922, "extshx", OpType::Integer, 1, FL_OUT_A | FL_IN_S | FL_RC_BIT},
{954, "extsbx", OpType::Integer, 1, FL_OUT_A | FL_IN_S | FL_RC_BIT},
{536, "srwx", OpType::Integer, 1, FL_OUT_A | FL_IN_SB | FL_RC_BIT},
{792, "srawx", OpType::Integer, 1, FL_OUT_A | FL_IN_SB | FL_SET_CA | FL_RC_BIT},
{824, "srawix", OpType::Integer, 1, FL_OUT_A | FL_IN_S | FL_SET_CA | FL_RC_BIT},
{24, "slwx", OpType::Integer, 1, FL_OUT_A | FL_IN_SB | FL_RC_BIT},
{54, "dcbst", OpType::DataCache, 5, FL_IN_A0B | FL_LOADSTORE},
{86, "dcbf", OpType::DataCache, 5, FL_IN_A0B | FL_LOADSTORE},
{246, "dcbtst", OpType::DataCache, 2, 0},
{278, "dcbt", OpType::DataCache, 2, 0},
{470, "dcbi", OpType::DataCache, 5, FL_IN_A0B | FL_LOADSTORE | FL_PROGRAMEXCEPTION},
{758, "dcba", OpType::DataCache, 5, 0},
{1014, "dcbz", OpType::DataCache, 5, FL_IN_A0B | FL_LOADSTORE},
// load word
{23, "lwzx", OpType::Load, 1, FL_OUT_D | FL_IN_A0B | FL_LOADSTORE},
{55, "lwzux", OpType::Load, 1, FL_OUT_D | FL_OUT_A | FL_IN_AB | FL_LOADSTORE},
// load halfword
{279, "lhzx", OpType::Load, 1, FL_OUT_D | FL_IN_A0B | FL_LOADSTORE},
{311, "lhzux", OpType::Load, 1, FL_OUT_D | FL_OUT_A | FL_IN_AB | FL_LOADSTORE},
// load halfword signextend
{343, "lhax", OpType::Load, 1, FL_OUT_D | FL_IN_A0B | FL_LOADSTORE},
{375, "lhaux", OpType::Load, 1, FL_OUT_D | FL_OUT_A | FL_IN_AB | FL_LOADSTORE},
// load byte
{87, "lbzx", OpType::Load, 1, FL_OUT_D | FL_IN_A0B | FL_LOADSTORE},
{119, "lbzux", OpType::Load, 1, FL_OUT_D | FL_OUT_A | FL_IN_AB | FL_LOADSTORE},
// load byte reverse
{534, "lwbrx", OpType::Load, 1, FL_OUT_D | FL_IN_A0B | FL_LOADSTORE},
{790, "lhbrx", OpType::Load, 1, FL_OUT_D | FL_IN_A0B | FL_LOADSTORE},
// Conditional load/store (Wii SMP)
{150, "stwcxd", OpType::Store, 1, FL_IN_S | FL_IN_A0B | FL_SET_CR0 | FL_LOADSTORE},
{20, "lwarx", OpType::Load, 1, FL_OUT_D | FL_IN_A0B | FL_SET_CR0 | FL_LOADSTORE},
// load string (Inst these)
{533, "lswx", OpType::Load, 1, FL_IN_A0B | FL_OUT_D | FL_LOADSTORE},
{597, "lswi", OpType::Load, 1, FL_IN_A0 | FL_OUT_D | FL_LOADSTORE},
// store word
{151, "stwx", OpType::Store, 1, FL_IN_S | FL_IN_A0B | FL_LOADSTORE},
{183, "stwux", OpType::Store, 1, FL_IN_S | FL_OUT_A | FL_IN_AB | FL_LOADSTORE},
// store halfword
{407, "sthx", OpType::Store, 1, FL_IN_S | FL_IN_A0B | FL_LOADSTORE},
{439, "sthux", OpType::Store, 1, FL_IN_S | FL_OUT_A | FL_IN_AB | FL_LOADSTORE},
// store byte
{215, "stbx", OpType::Store, 1, FL_IN_S | FL_IN_A0B | FL_LOADSTORE},
{247, "stbux", OpType::Store, 1, FL_IN_S | FL_OUT_A | FL_IN_AB | FL_LOADSTORE},
// store bytereverse
{662, "stwbrx", OpType::Store, 1, FL_IN_S | FL_IN_A0B | FL_LOADSTORE},
{918, "sthbrx", OpType::Store, 1, FL_IN_S | FL_IN_A0B | FL_LOADSTORE},
{661, "stswx", OpType::Store, 1, FL_IN_A0B | FL_LOADSTORE},
{725, "stswi", OpType::Store, 1, FL_IN_A0 | FL_LOADSTORE},
// fp load/store
{535, "lfsx", OpType::LoadFP, 1, FL_OUT_FLOAT_D | FL_IN_A0B | FL_USE_FPU | FL_LOADSTORE},
{567, "lfsux", OpType::LoadFP, 1,
FL_OUT_FLOAT_D | FL_IN_AB | FL_OUT_A | FL_USE_FPU | FL_LOADSTORE},
{599, "lfdx", OpType::LoadFP, 1, FL_INOUT_FLOAT_D | FL_IN_A0B | FL_USE_FPU | FL_LOADSTORE},
{631, "lfdux", OpType::LoadFP, 1,
FL_INOUT_FLOAT_D | FL_IN_AB | FL_OUT_A | FL_USE_FPU | FL_LOADSTORE},
{663, "stfsx", OpType::StoreFP, 1, FL_IN_FLOAT_S | FL_IN_A0B | FL_USE_FPU | FL_LOADSTORE},
{695, "stfsux", OpType::StoreFP, 1,
FL_IN_FLOAT_S | FL_IN_AB | FL_OUT_A | FL_USE_FPU | FL_LOADSTORE},
{727, "stfdx", OpType::StoreFP, 1, FL_IN_FLOAT_S | FL_IN_A0B | FL_USE_FPU | FL_LOADSTORE},
{759, "stfdux", OpType::StoreFP, 1,
FL_IN_FLOAT_S | FL_IN_AB | FL_OUT_A | FL_USE_FPU | FL_LOADSTORE},
{983, "stfiwx", OpType::StoreFP, 1, FL_IN_FLOAT_S | FL_IN_A0B | FL_USE_FPU | FL_LOADSTORE},
{19, "mfcr", OpType::System, 1, FL_OUT_D | FL_READ_ALL_CR},
{83, "mfmsr", OpType::System, 1, FL_OUT_D | FL_PROGRAMEXCEPTION},
{144, "mtcrf", OpType::System, 1, FL_IN_S | FL_SET_ALL_CR | FL_READ_ALL_CR},
{146, "mtmsr", OpType::System, 1,
FL_IN_S | FL_ENDBLOCK | FL_PROGRAMEXCEPTION | FL_FLOAT_EXCEPTION},
{210, "mtsr", OpType::System, 1, FL_IN_S | FL_PROGRAMEXCEPTION},
{242, "mtsrin", OpType::System, 1, FL_IN_SB | FL_PROGRAMEXCEPTION},
{339, "mfspr", OpType::SPR, 1, FL_OUT_D | FL_PROGRAMEXCEPTION},
{467, "mtspr", OpType::SPR, 2, FL_IN_S | FL_ENDBLOCK | FL_PROGRAMEXCEPTION},
{371, "mftb", OpType::System, 1, FL_OUT_D | FL_TIMER | FL_PROGRAMEXCEPTION},
{512, "mcrxr", OpType::System, 1, FL_SET_CRn | FL_READ_CA | FL_SET_CA},
{595, "mfsr", OpType::System, 3, FL_OUT_D | FL_PROGRAMEXCEPTION},
{659, "mfsrin", OpType::System, 3, FL_OUT_D | FL_IN_B | FL_PROGRAMEXCEPTION},
{4, "tw", OpType::System, 2, FL_IN_AB | FL_ENDBLOCK},
{598, "sync", OpType::System, 3, 0},
{982, "icbi", OpType::System, 4, FL_IN_A0B | FL_ENDBLOCK | FL_LOADSTORE},
// Unused instructions on GC
{310, "eciwx", OpType::System, 1, FL_IN_A0B | FL_OUT_D | FL_LOADSTORE},
{438, "ecowx", OpType::System, 1, FL_IN_A0B | FL_IN_S | FL_LOADSTORE},
{854, "eieio", OpType::System, 1, 0},
{306, "tlbie", OpType::System, 1, FL_IN_B | FL_PROGRAMEXCEPTION},
{566, "tlbsync", OpType::System, 1, FL_PROGRAMEXCEPTION},
}};
constexpr std::array<GekkoOPTemplate, 9> s_table59{{
{18, "fdivsx", OpType::SingleFP, 17,
FL_OUT_FLOAT_D | FL_IN_FLOAT_AB | FL_RC_BIT_F | FL_USE_FPU | FL_SET_FPRF | FL_FLOAT_EXCEPTION |
FL_FLOAT_DIV}, // TODO
{20, "fsubsx", OpType::SingleFP, 1,
FL_OUT_FLOAT_D | FL_IN_FLOAT_AB | FL_RC_BIT_F | FL_USE_FPU | FL_SET_FPRF | FL_FLOAT_EXCEPTION},
{21, "faddsx", OpType::SingleFP, 1,
FL_OUT_FLOAT_D | FL_IN_FLOAT_AB | FL_RC_BIT_F | FL_USE_FPU | FL_SET_FPRF | FL_FLOAT_EXCEPTION},
{24, "fresx", OpType::SingleFP, 1,
FL_OUT_FLOAT_D | FL_IN_FLOAT_B | FL_RC_BIT_F | FL_USE_FPU | FL_SET_FPRF | FL_FLOAT_EXCEPTION |
FL_FLOAT_DIV},
{25, "fmulsx", OpType::SingleFP, 1,
FL_OUT_FLOAT_D | FL_IN_FLOAT_AC | FL_RC_BIT_F | FL_USE_FPU | FL_SET_FPRF | FL_FLOAT_EXCEPTION},
{28, "fmsubsx", OpType::SingleFP, 1,
FL_OUT_FLOAT_D | FL_IN_FLOAT_ABC | FL_RC_BIT_F | FL_USE_FPU | FL_SET_FPRF |
FL_FLOAT_EXCEPTION},
{29, "fmaddsx", OpType::SingleFP, 1,
FL_OUT_FLOAT_D | FL_IN_FLOAT_ABC | FL_RC_BIT_F | FL_USE_FPU | FL_SET_FPRF |
FL_FLOAT_EXCEPTION},
{30, "fnmsubsx", OpType::SingleFP, 1,
FL_OUT_FLOAT_D | FL_IN_FLOAT_ABC | FL_RC_BIT_F | FL_USE_FPU | FL_SET_FPRF |
FL_FLOAT_EXCEPTION},
{31, "fnmaddsx", OpType::SingleFP, 1,
FL_OUT_FLOAT_D | FL_IN_FLOAT_ABC | FL_RC_BIT_F | FL_USE_FPU | FL_SET_FPRF |
FL_FLOAT_EXCEPTION},
}};
constexpr std::array<GekkoOPTemplate, 15> s_table63{{
{264, "fabsx", OpType::DoubleFP, 1,
FL_INOUT_FLOAT_D | FL_IN_FLOAT_B | FL_IN_FLOAT_B_BITEXACT | FL_RC_BIT_F | FL_USE_FPU},
// FIXME: fcmp modifies the FPRF flags, but if the flags are clobbered later,
// we don't actually need to calculate or store them here. So FL_READ_FPRF and FL_SET_FPRF is
// not an ideal representation of fcmp's effect on FPRF flags and might result in slightly
// sub-optimal code.
{32, "fcmpo", OpType::DoubleFP, 1,
FL_IN_FLOAT_AB | FL_SET_CRn | FL_USE_FPU | FL_READ_FPRF | FL_SET_FPRF | FL_FLOAT_EXCEPTION},
{0, "fcmpu", OpType::DoubleFP, 1,
FL_IN_FLOAT_AB | FL_SET_CRn | FL_USE_FPU | FL_READ_FPRF | FL_SET_FPRF | FL_FLOAT_EXCEPTION},
{14, "fctiwx", OpType::DoubleFP, 1,
FL_INOUT_FLOAT_D | FL_IN_FLOAT_B | FL_RC_BIT_F | FL_USE_FPU | FL_FLOAT_EXCEPTION},
{15, "fctiwzx", OpType::DoubleFP, 1,
FL_INOUT_FLOAT_D | FL_IN_FLOAT_B | FL_RC_BIT_F | FL_USE_FPU | FL_FLOAT_EXCEPTION},
{72, "fmrx", OpType::DoubleFP, 1,
FL_INOUT_FLOAT_D | FL_IN_FLOAT_B | FL_IN_FLOAT_B_BITEXACT | FL_RC_BIT_F | FL_USE_FPU},
{136, "fnabsx", OpType::DoubleFP, 1,
FL_INOUT_FLOAT_D | FL_IN_FLOAT_B | FL_RC_BIT_F | FL_IN_FLOAT_B_BITEXACT | FL_USE_FPU},
{40, "fnegx", OpType::DoubleFP, 1,
FL_INOUT_FLOAT_D | FL_IN_FLOAT_B | FL_RC_BIT_F | FL_IN_FLOAT_B_BITEXACT | FL_USE_FPU},
{12, "frspx", OpType::DoubleFP, 1,
FL_OUT_FLOAT_D | FL_IN_FLOAT_B | FL_RC_BIT_F | FL_USE_FPU | FL_SET_FPRF | FL_FLOAT_EXCEPTION},
{64, "mcrfs", OpType::SystemFP, 1, FL_SET_CRn | FL_USE_FPU | FL_READ_FPRF},
{583, "mffsx", OpType::SystemFP, 1, FL_RC_BIT_F | FL_INOUT_FLOAT_D | FL_USE_FPU | FL_READ_FPRF},
{70, "mtfsb0x", OpType::SystemFP, 3, FL_RC_BIT_F | FL_USE_FPU | FL_READ_FPRF | FL_SET_FPRF},
{38, "mtfsb1x", OpType::SystemFP, 3,
FL_RC_BIT_F | FL_USE_FPU | FL_READ_FPRF | FL_SET_FPRF | FL_FLOAT_EXCEPTION},
{134, "mtfsfix", OpType::SystemFP, 3,
FL_RC_BIT_F | FL_USE_FPU | FL_READ_FPRF | FL_SET_FPRF | FL_FLOAT_EXCEPTION},
{711, "mtfsfx", OpType::SystemFP, 3,
FL_RC_BIT_F | FL_IN_FLOAT_B | FL_USE_FPU | FL_READ_FPRF | FL_SET_FPRF | FL_FLOAT_EXCEPTION},
}};
constexpr std::array<GekkoOPTemplate, 10> s_table63_2{{
{18, "fdivx", OpType::DoubleFP, 31,
FL_INOUT_FLOAT_D | FL_IN_FLOAT_AB | FL_RC_BIT_F | FL_USE_FPU | FL_SET_FPRF |
FL_FLOAT_EXCEPTION | FL_FLOAT_DIV},
{20, "fsubx", OpType::DoubleFP, 1,
FL_INOUT_FLOAT_D | FL_IN_FLOAT_AB | FL_RC_BIT_F | FL_USE_FPU | FL_SET_FPRF |
FL_FLOAT_EXCEPTION},
{21, "faddx", OpType::DoubleFP, 1,
FL_INOUT_FLOAT_D | FL_IN_FLOAT_AB | FL_RC_BIT_F | FL_USE_FPU | FL_SET_FPRF |
FL_FLOAT_EXCEPTION},
{23, "fselx", OpType::DoubleFP, 1,
FL_INOUT_FLOAT_D | FL_IN_FLOAT_ABC | FL_IN_FLOAT_BC_BITEXACT | FL_RC_BIT_F | FL_USE_FPU},
{25, "fmulx", OpType::DoubleFP, 1,
FL_INOUT_FLOAT_D | FL_IN_FLOAT_AC | FL_RC_BIT_F | FL_USE_FPU | FL_SET_FPRF |
FL_FLOAT_EXCEPTION},
{26, "frsqrtex", OpType::DoubleFP, 1,
FL_INOUT_FLOAT_D | FL_IN_FLOAT_B | FL_RC_BIT_F | FL_USE_FPU | FL_SET_FPRF |
FL_FLOAT_EXCEPTION | FL_FLOAT_DIV},
{28, "fmsubx", OpType::DoubleFP, 1,
FL_INOUT_FLOAT_D | FL_IN_FLOAT_ABC | FL_RC_BIT_F | FL_USE_FPU | FL_SET_FPRF |
FL_FLOAT_EXCEPTION},
{29, "fmaddx", OpType::DoubleFP, 1,
FL_INOUT_FLOAT_D | FL_IN_FLOAT_ABC | FL_RC_BIT_F | FL_USE_FPU | FL_SET_FPRF |
FL_FLOAT_EXCEPTION},
{30, "fnmsubx", OpType::DoubleFP, 1,
FL_INOUT_FLOAT_D | FL_IN_FLOAT_ABC | FL_RC_BIT_F | FL_USE_FPU | FL_SET_FPRF |
FL_FLOAT_EXCEPTION},
{31, "fnmaddx", OpType::DoubleFP, 1,
FL_INOUT_FLOAT_D | FL_IN_FLOAT_ABC | FL_RC_BIT_F | FL_USE_FPU | FL_SET_FPRF |
FL_FLOAT_EXCEPTION},
}};
constexpr size_t TOTAL_INSTRUCTION_COUNT =
1 + s_primary_table.size() + s_table4_2.size() + s_table4_3.size() + s_table4.size() +
s_table31.size() + s_table19.size() + s_table59.size() + s_table63.size() + s_table63_2.size();
struct Tables
{
std::array<GekkoOPInfo, TOTAL_INSTRUCTION_COUNT> all_instructions{};
u32 unknown_op_info;
std::array<u32, 64> primary_table{};
std::array<u32, 1024> table4{};
std::array<u32, 1024> table19{};
std::array<u32, 1024> table31{};
std::array<u32, 32> table59{};
std::array<u32, 1024> table63{};
};
} // namespace
static std::array<GekkoOPStats, TOTAL_INSTRUCTION_COUNT> s_all_instructions_stats;
constexpr Tables s_tables = []() consteval
{
Tables tables{};
u32 counter = 0;
auto make_info = [&](const GekkoOPTemplate& inst) consteval->u32
{
ASSERT(counter < TOTAL_INSTRUCTION_COUNT);
GekkoOPInfo* info = &tables.all_instructions[counter];
info->opname = inst.opname;
info->flags = inst.flags;
info->type = inst.type;
info->num_cycles = inst.num_cycles;
info->stats = &s_all_instructions_stats[counter];
return counter++;
};
u32 unknown_op_info = make_info(s_unknown_op_info);
tables.unknown_op_info = unknown_op_info;
tables.primary_table.fill(unknown_op_info);
for (auto& tpl : s_primary_table)
{
ASSERT(tables.primary_table[tpl.opcode] == unknown_op_info);
tables.primary_table[tpl.opcode] = make_info(tpl);
};
tables.table4.fill(unknown_op_info);
for (const auto& tpl : s_table4_2)
{
u32 info = make_info(tpl);
for (u32 i = 0; i < 32; i++)
{
const u32 fill = i << 5;
const u32 op = fill + tpl.opcode;
ASSERT(tables.table4[op] == unknown_op_info);
tables.table4[op] = info;
}
}
for (const auto& tpl : s_table4_3)
{
u32 info = make_info(tpl);
for (u32 i = 0; i < 16; i++)
{
const u32 fill = i << 6;
const u32 op = fill + tpl.opcode;
ASSERT(tables.table4[op] == unknown_op_info);
tables.table4[op] = info;
}
}
for (const auto& tpl : s_table4)
{
const u32 op = tpl.opcode;
ASSERT(tables.table4[op] == unknown_op_info);
tables.table4[op] = make_info(tpl);
}
tables.table19.fill(unknown_op_info);
for (auto& tpl : s_table19)
{
ASSERT(tables.table19[tpl.opcode] == unknown_op_info);
tables.table19[tpl.opcode] = make_info(tpl);
};
tables.table31.fill(unknown_op_info);
for (auto& tpl : s_table31)
{
ASSERT(tables.table31[tpl.opcode] == unknown_op_info);
tables.table31[tpl.opcode] = make_info(tpl);
};
tables.table59.fill(unknown_op_info);
for (auto& tpl : s_table59)
{
ASSERT(tables.table59[tpl.opcode] == unknown_op_info);
tables.table59[tpl.opcode] = make_info(tpl);
};
tables.table63.fill(unknown_op_info);
for (auto& tpl : s_table63)
{
ASSERT(tables.table63[tpl.opcode] == unknown_op_info);
tables.table63[tpl.opcode] = make_info(tpl);
};
for (const auto& tpl : s_table63_2)
{
u32 info = make_info(tpl);
for (u32 i = 0; i < 32; i++)
{
const u32 fill = i << 5;
const u32 op = fill + tpl.opcode;
ASSERT(tables.table63[op] == unknown_op_info);
tables.table63[op] = info;
}
}
ASSERT(counter == TOTAL_INSTRUCTION_COUNT);
return tables;
}
();
const GekkoOPInfo* GetOpInfo(UGeckoInstruction inst, u32 pc)
{
const GekkoOPInfo* info = &s_tables.all_instructions[s_tables.primary_table[inst.OPCD]];
if (info->type == OpType::Subtable)
{
switch (inst.OPCD)
{
case 4:
return &s_tables.all_instructions[s_tables.table4[inst.SUBOP10]];
case 19:
return &s_tables.all_instructions[s_tables.table19[inst.SUBOP10]];
case 31:
return &s_tables.all_instructions[s_tables.table31[inst.SUBOP10]];
case 59:
return &s_tables.all_instructions[s_tables.table59[inst.SUBOP5]];
case 63:
return &s_tables.all_instructions[s_tables.table63[inst.SUBOP10]];
default:
ASSERT_MSG(POWERPC, 0, "GetOpInfo - invalid subtable op {:08x} @ {:08x}", inst.hex, pc);
return &s_tables.all_instructions[s_tables.unknown_op_info];
}
}
else
{
if (info->type == OpType::Invalid)
{
ASSERT_MSG(POWERPC, 0, "GetOpInfo - invalid op {:08x} @ {:08x}", inst.hex, pc);
return &s_tables.all_instructions[s_tables.unknown_op_info];
}
return info;
}
}
// #define OPLOG
// #define OP_TO_LOG "mtfsb0x"
#ifdef OPLOG
namespace
{
std::vector<u32> rsplocations;
}
#endif
const char* GetInstructionName(UGeckoInstruction inst, u32 pc)
{
const GekkoOPInfo* info = GetOpInfo(inst, pc);
return info->opname;
}
bool IsValidInstruction(UGeckoInstruction inst, u32 pc)
{
const GekkoOPInfo* info = GetOpInfo(inst, pc);
return info->type != OpType::Invalid && info->type != OpType::Unknown;
}
void CountInstruction(UGeckoInstruction inst, u32 pc)
{
const GekkoOPInfo* info = GetOpInfo(inst, pc);
info->stats->run_count++;
}
void CountInstructionCompile(const GekkoOPInfo* info, u32 pc)
{
info->stats->compile_count++;
info->stats->last_use = pc;
#ifdef OPLOG
if (!strcmp(info->opname, OP_TO_LOG))
{
rsplocations.push_back(pc);
}
#endif
}
void PrintInstructionRunCounts()
{
typedef std::pair<const char*, u64> OpInfo;
std::array<OpInfo, TOTAL_INSTRUCTION_COUNT> temp;
for (size_t i = 0; i < TOTAL_INSTRUCTION_COUNT; i++)
{
const GekkoOPInfo& info = s_tables.all_instructions[i];
temp[i] = std::make_pair(info.opname, info.stats->run_count);
}
std::sort(temp.begin(), temp.end(),
[](const OpInfo& a, const OpInfo& b) { return a.second > b.second; });
for (auto& inst : temp)
{
if (inst.second == 0)
break;
INFO_LOG_FMT(POWERPC, "{} : {}", inst.first, inst.second);
}
}
void LogCompiledInstructions()
{
static unsigned int time = 0;
File::IOFile f(fmt::format("{}inst_log{}.txt", File::GetUserPath(D_LOGS_IDX), time), "w");
for (size_t i = 0; i < TOTAL_INSTRUCTION_COUNT; i++)
{
const GekkoOPInfo& info = s_tables.all_instructions[i];
if (info.stats->compile_count > 0)
{
f.WriteString(fmt::format("{0}\t{1}\t{2}\t{3:08x}\n", info.opname, info.stats->compile_count,
info.stats->run_count, info.stats->last_use));
}
}
f.Open(fmt::format("{}inst_not{}.txt", File::GetUserPath(D_LOGS_IDX), time), "w");
for (size_t i = 0; i < TOTAL_INSTRUCTION_COUNT; i++)
{
const GekkoOPInfo& info = s_tables.all_instructions[i];
if (info.stats->compile_count == 0)
{
f.WriteString(fmt::format("{0}\t{1}\t{2}\n", info.opname, info.stats->compile_count,
info.stats->run_count));
}
}
#ifdef OPLOG
f.Open(fmt::format("{}" OP_TO_LOG "_at{}.txt", File::GetUserPath(D_LOGS_IDX), time), "w");
for (auto& rsplocation : rsplocations)
{
f.WriteString(fmt::format(OP_TO_LOG ": {0:08x}\n", rsplocation));
}
#endif
++time;
}
} // namespace PPCTables