diff --git a/emulator/src/foot-emulator.cpp b/emulator/src/foot-emulator.cpp index 47d495d..b525582 100644 --- a/emulator/src/foot-emulator.cpp +++ b/emulator/src/foot-emulator.cpp @@ -27,6 +27,7 @@ uint16_t& Device::memory(uint16_t index) Emulator::Emulator() : memory{}, registers{}, + configuration(0), mapped_base(0) {} @@ -349,7 +350,8 @@ void Emulator::DIVI() uint16_t b = decode_operand((instruction & 0x0000FF00) >> 8); uint16_t& d = decode_operand((instruction & 0x00FF0000) >> 16); - d = uint32_t((int32_t(a) >> shift()) / int32_t(b)); + // convert from unsigned to signed, then widen + d = uint32_t((int32_t(int16_t(a)) << shift()) / int32_t(int16_t(b))); } void Emulator::MODU() @@ -358,7 +360,7 @@ void Emulator::MODU() uint16_t b = decode_operand((instruction & 0x0000FF00) >> 8); uint16_t& d = decode_operand((instruction & 0x00FF0000) >> 16); - d = uint32_t((int32_t(a) >> shift()) / int32_t(b)); + d = int16_t(a) % int16_t(b); } bool Emulator::repeats() diff --git a/emulator/tests/CMakeLists.txt b/emulator/tests/CMakeLists.txt index e674353..7960f0b 100644 --- a/emulator/tests/CMakeLists.txt +++ b/emulator/tests/CMakeLists.txt @@ -17,3 +17,9 @@ test(band-instruction) test(bxor-instruction) test(srsh-instruction) test(zlsh-instruction) +test(clsh-instruction) +test(addi-instruction) +test(subt-instruction) +test(mult-instruction) +test(divi-instruction) +test(modu-instruction) diff --git a/emulator/tests/addi-instruction.cpp b/emulator/tests/addi-instruction.cpp new file mode 100644 index 0000000..bff41f1 --- /dev/null +++ b/emulator/tests/addi-instruction.cpp @@ -0,0 +1,36 @@ +#include "test-common.h" + +int main(int argc, char** argv) +{ + // CNST + // dst - 0, Direct + // imm - 0x4567 + // + // ADDI + // dst - 0, Direct + // a - 0, Direct + // b - 2, Immediate + { + foot::Emulator emu = run_instructions({ 0x00204567, 0x09200220 }); + if (!check(0x4569, emu.register_at(0))) { return 1; } + } + + // CNST + // dst - 0, Direct + // imm - 0x4567 + // + // CNST + // dst - 1, Direct + // imm = 0xFFFE (-2) + // + // ADDI + // dst - 0, Direct + // a - 0, Direct + // b - 1, Direct + { + foot::Emulator emu = run_instructions({ 0x00204567, 0x0021FFFE, 0x09202120 }); + if (!check(0x4565, emu.register_at(0))) { return 1; } + } + + return 0; +} diff --git a/emulator/tests/clsh-instruction.cpp b/emulator/tests/clsh-instruction.cpp new file mode 100644 index 0000000..c9c9db5 --- /dev/null +++ b/emulator/tests/clsh-instruction.cpp @@ -0,0 +1,19 @@ +#include "test-common.h" + +int main(int argc, char** argv) +{ + // CNST + // dst - 0, Direct + // imm - 0x4567 + // + // CLSH + // dst - 0, Direct + // a - 0, Direct + // b - 2, Immediate + { + foot::Emulator emu = run_instructions({ 0x00204567, 0x08200220 }); + if (!check(0x159D, emu.register_at(0))) { return 1; } + } + + return 0; +} diff --git a/emulator/tests/divi-instruction.cpp b/emulator/tests/divi-instruction.cpp new file mode 100644 index 0000000..4df438c --- /dev/null +++ b/emulator/tests/divi-instruction.cpp @@ -0,0 +1,75 @@ +#include "test-common.h" + +int main(int argc, char** argv) +{ + // CNST + // dst - 0, Direct + // imm - 0x0005 + // + // DIVI + // dst - 0, Direct + // a - 0, Direct + // b - 2, Immediate + { + foot::Emulator emu = run_instructions({ 0x00200005, 0x0E200220 }); + if (!check(0x0002, emu.register_at(0))) { return 1; } + } + + // CNST + // dst - 0, Direct + // imm - 0x0007 + // + // CNST + // dst - 1, Direct + // imm = 0xFFF9 (-7) + // + // DIVI + // dst - 0, Direct + // a - 0, Direct + // b - 1, Direct + { + foot::Emulator emu = run_instructions({ 0x00200007, 0x0021FFF9, 0x0E202120 }); + if (!check(0xFFFF, emu.register_at(0))) { return 1; } + } + + // CNST + // dst - 0, Direct + // imm - 0xFFF9 (-7) + // + // CNST + // dst - 1, Direct + // imm = 0xFFF9 (-7) + // + // DIVI + // dst - 0, Direct + // a - 0, Direct + // b - 1, Direct + { + foot::Emulator emu = run_instructions({ 0x0020FFF9, 0x0021FFF9, 0x0E202120 }); + if (!check(0x1, emu.register_at(0))) { return 1; } + } + + // CNST + // dst - 0, Direct + // imm - 0x0002 (1) + // + // CNST + // dst - 1, Direct + // imm = 0x0001 (0.5) + // + // CONF + // dst - X, Immediate + // a - 1, Immediate + // + // MULT + // dst - 0, Direct + // a - 0, Direct + // b - 1, Direct + { + foot::Emulator emu = run_instructions({ 0x00200002, 0x00210001, 0x01000401, 0x0E202120 }); + // 0x4 (2) + if (!check(0x4, emu.register_at(0))) { return 1; } + } + + return 0; +} diff --git a/emulator/tests/modu-instruction.cpp b/emulator/tests/modu-instruction.cpp new file mode 100644 index 0000000..5a27907 --- /dev/null +++ b/emulator/tests/modu-instruction.cpp @@ -0,0 +1,75 @@ +#include "test-common.h" + +int main(int argc, char** argv) +{ + // CNST + // dst - 0, Direct + // imm - 0x0005 + // + // DIVI + // dst - 0, Direct + // a - 0, Direct + // b - 2, Immediate + { + foot::Emulator emu = run_instructions({ 0x00200005, 0x0F200220 }); + if (!check(0x1, emu.register_at(0))) { return 1; } + } + + // CNST + // dst - 0, Direct + // imm - 0x0005 + // + // CNST + // dst - 1, Direct + // imm = 0xFFFE (-2) + // + // DIVI + // dst - 0, Direct + // a - 0, Direct + // b - 1, Direct + { + foot::Emulator emu = run_instructions({ 0x00200005, 0x0021FFFE, 0x0F202120 }); + if (!check(0x1, emu.register_at(0))) { return 1; } + } + + // CNST + // dst - 0, Direct + // imm - 0xFFFE (-2) + // + // CNST + // dst - 1, Direct + // imm = 0x0005 + // + // DIVI + // dst - 0, Direct + // a - 0, Direct + // b - 1, Direct + { + foot::Emulator emu = run_instructions({ 0x0020FFFE, 0x00210005, 0x0F202120 }); + if (!check(0xFFFE, emu.register_at(0))) { return 1; } + } + + // CNST + // dst - 0, Direct + // imm - 0x0005 (2.5) + // + // CNST + // dst - 1, Direct + // imm = 0x0003 (1.5) + // + // CONF + // dst - X, Immediate + // a - 1, Immediate + // + // MULT + // dst - 0, Direct + // a - 0, Direct + // b - 1, Direct + { + foot::Emulator emu = run_instructions({ 0x00200005, 0x00210003, 0x01000401, 0x0F202120 }); + + 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 new file mode 100644 index 0000000..4692761 --- /dev/null +++ b/emulator/tests/mult-instruction.cpp @@ -0,0 +1,75 @@ +#include "test-common.h" + +int main(int argc, char** argv) +{ + // CNST + // dst - 0, Direct + // imm - 0x0003 + // + // MULT + // dst - 0, Direct + // a - 0, Direct + // b - 2, Immediate + { + foot::Emulator emu = run_instructions({ 0x00200003, 0x0B200220 }); + if (!check(0x0006, emu.register_at(0))) { return 1; } + } + + // CNST + // dst - 0, Direct + // imm - 0x0007 + // + // CNST + // dst - 1, Direct + // imm = 0xFFF9 (-7) + // + // MULT + // dst - 0, Direct + // a - 0, Direct + // b - 1, Direct + { + foot::Emulator emu = run_instructions({ 0x00200007, 0x0021FFF9, 0x0B202120 }); + if (!check(0xFFCF, emu.register_at(0))) { return 1; } + } + + // CNST + // dst - 0, Direct + // imm - 0xFFF9 (-7) + // + // CNST + // dst - 1, Direct + // imm = 0xFFF9 (-7) + // + // MULT + // dst - 0, Direct + // a - 0, Direct + // b - 1, Direct + { + foot::Emulator emu = run_instructions({ 0x0020FFF9, 0x0021FFF9, 0x0B202120 }); + if (!check(0x31, emu.register_at(0))) { return 1; } + } + + // CNST + // dst - 0, Direct + // imm - 0x0007 (3.5) + // + // CNST + // dst - 1, Direct + // imm = 0x0007 (3.5) + // + // CONF + // dst - X, Immediate + // a - 1, Immediate + // + // MULT + // dst - 0, Direct + // a - 0, Direct + // b - 1, Direct + { + foot::Emulator emu = run_instructions({ 0x00200007, 0x00210007, 0x01000401, 0x0B202120 }); + // 0x18 (12) + if (!check(0x18, emu.register_at(0))) { return 1; } + } + + return 0; +} diff --git a/emulator/tests/subt-instruction.cpp b/emulator/tests/subt-instruction.cpp new file mode 100644 index 0000000..5d52f45 --- /dev/null +++ b/emulator/tests/subt-instruction.cpp @@ -0,0 +1,36 @@ +#include "test-common.h" + +int main(int argc, char** argv) +{ + // CNST + // dst - 0, Direct + // imm - 0x4567 + // + // SUBT + // dst - 0, Direct + // a - 0, Direct + // b - 2, Immediate + { + foot::Emulator emu = run_instructions({ 0x00204567, 0x0A200220 }); + if (!check(0x4565, emu.register_at(0))) { return 1; } + } + + // CNST + // dst - 0, Direct + // imm - 0x4567 + // + // CNST + // dst - 1, Direct + // imm = 0xFFFE (-2) + // + // SUBT + // dst - 0, Direct + // a - 0, Direct + // b - 1, Direct + { + foot::Emulator emu = run_instructions({ 0x00204567, 0x0021FFFE, 0x0A202120 }); + if (!check(0x4569, emu.register_at(0))) { return 1; } + } + + return 0; +}