// Simulator for the RISC-V[ECTOR] mini-ISA
// Copyright (C) 2025 Siddarth Suresh
// Copyright (C) 2025 bdunahu
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see .
#include "ex.h"
#include "instrDTO.h"
#include "pipe_spec.h"
#include "response.h"
#include "stage.h"
#include
// Switch statements for each instruction
void EX::advance_helper()
{
signed int s1, s2, s3;
std::array 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;
pc = this->curr_instr->slot_B;
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);
}
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;
}
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->operands.integer.slot_one = 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);
}
}