diff options
author | bd <bdunahu@operationnull.com> | 2025-04-22 02:16:10 -0400 |
---|---|---|
committer | bd <bdunahu@operationnull.com> | 2025-04-22 02:16:10 -0400 |
commit | 86a6253a2fb2d016a63e57d6a5e5461df87668e5 (patch) | |
tree | b262ededf7e993090d7a860b76ca528b5651c3c6 | |
parent | cf8f181af044141f754404c1174bc3317a123d93 (diff) |
Properly set condition codes for all operations sub SHIFTs
-rw-r--r-- | inc/ex.h | 25 | ||||
-rw-r--r-- | src/sim/ex.cc | 32 | ||||
-rw-r--r-- | tests/ex.cc | 249 |
3 files changed, 255 insertions, 51 deletions
@@ -23,6 +23,31 @@ #include <exception> #include <unordered_map> +#define ADDITION_OF_GUARD(a, b) \ + (b >= 0) && (a > MAX_INT - b) + +#define ADDITION_UF_GUARD(a, b) \ + (b < 0) && (a < (-(MAX_INT)-1) - b) + +#define SUBTRACTION_OF_GUARD(a, b) \ + (b < 0) && (a > MAX_INT + b) + +#define SUBTRACTION_UF_GUARD(a, b) \ + (b >= 0) && (a < (-(MAX_INT)-1) + b) + +#define MULTIPLICATION_OF_GUARD(a, b) \ + (b != 0) && \ + (((b > 0) && (a > 0) && (a > MAX_INT / b)) || \ + ((b < 0) && (a < 0) && (a < MAX_INT / b))) + +#define MULTIPLICATION_UF_GUARD(a, b) \ + (b != 0) && \ + (((b > 0) && (a < 0) && (a < (-(MAX_INT)-1) / b)) || \ + ((b < 0) && (a > 0) && (a > (-(MAX_INT)-1) / b))) + +#define DIVISION_OF_GUARD(a, b) \ + ((a == -(MAX_INT) - 1) && (b == -1)) || (b == 0) + class HaltException : public std::exception { const char *what() const noexcept override { diff --git a/src/sim/ex.cc b/src/sim/ex.cc index 4db9fa7..d345ecf 100644 --- a/src/sim/ex.cc +++ b/src/sim/ex.cc @@ -39,6 +39,8 @@ EX::EX(Stage *stage) : Stage(stage) INIT_INSTRUCTION( ADD, { + this->set_condition(OF, ADDITION_OF_GUARD(s1, s2)); + this->set_condition(UF, ADDITION_UF_GUARD(s1, s2)); s1 = s1 + s2; (void)pc; (void)s3; @@ -48,6 +50,8 @@ EX::EX(Stage *stage) : Stage(stage) INIT_INSTRUCTION( SUB, { + this->set_condition(OF, SUBTRACTION_OF_GUARD(s1, s2)); + this->set_condition(UF, SUBTRACTION_UF_GUARD(s1, s2)); s1 = s1 - s2; (void)pc; (void)s3; @@ -57,6 +61,8 @@ EX::EX(Stage *stage) : Stage(stage) INIT_INSTRUCTION( MUL, { + this->set_condition(OF, MULTIPLICATION_OF_GUARD(s1, s2)); + this->set_condition(UF, MULTIPLICATION_UF_GUARD(s1, s2)); s1 = s1 * s2; (void)pc; (void)s3; @@ -75,7 +81,6 @@ EX::EX(Stage *stage) : Stage(stage) REM, { this->handle_divide(s1, s2, true); - s1 = s1 % s2; (void)pc; (void)s3; (void)this; @@ -102,6 +107,8 @@ EX::EX(Stage *stage) : Stage(stage) INIT_INSTRUCTION( AND, { + this->set_condition(OF, false); + this->set_condition(UF, false); s1 = s1 & s2; (void)pc; (void)s3; @@ -111,6 +118,8 @@ EX::EX(Stage *stage) : Stage(stage) INIT_INSTRUCTION( OR, { + this->set_condition(OF, false); + this->set_condition(UF, false); s1 = s1 | s2; (void)pc; (void)s3; @@ -120,6 +129,8 @@ EX::EX(Stage *stage) : Stage(stage) INIT_INSTRUCTION( NOT, { + this->set_condition(OF, false); + this->set_condition(UF, false); s1 = ~s1; (void)pc; (void)s3; @@ -130,6 +141,8 @@ EX::EX(Stage *stage) : Stage(stage) INIT_INSTRUCTION( XOR, { + this->set_condition(OF, false); + this->set_condition(UF, false); s1 = s1 ^ s2; (void)pc; (void)s3; @@ -220,6 +233,8 @@ EX::EX(Stage *stage) : Stage(stage) INIT_INSTRUCTION( ADDI, { + this->set_condition(OF, ADDITION_OF_GUARD(s1, s3)); + this->set_condition(UF, ADDITION_UF_GUARD(s1, s3)); s1 = s1 + s3; (void)pc; (void)s2; @@ -229,6 +244,8 @@ EX::EX(Stage *stage) : Stage(stage) INIT_INSTRUCTION( SUBI, { + this->set_condition(OF, SUBTRACTION_OF_GUARD(s1, s3)); + this->set_condition(UF, SUBTRACTION_UF_GUARD(s1, s3)); s1 = s1 - s3; (void)pc; (void)s2; @@ -256,6 +273,8 @@ EX::EX(Stage *stage) : Stage(stage) INIT_INSTRUCTION( ANDI, { + this->set_condition(OF, false); + this->set_condition(UF, false); s1 = s1 & s3; (void)pc; (void)s2; @@ -265,6 +284,8 @@ EX::EX(Stage *stage) : Stage(stage) INIT_INSTRUCTION( ORI, { + this->set_condition(OF, false); + this->set_condition(UF, false); s1 = s1 | s3; (void)pc; (void)s2; @@ -274,6 +295,8 @@ EX::EX(Stage *stage) : Stage(stage) INIT_INSTRUCTION( XORI, { + this->set_condition(OF, false); + this->set_condition(UF, false); s1 = s1 ^ s3; (void)pc; (void)s2; @@ -415,12 +438,17 @@ void EX::advance_helper() void EX::handle_divide(signed int &s1, signed int s2, bool is_mod) { + this->set_condition(OF, DIVISION_OF_GUARD(s1, s2)); + this->set_condition(UF, false); if (s2 == 0) { // handle everything here this->curr_instr->set_s1(MAX_INT); this->status = OK; throw HaltException(); + } else if ((s1 == -(MAX_INT)-1) && s2 == -1) { + // undefined in C++ + s1 = -(MAX_INT)-1; } else { - s1 = (is_mod) ? s1 % s2 : s1 / s2; + s1 = (is_mod) ? (s1 % s2) : (s1 / s2); } } diff --git a/tests/ex.cc b/tests/ex.cc index a493a21..400916e 100644 --- a/tests/ex.cc +++ b/tests/ex.cc @@ -64,13 +64,39 @@ TEST_CASE_METHOD(EXFixture, "ADD within bounds", "[ex]") delete i; } -// TEST_CASE_METHOD(EXFixture, "ADD overflow", "[ex]") -// { -// } +TEST_CASE_METHOD(EXFixture, "ADD overflow", "[ex]") +{ + signed int s1, s2, s3; + Mnemonic m; + InstrDTO *i; -// TEST_CASE_METHOD(EXFixture, "ADD underflow", "[ex]") -// { -// } + m = ADD; + s1 = MAX_INT, s2 = 1, s3 = 0; + i = execute_instr(s1, s2, s3, m); + + CHECK(i->get_s1() == -(MAX_INT)-1); + CHECK(ct->get_condition(OF)); + CHECK(!ct->get_condition(UF)); + + delete i; +} + +TEST_CASE_METHOD(EXFixture, "ADD underflow", "[ex]") +{ + signed int s1, s2, s3; + Mnemonic m; + InstrDTO *i; + + m = ADD; + s1 = -(MAX_INT)-1, s2 = -1, s3 = 0; + i = execute_instr(s1, s2, s3, m); + + CHECK(i->get_s1() == MAX_INT); + CHECK(!ct->get_condition(OF)); + CHECK(ct->get_condition(UF)); + + delete i; +} TEST_CASE_METHOD(EXFixture, "SUB within bounds", "[ex]") { @@ -89,13 +115,39 @@ TEST_CASE_METHOD(EXFixture, "SUB within bounds", "[ex]") delete i; } -// TEST_CASE_METHOD(EXFixture, "SUB overflow", "[ex]") -// { -// } +TEST_CASE_METHOD(EXFixture, "SUB overflow", "[ex]") +{ + signed int s1, s2, s3; + Mnemonic m; + InstrDTO *i; -// TEST_CASE_METHOD(EXFixture, "SUB underflow", "[ex]") -// { -// } + m = SUB; + s1 = MAX_INT, s2 = -1, s3 = 0; + i = execute_instr(s1, s2, s3, m); + + CHECK(i->get_s1() == -(MAX_INT)-1); + CHECK(ct->get_condition(OF)); + CHECK(!ct->get_condition(UF)); + + delete i; +} + +TEST_CASE_METHOD(EXFixture, "SUB underflow", "[ex]") +{ + signed int s1, s2, s3; + Mnemonic m; + InstrDTO *i; + + m = SUB; + s1 = -(MAX_INT)-1, s2 = 1, s3 = 0; + i = execute_instr(s1, s2, s3, m); + + CHECK(i->get_s1() == MAX_INT); + CHECK(!ct->get_condition(OF)); + CHECK(ct->get_condition(UF)); + + delete i; +} TEST_CASE_METHOD(EXFixture, "MUL within bounds", "[ex]") { @@ -114,13 +166,39 @@ TEST_CASE_METHOD(EXFixture, "MUL within bounds", "[ex]") delete i; } -// TEST_CASE_METHOD(EXFixture, "MUL overflow", "[ex]") -// { -// } +TEST_CASE_METHOD(EXFixture, "MUL overflow", "[ex]") +{ + signed int s1, s2, s3; + Mnemonic m; + InstrDTO *i; -// TEST_CASE_METHOD(EXFixture, "MUL underflow", "[ex]") -// { -// } + m = MUL; + s1 = MAX_INT, s2 = MAX_INT, s3 = 0; + i = execute_instr(s1, s2, s3, m); + + CHECK(i->get_s1() == 1); + CHECK(ct->get_condition(OF)); + CHECK(!ct->get_condition(UF)); + + delete i; +} + +TEST_CASE_METHOD(EXFixture, "MUL underflow", "[ex]") +{ + signed int s1, s2, s3; + Mnemonic m; + InstrDTO *i; + + m = MUL; + s1 = MAX_INT, s2 = -MAX_INT, s3 = 0; + i = execute_instr(s1, s2, s3, m); + + CHECK(i->get_s1() == -1); + CHECK(!ct->get_condition(OF)); + CHECK(ct->get_condition(UF)); + + delete i; +} TEST_CASE_METHOD(EXFixture, "QUOT within bounds", "[ex]") { @@ -139,17 +217,36 @@ TEST_CASE_METHOD(EXFixture, "QUOT within bounds", "[ex]") delete i; } -// TEST_CASE_METHOD(EXFixture, "QUOT overflow", "[ex]") -// { -// } +TEST_CASE_METHOD(EXFixture, "QUOT overflow", "[ex]") +{ + signed int s1, s2, s3; + Mnemonic m; + InstrDTO *i; -// TEST_CASE_METHOD(EXFixture, "QUOT underflow", "[ex]") -// { -// } + m = QUOT; + s1 = -(MAX_INT)-1, s2 = -1, s3 = 0; + i = execute_instr(s1, s2, s3, m); -// TEST_CASE_METHOD(EXFixture, "QUOT halt", "[ex]") -// { -// } + CHECK(i->get_s1() == -(MAX_INT)-1); + CHECK(ct->get_condition(OF)); + CHECK(!ct->get_condition(UF)); + + delete i; +} + +TEST_CASE_METHOD(EXFixture, "QUOT halt", "[ex]") +{ + try { + signed int s1, s2, s3; + Mnemonic m; + + m = QUOT; + s1 = 1, s2 = 0, s3 = 0; + execute_instr(s1, s2, s3, m); + FAIL(true); + } catch (HaltException &e) { + } +} TEST_CASE_METHOD(EXFixture, "REM within bounds", "[ex]") { @@ -168,17 +265,19 @@ TEST_CASE_METHOD(EXFixture, "REM within bounds", "[ex]") delete i; } -// TEST_CASE_METHOD(EXFixture, "REM overflow", "[ex]") -// { -// } - -// TEST_CASE_METHOD(EXFixture, "REM underflow", "[ex]") -// { -// } +TEST_CASE_METHOD(EXFixture, "REM halt", "[ex]") +{ + try { + signed int s1, s2, s3; + Mnemonic m; -// TEST_CASE_METHOD(EXFixture, "REM halt", "[ex]") -// { -// } + m = REM; + s1 = 1, s2 = 0, s3 = 0; + execute_instr(s1, s2, s3, m); + FAIL(true); + } catch (HaltException &e) { + } +} TEST_CASE_METHOD(EXFixture, "SFTR within bounds", "[ex]") { @@ -461,13 +560,39 @@ TEST_CASE_METHOD(EXFixture, "ADDI within bounds", "[ex]") delete i; } -// TEST_CASE_METHOD(EXFixture, "ADDI overflow", "[ex]") -// { -// } +TEST_CASE_METHOD(EXFixture, "ADDI overflow", "[ex]") +{ + signed int s1, s2, s3; + Mnemonic m; + InstrDTO *i; -// TEST_CASE_METHOD(EXFixture, "ADDI underflow", "[ex]") -// { -// } + m = ADDI; + s1 = MAX_INT, s2 = 0, s3 = 1; + i = execute_instr(s1, s2, s3, m); + + CHECK(i->get_s1() == -(MAX_INT)-1); + CHECK(ct->get_condition(OF)); + CHECK(!ct->get_condition(UF)); + + delete i; +} + +TEST_CASE_METHOD(EXFixture, "ADDI underflow", "[ex]") +{ + signed int s1, s2, s3; + Mnemonic m; + InstrDTO *i; + + m = ADDI; + s1 = -(MAX_INT)-1, s2 = 0, s3 = -1; + i = execute_instr(s1, s2, s3, m); + + CHECK(i->get_s1() == MAX_INT); + CHECK(!ct->get_condition(OF)); + CHECK(ct->get_condition(UF)); + + delete i; +} TEST_CASE_METHOD(EXFixture, "SUBI within bounds", "[ex]") { @@ -486,13 +611,39 @@ TEST_CASE_METHOD(EXFixture, "SUBI within bounds", "[ex]") delete i; } -// TEST_CASE_METHOD(EXFixture, "SUBI overflow", "[ex]") -// { -// } +TEST_CASE_METHOD(EXFixture, "SUBI overflow", "[ex]") +{ + signed int s1, s2, s3; + Mnemonic m; + InstrDTO *i; -// TEST_CASE_METHOD(EXFixture, "SUBI underflow", "[ex]") -// { -// } + m = SUBI; + s1 = -(MAX_INT)-1, s2 = 0, s3 = 1; + i = execute_instr(s1, s2, s3, m); + + CHECK(i->get_s1() == MAX_INT); + CHECK(!ct->get_condition(OF)); + CHECK(ct->get_condition(UF)); + + delete i; +} + +TEST_CASE_METHOD(EXFixture, "SUBI underflow", "[ex]") +{ + signed int s1, s2, s3; + Mnemonic m; + InstrDTO *i; + + m = SUBI; + s1 = MAX_INT, s2 = 0, s3 = -1; + i = execute_instr(s1, s2, s3, m); + + CHECK(i->get_s1() == -(MAX_INT)-1); + CHECK(ct->get_condition(OF)); + CHECK(!ct->get_condition(UF)); + + delete i; +} TEST_CASE_METHOD(EXFixture, "SFTRI within bounds", "[ex]") { |