diff --git a/src/dynarmic/src/dynarmic/backend/arm64/verbose_debugging_output.h b/src/dynarmic/src/dynarmic/backend/arm64/verbose_debugging_output.h index 84beda4057..b5187f6375 100644 --- a/src/dynarmic/src/dynarmic/backend/arm64/verbose_debugging_output.h +++ b/src/dynarmic/src/dynarmic/backend/arm64/verbose_debugging_output.h @@ -20,7 +20,7 @@ struct Label; } // namespace oaknut namespace Dynarmic::IR { -enum class Type; +enum class Type : u16; } // namespace Dynarmic::IR namespace Dynarmic::Backend::Arm64 { diff --git a/src/dynarmic/src/dynarmic/ir/microinstruction.h b/src/dynarmic/src/dynarmic/ir/microinstruction.h index bc5a355793..6651aab7c5 100644 --- a/src/dynarmic/src/dynarmic/ir/microinstruction.h +++ b/src/dynarmic/src/dynarmic/ir/microinstruction.h @@ -19,7 +19,7 @@ namespace Dynarmic::IR { enum class Opcode; -enum class Type; +enum class Type : u16; constexpr size_t max_arg_count = 4; diff --git a/src/dynarmic/src/dynarmic/ir/opcodes.cpp b/src/dynarmic/src/dynarmic/ir/opcodes.cpp index e7e73b7032..3d803674ea 100644 --- a/src/dynarmic/src/dynarmic/ir/opcodes.cpp +++ b/src/dynarmic/src/dynarmic/ir/opcodes.cpp @@ -16,12 +16,6 @@ namespace Dynarmic::IR { namespace OpcodeInfo { -struct Meta { - std::vector arg_types; - const char* name; - Type type; -}; - constexpr Type Void = Type::Void; constexpr Type A32Reg = Type::A32Reg; constexpr Type A32ExtReg = Type::A32ExtReg; @@ -40,10 +34,36 @@ constexpr Type Cond = Type::Cond; constexpr Type Table = Type::Table; constexpr Type AccType = Type::AccType; -alignas(64) static const std::array opcode_info{ -#define OPCODE(name, type, ...) Meta{{__VA_ARGS__}, #name, type}, -#define A32OPC(name, type, ...) Meta{{__VA_ARGS__}, #name, type}, -#define A64OPC(name, type, ...) Meta{{__VA_ARGS__}, #name, type}, +struct Meta { + std::array arg_types; + Type type; + uint8_t count; +}; + +// Evil macro magic for Intel C++ compiler +#define PP_ARG_N( \ + _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, \ + _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, \ + _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, \ + _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, \ + _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, \ + _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, \ + _61, _62, _63, N, ...) N +#define PP_RSEQ_N() \ + 63, 62, 61, 60, \ + 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, \ + 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, \ + 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, \ + 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, \ + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, \ + 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 +#define PP_NARG_(...) PP_ARG_N(__VA_ARGS__) +#define PP_NARG(...) (sizeof(#__VA_ARGS__) - 1 ? PP_NARG_(__VA_ARGS__, PP_RSEQ_N()) : 0) + +alignas(64) static const Meta opcode_info[] = { +#define OPCODE(name, type, ...) Meta{{__VA_ARGS__}, type, PP_NARG(__VA_ARGS__)}, +#define A32OPC(name, type, ...) Meta{{__VA_ARGS__}, type, PP_NARG(__VA_ARGS__)}, +#define A64OPC(name, type, ...) Meta{{__VA_ARGS__}, type, PP_NARG(__VA_ARGS__)}, #include "./opcodes.inc" #undef OPCODE #undef A32OPC @@ -54,22 +74,31 @@ alignas(64) static const std::array opcode_info{ /// @brief Get return type of an opcode Type GetTypeOf(Opcode op) noexcept { - return OpcodeInfo::opcode_info.at(size_t(op)).type; + return OpcodeInfo::opcode_info[size_t(op)].type; } /// @brief Get the number of arguments an opcode accepts size_t GetNumArgsOf(Opcode op) noexcept { - return OpcodeInfo::opcode_info.at(size_t(op)).arg_types.size(); + return OpcodeInfo::opcode_info[size_t(op)].count; } /// @brief Get the required type of an argument of an opcode Type GetArgTypeOf(Opcode op, size_t arg_index) noexcept { - return OpcodeInfo::opcode_info.at(size_t(op)).arg_types.at(arg_index); + return OpcodeInfo::opcode_info[size_t(op)].arg_types[arg_index]; } /// @brief Get the name of an opcode. -std::string GetNameOf(Opcode op) noexcept { - return OpcodeInfo::opcode_info.at(size_t(op)).name; +std::string_view GetNameOf(Opcode op) noexcept { + static const std::string_view opcode_names[] = { +#define OPCODE(name, type, ...) #name, +#define A32OPC(name, type, ...) #name, +#define A64OPC(name, type, ...) #name, +#include "./opcodes.inc" +#undef OPCODE +#undef A32OPC +#undef A64OPC + }; + return opcode_names[size_t(op)]; } } // namespace Dynarmic::IR diff --git a/src/dynarmic/src/dynarmic/ir/opcodes.h b/src/dynarmic/src/dynarmic/ir/opcodes.h index c11ad549da..a231365fa7 100644 --- a/src/dynarmic/src/dynarmic/ir/opcodes.h +++ b/src/dynarmic/src/dynarmic/ir/opcodes.h @@ -15,7 +15,7 @@ namespace Dynarmic::IR { -enum class Type; +enum class Type : u16; /// @brief The Opcodes of our intermediate representation. /// Type signatures for each opcode can be found in opcodes.inc @@ -35,7 +35,7 @@ constexpr size_t OpcodeCount = static_cast(Opcode::NUM_OPCODE); Type GetTypeOf(Opcode op) noexcept; size_t GetNumArgsOf(Opcode op) noexcept; Type GetArgTypeOf(Opcode op, size_t arg_index) noexcept; -std::string GetNameOf(Opcode op) noexcept; +std::string_view GetNameOf(Opcode op) noexcept; /// @brief Determines whether or not this instruction performs an arithmetic shift. constexpr bool IsArithmeticShift(const Opcode op) noexcept { diff --git a/src/dynarmic/src/dynarmic/ir/type.h b/src/dynarmic/src/dynarmic/ir/type.h index 0aaf9d9414..e223513367 100644 --- a/src/dynarmic/src/dynarmic/ir/type.h +++ b/src/dynarmic/src/dynarmic/ir/type.h @@ -18,7 +18,7 @@ namespace Dynarmic::IR { /** * The intermediate representation is typed. These are the used by our IR. */ -enum class Type { +enum class Type : u16 { Void = 0, A32Reg = 1 << 0, A32ExtReg = 1 << 1,