summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSiddarth Suresh <155843085+SiddarthSuresh98@users.noreply.github.com>2025-04-22 15:23:50 -0400
committerGitHub <noreply@github.com>2025-04-22 15:23:50 -0400
commit3d0133c2f793e82d7519d8e2c5023114cd0f0eab (patch)
treeb262ededf7e993090d7a860b76ca528b5651c3c6
parent1250359dfcbcad18c0a1078290f95479aa23e26a (diff)
parent86a6253a2fb2d016a63e57d6a5e5461df87668e5 (diff)
Merge pull request #67 from bdunahu/bdunahu
add RET instruction, JAL ob1 error (full subroutine support), condition codes for everything but shifts
-rw-r--r--gui/gui.h2
-rw-r--r--inc/ex.h25
-rw-r--r--inc/instr.h1
-rw-r--r--src/sim/ex.cc42
-rw-r--r--src/sim/id.cc5
-rw-r--r--src/sim/instr.cc2
-rw-r--r--src/sim/wb.cc2
-rw-r--r--tests/ex.cc249
8 files changed, 273 insertions, 55 deletions
diff --git a/gui/gui.h b/gui/gui.h
index cf31142..7b03f75 100644
--- a/gui/gui.h
+++ b/gui/gui.h
@@ -160,7 +160,7 @@ class GUI : public QMainWindow
{Mnemonic::BEQ, "BEQ"}, {Mnemonic::BGT, "BGT"},
{Mnemonic::BUF, "BUF"}, {Mnemonic::BOF, "BOF"},
{Mnemonic::PUSH, "PUSH"}, {Mnemonic::POP, "POP"},
- {Mnemonic::NOP, "NOP"},
+ {Mnemonic::NOP, "NOP"}, {Mnemonic::RET, "RET"},
};
QString mnemonicToString(Mnemonic mnemonic)
{
diff --git a/inc/ex.h b/inc/ex.h
index 1c06ac2..f7428da 100644
--- a/inc/ex.h
+++ b/inc/ex.h
@@ -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/inc/instr.h b/inc/instr.h
index b5b782a..62af09a 100644
--- a/inc/instr.h
+++ b/inc/instr.h
@@ -58,6 +58,7 @@ enum Mnemonic {
BOF,
PUSH,
POP,
+ RET,
NOP,
};
diff --git a/src/sim/ex.cc b/src/sim/ex.cc
index f098917..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;
@@ -372,6 +395,16 @@ EX::EX(Stage *stage) : Stage(stage)
(void)this;
}),
+ INIT_INSTRUCTION(
+ RET,
+ {
+ (void)pc;
+ (void)s3;
+ (void)s2;
+ (void)s1;
+ (void)this;
+ }),
+
/* NOP */
INIT_INSTRUCTION(
NOP,
@@ -405,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/src/sim/id.cc b/src/sim/id.cc
index 3753f83..cdbaba9 100644
--- a/src/sim/id.cc
+++ b/src/sim/id.cc
@@ -211,8 +211,11 @@ void ID::decode_J_type(
}
this->status = r1;
break;
+ case RET:
+ s1 = 1; // link register
+ [[fallthrough]];
default:
- this->status = this->read_guard(*&s1);
+ this->status = this->read_guard(s1);
}
}
diff --git a/src/sim/instr.cc b/src/sim/instr.cc
index c8d1039..9bd951b 100644
--- a/src/sim/instr.cc
+++ b/src/sim/instr.cc
@@ -35,6 +35,6 @@ const std::unordered_map<unsigned int, Mnemonic> mnemonic_map = {
{0b0101101, STOREV}, {0b0000110, JMP}, {0b0001010, JRL},
{0b0001110, JAL}, {0b0010010, BEQ}, {0b0010110, BGT},
{0b0011010, BUF}, {0b0011110, BOF}, {0b0100010, PUSH},
- {0b0100110, POP},
+ {0b0100110, POP}, {0b0101010, RET},
};
} // namespace instr
diff --git a/src/sim/wb.cc b/src/sim/wb.cc
index fbbdd4c..0348b51 100644
--- a/src/sim/wb.cc
+++ b/src/sim/wb.cc
@@ -62,7 +62,7 @@ void WB::jump_handler()
{
if (this->curr_instr->get_s1() > 0) {
if (this->curr_instr->get_mnemonic() == JAL)
- this->gprs[1] = this->pc + 1;
+ this->gprs[1] = this->curr_instr->get_pc() + 1;;
this->pc = this->curr_instr->get_s1();
this->checked_out = {};
this->next->squash();
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]")
{