summaryrefslogtreecommitdiff
path: root/src/ex.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/ex.cc')
-rw-r--r--src/ex.cc613
1 files changed, 214 insertions, 399 deletions
diff --git a/src/ex.cc b/src/ex.cc
index eac24ff..286c7ba 100644
--- a/src/ex.cc
+++ b/src/ex.cc
@@ -22,415 +22,230 @@
#include "stage.h"
#include <unordered_map>
-// clang-format off
-#define INIT_INSTRUCTION(mnemonic, body) \
- {mnemonic, [this](signed int &s1, signed int s2, signed int s3, unsigned int pc) { \
- body; \
- }}
-// clang-format on
-
-EX::EX(Stage *stage) : Stage(stage)
-{
- instr_map = {
-
- /* R type instructions */
- 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;
- (void)this;
- }),
-
- 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;
- (void)this;
- }),
-
- 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;
- (void)this;
- }),
-
- INIT_INSTRUCTION(
- QUOT,
- {
- this->handle_divide(s1, s2, false);
- (void)pc;
- (void)s3;
- }),
-
- INIT_INSTRUCTION(
- REM,
- {
- this->handle_divide(s1, s2, true);
- (void)pc;
- (void)s3;
- (void)this;
- }),
-
- INIT_INSTRUCTION(
- SFTR,
- {
- s1 = s1 >> s2;
- (void)pc;
- (void)s3;
- (void)this;
- }),
-
- INIT_INSTRUCTION(
- SFTL,
- {
- s1 = s1 << s2;
- (void)pc;
- (void)s3;
- (void)this;
- }),
-
- INIT_INSTRUCTION(
- AND,
- {
- this->set_condition(OF, false);
- this->set_condition(UF, false);
- s1 = s1 & s2;
- (void)pc;
- (void)s3;
- (void)this;
- }),
-
- INIT_INSTRUCTION(
- OR,
- {
- this->set_condition(OF, false);
- this->set_condition(UF, false);
- s1 = s1 | s2;
- (void)pc;
- (void)s3;
- (void)this;
- }),
-
- INIT_INSTRUCTION(
- NOT,
- {
- this->set_condition(OF, false);
- this->set_condition(UF, false);
- s1 = ~s1;
- (void)pc;
- (void)s3;
- (void)s2;
- (void)this;
- }),
-
- INIT_INSTRUCTION(
- XOR,
- {
- this->set_condition(OF, false);
- this->set_condition(UF, false);
- s1 = s1 ^ s2;
- (void)pc;
- (void)s3;
- (void)this;
- }),
-
- INIT_INSTRUCTION(
- ADDV,
- {
- (void)pc;
- (void)s3;
- (void)s2;
- (void)s1;
- (void)this;
- }),
-
- INIT_INSTRUCTION(
- SUBV,
- {
- (void)pc;
- (void)s3;
- (void)s2;
- (void)s1;
- (void)this;
- }),
-
- INIT_INSTRUCTION(
- MULV,
- {
- (void)pc;
- (void)s3;
- (void)s2;
- (void)s1;
- (void)this;
- }),
-
- INIT_INSTRUCTION(
- DIVV,
- {
- (void)pc;
- (void)s3;
- (void)s2;
- (void)s1;
- (void)this;
- }),
-
- INIT_INSTRUCTION(
- CMP,
- {
- (s1 > s2) ? this->set_condition(GT, true)
- : this->set_condition(GT, false);
- (s1 == s2) ? this->set_condition(EQ, true)
- : this->set_condition(EQ, false);
- (void)pc;
- (void)s3;
- }),
-
- INIT_INSTRUCTION(
- CEV,
- {
- (void)pc;
- (void)s3;
- (void)s2;
- (void)s1;
- (void)this;
- }),
-
- /* I type instructions */
- INIT_INSTRUCTION(
- LOAD,
- {
- s1 = s1 + s3;
- (void)pc;
- (void)s2;
- (void)this;
- }),
-
- INIT_INSTRUCTION(
- LOADV,
- {
- (void)pc;
- (void)s3;
- (void)s2;
- (void)s1;
- (void)this;
- }),
-
- 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;
- (void)this;
- }),
-
- 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;
- (void)this;
- }),
-
- INIT_INSTRUCTION(
- SFTRI,
- {
- s1 = s1 >> s3;
- (void)pc;
- (void)s2;
- (void)this;
- }),
-
- INIT_INSTRUCTION(
- SFTLI,
- {
- s1 = s1 << s3;
- (void)pc;
- (void)s2;
- (void)this;
- }),
-
- INIT_INSTRUCTION(
- ANDI,
- {
- this->set_condition(OF, false);
- this->set_condition(UF, false);
- s1 = s1 & s3;
- (void)pc;
- (void)s2;
- (void)this;
- }),
-
- INIT_INSTRUCTION(
- ORI,
- {
- this->set_condition(OF, false);
- this->set_condition(UF, false);
- s1 = s1 | s3;
- (void)pc;
- (void)s2;
- (void)this;
- }),
-
- INIT_INSTRUCTION(
- XORI,
- {
- this->set_condition(OF, false);
- this->set_condition(UF, false);
- s1 = s1 ^ s3;
- (void)pc;
- (void)s2;
- (void)this;
- }),
-
- INIT_INSTRUCTION(
- STORE,
- {
- s1 = s1 + s3;
- (void)pc;
- (void)s2;
- (void)this;
- }),
-
- INIT_INSTRUCTION(
- STOREV,
- {
- (void)pc;
- (void)s3;
- (void)s2;
- (void)s1;
- (void)this;
- }),
-
- /* J type instructions */
- INIT_INSTRUCTION(
- JMP,
- {
- s1 = s1 + s2;
- (void)pc;
- (void)s3;
- (void)this;
- }),
-
- INIT_INSTRUCTION(
- JRL,
- {
- s1 = pc + s2;
- (void)s3;
- (void)this;
- }),
-
- INIT_INSTRUCTION(
- JAL,
- {
- s1 = s1 + s2;
- (void)pc;
- (void)s3;
- (void)this;
- }),
-
- INIT_INSTRUCTION(
- BEQ,
- {
- (this->get_condition(EQ)) ? s1 = pc + s2 : s1 = -1;
- (void)s3;
- }),
-
- INIT_INSTRUCTION(
- BGT,
- {
- (this->get_condition(GT)) ? s1 = pc + s2 : s1 = -1;
- (void)s3;
- }),
-
- INIT_INSTRUCTION(
- BUF,
- {
- (this->get_condition(UF)) ? s1 = pc + s2 : s1 = -1;
- (void)s3;
- }),
-
- INIT_INSTRUCTION(
- BOF,
- {
- (this->get_condition(OF)) ? s1 = pc + s2 : s1 = -1;
- (void)s3;
- }),
-
- INIT_INSTRUCTION(
- PUSH,
- {
- s1 = s1 + s3;
- (void)pc;
- (void)s2;
- (void)this;
- }),
-
- INIT_INSTRUCTION(
- POP,
- {
- s1 = s1 + s3;
- (void)pc;
- (void)s2;
- (void)this;
- }),
-
- INIT_INSTRUCTION(
- RET,
- {
- (void)pc;
- (void)s3;
- (void)s2;
- (void)s1;
- (void)this;
- }),
-
- /* NOP */
- INIT_INSTRUCTION(
- NOP,
- {
- (void)pc;
- (void)s3;
- (void)s2;
- (void)s1;
- (void)this;
- }),
- };
-}
-
+// Switch statements for each instruction
void EX::advance_helper()
{
signed int s1, s2, s3;
+ std::array<signed int, V_R_LIMIT> v1, v2, v3;
+ signed int v_len, v_immediate, v_base_addr;
unsigned int pc;
Mnemonic m;
+ s1 = 0, s2 = 0, s3 = 0;
+ v1 = {0}, v2 = {0}, v3 = {0};
+ v_len = 0, v_immediate = 0, v_base_addr = 0;
m = this->curr_instr->mnemonic;
- s1 = this->curr_instr->operands.integer.slot_one;
- s2 = this->curr_instr->operands.integer.slot_two;
- s3 = this->curr_instr->operands.integer.slot_three;
pc = this->curr_instr->slot_B;
- this->instr_map[m](s1, s2, s3, pc);
+ if (this->is_vector_type(m)) {
+ if (this->curr_instr->mnemonic != LOADV &&
+ this->curr_instr->mnemonic != STOREV) {
+ v1 = this->curr_instr->operands.vector.slot_one;
+ v2 = this->curr_instr->operands.vector.slot_two;
+ v3 = this->curr_instr->operands.vector.slot_three;
+ } else {
+ v_immediate =
+ this->curr_instr->operands.load_store_vector.immediate;
+ v_base_addr =
+ this->curr_instr->operands.load_store_vector.base_addr;
+ }
+ v_len = this->curr_instr->slot_A;
+ if (v_len == 0) {
+ // clear destination vector reg
+ v1.fill(0);
+ }
+ } else {
+ s1 = this->curr_instr->operands.integer.slot_one;
+ s2 = this->curr_instr->operands.integer.slot_two;
+ s3 = this->curr_instr->operands.integer.slot_three;
+ }
+
+ if (this->is_logical(m)) {
+ this->set_condition(OF, false);
+ this->set_condition(UF, false);
+ }
- this->curr_instr->operands.integer.slot_one = s1;
+ switch (m) {
+ case ADD:
+ this->set_condition(OF, ADDITION_OF_GUARD(s1, s2));
+ this->set_condition(UF, 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));
+ s1 = s1 - s2;
+ break;
+
+ case MUL:
+ this->set_condition(OF, MULTIPLICATION_OF_GUARD(s1, s2));
+ this->set_condition(UF, MULTIPLICATION_UF_GUARD(s1, s2));
+ s1 = s1 * s2;
+ break;
+
+ case QUOT:
+ this->handle_divide(s1, s2, false);
+ break;
+
+ case REM:
+ this->handle_divide(s1, s2, true);
+ break;
+
+ case SFTR:
+ s1 = s1 >> s2;
+ break;
+
+ case SFTL:
+ s1 = s1 << s2;
+ break;
+
+ case AND:
+ s1 = s1 & s2;
+ break;
+
+ case OR:
+ s1 = s1 | s2;
+ break;
+
+ case XOR:
+ s1 = s1 ^ s2;
+ break;
+
+ case NOT:
+ s1 = ~s1;
+ break;
+
+ case CMP:
+ (s1 > s2) ? this->set_condition(GT, true)
+ : this->set_condition(GT, false);
+ (s1 == s2) ? this->set_condition(EQ, true)
+ : this->set_condition(EQ, false);
+ break;
+
+ case ADDI:
+ this->set_condition(OF, ADDITION_OF_GUARD(s1, s3));
+ this->set_condition(UF, 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));
+ s1 = s1 - s3;
+ break;
+
+ case SFTRI:
+ s1 = s1 >> s3;
+ break;
+
+ case SFTLI:
+ s1 = s1 << s3;
+ break;
+
+ case ANDI:
+ s1 = s1 & s3;
+ break;
+
+ case ORI:
+ s1 = s1 | s3;
+ break;
+
+ case XORI:
+ s1 = s1 ^ s3;
+ break;
+
+ case LOAD:
+ case STORE:
+ case PUSH:
+ case POP:
+ s1 = s1 + s3;
+ break;
+
+ case JMP:
+ case JAL:
+ s1 = s1 + s2;
+ break;
+
+ case JRL:
+ s1 = pc + s2;
+ break;
+
+ case BEQ:
+ (this->get_condition(EQ)) ? s1 = pc + s2 : s1 = -1;
+ break;
+
+ case BGT:
+ (this->get_condition(GT)) ? s1 = pc + s2 : s1 = -1;
+ break;
+
+ case BUF:
+ (this->get_condition(UF)) ? s1 = pc + s2 : s1 = -1;
+ break;
+
+ case BOF:
+ (this->get_condition(OF)) ? s1 = pc + s2 : s1 = -1;
+ break;
+
+ case ADDV:
+ for (int i = 0; i < v_len; i++) {
+ this->set_condition(OF, ADDITION_OF_GUARD(v1[i], v2[i]));
+ this->set_condition(UF, ADDITION_UF_GUARD(v1[i], v2[i]));
+ v1[i] = v1[i] + v2[i];
+ }
+ break;
+ case SUBV:
+ for (int i = 0; i < v_len; i++) {
+ this->set_condition(OF, SUBTRACTION_OF_GUARD(v1[i], v2[i]));
+ this->set_condition(UF, SUBTRACTION_UF_GUARD(v1[i], v2[i]));
+ v1[i] = v1[i] - v2[i];
+ }
+ break;
+ case MULV:
+ for (int i = 0; i < v_len; i++) {
+ this->set_condition(OF, MULTIPLICATION_OF_GUARD(v1[i], v2[i]));
+ this->set_condition(UF, MULTIPLICATION_UF_GUARD(v1[i], v2[i]));
+ v1[i] = v1[i] * v2[i];
+ }
+ break;
+ case DIVV:
+ for (int i = 0; i < v_len; i++) {
+ this->handle_divide(v1[i], v2[i], false);
+ }
+ break;
+ case CEV:
+ int i;
+ for (i = 0; i < v_len; i++) {
+ if (v1[i] != v2[i]) {
+ break;
+ }
+ }
+ if (i == v_len) {
+ this->set_condition(EQ, true);
+ } else {
+ this->set_condition(EQ, false);
+ }
+ break;
+ case LOADV:
+ case STOREV:
+ v_base_addr = v_base_addr + v_immediate;
+ break;
+
+ case RET:
+ case NOP:
+ break;
+ }
+ if (this->is_vector_type(m)) {
+ if (this->curr_instr->mnemonic != LOADV &&
+ this->curr_instr->mnemonic != STOREV) {
+ this->curr_instr->operands.vector.slot_one = v1;
+ } else {
+ this->curr_instr->operands.load_store_vector.base_addr =
+ v_base_addr;
+ }
+ } else {
+ this->curr_instr->operands.integer.slot_one = s1;
+ }
this->status = OK;
}