Tidy EightBit library header usage (avoids compilation error with latest VS2019, "Memory.h")

Signed-off-by: Adrian Conlon <adrian.conlon@gmail.com>
This commit is contained in:
Adrian Conlon 2021-05-29 10:31:32 +01:00
parent b1ca06447f
commit d199adb027
18 changed files with 45 additions and 58 deletions

View File

@ -1,14 +1,15 @@
#pragma once #pragma once
#include <cassert>
#ifdef _MSC_VER #ifdef _MSC_VER
# include <intrin.h> # include <intrin.h>
#endif #endif
#ifdef __GNUG__ #ifdef __GNUG__
# include <x86intrin.h> # include <x86intrin.h>
#else #endif
#if !(defined(_MSC_VER) || defined(__GNUG__))
# include <cassert>
# include <bitset> # include <bitset>
#endif #endif
@ -16,12 +17,13 @@ namespace EightBit {
[[nodiscard]] int countBits(uint8_t value) noexcept; [[nodiscard]] int countBits(uint8_t value) noexcept;
[[nodiscard]] bool oddParity(uint8_t value) noexcept; [[nodiscard]] bool oddParity(uint8_t value) noexcept;
[[nodiscard]] int findFirstSet(unsigned long value) noexcept; [[nodiscard]] int findFirstSet(unsigned long value) noexcept;
constexpr void assume(int expression);
} }
inline int EightBit::countBits(uint8_t value) noexcept { inline int EightBit::countBits(uint8_t value) noexcept {
#ifdef _MSC_VER #if defined(_MSC_VER)
return __popcnt(value); return __popcnt(value);
#elif defined(__GNUG__)
return __builtin_popcount(value);
#else #else
/* /*
Published in 1988, the C Programming Language 2nd Ed. Published in 1988, the C Programming Language 2nd Ed.
@ -40,12 +42,16 @@ inline int EightBit::countBits(uint8_t value) noexcept {
} }
inline bool EightBit::oddParity(const uint8_t value) noexcept { inline bool EightBit::oddParity(const uint8_t value) noexcept {
#ifdef __GNUG__
return __builtin_parity(value)
#else
return countBits(value) % 2; return countBits(value) % 2;
#endif
} }
inline int EightBit::findFirstSet(const unsigned long value) noexcept { inline int EightBit::findFirstSet(const unsigned long value) noexcept {
#ifdef _MSC_VER #if defined(_MSC_VER)
unsigned long index; unsigned long index = 0;
if (_BitScanForward(&index, value)) if (_BitScanForward(&index, value))
return index + 1; return index + 1;
return 0; return 0;
@ -60,44 +66,33 @@ inline int EightBit::findFirstSet(const unsigned long value) noexcept {
#endif #endif
} }
inline constexpr void EightBit::assume(const int expression) { #define PARITY(x) EightBit::oddParity(x)
#ifdef _MSC_VER
__assume(expression);
#elif defined(__GNUG__)
if (!expression)
__builtin_unreachable();
#else
assert(expression);
#endif
}
#define ASSUME(x) EightBit::assume(x)
#ifdef _MSC_VER #ifdef _MSC_VER
# define ASSUME(x) __assume(x);
# define LIKELY(x) (x) # define LIKELY(x) (x)
# define UNLIKELY(x) (x) # define UNLIKELY(x) (x)
# define PARITY(x) EightBit::oddParity(x)
# define UNREACHABLE { ASSUME(0); throw std::exception("unreachable"); } # define UNREACHABLE { ASSUME(0); throw std::exception("unreachable"); }
#elif defined(__GNUG__) #elif defined(__GNUG__)
# define ASSUME(x) { if (!x) __builtin_unreachable(); }
# define LIKELY(x) __builtin_expect(!!(x), 1) # define LIKELY(x) __builtin_expect(!!(x), 1)
# define UNLIKELY(x) __builtin_expect(!!(x), 0) # define UNLIKELY(x) __builtin_expect(!!(x), 0)
# define PARITY(x) __builtin_parity(x)
# define UNREACHABLE __builtin_unreachable(); # define UNREACHABLE __builtin_unreachable();
#else #else
# define ASSUME(x) assert(x);
# define LIKELY(x) (x) # define LIKELY(x) (x)
# define UNLIKELY(x) (x) # define UNLIKELY(x) (x)
# define PARITY(x) EightBit::oddParity(x)
# define UNREACHABLE ASSUME(0) # define UNREACHABLE ASSUME(0)
#endif #endif

View File

@ -11,9 +11,15 @@
namespace EightBit { namespace EightBit {
class Processor : public ClockedChip { class Processor : public ClockedChip {
public: public:
// http://graphics.stanford.edu/~seander/bithacks.html#FixedSignExtend
// b: number of bits representing the number in x // b: number of bits representing the number in x
// x: sign extend this b-bit number to r // x: sign extend this b-bit number to r
[[nodiscard]] static int8_t signExtend(int b, uint8_t x) noexcept; [[nodiscard]] static constexpr int8_t signExtend(int b, uint8_t x) noexcept {
const uint8_t m = bit(b - 1); // mask can be pre-computed if b is fixed
x = x & (bit(b) - 1); // (Skip this if bits in x above position b are already zero.)
const auto result = (x ^ m) - m;
return result;
}
~Processor() = default; ~Processor() = default;

View File

@ -1,5 +1,5 @@
#include "stdafx.h" #include "stdafx.h"
#include "BigEndianProcessor.h" #include "../inc/BigEndianProcessor.h"
EightBit::BigEndianProcessor::BigEndianProcessor(Bus& memory) EightBit::BigEndianProcessor::BigEndianProcessor(Bus& memory)
: Processor(memory) {} : Processor(memory) {}

View File

@ -1,8 +1,8 @@
#include "stdafx.h" #include "stdafx.h"
#include "Bus.h" #include "../inc/Bus.h"
#include "Ram.h" #include "../inc/Ram.h"
#include "IntelHexFile.h" #include "../inc/IntelHexFile.h"
#include "EightBitCompilerDefinitions.h" #include "../inc/EightBitCompilerDefinitions.h"
void EightBit::Bus::raisePOWER() {} void EightBit::Bus::raisePOWER() {}

View File

@ -1,5 +1,5 @@
#include "stdafx.h" #include "stdafx.h"
#include "ClockedChip.h" #include "../inc/ClockedChip.h"
void EightBit::ClockedChip::tick(const int extra) { void EightBit::ClockedChip::tick(const int extra) {
for (int i = 0; i < extra; ++i) for (int i = 0; i < extra; ++i)

View File

@ -1,4 +1,4 @@
#include "stdafx.h" #include "stdafx.h"
#include "Device.h" #include "../inc/Device.h"
DEFINE_PIN_LEVEL_CHANGERS(POWER, Device); DEFINE_PIN_LEVEL_CHANGERS(POWER, Device);

View File

@ -70,19 +70,15 @@
</ImportGroup> </ImportGroup>
<PropertyGroup Label="UserMacros" /> <PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<IncludePath>..\inc;$(VC_IncludePath);$(WindowsSDK_IncludePath)</IncludePath>
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet> <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<IncludePath>..\inc;$(VC_IncludePath);$(WindowsSDK_IncludePath)</IncludePath>
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet> <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<IncludePath>..\inc;$(VC_IncludePath);$(WindowsSDK_IncludePath)</IncludePath>
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet> <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<IncludePath>..\inc;$(VC_IncludePath);$(WindowsSDK_IncludePath)</IncludePath>
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet> <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup> </PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

View File

@ -1,4 +1,4 @@
#include "stdafx.h" #include "stdafx.h"
#include "EventArgs.h" #include "../inc/EventArgs.h"
EightBit::EventArgs EightBit::EventArgs::m_empty; EightBit::EventArgs EightBit::EventArgs::m_empty;

View File

@ -1,9 +1,9 @@
#include "stdafx.h" #include "stdafx.h"
#include "InputOutput.h" #include "../inc/InputOutput.h"
#include <stdexcept> #include <stdexcept>
#include "Register.h" #include "../inc/Register.h"
size_t EightBit::InputOutput::size() const noexcept { size_t EightBit::InputOutput::size() const noexcept {
return 0x100; return 0x100;

View File

@ -1,5 +1,5 @@
#include "stdafx.h" #include "stdafx.h"
#include "IntelHexFile.h" #include "../inc/IntelHexFile.h"
#include <sstream> #include <sstream>

View File

@ -1,5 +1,5 @@
#include "stdafx.h" #include "stdafx.h"
#include "IntelProcessor.h" #include "../inc/IntelProcessor.h"
EightBit::IntelProcessor::IntelProcessor(Bus& bus) EightBit::IntelProcessor::IntelProcessor(Bus& bus)
: LittleEndianProcessor(bus) { : LittleEndianProcessor(bus) {

View File

@ -1,5 +1,5 @@
#include "stdafx.h" #include "stdafx.h"
#include "LittleEndianProcessor.h" #include "../inc/LittleEndianProcessor.h"
EightBit::LittleEndianProcessor::LittleEndianProcessor(Bus& memory) EightBit::LittleEndianProcessor::LittleEndianProcessor(Bus& memory)
: Processor(memory) {} : Processor(memory) {}

View File

@ -1,7 +1,5 @@
LIB = libeightbit.a LIB = libeightbit.a
CXXFLAGS = -I ../inc
CXXFILES = BigEndianProcessor.cpp Bus.cpp ClockedChip.cpp Device.cpp EventArgs.cpp InputOutput.cpp IntelHexFile.cpp IntelProcessor.cpp LittleEndianProcessor.cpp Memory.cpp Processor.cpp Ram.cpp Rom.cpp UnusedMemory.cpp CXXFILES = BigEndianProcessor.cpp Bus.cpp ClockedChip.cpp Device.cpp EventArgs.cpp InputOutput.cpp IntelHexFile.cpp IntelProcessor.cpp LittleEndianProcessor.cpp Memory.cpp Processor.cpp Ram.cpp Rom.cpp UnusedMemory.cpp
include ../compile.mk include ../compile.mk

View File

@ -1,5 +1,5 @@
#include "stdafx.h" #include "stdafx.h"
#include "Memory.h" #include "../inc/Memory.h"
#include <stdexcept> #include <stdexcept>

View File

@ -1,5 +1,5 @@
#include "stdafx.h" #include "stdafx.h"
#include "Processor.h" #include "../inc/Processor.h"
EightBit::Processor::Processor(Bus& bus) EightBit::Processor::Processor(Bus& bus)
: m_bus(bus) { : m_bus(bus) {
@ -86,14 +86,6 @@ int EightBit::Processor::execute(const uint8_t value) {
return execute(); return execute();
} }
// http://graphics.stanford.edu/~seander/bithacks.html#FixedSignExtend
int8_t EightBit::Processor::signExtend(const int b, uint8_t x) noexcept {
const uint8_t m = bit(b - 1); // mask can be pre-computed if b is fixed
x = x & (bit(b) - 1); // (Skip this if bits in x above position b are already zero.)
const auto result = (x ^ m) - m;
return result;
}
void EightBit::Processor::jump(const register16_t destination) noexcept { void EightBit::Processor::jump(const register16_t destination) noexcept {
PC() = destination; PC() = destination;
} }

View File

@ -1,5 +1,5 @@
#include "stdafx.h" #include "stdafx.h"
#include "Ram.h" #include "../inc/Ram.h"
EightBit::Ram::Ram(const size_t size) noexcept EightBit::Ram::Ram(const size_t size) noexcept
: Rom(size) {} : Rom(size) {}

View File

@ -1,5 +1,5 @@
#include "stdafx.h" #include "stdafx.h"
#include "Rom.h" #include "../inc/Rom.h"
#include <iostream> #include <iostream>

View File

@ -1,5 +1,5 @@
#include "stdafx.h" #include "stdafx.h"
#include "UnusedMemory.h" #include "../inc/UnusedMemory.h"
EightBit::UnusedMemory::UnusedMemory(const size_t size, const uint8_t value) EightBit::UnusedMemory::UnusedMemory(const size_t size, const uint8_t value)
: m_size(size), m_value(value) {} : m_size(size), m_value(value) {}