bsnes/nall/intrinsics.hpp
Tim Allen 83f684c66c Update to v094r29 release.
byuu says:

Note: for Windows users, please go to nall/intrinsics.hpp line 60 and
correct the typo from "DISPLAY_WINDOW" to "DISPLAY_WINDOWS" before
compiling, otherwise things won't work at all.

This will be a really major WIP for the core SNES emulation, so please
test as thoroughly as possible.

I rewrote the 65816 CPU core's dispatcher from a jump table to a switch
table. This was so that I could pass class variables as parameters to
opcodes without crazy theatrics.

With that, I killed the regs.r[N] stuff, the flag_t operator|=, &=, ^=
stuff, and all of the template versions of opcodes.

I also removed some stupid pointless flag tests in xcn and pflag that
would always be true.

I sure hope that AWJ is happy with this; because this change was so that
my flag assignments and branch tests won't need to build regs.P into
a full 8-bit variable anymore.

It does of course incur a slight performance hit when you pass in
variables by-value to functions, but it should help with binary size
(and thus cache) by reducing a lot of extra functions. (I know I could
have used template parameters for some things even with a switch table,
but chose not to for the aforementioned reasons.)

Overall, it's about a ~1% speedup from the previous build. The CPU core
instructions were never a bottleneck, but I did want to fix the P flag
building stuff because that really was a dumb mistake v_v'
2015-06-22 23:31:49 +10:00

151 lines
5.1 KiB
C++

#ifndef NALL_INTRINSICS_HPP
#define NALL_INTRINSICS_HPP
namespace nall {
struct Intrinsics {
enum class Compiler : unsigned { Clang, GCC, VisualCPP, Unknown };
enum class Platform : unsigned { Windows, MacOSX, Linux, BSD, Unknown };
enum class API : unsigned { Windows, Posix, Unknown };
enum class Display : unsigned { Windows, Quartz, Xorg, Unknown };
enum class Processor : unsigned { x86, amd64, ARM, PPC32, PPC64, Unknown };
enum class Endian : unsigned { LSB, MSB, Unknown };
static inline auto compiler() -> Compiler;
static inline auto platform() -> Platform;
static inline auto api() -> API;
static inline auto display() -> Display;
static inline auto processor() -> Processor;
static inline auto endian() -> Endian;
};
}
/* Compiler detection */
namespace nall {
#if defined(__clang__)
#define COMPILER_CLANG
auto Intrinsics::compiler() -> Compiler { return Compiler::Clang; }
#pragma clang diagnostic ignored "-Wunknown-pragmas"
#pragma clang diagnostic ignored "-Wempty-body"
#pragma clang diagnostic ignored "-Wparentheses"
#pragma clang diagnostic ignored "-Wreturn-type"
#pragma clang diagnostic ignored "-Wswitch"
#pragma clang diagnostic ignored "-Wswitch-bool"
#pragma clang diagnostic ignored "-Wtautological-compare"
#elif defined(__GNUC__)
#define COMPILER_GCC
auto Intrinsics::compiler() -> Compiler { return Compiler::GCC; }
#elif defined(_MSC_VER)
#define COMPILER_VISUALCPP
auto Intrinsics::compiler() -> Compiler { return Compiler::VisualCPP; }
#pragma warning(disable:4996) //disable libc "deprecation" warnings
#else
#warning "unable to detect compiler"
#define COMPILER_UNKNOWN
auto Intrinsics::compiler() -> Compiler { return Compiler::Unknown; }
#endif
}
/* Platform detection */
namespace nall {
#if defined(_WIN32)
#define PLATFORM_WINDOWS
#define API_WINDOWS
#define DISPLAY_WINDOW
auto Intrinsics::platform() -> Platform { return Platform::Windows; }
auto Intrinsics::api() -> API { return API::Windows; }
auto Intrinsics::display() -> Display { return Display::Windows; }
#elif defined(__APPLE__)
#define PLATFORM_MACOSX
#define API_POSIX
#define DISPLAY_QUARTZ
auto Intrinsics::platform() -> Platform { return Platform::MacOSX; }
auto Intrinsics::api() -> API { return API::Posix; }
auto Intrinsics::display() -> Display { return Display::Quartz; }
#elif defined(linux) || defined(__linux__)
#define PLATFORM_LINUX
#define API_POSIX
#define DISPLAY_XORG
auto Intrinsics::platform() -> Platform { return Platform::Linux; }
auto Intrinsics::api() -> API { return API::Posix; }
auto Intrinsics::display() -> Display { return Display::Xorg; }
#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__NetBSD__) || defined(__OpenBSD__)
#define PLATFORM_BSD
#define API_POSIX
#define DISPLAY_XORG
auto Intrinsics::platform() -> Platform { return Platform::BSD; }
auto Intrinsics::api() -> API { return API::Posix; }
auto Intrinsics::display() -> Display { return Display::Xorg; }
#else
#warning "unable to detect platform"
#define PLATFORM_UNKNOWN
#define API_UNKNOWN
#define DISPLAY_UNKNOWN
auto Intrinsics::platform() -> Platform { return Platform::Unknown; }
auto Intrinsics::api() -> API { return API::Unknown; }
auto Intrinsics::display() -> Display { return Display::Unknown; }
#endif
}
#if defined(PLATFORM_MACOSX)
#include <machine/endian.h>
#elif defined(PLATFORM_LINUX)
#include <endian.h>
#elif defined(PLATFORM_BSD)
#include <sys/endian.h>
#endif
/* Processor Detection */
namespace nall {
#if defined(__i386__) || defined(_M_IX86)
#define PROCESSOR_X86
auto Intrinsics::processor() -> Processor { return Processor::x86; }
#elif defined(__amd64__) || defined(_M_AMD64)
#define PROCESSOR_AMD64
auto Intrinsics::processor() -> Processor { return Processor::amd64; }
#elif defined(__arm__)
#define PROCESSOR_ARM
auto Intrinsics::processor() -> Processor { return Processor::ARM; }
#elif defined(__ppc64__) || defined(_ARCH_PPC64)
#define PROCESSOR_PPC64
auto Intrinsics::processor() -> Processor { return Processor::PPC64; }
#elif defined(__ppc__) || defined(_ARCH_PPC) || defined(_M_PPC)
#define PROCESSOR_PPC32
auto Intrinsics::processor() -> Processor { return Processor::PPC32; }
#else
#warning "unable to detect processor"
#define PROCESSOR_UNKNOWN
auto Intrinsics::processor() -> Processor { return Processor::Unknown; }
#endif
}
/* Endian detection */
namespace nall {
#if (defined(__BYTE_ORDER) && defined(__LITTLE_ENDIAN) && __BYTE_ORDER == __LITTLE_ENDIAN) || defined(__LITTLE_ENDIAN__) || defined(__i386__) || defined(__amd64__) || defined(_M_IX86) || defined(_M_AMD64)
#define ENDIAN_LSB
auto Intrinsics::endian() -> Endian { return Endian::LSB; }
#elif (defined(__BYTE_ORDER) && defined(__BIG_ENDIAN) && __BYTE_ORDER == __BIG_ENDIAN) || defined(__BIG_ENDIAN__) || defined(__powerpc__) || defined(_M_PPC)
#define ENDIAN_MSB
auto Intrinsics::endian() -> Endian { return Endian::MSB; }
#else
#warning "unable to detect endian"
#define ENDIAN_UNKNOWN
auto Intrinsics::endian() -> Endian { return Endian::Unknown; }
#endif
}
#endif