#ifndef INSTRUCTIONS_HPP #define INSTRUCTIONS_HPP #include #include #include #include #include "kblib/convert.h" #include "kblib/simple.h" #include "ints.h" struct memory_store { constexpr static u64 segment_count = 1u << 16u, segment_size = 1u << 16u, word_size = 8; constexpr static u64 mem_size = segment_count * segment_size * word_size; using address = u64; using byte = unsigned char; using word = std::array; static_assert(CHAR_BIT == 8, "The host must have byte-addressible memory"); byte& operator[](address addr); byte& operator()(u16 segment, u32 word, unsigned char byte); word& operator()(u16 segment, u32 word); std::array main_memory; std::array registers; }; inline memory_store memory; namespace detail { using str_type = std::array; template constexpr str_type str_impl(const char (&arr)[N], std::integer_sequence) { return {arr[I]...}; } template > constexpr str_type str(const char (&arr)[N]) { return str_impl(arr, Indices{}); } } // namespace detail using segment = std::array; enum class stack_dir : char { up, down }; template class stack_cache { std::array, (1u << 12u)>* memory; u32 top; }; struct computer_state { std::array, (1u << 12u)> memory; u64 registers[16]; u64 internal[4]; stack_cache stack; stack_cache hstack; stack_cache cstack; }; inline u64 saturating_add(u64 a, u64 b) { u64 result; return __builtin_add_overflow(a, b, &result) ? -1_u64 : result; } inline u64 saturating_sub(u64 a, u64 b) { u64 result; return __builtin_sub_overflow(a, b, &result) ? -1_u64 : result; } #endif // INSTRUCTIONS_HPP