From 727afe4ffac0f193696c99234a2ade3a02f73157 Mon Sep 17 00:00:00 2001 From: bd Date: Sat, 10 May 2025 20:35:18 -0400 Subject: Separate ex advance into methods handling different field types --- inc/ex.h | 73 +++++++++++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 51 insertions(+), 22 deletions(-) (limited to 'inc/ex.h') diff --git a/inc/ex.h b/inc/ex.h index 5a5c046..0e235cb 100644 --- a/inc/ex.h +++ b/inc/ex.h @@ -23,36 +23,28 @@ #include #include -#define ADDITION_OF_GUARD(a, b) \ - (b >= 0) && (a > MAX_INT - b) +#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 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_OF_GUARD(a, b) (b < 0) && (a > MAX_INT + b) -#define SUBTRACTION_UF_GUARD(a, b) \ - (b >= 0) && (a < (-(MAX_INT)-1) + 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_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 != -1) && \ - (((b > 0) && (a < 0) && (a < (-(MAX_INT)-1) / b)) || \ - ((b < 0) && (a > 0) && (a > (-(MAX_INT)-1) / b))) +#define MULTIPLICATION_UF_GUARD(a, b) \ + (b != 0) && (b != -1) && \ + (((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) +#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 { - return ""; - } + const char *what() const noexcept override { return ""; } }; class EX : public Stage @@ -63,11 +55,48 @@ class EX : public Stage * @param The next stage in the pipeline. * @return A newly allocated EX object. */ - using Stage::Stage; using Stage::advance; + using Stage::Stage; private: void advance_helper(); + /** + * Handles operations involving three ints. + * @param slot 1, and later, the result of the mnemonic operation. + * @param slot 2 + * @param slot 3 + * @param the mnemonic + * @param the program counter + */ + void handle_int_operations( + signed int &s1, + signed int s2, + signed int s3, + Mnemonic m, + unsigned int pc); + /** + * Handles operations involving three vector registers. + * @param slot 1, and later, the result of the mnemonic operation. + * @param slot 2 + * @param slot 3 + * @param the mnemonic + * @param the vector length register + */ + void handle_vector_operations( + std::array &s1, + std::array s2, + Mnemonic m, + unsigned int v_len); + + /** + * Handles operations involving a single vector register. + * Currently, this is LOADV and STOREV + * @param slot 1, and later, the result of the mnemonic operation. + * @param slot 2 + * @param the mnemonic + * @param the vector length register + */ + void handle_i_vector_operations(signed int &s1, signed int s2, Mnemonic m); /** * Wrapper for division functions, which detects HALT instructinos (division * by 0). -- cgit v1.2.3 From 714622080d510de1591de2c689d8bd319b54f432 Mon Sep 17 00:00:00 2001 From: bd Date: Sat, 10 May 2025 21:15:24 -0400 Subject: Fix overflow/underflow conditions in vector ops --- inc/ex.h | 3 ++- src/ex.cc | 90 ++++++++++++++++++++++++++++++++++++++------------------------- 2 files changed, 56 insertions(+), 37 deletions(-) (limited to 'inc/ex.h') diff --git a/inc/ex.h b/inc/ex.h index 0e235cb..ff4041b 100644 --- a/inc/ex.h +++ b/inc/ex.h @@ -103,8 +103,9 @@ class EX : public Stage * @param the numerator * @param the denominator * @param if the modulo operator should instead be used + * @return if the operation overflowed */ - void handle_divide(signed int &s1, signed int s2, bool is_mod); + bool handle_divide(signed int &s1, signed int s2, bool is_mod); }; #endif /* EX_H_INCLUDED */ diff --git a/src/ex.cc b/src/ex.cc index 810461f..4fcda0a 100644 --- a/src/ex.cc +++ b/src/ex.cc @@ -27,31 +27,36 @@ void EX::handle_int_operations( signed int &s1, signed int s2, signed int s3, Mnemonic m, unsigned int pc) { + bool overflow, underflow; + + overflow = get_condition(OF), underflow = get_condition(UF); switch (m) { case ADD: - this->set_condition(OF, ADDITION_OF_GUARD(s1, s2)); - this->set_condition(UF, ADDITION_UF_GUARD(s1, s2)); + overflow = ADDITION_OF_GUARD(s1, s2); + underflow = ADDITION_UF_GUARD(s1, s2); s1 = s1 + s2; break; case SUB: - this->set_condition(OF, SUBTRACTION_OF_GUARD(s1, s2)); - this->set_condition(UF, SUBTRACTION_UF_GUARD(s1, s2)); + overflow = SUBTRACTION_OF_GUARD(s1, s2); + underflow = SUBTRACTION_UF_GUARD(s1, s2); s1 = s1 - s2; break; case MUL: - this->set_condition(OF, MULTIPLICATION_OF_GUARD(s1, s2)); - this->set_condition(UF, MULTIPLICATION_UF_GUARD(s1, s2)); + overflow = MULTIPLICATION_OF_GUARD(s1, s2); + underflow = MULTIPLICATION_UF_GUARD(s1, s2); s1 = s1 * s2; break; case QUOT: - this->handle_divide(s1, s2, false); + overflow = this->handle_divide(s1, s2, false); + underflow = 0; break; case REM: - this->handle_divide(s1, s2, true); + overflow = this->handle_divide(s1, s2, true); + underflow = 0; break; case SFTR: @@ -63,26 +68,26 @@ void EX::handle_int_operations( break; case AND: - this->set_condition(OF, false); - this->set_condition(UF, false); + overflow = false; + underflow = false; s1 = s1 & s2; break; case OR: - this->set_condition(OF, false); - this->set_condition(UF, false); + overflow = false; + underflow = false; s1 = s1 | s2; break; case XOR: - this->set_condition(OF, false); - this->set_condition(UF, false); + overflow = false; + underflow = false; s1 = s1 ^ s2; break; case NOT: - this->set_condition(OF, false); - this->set_condition(UF, false); + overflow = false; + underflow = false; s1 = ~s1; break; @@ -94,14 +99,14 @@ void EX::handle_int_operations( break; case ADDI: - this->set_condition(OF, ADDITION_OF_GUARD(s1, s3)); - this->set_condition(UF, ADDITION_UF_GUARD(s1, s3)); + overflow = ADDITION_OF_GUARD(s1, s3); + underflow = ADDITION_UF_GUARD(s1, s3); s1 = s1 + s3; break; case SUBI: - this->set_condition(OF, SUBTRACTION_OF_GUARD(s1, s3)); - this->set_condition(UF, SUBTRACTION_UF_GUARD(s1, s3)); + overflow = SUBTRACTION_OF_GUARD(s1, s3); + underflow = SUBTRACTION_UF_GUARD(s1, s3); s1 = s1 - s3; break; @@ -114,20 +119,20 @@ void EX::handle_int_operations( break; case ANDI: - this->set_condition(OF, false); - this->set_condition(UF, false); + overflow = false; + underflow = false; s1 = s1 & s3; break; case ORI: - this->set_condition(OF, false); - this->set_condition(UF, false); + overflow = false; + underflow = false; s1 = s1 | s3; break; case XORI: - this->set_condition(OF, false); - this->set_condition(UF, false); + overflow = false; + underflow = false; s1 = s1 ^ s3; break; @@ -171,6 +176,9 @@ void EX::handle_int_operations( throw std::invalid_argument( "handle_int_operations received a vector operation!"); } + + this->set_condition(OF, overflow); + this->set_condition(UF, underflow); } void EX::handle_vector_operations( @@ -180,32 +188,36 @@ void EX::handle_vector_operations( unsigned int v_len) { unsigned int i; + bool overflow, underflow; + + overflow = 0, underflow = 0; switch (m) { case ADDV: for (i = 0; i < v_len; i++) { - this->set_condition(OF, ADDITION_OF_GUARD(s1[i], s2[i])); - this->set_condition(UF, ADDITION_UF_GUARD(s1[i], s2[i])); + overflow = overflow || (ADDITION_OF_GUARD(s1[i], s2[i])); + underflow = underflow || (ADDITION_UF_GUARD(s1[i], s2[i])); s1[i] = s1[i] + s2[i]; } break; case SUBV: for (i = 0; i < v_len; i++) { - this->set_condition(OF, SUBTRACTION_OF_GUARD(s1[i], s2[i])); - this->set_condition(UF, SUBTRACTION_UF_GUARD(s1[i], s2[i])); + overflow = overflow || (SUBTRACTION_OF_GUARD(s1[i], s2[i])); + underflow = underflow || (SUBTRACTION_UF_GUARD(s1[i], s2[i])); s1[i] = s1[i] - s2[i]; } break; case MULV: for (i = 0; i < v_len; i++) { - this->set_condition(OF, MULTIPLICATION_OF_GUARD(s1[i], s2[i])); - this->set_condition(UF, MULTIPLICATION_UF_GUARD(s1[i], s2[i])); + overflow = overflow || (MULTIPLICATION_OF_GUARD(s1[i], s2[i])); + underflow = underflow || (MULTIPLICATION_UF_GUARD(s1[i], s2[i])); s1[i] = s1[i] * s2[i]; } break; case DIVV: for (i = 0; i < v_len; i++) { - this->handle_divide(s1[i], s2[i], false); + // short-circuiting---this order required + overflow = this->handle_divide(s1[i], s2[i], false) | overflow; } break; case CEV: @@ -226,6 +238,9 @@ void EX::handle_vector_operations( throw std::invalid_argument( "handle_vector_operations received an integer operation!"); } + + this->set_condition(OF, overflow); + this->set_condition(UF, underflow); } void EX::handle_i_vector_operations(signed int &s1, signed int s2, Mnemonic m) @@ -271,10 +286,11 @@ void EX::advance_helper() this->status = OK; } -void EX::handle_divide(signed int &s1, signed int s2, bool is_mod) +bool 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); + bool ret; + + ret = DIVISION_OF_GUARD(s1, s2); if (s2 == 0) { // handle everything here this->curr_instr->operands.integer.slot_one = MAX_INT; @@ -286,4 +302,6 @@ void EX::handle_divide(signed int &s1, signed int s2, bool is_mod) } else { s1 = (is_mod) ? (s1 % s2) : (s1 / s2); } + + return ret; } -- cgit v1.2.3