From 6007426eb363b1640c4bae9ce00246c7c6df16cf Mon Sep 17 00:00:00 2001 From: shylie Date: Wed, 25 Mar 2026 01:43:20 -0400 Subject: [PATCH] Add vcd waveform tracing --- .clang-format | 64 ++------ .gitmodules | 3 + CMakeLists.txt | 1 + emulator/CMakeLists.txt | 3 + emulator/include/foot-emulator.h | 20 ++- emulator/src/foot-emulator.cpp | 239 +++++++++++++++++----------- emulator/src/main.cpp | 19 +-- emulator/tests/CMakeLists.txt | 3 +- emulator/tests/addi-instruction.cpp | 5 +- emulator/tests/arng-instruction.cpp | 10 +- emulator/tests/band-instruction.cpp | 8 +- emulator/tests/bwng-instruction.cpp | 5 +- emulator/tests/bwor-instruction.cpp | 8 +- emulator/tests/bxor-instruction.cpp | 8 +- emulator/tests/clsh-instruction.cpp | 5 +- emulator/tests/cnst-instruction.cpp | 20 ++- emulator/tests/divi-instruction.cpp | 30 +++- emulator/tests/long-instruction.cpp | 16 +- emulator/tests/modu-instruction.cpp | 29 +++- emulator/tests/mult-instruction.cpp | 30 +++- emulator/tests/srsh-instruction.cpp | 18 ++- emulator/tests/subt-instruction.cpp | 13 +- emulator/tests/test-common.h | 7 +- emulator/tests/zlsh-instruction.cpp | 16 +- emulator/tests/zrsh-instruction.cpp | 13 +- foot.script | 15 +- vcppd | 1 + 27 files changed, 391 insertions(+), 218 deletions(-) create mode 100644 .gitmodules create mode 160000 vcppd diff --git a/.clang-format b/.clang-format index 4b09ee9..f1b5bbc 100644 --- a/.clang-format +++ b/.clang-format @@ -1,54 +1,12 @@ -# Generated from CLion C/C++ Code Style settings ---- -Language: Cpp -BasedOnStyle: LLVM -AlignConsecutiveAssignments: false -AlignConsecutiveDeclarations: false -AlignOperands: false -AlignTrailingComments: false -AlwaysBreakTemplateDeclarations: Yes -BraceWrapping: - AfterCaseLabel: true - AfterClass: true - AfterControlStatement: true - AfterEnum: true - AfterFunction: true - AfterNamespace: true - AfterStruct: true - AfterUnion: true - AfterExternBlock: false - BeforeCatch: true - BeforeElse: true - BeforeLambdaBody: true - BeforeWhile: true - SplitEmptyFunction: true - SplitEmptyRecord: true - SplitEmptyNamespace: true -BreakBeforeBraces: Custom -BreakConstructorInitializers: AfterColon -BreakConstructorInitializersBeforeComma: false -ColumnLimit: 120 -ConstructorInitializerAllOnOneLineOrOnePerLine: false -ContinuationIndentWidth: 2 -IncludeCategories: - - Regex: '^<.*' - Priority: 1 - - Regex: '^".*' - Priority: 2 - - Regex: '.*' - Priority: 3 -IncludeIsMainRegex: '([-_](test|unittest))?$' -IndentCaseBlocks: true -InsertNewlineAtEOF: false -MacroBlockBegin: '' -MacroBlockEnd: '' -MaxEmptyLinesToKeep: 2 -NamespaceIndentation: All +BasedOnStyle: GNU +SpaceBeforeParens: ControlStatementsExceptControlMacros PointerAlignment: Left -SpaceInEmptyParentheses: false -SpacesInAngles: false -SpacesInConditionalStatement: false -SpacesInCStyleCastParentheses: false -SpacesInParentheses: false -TabWidth: 4 -... +UseTab: Never +IndentWidth: 2 +ContinuationIndentWidth: 2 +ConstructorInitializerIndentWidth: 2 +BreakAfterReturnType: Automatic +BreakConstructorInitializers: AfterColon +PackConstructorInitializers: Never +IncludeBlocks: Regroup +BreakBeforeBraces: Allman diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..892e642 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "vcppd"] + path = vcppd + url = https://git.shylie.info/shylie/vcppd.git diff --git a/CMakeLists.txt b/CMakeLists.txt index 6852d9c..fbb5abb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,4 +9,5 @@ else() set(FOOT_TESTS OFF) endif() +add_subdirectory(vcppd) add_subdirectory(emulator) diff --git a/emulator/CMakeLists.txt b/emulator/CMakeLists.txt index ebb9bc0..d2f6dfa 100644 --- a/emulator/CMakeLists.txt +++ b/emulator/CMakeLists.txt @@ -4,11 +4,14 @@ project(foot-emulator) add_library(foot-emulator src/foot-emulator.cpp include/foot-emulator.h) target_include_directories(foot-emulator PUBLIC include) +target_link_libraries(foot-emulator PUBLIC vcppd) +set_target_properties(foot-emulator PROPERTIES CXX_STANDARD 20) find_package(SDL3 REQUIRED CONFIG) add_executable(foot-emulator-cli src/main.cpp) target_link_libraries(foot-emulator-cli PUBLIC foot-emulator SDL3::SDL3) +set_target_properties(foot-emulator-cli PROPERTIES CXX_STANDARD 20) if(FOOT_TESTS) add_subdirectory(tests) diff --git a/emulator/include/foot-emulator.h b/emulator/include/foot-emulator.h index b52bc8d..fc2e47c 100644 --- a/emulator/include/foot-emulator.h +++ b/emulator/include/foot-emulator.h @@ -3,7 +3,9 @@ #include #include +#include #include +#include #include namespace foot @@ -26,6 +28,7 @@ struct Operand class Device { friend class Emulator; + public: virtual ~Device() = default; @@ -39,7 +42,7 @@ protected: private: uint32_t* assigned_memory_base; - uint32_t assigned_memory_size; + uint32_t assigned_memory_size; unsigned int update_frequency; }; @@ -52,7 +55,7 @@ public: static constexpr uint8_t RA = 29; static constexpr uint8_t SP = 28; - Emulator(); + explicit Emulator(bool should_trace = false); void run(const std::vector& program); void run(const std::string& filename); @@ -80,6 +83,10 @@ private: std::vector, unsigned int>> devices; uint32_t mapped_base; bool keep_running; + std::unique_ptr vcd_file; + std::unique_ptr null_stream; + vcppd::Vcd vcd; + bool should_trace; void run_internal(); void read_instruction(); @@ -109,8 +116,11 @@ private: uint8_t simd_elements() const; uint8_t shift() const; - uint32_t apply_many_unary(uint32_t a, uint32_t (Emulator::*fn)(uint32_t a) const) const; - uint32_t apply_many_binary(uint32_t a, uint32_t b, uint32_t (Emulator::*fn)(uint32_t a, uint32_t b) const) const; + uint32_t apply_many_unary(uint32_t a, + uint32_t (Emulator::*fn)(uint32_t a) const) const; + uint32_t apply_many_binary(uint32_t a, uint32_t b, + uint32_t (Emulator::*fn)(uint32_t a, uint32_t b) + const) const; uint32_t op_arithmetic_negate(uint32_t a) const; uint32_t op_logical_negate(uint32_t a) const; @@ -127,4 +137,4 @@ private: } -#endif//FOOT_EMULATOR +#endif // FOOT_EMULATOR diff --git a/emulator/src/foot-emulator.cpp b/emulator/src/foot-emulator.cpp index 4e1f1ff..9b84114 100644 --- a/emulator/src/foot-emulator.cpp +++ b/emulator/src/foot-emulator.cpp @@ -1,8 +1,7 @@ #include "foot-emulator.h" -#include - #include +#include namespace foot { @@ -10,13 +9,15 @@ namespace foot Operand::Operand(uint8_t bits) : addressing_mode(static_cast((bits & 0b01100000) >> 5)), register_index(bits & 0b00011111) -{} +{ +} Device::Device(uint16_t size, unsigned int update_frequency) : assigned_memory_base(nullptr), assigned_memory_size(size), update_frequency(update_frequency) -{} +{ +} uint32_t& Device::memory(uint16_t index) { @@ -27,11 +28,54 @@ uint32_t& Device::memory(uint16_t index) return assigned_memory_base[index]; } -Emulator::Emulator() : +Emulator::Emulator(bool should_trace) : memory{}, registers{}, configuration(0), - mapped_base(0x00010000) + mapped_base(0x00010000), + vcd_file(should_trace ? std::make_unique("trace.vcd") + : nullptr), + null_stream(should_trace ? nullptr + : std::make_unique(nullptr)), + vcd(vcppd::Builder(should_trace ? *vcd_file : *null_stream) + .scope("CPU") + .scope("REGISTERS") + .trace("0", registers[0]) + .trace("1", registers[1]) + .trace("2", registers[2]) + .trace("3", registers[3]) + .trace("4", registers[4]) + .trace("5", registers[5]) + .trace("6", registers[6]) + .trace("7", registers[7]) + .trace("8", registers[8]) + .trace("9", registers[9]) + .trace("10", registers[10]) + .trace("11", registers[11]) + .trace("12", registers[12]) + .trace("13", registers[13]) + .trace("14", registers[14]) + .trace("15", registers[15]) + .trace("16", registers[16]) + .trace("17", registers[17]) + .trace("18", registers[18]) + .trace("19", registers[19]) + .trace("20", registers[20]) + .trace("21", registers[21]) + .trace("22", registers[22]) + .trace("23", registers[23]) + .trace("24", registers[24]) + .trace("25", registers[25]) + .trace("26", registers[26]) + .trace("27", registers[27]) + .trace("28", registers[28]) + .trace("29", registers[29]) + .trace("30", registers[30]) + .trace("31", registers[31]) + .unscope() + .unscope() + .build()), + should_trace(should_trace) { registers[SP] = 0xFFFF; // stack pointer } @@ -47,13 +91,21 @@ void Emulator::run(const std::string& filename) { ELFIO::elfio reader; - if (!reader.load(filename)) { return; } + if (!reader.load(filename)) + { + return; + } for (const auto& segment : reader.segments) { - if (segment->get_type() != ELFIO::PT_LOAD) { continue; } + if (segment->get_type() != ELFIO::PT_LOAD) + { + continue; + } - memcpy(reinterpret_cast(memory.data()) + segment->get_virtual_address(), segment->get_data(), segment->get_file_size()); + memcpy(reinterpret_cast(memory.data()) + + segment->get_virtual_address(), + segment->get_data(), segment->get_file_size()); } registers[PC] = reader.get_entry() / 4; @@ -68,10 +120,7 @@ void Emulator::map_device(std::unique_ptr&& device) devices.emplace_back(std::move(device), 0); } -uint32_t& Emulator::memory_at(uint32_t address) -{ - return memory[address]; -} +uint32_t& Emulator::memory_at(uint32_t address) { return memory[address]; } uint32_t& Emulator::decode_operand(Operand operand) { @@ -88,20 +137,22 @@ uint32_t& Emulator::decode_operand(Operand operand) return memory[registers[operand.register_index]++]; case Operand::AddressingMode::Indirect: - return memory[registers[operand.register_index]]; + return memory[registers[operand.register_index]]; default: return dummy_value; } } -uint32_t& Emulator::register_at(uint8_t index) -{ - return registers[index]; -} +uint32_t& Emulator::register_at(uint8_t index) { return registers[index]; } void Emulator::run_instruction() { + if (should_trace) + { + vcd.tick(); + } + read_instruction(); if (!should_run()) @@ -114,7 +165,10 @@ void Emulator::run_instruction() for (int iteration = 0; iteration < loop_count; iteration++) { - if (rep) { registers[LC] = iteration; } + if (rep) + { + registers[LC] = iteration; + } switch ((instruction & 0x0F000000) >> 24) { @@ -204,7 +258,10 @@ void Emulator::run_instruction() } } - if (rep) { registers[LC] = loop_count; } + if (rep) + { + registers[LC] = loop_count; + } } void Emulator::run_internal() @@ -229,12 +286,15 @@ void Emulator::run_internal() } } } + + if (vcd_file) + { + vcd_file->flush(); + vcd_file->close(); + } } -void Emulator::read_instruction() -{ - instruction = memory[registers[PC]++]; -} +void Emulator::read_instruction() { instruction = memory[registers[PC]++]; } void Emulator::CNST() { @@ -262,7 +322,7 @@ void Emulator::CMPR() void Emulator::BWNG() { - uint32_t a = decode_operand(instruction & 0x000000FF); + uint32_t a = decode_operand(instruction & 0x000000FF); uint32_t& d = decode_operand((instruction & 0x00FF0000) >> 16); d = ~a; @@ -270,7 +330,7 @@ void Emulator::BWNG() void Emulator::ARNG() { - uint32_t a = decode_operand(instruction & 0x000000FF); + uint32_t a = decode_operand(instruction & 0x000000FF); uint32_t& d = decode_operand((instruction & 0x00FF0000) >> 16); d = apply_many_unary(a, &Emulator::op_arithmetic_negate); @@ -278,7 +338,7 @@ void Emulator::ARNG() void Emulator::LONG() { - uint32_t a = decode_operand(instruction & 0x000000FF); + uint32_t a = decode_operand(instruction & 0x000000FF); uint32_t& d = decode_operand((instruction & 0x00FF0000) >> 16); d = apply_many_unary(a, &Emulator::op_logical_negate); @@ -286,7 +346,7 @@ void Emulator::LONG() void Emulator::CONF() { - uint32_t a = decode_operand(instruction & 0x000000FF); + uint32_t a = decode_operand(instruction & 0x000000FF); uint32_t& d = decode_operand((instruction & 0x00FF0000) >> 16); d = configuration; @@ -295,7 +355,7 @@ void Emulator::CONF() void Emulator::COPY() { - uint32_t a = decode_operand(instruction & 0x000000FF); + uint32_t a = decode_operand(instruction & 0x000000FF); uint32_t& d = decode_operand((instruction & 0x00FF0000) >> 16); d = a; @@ -303,8 +363,8 @@ void Emulator::COPY() void Emulator::BWOR() { - uint32_t a = decode_operand(instruction & 0x000000FF); - uint32_t b = decode_operand((instruction & 0x0000FF00) >> 8); + uint32_t a = decode_operand(instruction & 0x000000FF); + uint32_t b = decode_operand((instruction & 0x0000FF00) >> 8); uint32_t& d = decode_operand((instruction & 0x00FF0000) >> 16); d = a | b; @@ -312,8 +372,8 @@ void Emulator::BWOR() void Emulator::BAND() { - uint32_t a = decode_operand(instruction & 0x000000FF); - uint32_t b = decode_operand((instruction & 0x0000FF00) >> 8); + uint32_t a = decode_operand(instruction & 0x000000FF); + uint32_t b = decode_operand((instruction & 0x0000FF00) >> 8); uint32_t& d = decode_operand((instruction & 0x00FF0000) >> 16); d = a & b; @@ -321,8 +381,8 @@ void Emulator::BAND() void Emulator::BXOR() { - uint32_t a = decode_operand(instruction & 0x000000FF); - uint32_t b = decode_operand((instruction & 0x0000FF00) >> 8); + uint32_t a = decode_operand(instruction & 0x000000FF); + uint32_t b = decode_operand((instruction & 0x0000FF00) >> 8); uint32_t& d = decode_operand((instruction & 0x00FF0000) >> 16); d = a ^ b; @@ -330,8 +390,8 @@ void Emulator::BXOR() void Emulator::ZRSH() { - uint32_t a = decode_operand(instruction & 0x000000FF); - uint32_t b = decode_operand((instruction & 0x0000FF00) >> 8); + uint32_t a = decode_operand(instruction & 0x000000FF); + uint32_t b = decode_operand((instruction & 0x0000FF00) >> 8); uint32_t& d = decode_operand((instruction & 0x00FF0000) >> 16); d = apply_many_binary(a, b, &Emulator::op_pad_zero_right_shift); @@ -339,8 +399,8 @@ void Emulator::ZRSH() void Emulator::SRSH() { - uint32_t a = decode_operand(instruction & 0x000000FF); - uint32_t b = decode_operand((instruction & 0x0000FF00) >> 8); + uint32_t a = decode_operand(instruction & 0x000000FF); + uint32_t b = decode_operand((instruction & 0x0000FF00) >> 8); uint32_t& d = decode_operand((instruction & 0x00FF0000) >> 16); d = apply_many_binary(a, b, &Emulator::op_signed_right_shift); @@ -348,8 +408,8 @@ void Emulator::SRSH() void Emulator::ZLSH() { - uint32_t a = decode_operand(instruction & 0x000000FF); - uint32_t b = decode_operand((instruction & 0x0000FF00) >> 8); + uint32_t a = decode_operand(instruction & 0x000000FF); + uint32_t b = decode_operand((instruction & 0x0000FF00) >> 8); uint32_t& d = decode_operand((instruction & 0x00FF0000) >> 16); d = apply_many_binary(a, b, &Emulator::op_pad_zero_left_shift); @@ -357,8 +417,8 @@ void Emulator::ZLSH() void Emulator::CLSH() { - uint32_t a = decode_operand(instruction & 0x000000FF); - uint32_t b = decode_operand((instruction & 0x0000FF00) >> 8); + uint32_t a = decode_operand(instruction & 0x000000FF); + uint32_t b = decode_operand((instruction & 0x0000FF00) >> 8); uint32_t& d = decode_operand((instruction & 0x00FF0000) >> 16); d = apply_many_binary(a, b, &Emulator::op_circular_left_shift); @@ -366,8 +426,8 @@ void Emulator::CLSH() void Emulator::ADDI() { - uint32_t a = decode_operand(instruction & 0x000000FF); - uint32_t b = decode_operand((instruction & 0x0000FF00) >> 8); + uint32_t a = decode_operand(instruction & 0x000000FF); + uint32_t b = decode_operand((instruction & 0x0000FF00) >> 8); uint32_t& d = decode_operand((instruction & 0x00FF0000) >> 16); d = apply_many_binary(a, b, &Emulator::op_add); @@ -375,8 +435,8 @@ void Emulator::ADDI() void Emulator::SUBT() { - uint32_t a = decode_operand(instruction & 0x000000FF); - uint32_t b = decode_operand((instruction & 0x0000FF00) >> 8); + uint32_t a = decode_operand(instruction & 0x000000FF); + uint32_t b = decode_operand((instruction & 0x0000FF00) >> 8); uint32_t& d = decode_operand((instruction & 0x00FF0000) >> 16); d = apply_many_binary(a, b, &Emulator::op_sub); @@ -384,8 +444,8 @@ void Emulator::SUBT() void Emulator::MULT() { - uint32_t a = decode_operand(instruction & 0x000000FF); - uint32_t b = decode_operand((instruction & 0x0000FF00) >> 8); + uint32_t a = decode_operand(instruction & 0x000000FF); + uint32_t b = decode_operand((instruction & 0x0000FF00) >> 8); uint32_t& d = decode_operand((instruction & 0x00FF0000) >> 16); d = apply_many_binary(a, b, &Emulator::op_mul); @@ -393,8 +453,8 @@ void Emulator::MULT() void Emulator::DIVI() { - uint32_t a = decode_operand(instruction & 0x000000FF); - uint32_t b = decode_operand((instruction & 0x0000FF00) >> 8); + uint32_t a = decode_operand(instruction & 0x000000FF); + uint32_t b = decode_operand((instruction & 0x0000FF00) >> 8); uint32_t& d = decode_operand((instruction & 0x00FF0000) >> 16); d = apply_many_binary(a, b, &Emulator::op_div); @@ -402,8 +462,8 @@ void Emulator::DIVI() void Emulator::MODU() { - uint32_t a = decode_operand(instruction & 0x000000FF); - uint32_t b = decode_operand((instruction & 0x0000FF00) >> 8); + uint32_t a = decode_operand(instruction & 0x000000FF); + uint32_t b = decode_operand((instruction & 0x0000FF00) >> 8); uint32_t& d = decode_operand((instruction & 0x00FF0000) >> 16); d = apply_many_binary(a, b, &Emulator::op_mod); @@ -426,78 +486,85 @@ bool Emulator::should_run() const return status_register == Status::Equal; case 4: - return status_register == Status::Greater || status_register == Status::Equal; + return status_register == Status::Greater + || status_register == Status::Equal; case 5: return status_register == Status::Greater; case 6: - return status_register == Status::Less || status_register == Status::Greater; + return status_register == Status::Less + || status_register == Status::Greater; default: return false; } } -bool Emulator::repeats() const -{ - return instruction & 0x10000000; -} +bool Emulator::repeats() const { return instruction & 0x10000000; } uint8_t Emulator::simd_elements() const { uint8_t bits = 0; - if (instruction & (1 << 7)) { bits |= 0b01; } - if (instruction & (1 << 23)) { bits |= 0b10; } + if (instruction & (1 << 7)) + { + bits |= 0b01; + } + if (instruction & (1 << 23)) + { + bits |= 0b10; + } return 1 << bits; } -uint8_t Emulator::shift() const -{ - return configuration & 0x0000001F; -} +uint8_t Emulator::shift() const { return configuration & 0x0000001F; } -uint32_t Emulator::apply_many_unary(uint32_t a, uint32_t (Emulator::*fn)(uint32_t a) const) const +uint32_t Emulator::apply_many_unary(uint32_t a, + uint32_t (Emulator::*fn)(uint32_t a) + const) const { uint32_t result = 0; for (int i = 0; i < simd_elements(); i++) { uint32_t simd_width_mask = ((uint64_t(1) << (32 / simd_elements())) - 1); - uint32_t simd_element_a = (a >> (i * 32 / simd_elements())) & simd_width_mask; - uint32_t simd_result = ((this->*fn)(simd_element_a) & simd_width_mask) << (i * 32 / simd_elements()); + uint32_t simd_element_a + = (a >> (i * 32 / simd_elements())) & simd_width_mask; + uint32_t simd_result = ((this->*fn)(simd_element_a)&simd_width_mask) + << (i * 32 / simd_elements()); result |= simd_result; } return result; } -uint32_t Emulator::apply_many_binary(uint32_t a, uint32_t b, uint32_t (Emulator::*fn)(uint32_t a, uint32_t b) const) const +uint32_t Emulator::apply_many_binary(uint32_t a, uint32_t b, + uint32_t (Emulator::*fn)(uint32_t a, + uint32_t b) + const) const { uint32_t result = 0; for (int i = 0; i < simd_elements(); i++) { uint32_t simd_width_mask = ((uint64_t(1) << (32 / simd_elements())) - 1); - uint32_t simd_element_a = (a >> (i * 32 / simd_elements())) & simd_width_mask; - uint32_t simd_element_b = (b >> (i * 32 / simd_elements())) & simd_width_mask; - uint32_t simd_result = ((this->*fn)(simd_element_a, simd_element_b) & simd_width_mask) << (i * 32 / simd_elements()); + uint32_t simd_element_a + = (a >> (i * 32 / simd_elements())) & simd_width_mask; + uint32_t simd_element_b + = (b >> (i * 32 / simd_elements())) & simd_width_mask; + uint32_t simd_result + = ((this->*fn)(simd_element_a, simd_element_b) & simd_width_mask) + << (i * 32 / simd_elements()); result |= simd_result; } return result; } -uint32_t Emulator::op_arithmetic_negate(uint32_t a) const -{ - return -a; -} +uint32_t Emulator::op_arithmetic_negate(uint32_t a) const { return -a; } -uint32_t Emulator::op_logical_negate(uint32_t a) const -{ - return !a; -} +uint32_t Emulator::op_logical_negate(uint32_t a) const { return !a; } uint32_t Emulator::op_pad_zero_right_shift(uint32_t a, uint32_t b) const { @@ -519,15 +586,9 @@ uint32_t Emulator::op_circular_left_shift(uint32_t a, uint32_t b) const return (a << b) | (a >> (32 - b)); } -uint32_t Emulator::op_add(uint32_t a, uint32_t b) const -{ - return a + b; -} +uint32_t Emulator::op_add(uint32_t a, uint32_t b) const { return a + b; } -uint32_t Emulator::op_sub(uint32_t a, uint32_t b) const -{ - return a - b; -} +uint32_t Emulator::op_sub(uint32_t a, uint32_t b) const { return a - b; } uint32_t Emulator::op_mul(uint32_t a, uint32_t b) const { @@ -545,4 +606,4 @@ uint32_t Emulator::op_mod(uint32_t a, uint32_t b) const return int32_t(a) % int32_t(b); } -} \ No newline at end of file +} diff --git a/emulator/src/main.cpp b/emulator/src/main.cpp index cf336fb..072896f 100644 --- a/emulator/src/main.cpp +++ b/emulator/src/main.cpp @@ -1,9 +1,7 @@ #include "foot-emulator.h" -#include -#include - #include +#include namespace { @@ -26,7 +24,7 @@ public: value = 0; } - return false; + return false; } }; @@ -36,16 +34,14 @@ public: MemoryViewDevice(SDL_Renderer* render, uint8_t width, uint8_t height) : Device(width * height, 10000), render(render), - texture(SDL_CreateTexture(render, SDL_PIXELFORMAT_RGBA32, SDL_TEXTUREACCESS_STREAMING, width, height)), + texture(SDL_CreateTexture(render, SDL_PIXELFORMAT_RGBA32, + SDL_TEXTUREACCESS_STREAMING, width, height)), width(width), height(height) { SDL_SetTextureScaleMode(texture, SDL_SCALEMODE_NEAREST); } - ~MemoryViewDevice() - { - SDL_DestroyTexture(texture); - } + ~MemoryViewDevice() { SDL_DestroyTexture(texture); } bool update() override { @@ -100,9 +96,10 @@ int main(int argc, char** argv) SDL_Renderer* render; SDL_Init(SDL_INIT_VIDEO); - SDL_CreateWindowAndRenderer("foot emulator", WIDTH * 8, HEIGHT * 8, 0, &window, &render); + SDL_CreateWindowAndRenderer("foot emulator", WIDTH * 8, HEIGHT * 8, 0, + &window, &render); - foot::Emulator emu; + foot::Emulator emu(true); emu.map_device(std::make_unique()); emu.map_device(std::make_unique(render, WIDTH, HEIGHT)); diff --git a/emulator/tests/CMakeLists.txt b/emulator/tests/CMakeLists.txt index d6e426b..2317d42 100644 --- a/emulator/tests/CMakeLists.txt +++ b/emulator/tests/CMakeLists.txt @@ -6,6 +6,7 @@ function(test name) add_executable(foot-emulator-test-${name} ${name}.cpp test-common.h) target_link_libraries(foot-emulator-test-${name} PUBLIC foot-emulator) add_test(NAME ${name} COMMAND foot-emulator-test-${name}) + set_target_properties(foot-emulator-test-${name} PROPERTIES CXX_STANDARD 20) endfunction() test(cnst-instruction) @@ -23,4 +24,4 @@ test(addi-instruction) test(subt-instruction) test(mult-instruction) test(divi-instruction) -test(modu-instruction) \ No newline at end of file +test(modu-instruction) diff --git a/emulator/tests/addi-instruction.cpp b/emulator/tests/addi-instruction.cpp index c682d1b..a2ea5bb 100644 --- a/emulator/tests/addi-instruction.cpp +++ b/emulator/tests/addi-instruction.cpp @@ -12,7 +12,10 @@ int main(int argc, char** argv) // b - 2, Immediate { foot::Emulator emu = run_instructions({ 0x00204567, 0x09200220 }); - if (!check(0x00004569, emu.register_at(0))) { return 1; } + if (!check(0x00004569, emu.register_at(0))) + { + return 1; + } } return 0; diff --git a/emulator/tests/arng-instruction.cpp b/emulator/tests/arng-instruction.cpp index 3e48ebf..4ec9222 100644 --- a/emulator/tests/arng-instruction.cpp +++ b/emulator/tests/arng-instruction.cpp @@ -11,7 +11,10 @@ int main(int argc, char** argv) // a - 0, Direct { foot::Emulator emu = run_instructions({ 0x00204567, 0x01200220 }); - if (!check(0xFFFFBA99, emu.register_at(0))) { return 1; } + if (!check(0xFFFFBA99, emu.register_at(0))) + { + return 1; + } } // CNST @@ -23,7 +26,10 @@ int main(int argc, char** argv) // a - 0, Direct { foot::Emulator emu = run_instructions({ 0x00204567, 0x01A002A0 }); - if (!check(0x0000CBA9, emu.register_at(0))) { return 1; } + if (!check(0x0000CBA9, emu.register_at(0))) + { + return 1; + } } return 0; diff --git a/emulator/tests/band-instruction.cpp b/emulator/tests/band-instruction.cpp index af3cc79..c1ee128 100644 --- a/emulator/tests/band-instruction.cpp +++ b/emulator/tests/band-instruction.cpp @@ -15,8 +15,12 @@ int main(int argc, char** argv) // a - 0, Direct // b - 1, Direct { - foot::Emulator emu = run_instructions({ 0x00204567, 0x00212345, 0x03202021 }); - if (!check(0x00004567 & 0x00002345, emu.register_at(0))) { return 1; } + foot::Emulator emu + = run_instructions({ 0x00204567, 0x00212345, 0x03202021 }); + if (!check(0x00004567 & 0x00002345, emu.register_at(0))) + { + return 1; + } } return 0; diff --git a/emulator/tests/bwng-instruction.cpp b/emulator/tests/bwng-instruction.cpp index 2bda5cb..d283d4f 100644 --- a/emulator/tests/bwng-instruction.cpp +++ b/emulator/tests/bwng-instruction.cpp @@ -11,7 +11,10 @@ int main(int argc, char** argv) // a - 0, Direct { foot::Emulator emu = run_instructions({ 0x00204567, 0x01200120 }); - if (!check(0xFFFFBA98, emu.register_at(0))) { return 1; } + if (!check(0xFFFFBA98, emu.register_at(0))) + { + return 1; + } } return 0; diff --git a/emulator/tests/bwor-instruction.cpp b/emulator/tests/bwor-instruction.cpp index d64725c..c8aca4b 100644 --- a/emulator/tests/bwor-instruction.cpp +++ b/emulator/tests/bwor-instruction.cpp @@ -15,8 +15,12 @@ int main(int argc, char** argv) // a - 0, Direct // b - 1, Direct { - foot::Emulator emu = run_instructions({ 0x00204567, 0x00212345, 0x02202021 }); - if (!check(0x00004567 | 0x00002345, emu.register_at(0))) { return 1; } + foot::Emulator emu + = run_instructions({ 0x00204567, 0x00212345, 0x02202021 }); + if (!check(0x00004567 | 0x00002345, emu.register_at(0))) + { + return 1; + } } return 0; diff --git a/emulator/tests/bxor-instruction.cpp b/emulator/tests/bxor-instruction.cpp index 14ffda5..85a6dac 100644 --- a/emulator/tests/bxor-instruction.cpp +++ b/emulator/tests/bxor-instruction.cpp @@ -15,8 +15,12 @@ int main(int argc, char** argv) // a - 0, Direct // b - 1, Direct { - foot::Emulator emu = run_instructions({ 0x00204567, 0x00212345, 0x04202021 }); - if (!check(0x00004567 ^ 0x00002345, emu.register_at(0))) { return 1; } + foot::Emulator emu + = run_instructions({ 0x00204567, 0x00212345, 0x04202021 }); + if (!check(0x00004567 ^ 0x00002345, emu.register_at(0))) + { + return 1; + } } return 0; diff --git a/emulator/tests/clsh-instruction.cpp b/emulator/tests/clsh-instruction.cpp index 6b0dfb9..87cf948 100644 --- a/emulator/tests/clsh-instruction.cpp +++ b/emulator/tests/clsh-instruction.cpp @@ -12,7 +12,10 @@ int main(int argc, char** argv) // b - 2, Immediate { foot::Emulator emu = run_instructions({ 0x00204567, 0x08201820 }); - if (!check(0x67000045, emu.register_at(0))) { return 1; } + if (!check(0x67000045, emu.register_at(0))) + { + return 1; + } } return 0; diff --git a/emulator/tests/cnst-instruction.cpp b/emulator/tests/cnst-instruction.cpp index 4c62fe9..637578d 100644 --- a/emulator/tests/cnst-instruction.cpp +++ b/emulator/tests/cnst-instruction.cpp @@ -7,7 +7,10 @@ int main(int argc, char** argv) // imm - 0xFFFF { foot::Emulator emu = run_instruction(0x0020FFFF); - if (!check(0xFFFF, emu.register_at(0))) { return 1; } + if (!check(0xFFFF, emu.register_at(0))) + { + return 1; + } } // CNST @@ -19,7 +22,10 @@ int main(int argc, char** argv) // imm = 0x7777 { foot::Emulator emu = run_instructions({ 0x0020FFFF, 0x00407777 }); - if (!check(0x7777, emu.memory_at(0xFFFF))) { return 1; } + if (!check(0x7777, emu.memory_at(0xFFFF))) + { + return 1; + } } // CNST @@ -34,10 +40,16 @@ int main(int argc, char** argv) foot::Emulator emu = run_instructions({ 0x003E0010, 0x10601234 }); for (int i = 0; i < 0x10; i++) { - if (!check(0x1234, emu.memory_at(i))) { failed = true; } + if (!check(0x1234, emu.memory_at(i))) + { + failed = true; + } } - if (failed) { return 1; } + if (failed) + { + return 1; + } } return 0; diff --git a/emulator/tests/divi-instruction.cpp b/emulator/tests/divi-instruction.cpp index 23939cf..0f45ea9 100644 --- a/emulator/tests/divi-instruction.cpp +++ b/emulator/tests/divi-instruction.cpp @@ -12,7 +12,10 @@ int main(int argc, char** argv) // b - 2, Immediate { foot::Emulator emu = run_instructions({ 0x00200005, 0x0C200220 }); - if (!check(0x00000002, emu.register_at(0))) { return 1; } + if (!check(0x00000002, emu.register_at(0))) + { + return 1; + } } // CNST @@ -28,8 +31,12 @@ int main(int argc, char** argv) // a - 0, Direct // b - 1, Direct { - foot::Emulator emu = run_instructions({ 0x00200007, 0x01210207, 0x0C202120 }); - if (!check(0xFFFFFFFF, emu.register_at(0))) { return 1; } + foot::Emulator emu + = run_instructions({ 0x00200007, 0x01210207, 0x0C202120 }); + if (!check(0xFFFFFFFF, emu.register_at(0))) + { + return 1; + } } // ARNG @@ -45,8 +52,12 @@ int main(int argc, char** argv) // a - 0, Direct // b - 1, Direct { - foot::Emulator emu = run_instructions({0x01200207, 0x01210207, 0x0C202120 }); - if (!check(0x1, emu.register_at(0))) { return 1; } + foot::Emulator emu + = run_instructions({ 0x01200207, 0x01210207, 0x0C202120 }); + if (!check(0x1, emu.register_at(0))) + { + return 1; + } } // CNST @@ -66,9 +77,14 @@ int main(int argc, char** argv) // a - 0, Direct // b - 1, Direct { - foot::Emulator emu = run_instructions({ 0x00200002, 0x00210001, 0x01000401, 0x0C202120 }); + foot::Emulator emu + = run_instructions({ 0x00200002, 0x00210001, 0x01000401, 0x0C202120 }); // 1 / 0.5 = 2 - if (!check(2 << 1 /* shift 1 for 31.1 fixed-point format */, emu.register_at(0))) { return 1; } + if (!check(2 << 1 /* shift 1 for 31.1 fixed-point format */, + emu.register_at(0))) + { + return 1; + } } return 0; diff --git a/emulator/tests/long-instruction.cpp b/emulator/tests/long-instruction.cpp index 6703838..56313dc 100644 --- a/emulator/tests/long-instruction.cpp +++ b/emulator/tests/long-instruction.cpp @@ -11,7 +11,10 @@ int main(int argc, char** argv) // a - 0, Direct { foot::Emulator emu = run_instructions({ 0x00204567, 0x01200320 }); - if (!check(0x00000000, emu.register_at(0))) { return 1; } + if (!check(0x00000000, emu.register_at(0))) + { + return 1; + } } // LONG @@ -19,7 +22,10 @@ int main(int argc, char** argv) // a - 0, Direct { foot::Emulator emu = run_instruction(0x01200320); - if (!check(0x00000001, emu.register_at(0))) { return 1; } + if (!check(0x00000001, emu.register_at(0))) + { + return 1; + } } // CNST @@ -31,9 +37,11 @@ int main(int argc, char** argv) // a - 0, Direct { foot::Emulator emu = run_instructions({ 0x00200230, 0x01A003A0 }); - if (!check(0x11111001, emu.register_at(0))) { return 1; } + if (!check(0x11111001, emu.register_at(0))) + { + return 1; + } } - return 0; } diff --git a/emulator/tests/modu-instruction.cpp b/emulator/tests/modu-instruction.cpp index 3a2ef51..b87903a 100644 --- a/emulator/tests/modu-instruction.cpp +++ b/emulator/tests/modu-instruction.cpp @@ -12,7 +12,10 @@ int main(int argc, char** argv) // b - 2, Immediate { foot::Emulator emu = run_instructions({ 0x00200005, 0x0D200220 }); - if (!check(0x1, emu.register_at(0))) { return 1; } + if (!check(0x1, emu.register_at(0))) + { + return 1; + } } // CNST @@ -28,8 +31,12 @@ int main(int argc, char** argv) // a - 0, Direct // b - 1, Direct { - foot::Emulator emu = run_instructions({ 0x00200005, 0x01210202, 0x0D202120 }); - if (!check(0x1, emu.register_at(0))) { return 1; } + foot::Emulator emu + = run_instructions({ 0x00200005, 0x01210202, 0x0D202120 }); + if (!check(0x1, emu.register_at(0))) + { + return 1; + } } // ARNG @@ -45,8 +52,12 @@ int main(int argc, char** argv) // a - 0, Direct // b - 1, Direct { - foot::Emulator emu = run_instructions({ 0x01200202, 0x00210005, 0x0D202120 }); - if (!check(0xFFFFFFFE, emu.register_at(0))) { return 1; } + foot::Emulator emu + = run_instructions({ 0x01200202, 0x00210005, 0x0D202120 }); + if (!check(0xFFFFFFFE, emu.register_at(0))) + { + return 1; + } } // CNST @@ -66,9 +77,13 @@ int main(int argc, char** argv) // a - 0, Direct // b - 1, Direct { - foot::Emulator emu = run_instructions({ 0x00200005, 0x00210003, 0x01000401, 0x0D202120 }); + foot::Emulator emu + = run_instructions({ 0x00200005, 0x00210003, 0x01000401, 0x0D202120 }); - if (!check(0x2, emu.register_at(0))) { return 1; } + if (!check(0x2, emu.register_at(0))) + { + return 1; + } } return 0; diff --git a/emulator/tests/mult-instruction.cpp b/emulator/tests/mult-instruction.cpp index ca5e841..4597b87 100644 --- a/emulator/tests/mult-instruction.cpp +++ b/emulator/tests/mult-instruction.cpp @@ -12,7 +12,10 @@ int main(int argc, char** argv) // b - 2, Immediate { foot::Emulator emu = run_instructions({ 0x00200003, 0x0B200220 }); - if (!check(0x0006, emu.register_at(0))) { return 1; } + if (!check(0x0006, emu.register_at(0))) + { + return 1; + } } // CNST @@ -28,8 +31,12 @@ int main(int argc, char** argv) // a - 0, Direct // b - 1, Direct { - foot::Emulator emu = run_instructions({ 0x00200007, 0x01210207, 0x0B202120 }); - if (!check(0xFFFFFFCF, emu.register_at(0))) { return 1; } + foot::Emulator emu + = run_instructions({ 0x00200007, 0x01210207, 0x0B202120 }); + if (!check(0xFFFFFFCF, emu.register_at(0))) + { + return 1; + } } // ARNG @@ -45,8 +52,12 @@ int main(int argc, char** argv) // a - 0, Direct // b - 1, Direct { - foot::Emulator emu = run_instructions({ 0x01200207, 0x01210207, 0x0B202120 }); - if (!check(0x31, emu.register_at(0))) { return 1; } + foot::Emulator emu + = run_instructions({ 0x01200207, 0x01210207, 0x0B202120 }); + if (!check(0x31, emu.register_at(0))) + { + return 1; + } } // CNST @@ -66,9 +77,14 @@ int main(int argc, char** argv) // a - 0, Direct // b - 1, Direct { - foot::Emulator emu = run_instructions({ 0x00200007, 0x00210007, 0x01000401, 0x0B202120 }); + foot::Emulator emu + = run_instructions({ 0x00200007, 0x00210007, 0x01000401, 0x0B202120 }); // 3.5 * 3.5 = 12.25 -- truncated to 12 with 31.1 fixed-point format - if (!check(12 << 1 /* shift 1 for 31.1 fixed-point format */, emu.register_at(0))) { return 1; } + if (!check(12 << 1 /* shift 1 for 31.1 fixed-point format */, + emu.register_at(0))) + { + return 1; + } } return 0; diff --git a/emulator/tests/srsh-instruction.cpp b/emulator/tests/srsh-instruction.cpp index f48f80d..c6a5ccf 100644 --- a/emulator/tests/srsh-instruction.cpp +++ b/emulator/tests/srsh-instruction.cpp @@ -12,7 +12,10 @@ int main(int argc, char** argv) // b - 2, Immediate { foot::Emulator emu = run_instructions({ 0x00204567, 0x06200220 }); - if (!check(0x4567 >> 2, emu.register_at(0))) { return 1; } + if (!check(0x4567 >> 2, emu.register_at(0))) + { + return 1; + } } // ARNG @@ -24,7 +27,10 @@ int main(int argc, char** argv) // a - 0, Direct { foot::Emulator emu = run_instructions({ 0x01200204, 0x06200220 }); - if (!check((-2) >> 2, emu.register_at(0))) { return 1; } + if (!check((-2) >> 2, emu.register_at(0))) + { + return 1; + } } // CNST @@ -40,8 +46,12 @@ int main(int argc, char** argv) // a - 0, Direct // b - 1, Direct { - foot::Emulator emu = run_instructions({ 0x00208686, 0x00211122, 0x06A021A0 }); - if (!check(0x4321, emu.register_at(0))) { return 1; } + foot::Emulator emu + = run_instructions({ 0x00208686, 0x00211122, 0x06A021A0 }); + if (!check(0x4321, emu.register_at(0))) + { + return 1; + } } return 0; diff --git a/emulator/tests/subt-instruction.cpp b/emulator/tests/subt-instruction.cpp index 3e2b126..c989fc2 100644 --- a/emulator/tests/subt-instruction.cpp +++ b/emulator/tests/subt-instruction.cpp @@ -12,7 +12,10 @@ int main(int argc, char** argv) // b - 2, Immediate { foot::Emulator emu = run_instructions({ 0x00204567, 0x0A200220 }); - if (!check(0x4565, emu.register_at(0))) { return 1; } + if (!check(0x4565, emu.register_at(0))) + { + return 1; + } } // CNST @@ -28,8 +31,12 @@ int main(int argc, char** argv) // a - 0, Direct // b - 1, Direct { - foot::Emulator emu = run_instructions({ 0x00204567, 0x01210202, 0x0A202120 }); - if (!check(0x4569, emu.register_at(0))) { return 1; } + foot::Emulator emu + = run_instructions({ 0x00204567, 0x01210202, 0x0A202120 }); + if (!check(0x4569, emu.register_at(0))) + { + return 1; + } } return 0; diff --git a/emulator/tests/test-common.h b/emulator/tests/test-common.h index d51598a..97e198c 100644 --- a/emulator/tests/test-common.h +++ b/emulator/tests/test-common.h @@ -1,5 +1,4 @@ #include - #include inline foot::Emulator run_instruction(uint32_t instruction) @@ -12,7 +11,8 @@ inline foot::Emulator run_instruction(uint32_t instruction) return emu; } -inline foot::Emulator run_instructions(const std::vector& instructions) +inline foot::Emulator +run_instructions(const std::vector& instructions) { foot::Emulator emu; for (int i = 0; i < instructions.size(); i++) @@ -32,7 +32,8 @@ inline bool check(uint32_t expected, uint32_t actual) { if (actual != expected) { - std::cout << std::hex << "Expected " << expected << ", got " << actual << ".\n"; + std::cout << std::hex << "Expected " << expected << ", got " << actual + << ".\n"; return false; } diff --git a/emulator/tests/zlsh-instruction.cpp b/emulator/tests/zlsh-instruction.cpp index 287b2d0..c0b57ad 100644 --- a/emulator/tests/zlsh-instruction.cpp +++ b/emulator/tests/zlsh-instruction.cpp @@ -1,4 +1,4 @@ -#include "test-common.h" +#include "test-common.h" int main(int argc, char** argv) { @@ -12,7 +12,10 @@ int main(int argc, char** argv) // b - 2, Immediate { foot::Emulator emu = run_instructions({ 0x00204567, 0x07200220 }); - if (!check(0x0001159C, emu.register_at(0))) { return 1; } + if (!check(0x0001159C, emu.register_at(0))) + { + return 1; + } } // CNST @@ -28,10 +31,13 @@ int main(int argc, char** argv) // a - 0, Direct // b - 1, Direct { - foot::Emulator emu = run_instructions({ 0x00204343, 0x00211122, 0x07A021A0 }); - if (!check(0x860C, emu.register_at(0))) { return 1; } + foot::Emulator emu + = run_instructions({ 0x00204343, 0x00211122, 0x07A021A0 }); + if (!check(0x860C, emu.register_at(0))) + { + return 1; + } } - return 0; } diff --git a/emulator/tests/zrsh-instruction.cpp b/emulator/tests/zrsh-instruction.cpp index b9ccb7b..9c1e834 100644 --- a/emulator/tests/zrsh-instruction.cpp +++ b/emulator/tests/zrsh-instruction.cpp @@ -12,7 +12,10 @@ int main(int argc, char** argv) // b - 2, Immediate { foot::Emulator emu = run_instructions({ 0x00204567, 0x05200220 }); - if (!check(0x1159, emu.register_at(0))) { return 1; } + if (!check(0x1159, emu.register_at(0))) + { + return 1; + } } // CNST @@ -28,8 +31,12 @@ int main(int argc, char** argv) // a - 0, Direct // b - 1, Direct { - foot::Emulator emu = run_instructions({ 0x00204343, 0x00211122, 0x05A021A0 }); - if (!check(0x2110, emu.register_at(0))) { return 1; } + foot::Emulator emu + = run_instructions({ 0x00204343, 0x00211122, 0x05A021A0 }); + if (!check(0x2110, emu.register_at(0))) + { + return 1; + } } return 0; diff --git a/foot.script b/foot.script index d6b2233..fa8fb8e 100644 --- a/foot.script +++ b/foot.script @@ -7,5 +7,18 @@ ENTRY(entry); SECTIONS { - . = 0x0; + .text : + { + *(.text) + *(.text.*) + _etext = .; + } + + .data : AT(_etext) + { + *(.rodata) + *(.rodata.*) + *(.data) + *(.data.*) + } } diff --git a/vcppd b/vcppd new file mode 160000 index 0000000..83ff5b4 --- /dev/null +++ b/vcppd @@ -0,0 +1 @@ +Subproject commit 83ff5b450cf5590d222aeb13e4dbd3f7fcf47f63