diff --git a/.clang-format b/.clang-format index fd984f8..4b09ee9 100644 --- a/.clang-format +++ b/.clang-format @@ -39,7 +39,7 @@ IncludeCategories: Priority: 3 IncludeIsMainRegex: '([-_](test|unittest))?$' IndentCaseBlocks: true -InsertNewlineAtEOF: true +InsertNewlineAtEOF: false MacroBlockBegin: '' MacroBlockEnd: '' MaxEmptyLinesToKeep: 2 diff --git a/.gitignore b/.gitignore index 317a2a6..f794005 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,4 @@ .cache/ .idea/ build/ -emulator/customasm/*.bin +cmake-build-*/ \ No newline at end of file diff --git a/DOCS.txt b/DOCS.txt index 23e546c..6bd3abf 100644 --- a/DOCS.txt +++ b/DOCS.txt @@ -19,31 +19,33 @@ ╠══════════╬══════════════════════╬════════════════╬══════╬══════╬══════╬══════╬══════╬══════╬══════╬══════╣ ╠══════╬═════════════════════════╣ ║ CONF ║ Configure processor ║ D = old config ║ CCCR ║ 0001 ║ 0DDd ║ dddd ║ 0000 ║ 0100 ║ 0AAa ║ aaaa ║ ║ 010 ║ A <= B ║ ╠══════════╬══════════════════════╬════════════════╬══════╬══════╬══════╬══════╬══════╬══════╬══════╬══════╣ ╠══════╬═════════════════════════╣ -║ BWOR ║ Bitwise or ║ D = A | B ║ CCCR ║ 0010 ║ 0DDd ║ dddd ║ 0BBb ║ bbbb ║ 0AAa ║ aaaa ║ ║ 011 ║ A = B ║ +║ COPY ║ Copy data ║ D = A ║ CCCR ║ 0001 ║ 0DDd ║ dddd ║ 0000 ║ 0101 ║ 0AAa ║ aaaa ║ ║ 011 ║ A = B ║ ╠══════════╬══════════════════════╬════════════════╬══════╬══════╬══════╬══════╬══════╬══════╬══════╬══════╣ ╠══════╬═════════════════════════╣ -║ BAND ║ Bitwise and ║ D = A & B ║ CCCR ║ 0011 ║ 0DDd ║ dddd ║ 0BBb ║ bbbb ║ 0AAa ║ aaaa ║ ║ 100 ║ A >= B ║ +║ BWOR ║ Bitwise or ║ D = A | B ║ CCCR ║ 0010 ║ 0DDd ║ dddd ║ 0BBb ║ bbbb ║ 0AAa ║ aaaa ║ ║ 100 ║ A >= B ║ ╠══════════╬══════════════════════╬════════════════╬══════╬══════╬══════╬══════╬══════╬══════╬══════╬══════╣ ╠══════╬═════════════════════════╣ -║ BXOR ║ Bitwise exclusive or ║ D = A ^ B ║ CCCR ║ 0100 ║ 0DDd ║ dddd ║ 0BBb ║ bbbb ║ 0AAa ║ aaaa ║ ║ 101 ║ A > B ║ +║ BAND ║ Bitwise and ║ D = A & B ║ CCCR ║ 0011 ║ 0DDd ║ dddd ║ 0BBb ║ bbbb ║ 0AAa ║ aaaa ║ ║ 101 ║ A > B ║ ╠══════════╬══════════════════════╬════════════════╬══════╬══════╬══════╬══════╬══════╬══════╬══════╬══════╣ ╠══════╬═════════════════════════╣ -║ ZRSH ║ Pad zero right shift ║ D = A >> B ║ CCCR ║ 0101 ║ 0DDd ║ dddd ║ 0BBb ║ bbbb ║ 0AAa ║ aaaa ║ ║ 110 ║ A != B ║ +║ BXOR ║ Bitwise exclusive or ║ D = A ^ B ║ CCCR ║ 0100 ║ 0DDd ║ dddd ║ 0BBb ║ bbbb ║ 0AAa ║ aaaa ║ ║ 110 ║ A != B ║ ╠══════════╬══════════════════════╬════════════════╬══════╬══════╬══════╬══════╬══════╬══════╬══════╬══════╣ ╠══════╬═════════════════════════╣ -║ SRSH ║ Signed right shift ║ D = A >> B ║ CCCR ║ 0110 ║ xDDd ║ dddd ║ 0BBb ║ bbbb ║ xAAa ║ aaaa ║ ║ 111 ║ Reserved ║ +║ ZRSH ║ Pad zero right shift ║ D = A >> B ║ CCCR ║ 0101 ║ 0DDd ║ dddd ║ 0BBb ║ bbbb ║ 0AAa ║ aaaa ║ ║ 111 ║ Reserved ║ ╠══════════╬══════════════════════╬════════════════╬══════╬══════╬══════╬══════╬══════╬══════╬══════╬══════╣ ╠══════╩═════════════════════════╣ -║ ZLSH ║ Pad zero left shift ║ D = A << B ║ CCCR ║ 0111 ║ xDDd ║ dddd ║ 0BBb ║ bbbb ║ xAAa ║ aaaa ║ ║ SIMD bits ║ +║ SRSH ║ Signed right shift ║ D = A >> B ║ CCCR ║ 0110 ║ xDDd ║ dddd ║ 0BBb ║ bbbb ║ xAAa ║ aaaa ║ ║ SIMD bits ║ ╠══════════╬══════════════════════╬════════════════╬══════╬══════╬══════╬══════╬══════╬══════╬══════╬══════╣ ╠══════╦═════════════════════════╣ -║ CLSH ║ Circular left shift ║ D = A << B ║ CCCR ║ 1000 ║ xDDd ║ dddd ║ 0BBb ║ bbbb ║ xAAa ║ aaaa ║ ║ 00 ║ 1 32-bit number ║ +║ ZLSH ║ Pad zero left shift ║ D = A << B ║ CCCR ║ 0111 ║ xDDd ║ dddd ║ 0BBb ║ bbbb ║ xAAa ║ aaaa ║ ║ 00 ║ 1 32-bit number ║ +╠══════════╬══════════════════════╬════════════════╬══════╬══════╬══════╬══════╬══════╬══════╬══════╬══════╣ ╠══════╦═════════════════════════╣ +║ CLSH ║ Circular left shift ║ D = A << B ║ CCCR ║ 1000 ║ xDDd ║ dddd ║ 0BBb ║ bbbb ║ xAAa ║ aaaa ║ ║ 01 ║ 2 16-bit numbers ║ ╠══════════╬══════════════════════╬════════════════╬══════╬══════╬══════╬══════╬══════╬══════╬══════╬══════╣ ╠══════╬═════════════════════════╣ -║ ADDI ║ Addition ║ D = A + B ║ CCCR ║ 1001 ║ xDDd ║ dddd ║ 0BBb ║ bbbb ║ xAAa ║ aaaa ║ ║ 01 ║ 2 16-bit numbers ║ +║ ADDI ║ Addition ║ D = A + B ║ CCCR ║ 1001 ║ xDDd ║ dddd ║ 0BBb ║ bbbb ║ xAAa ║ aaaa ║ ║ 10 ║ 4 8-bit numbers ║ ╠══════════╬══════════════════════╬════════════════╬══════╬══════╬══════╬══════╬══════╬══════╬══════╬══════╣ ╠══════╬═════════════════════════╣ -║ SUBT ║ Subtraction ║ D = A - B ║ CCCR ║ 1010 ║ xDDd ║ dddd ║ 0BBb ║ bbbb ║ xAAa ║ aaaa ║ ║ 10 ║ 4 8-bit numbers ║ -╠══════════╬══════════════════════╬════════════════╬══════╬══════╬══════╬══════╬══════╬══════╬══════╬══════╣ ╠══════╬═════════════════════════╣ -║ MULT ║ Multiplication ║ D = A * B ║ CCCR ║ 1011 ║ xDDd ║ dddd ║ 0BBb ║ bbbb ║ xAAa ║ aaaa ║ ║ 11 ║ 8 4-bit numbers ║ +║ SUBT ║ Subtraction ║ D = A - B ║ CCCR ║ 1010 ║ xDDd ║ dddd ║ 0BBb ║ bbbb ║ xAAa ║ aaaa ║ ║ 11 ║ 8 4-bit numbers ║ ╠══════════╬══════════════════════╬════════════════╬══════╬══════╬══════╬══════╬══════╬══════╬══════╬══════╣ ╠══════╩═════════════════════════╣ -║ DIVI ║ Division ║ D = A / B ║ CCCR ║ 1100 ║ xDDd ║ dddd ║ 0BBb ║ bbbb ║ xAAa ║ aaaa ║ ║ Processor configuration bits ║ +║ MULT ║ Multiplication ║ D = A * B ║ CCCR ║ 1011 ║ xDDd ║ dddd ║ 0BBb ║ bbbb ║ xAAa ║ aaaa ║ ║ Processor configuration bits ║ ╠══════════╬══════════════════════╬════════════════╬══════╬══════╬══════╬══════╬══════╬══════╬══════╬══════╣ ╠══════╦═════════════════════════╣ -║ MODU ║ Modulus ║ D = A % B ║ CCCR ║ 1101 ║ xDDd ║ dddd ║ 0BBb ║ bbbb ║ xAAa ║ aaaa ║ ║ 4-0 ║ Multiplication shift ║ +║ DIVI ║ Division ║ D = A / B ║ CCCR ║ 1100 ║ xDDd ║ dddd ║ 0BBb ║ bbbb ║ xAAa ║ aaaa ║ ║ 4-0 ║ Multiplication shift ║ ╠══════════╬══════════════════════╬════════════════╬══════╬══════╬══════╬══════╬══════╬══════╬══════╬══════╣ ╠══════╬═════════════════════════╣ -║ RESERVED ║ ║ ║ ║ 1110 ║ ║ ║ ║ ║ ║ ║ ║ 31-4 ║ Reserved ║ +║ MODU ║ Modulus ║ D = A % B ║ CCCR ║ 1101 ║ xDDd ║ dddd ║ 0BBb ║ bbbb ║ xAAa ║ aaaa ║ ║ 31-4 ║ Reserved ║ +╠══════════╬══════════════════════╬════════════════╬══════╬══════╬══════╬══════╬══════╬══════╬══════╬══════╣ ╠══════╬═════════════════════════╣ +║ RESERVED ║ ║ ║ ║ 1110 ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ╠══════════╬══════════════════════╬════════════════╬══════╬══════╬══════╬══════╬══════╬══════╬══════╬══════╣ ╠══════╬═════════════════════════╣ ║ RESERVED ║ ║ ║ ║ 1111 ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ ╚══════════╩══════════════════════╩════════════════╩══════╩══════╩══════╩══════╩══════╩══════╩══════╩══════╩══╩══════╩═════════════════════════╝ diff --git a/emulator/CMakeLists.txt b/emulator/CMakeLists.txt index ebb9bc0..0085792 100644 --- a/emulator/CMakeLists.txt +++ b/emulator/CMakeLists.txt @@ -4,6 +4,7 @@ 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 dwarf) find_package(SDL3 REQUIRED CONFIG) diff --git a/emulator/customasm/first.asm b/emulator/customasm/first.asm deleted file mode 100644 index 32e33e7..0000000 --- a/emulator/customasm/first.asm +++ /dev/null @@ -1,8 +0,0 @@ -#include "foot.asm" - -CNST. r1, #0xFFFF - -loop: -CNST. [r1], #65 -CNST. [r1], #66 -CNST. r31, #loop diff --git a/emulator/customasm/foot.asm b/emulator/customasm/foot.asm deleted file mode 100644 index 4a5c3de..0000000 --- a/emulator/customasm/foot.asm +++ /dev/null @@ -1,59 +0,0 @@ -#once - -#subruledef operand -{ - #{immediate: i5} => 0b00 @ immediate - r{register: u5} => 0b01 @ register - [r{register: u5}] => 0b10 @ register - [r{register: u5}++] => 0b11 @ register -} - -#subruledef crflags -{ - . => 0b0000 - .l => 0b0010 - .le => 0b0100 - .e => 0b0110 - .ge => 0b1000 - .g => 0b1010 - .ne => 0b1100 - .r => 0b0001 - .rl => 0b0011 - .rle => 0b0101 - .re => 0b0111 - .rge => 0b1001 - .re => 0b1011 - .rne => 0b1101 -} - -#ruledef -{ - CNST{flags: crflags} {dst: operand}, #{imm: i16} => imm[7:0] @ imm[15:8] @ 0b0 @ dst @ flags @ 0b0000 - CMPR{flags: crflags} {dst: operand}, {a: operand} => 0b0 @ a @ 0x00 @ 0b0 @ dst @ flags @ 0b0001 - BWNG{flags: crflags} {dst: operand}, {a: operand} => 0b0 @ a @ 0x01 @ 0b0 @ dst @ flags @ 0b0001 - ARNG{flags: crflags} {dst: operand}, {a: operand} => 0b0 @ a @ 0x02 @ 0b0 @ dst @ flags @ 0b0001 - LONG{flags: crflags} {dst: operand}, {a: operand} => 0b0 @ a @ 0x03 @ 0b0 @ dst @ flags @ 0b0001 - CONF{flags: crflags} {dst: operand}, {a: operand} => 0b0 @ a @ 0x04 @ 0b0 @ dst @ flags @ 0b0001 - BWOR{flags: crflags} {dst: operand}, {a: operand}, {b: operand} => 0b0 @ a @ 0b0 @ b @ 0b0 @ dst @ flags @ 0b0010 - BAND{flags: crflags} {dst: operand}, {a: operand}, {b: operand} => 0b0 @ a @ 0b0 @ b @ 0b0 @ dst @ flags @ 0b0011 - BXOR{flags: crflags} {dst: operand}, {a: operand}, {b: operand} => 0b0 @ a @ 0b0 @ b @ 0b0 @ dst @ flags @ 0b0100 - SRSH{flags: crflags} {dst: operand}, {a: operand}, {b: operand} => 0b0 @ a @ 0b0 @ b @ 0b0 @ dst @ flags @ 0b0110 - ZLSH{flags: crflags} {dst: operand}, {a: operand}, {b: operand} => 0b0 @ a @ 0b0 @ b @ 0b0 @ dst @ flags @ 0b0111 - CLSH{flags: crflags} {dst: operand}, {a: operand}, {b: operand} => 0b0 @ a @ 0b0 @ b @ 0b0 @ dst @ flags @ 0b1000 - ADDI{flags: crflags} {dst: operand}, {a: operand}, {b: operand} => 0b0 @ a @ 0b0 @ b @ 0b0 @ dst @ flags @ 0b1001 - ADDI{flags: crflags}v {dst: operand}, {a: operand}, {b: operand} => 0b1 @ a @ 0b0 @ b @ 0b1 @ dst @ flags @ 0b1001 - SUBT{flags: crflags} {dst: operand}, {a: operand}, {b: operand} => 0b0 @ a @ 0b0 @ b @ 0b0 @ dst @ flags @ 0b1010 - MULT{flags: crflags} {dst: operand}, {a: operand}, {b: operand} => 0b0 @ a @ 0b0 @ b @ 0b0 @ dst @ flags @ 0b1011 - DIVI{flags: crflags} {dst: operand}, {a: operand}, {b: operand} => 0b0 @ a @ 0b0 @ b @ 0b0 @ dst @ flags @ 0b1100 - MODU{flags: crflags} {dst: operand}, {a: operand}, {b: operand} => 0b0 @ a @ 0b0 @ b @ 0b0 @ dst @ flags @ 0b1101 -} - -#bankdef mem -{ - #bits 32 - #addr 0 - #size 0x10000 - #outp 0 -} - -#bank mem diff --git a/emulator/customasm/memview.asm b/emulator/customasm/memview.asm deleted file mode 100644 index 81cdd8f..0000000 --- a/emulator/customasm/memview.asm +++ /dev/null @@ -1,10 +0,0 @@ -#include "foot.asm" - -CNST. r30, #0x1000 - -loop: -CNST. r0, #0xEFFE -ADDI.r [r0++], [r0], r30 -CNST. r0, #0xEFFE -ADDI.rv [r0++], [r0], r30 -CNST. r31, #loop diff --git a/emulator/include/foot-emulator.h b/emulator/include/foot-emulator.h index cc4a2ce..542ae7b 100644 --- a/emulator/include/foot-emulator.h +++ b/emulator/include/foot-emulator.h @@ -33,13 +33,15 @@ public: virtual uint16_t mapped_memory_size() const { return assigned_memory_size; } protected: - Device(uint16_t size); + Device(uint16_t size, unsigned int update_frequency); uint32_t& memory(uint16_t index); private: uint32_t* assigned_memory_base; uint32_t assigned_memory_size; + + unsigned int update_frequency; }; class Emulator @@ -52,8 +54,11 @@ public: Emulator(); + Emulator(const Emulator&) = delete; + Emulator& operator=(const Emulator&) = delete; + void run(const std::vector& program); - void run(std::istream& program); + void run(const std::string& filename); void map_device(std::unique_ptr&& device); @@ -75,7 +80,7 @@ private: uint32_t instruction; uint32_t configuration; uint32_t dummy_value; - std::vector> devices; + std::vector, unsigned int>> devices; uint32_t mapped_base; bool keep_running; @@ -88,6 +93,7 @@ private: void ARNG(); void LONG(); void CONF(); + void COPY(); void BWOR(); void BAND(); void BXOR(); diff --git a/emulator/src/foot-emulator.cpp b/emulator/src/foot-emulator.cpp index 145f9d3..4e1f1ff 100644 --- a/emulator/src/foot-emulator.cpp +++ b/emulator/src/foot-emulator.cpp @@ -12,9 +12,10 @@ Operand::Operand(uint8_t bits) : register_index(bits & 0b00011111) {} -Device::Device(uint16_t size) : +Device::Device(uint16_t size, unsigned int update_frequency) : assigned_memory_base(nullptr), - assigned_memory_size(size) + assigned_memory_size(size), + update_frequency(update_frequency) {} uint32_t& Device::memory(uint16_t index) @@ -42,25 +43,17 @@ void Emulator::run(const std::vector& program) run_internal(); } -void Emulator::run(std::istream& program) +void Emulator::run(const std::string& filename) { ELFIO::elfio reader; - reader.load(program); - for (const auto& seg : reader.segments) + if (!reader.load(filename)) { return; } + + for (const auto& segment : reader.segments) { + if (segment->get_type() != ELFIO::PT_LOAD) { continue; } - uint64_t dest = seg->get_virtual_address(); - uint64_t msize = seg->get_memory_size(); - uint64_t fsize = seg->get_file_size(); - const char* data = seg->get_data(); - - if (seg->get_type() != ELFIO::PT_LOAD) - { - continue; - } - - memcpy(reinterpret_cast(memory.data()) + dest, data, fsize); + memcpy(reinterpret_cast(memory.data()) + segment->get_virtual_address(), segment->get_data(), segment->get_file_size()); } registers[PC] = reader.get_entry() / 4; @@ -72,7 +65,7 @@ void Emulator::map_device(std::unique_ptr&& device) { device->assigned_memory_base = &memory[mapped_base]; mapped_base += device->mapped_memory_size(); - devices.push_back(std::move(device)); + devices.emplace_back(std::move(device), 0); } uint32_t& Emulator::memory_at(uint32_t address) @@ -151,6 +144,10 @@ void Emulator::run_instruction() case 4: CONF(); break; + + case 5: + COPY(); + break; } break; @@ -216,11 +213,19 @@ void Emulator::run_internal() while (keep_running) { run_instruction(); - for (const auto& device : devices) + for (auto& [device, current_interval] : devices) { - if (device->update()) + if (current_interval == device->update_frequency) { - keep_running = false; + current_interval = 0; + if (device->update()) + { + keep_running = false; + } + } + else + { + current_interval += 1; } } } @@ -288,6 +293,14 @@ void Emulator::CONF() configuration = a; } +void Emulator::COPY() +{ + uint32_t a = decode_operand(instruction & 0x000000FF); + uint32_t& d = decode_operand((instruction & 0x00FF0000) >> 16); + + d = a; +} + void Emulator::BWOR() { uint32_t a = decode_operand(instruction & 0x000000FF); @@ -532,4 +545,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 6faa957..966dfc9 100644 --- a/emulator/src/main.cpp +++ b/emulator/src/main.cpp @@ -12,7 +12,7 @@ class PrintDevice : public foot::Device { public: PrintDevice() : - Device(1) + Device(1, 1) { } @@ -21,7 +21,8 @@ public: uint32_t& value = memory(0); if (value != 0) { - SDL_Log("%1s", (char*)&value); + fprintf(stdout, "%d\n", value); + fflush(stdout); value = 0; } @@ -33,7 +34,7 @@ class MemoryViewDevice : public foot::Device { public: MemoryViewDevice(SDL_Renderer* render, uint8_t width, uint8_t height) : - Device(width * height), + Device(width * height, 100000), render(render), texture(SDL_CreateTexture(render, SDL_PIXELFORMAT_RGBA32, SDL_TEXTUREACCESS_STREAMING, width, height)), width(width), @@ -54,12 +55,11 @@ public: { std::cout << SDL_GetError() << std::endl; } - int idx = 0; for (int i = 0; i < width; i++) { for (int j = 0; j < height; j++) { - pixels[i + j * width] = memory(i + j * width); + pixels[i + j * width] = memory(i + j * width) | 0xFF000000; } } SDL_UnlockTexture(texture); @@ -96,14 +96,6 @@ int main(int argc, char** argv) constexpr int WIDTH = 64; constexpr int HEIGHT = 64; - std::ifstream file(argv[1], std::ios::binary); - - if (!file.is_open()) - { - std::cerr << "Failed to open file: " << argv[1] << std::endl; - return 1; - } - SDL_Window* window; SDL_Renderer* render; @@ -114,7 +106,7 @@ int main(int argc, char** argv) emu.map_device(std::make_unique()); emu.map_device(std::make_unique(render, WIDTH, HEIGHT)); - emu.run(file); + emu.run(argv[1]); SDL_DestroyRenderer(render); SDL_DestroyWindow(window); @@ -127,4 +119,4 @@ int main(int argc, char** argv) } return 1; -} +} \ No newline at end of file diff --git a/emulator/tests/zlsh-instruction.cpp b/emulator/tests/zlsh-instruction.cpp index 128893d..287b2d0 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) { diff --git a/foot.script b/foot.script new file mode 100644 index 0000000..d6b2233 --- /dev/null +++ b/foot.script @@ -0,0 +1,11 @@ +MEMORY +{ + default (RWX) : ORIGIN = 0x0, LENGTH = 256K +} + +ENTRY(entry); + +SECTIONS +{ + . = 0x0; +}