From e647b9e146d91f81332c28ea8be3cf5ceb7df6e9 Mon Sep 17 00:00:00 2001 From: shylie Date: Tue, 19 Aug 2025 08:03:58 -0400 Subject: [PATCH] Add some tests for SIMD instruction variants --- emulator/customasm/first.asm | 6 ++-- emulator/customasm/foot.asm | 47 ++++++++++++++--------------- emulator/customasm/memview.asm | 4 ++- emulator/include/foot-emulator.h | 4 +-- emulator/src/foot-emulator.cpp | 12 +++++--- emulator/src/main.cpp | 39 +++++++++--------------- emulator/tests/arng-instruction.cpp | 12 ++++++++ emulator/tests/cnst-instruction.cpp | 2 +- emulator/tests/long-instruction.cpp | 13 ++++++++ emulator/tests/srsh-instruction.cpp | 17 +++++++++++ emulator/tests/zlsh-instruction.cpp | 18 +++++++++++ 11 files changed, 113 insertions(+), 61 deletions(-) diff --git a/emulator/customasm/first.asm b/emulator/customasm/first.asm index 8959677..32e33e7 100644 --- a/emulator/customasm/first.asm +++ b/emulator/customasm/first.asm @@ -1,8 +1,8 @@ #include "foot.asm" -CNST. r0, #0xFFFF +CNST. r1, #0xFFFF loop: -CNST. [r0], #65 -CNST. [r0], #66 +CNST. [r1], #65 +CNST. [r1], #66 CNST. r31, #loop diff --git a/emulator/customasm/foot.asm b/emulator/customasm/foot.asm index 049dc5c..4a5c3de 100644 --- a/emulator/customasm/foot.asm +++ b/emulator/customasm/foot.asm @@ -2,12 +2,10 @@ #subruledef operand { - #{immediate: i5} => 0b000 @ immediate - r{register: u5} => 0b001 @ register - [r{register: u5}++] => 0b010 @ register - [r{register: u5}--] => 0b011 @ register - [r{register: u5}] => 0b100 @ register - [r{register: u5} + {offset: u2}] => 0b1 @ offset @ register + #{immediate: i5} => 0b00 @ immediate + r{register: u5} => 0b01 @ register + [r{register: u5}] => 0b10 @ register + [r{register: u5}++] => 0b11 @ register } #subruledef crflags @@ -30,28 +28,29 @@ #ruledef { - CNST{flags: crflags} {dst: operand}, #{imm: i16} => imm @ flags @ 0b0000 @ dst - CMPR{flags: crflags} {dst: operand}, {a: operand} => 0x00 @ a @ flags @ 0b0001 @ dst - BWNG{flags: crflags} {dst: operand}, {a: operand} => 0x01 @ a @ flags @ 0b0001 @ dst - ARNG{flags: crflags} {dst: operand}, {a: operand} => 0x02 @ a @ flags @ 0b0001 @ dst - LONG{flags: crflags} {dst: operand}, {a: operand} => 0x03 @ a @ flags @ 0b0001 @ dst - BWOR{flags: crflags} {dst: operand}, {a: operand}, {b: operand} => b @ a @ flags @ 0b0010 @ dst - BAND{flags: crflags} {dst: operand}, {a: operand}, {b: operand} => b @ a @ flags @ 0b0011 @ dst - BXOR{flags: crflags} {dst: operand}, {a: operand}, {b: operand} => b @ a @ flags @ 0b0100 @ dst - URSH{flags: crflags} {dst: operand}, {a: operand}, {b: operand} => b @ a @ flags @ 0b0101 @ dst - SRSH{flags: crflags} {dst: operand}, {a: operand}, {b: operand} => b @ a @ flags @ 0b0110 @ dst - ZLSH{flags: crflags} {dst: operand}, {a: operand}, {b: operand} => b @ a @ flags @ 0b0111 @ dst - CLSH{flags: crflags} {dst: operand}, {a: operand}, {b: operand} => b @ a @ flags @ 0b1000 @ dst - ADDI{flags: crflags} {dst: operand}, {a: operand}, {b: operand} => b @ a @ flags @ 0b1001 @ dst - SUBT{flags: crflags} {dst: operand}, {a: operand}, {b: operand} => b @ a @ flags @ 0b1010 @ dst - MULT{flags: crflags} {dst: operand}, {a: operand}, {b: operand} => b @ a @ flags @ 0b1011 @ dst - DIVI{flags: crflags} {dst: operand}, {a: operand}, {b: operand} => b @ a @ flags @ 0b1110 @ dst - MODU{flags: crflags} {dst: operand}, {a: operand}, {b: operand} => b @ a @ flags @ 0b1111 @ dst + 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 16 + #bits 32 #addr 0 #size 0x10000 #outp 0 diff --git a/emulator/customasm/memview.asm b/emulator/customasm/memview.asm index 5993a65..81cdd8f 100644 --- a/emulator/customasm/memview.asm +++ b/emulator/customasm/memview.asm @@ -4,5 +4,7 @@ CNST. r30, #0x1000 loop: CNST. r0, #0xEFFE -CNST.r [r0++], #29 +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 8683742..3d57f03 100644 --- a/emulator/include/foot-emulator.h +++ b/emulator/include/foot-emulator.h @@ -17,8 +17,8 @@ struct Operand { Immediate = 0, Direct, - IndirectAutoIncrement, - Indirect + Indirect, + IndirectAutoIncrement } addressing_mode; uint8_t register_index; }; diff --git a/emulator/src/foot-emulator.cpp b/emulator/src/foot-emulator.cpp index 2acb44a..6edd161 100644 --- a/emulator/src/foot-emulator.cpp +++ b/emulator/src/foot-emulator.cpp @@ -369,8 +369,9 @@ uint32_t Emulator::apply_many_unary(uint32_t a, uint32_t (Emulator::*fn)(uint32_ for (int i = 0; i < simd_elements(); i++) { - uint32_t simd_element_a = (a >> (i * 32 / simd_elements())) & ((uint64_t(1) << (32 / simd_elements())) - 1); - uint32_t simd_result = (this->*fn)(simd_element_a) << (i * 32 / simd_elements()); + 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()); result |= simd_result; } @@ -383,9 +384,10 @@ uint32_t Emulator::apply_many_binary(uint32_t a, uint32_t b, uint32_t (Emulator: for (int i = 0; i < simd_elements(); i++) { - uint32_t simd_element_a = (a >> (i * 32 / simd_elements())) & ((uint64_t(1) << (32 / simd_elements())) - 1); - uint32_t simd_element_b = (b >> (i * 32 / simd_elements())) & ((uint64_t(1) << (32 / simd_elements())) - 1); - uint32_t simd_result = (this->*fn)(simd_element_a, simd_element_b) << (i * 32 / simd_elements()); + 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()); result |= simd_result; } diff --git a/emulator/src/main.cpp b/emulator/src/main.cpp index 40589fd..d221f62 100644 --- a/emulator/src/main.cpp +++ b/emulator/src/main.cpp @@ -15,14 +15,14 @@ std::vector read_file(std::istream& stream) std::streampos pos = stream.tellg(); stream.seekg(0, std::ios::end); pos = stream.tellg() - pos; - buf.resize(pos / 2); + buf.resize(pos / 4); stream.seekg(0, std::ios::beg); for (int i = 0; i < buf.size(); i++) { - char value[4] = {}; - stream.read(value, 4); - buf[i] = uint32_t(value[0]) | uint32_t(value[1]) << 8 | uint32_t(value[2]) << 16 | uint32_t(value[3]) << 24; + unsigned char value[4] = {}; + stream.read((char*)value, 4); + buf[i] = uint32_t(value[0]) | (uint32_t(value[1]) << 8) | (uint32_t(value[2]) << 16) | (uint32_t(value[3]) << 24); } return buf; @@ -53,12 +53,14 @@ class MemoryViewDevice : public foot::Device { public: MemoryViewDevice(SDL_Renderer* render, uint8_t width, uint8_t height) : - Device(width * height / 2), + Device(width * height), render(render), - texture(SDL_CreateTexture(render, SDL_PIXELFORMAT_RGB24, 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); @@ -67,34 +69,22 @@ public: bool update() override { int pitch; - uint8_t* pixels; + uint32_t* pixels; if (!SDL_LockTexture(texture, nullptr, (void**)&pixels, &pitch)) { std::cout << SDL_GetError() << std::endl; } int idx = 0; - for (int i = 0; i < width / 2; i++) + for (int i = 0; i < width; i++) { for (int j = 0; j < height; j++) { - //TODO: fix - const uint16_t mem = memory(i + j * width / 2); - - const uint8_t left = mem & 0xFF; - const uint8_t right = mem >> 8; - - pixels[idx + 0] = left; - pixels[idx + 1] = left; - pixels[idx + 2] = left; - pixels[idx + 3] = right; - pixels[idx + 4] = right; - pixels[idx + 5] = right; - - idx += 6; + pixels[i + j * width] = memory(i + j * width); } } SDL_UnlockTexture(texture); + SDL_RenderTexture(render, texture, nullptr, nullptr); SDL_RenderPresent(render); SDL_Event event; @@ -121,7 +111,6 @@ private: int main(int argc, char** argv) { - if (argc > 1) { constexpr int WIDTH = 64; @@ -139,7 +128,7 @@ int main(int argc, char** argv) SDL_Renderer* render; SDL_Init(SDL_INIT_VIDEO); - SDL_CreateWindowAndRenderer("foot emulator", WIDTH * 4, HEIGHT * 4, 0, &window, &render); + SDL_CreateWindowAndRenderer("foot emulator", WIDTH * 8, HEIGHT * 8, 0, &window, &render); foot::Emulator emu; emu.map_device(std::make_unique()); diff --git a/emulator/tests/arng-instruction.cpp b/emulator/tests/arng-instruction.cpp index 0ced256..3e48ebf 100644 --- a/emulator/tests/arng-instruction.cpp +++ b/emulator/tests/arng-instruction.cpp @@ -14,5 +14,17 @@ int main(int argc, char** argv) if (!check(0xFFFFBA99, emu.register_at(0))) { return 1; } } + // CNST + // dst - 0, Direct + // imm - 0x4567 + // + // ARNG 4-bit SIMD + // dst - 0, Direct + // a - 0, Direct + { + foot::Emulator emu = run_instructions({ 0x00204567, 0x01A002A0 }); + if (!check(0x0000CBA9, emu.register_at(0))) { return 1; } + } + return 0; } diff --git a/emulator/tests/cnst-instruction.cpp b/emulator/tests/cnst-instruction.cpp index 3150fac..4c62fe9 100644 --- a/emulator/tests/cnst-instruction.cpp +++ b/emulator/tests/cnst-instruction.cpp @@ -31,7 +31,7 @@ int main(int argc, char** argv) // imm = 0x1234 { bool failed = false; - foot::Emulator emu = run_instructions({ 0x003E0010, 0x10501234 }); + foot::Emulator emu = run_instructions({ 0x003E0010, 0x10601234 }); for (int i = 0; i < 0x10; i++) { if (!check(0x1234, emu.memory_at(i))) { failed = true; } diff --git a/emulator/tests/long-instruction.cpp b/emulator/tests/long-instruction.cpp index f6e22b0..6703838 100644 --- a/emulator/tests/long-instruction.cpp +++ b/emulator/tests/long-instruction.cpp @@ -22,5 +22,18 @@ int main(int argc, char** argv) if (!check(0x00000001, emu.register_at(0))) { return 1; } } + // CNST + // dst - 0, Direct + // imm - 0x0230 + // + // LONG 4-bit SIMD + // dst - 0, Direct + // a - 0, Direct + { + foot::Emulator emu = run_instructions({ 0x00200230, 0x01A003A0 }); + if (!check(0x11111001, emu.register_at(0))) { return 1; } + } + + return 0; } diff --git a/emulator/tests/srsh-instruction.cpp b/emulator/tests/srsh-instruction.cpp index 405942a..f48f80d 100644 --- a/emulator/tests/srsh-instruction.cpp +++ b/emulator/tests/srsh-instruction.cpp @@ -27,5 +27,22 @@ int main(int argc, char** argv) if (!check((-2) >> 2, emu.register_at(0))) { return 1; } } + // CNST + // dst - 0, Direct + // imm - 0x8686 + // + // CNST + // dst - 1, Direct + // imm - 0x1122 + // + // SRSH - 4-bit SIMD + // dst - 0, Direct + // a - 0, Direct + // b - 1, Direct + { + foot::Emulator emu = run_instructions({ 0x00208686, 0x00211122, 0x06A021A0 }); + if (!check(0x4321, emu.register_at(0))) { return 1; } + } + return 0; } diff --git a/emulator/tests/zlsh-instruction.cpp b/emulator/tests/zlsh-instruction.cpp index 24bd1e5..128893d 100644 --- a/emulator/tests/zlsh-instruction.cpp +++ b/emulator/tests/zlsh-instruction.cpp @@ -15,5 +15,23 @@ int main(int argc, char** argv) if (!check(0x0001159C, emu.register_at(0))) { return 1; } } + // CNST + // dst - 0, Direct + // imm - 0x4343 + // + // CNST + // dst - 1, Direct + // imm - 0x1122 + // + // ZLSH - 4-bit SIMD + // dst - 0, Direct + // a - 0, Direct + // b - 1, Direct + { + foot::Emulator emu = run_instructions({ 0x00204343, 0x00211122, 0x07A021A0 }); + if (!check(0x860C, emu.register_at(0))) { return 1; } + } + + return 0; }