summaryrefslogtreecommitdiff
path: root/src/sim/ex.cc
blob: fbf460f0a22d7cd9c0bb7303147ff02471ab142b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
#include "ex.h"
#include "accessor.h"
#include "definitions.h"
#include "instrDTO.h"
#include "response.h"
#include "stage.h"
#include <unordered_map>

// clang-format off
#define INIT_INSTRUCTION(mnemonic, body)					\
	{mnemonic, [this](signed int &s1, signed int &s2) { \
		body; \
	}}
// clang-format on

EX::EX(Stage *stage) : Stage(stage)
{
	this->id = EXEC;
	instr_map = {

		/* R type instructions */
		INIT_INSTRUCTION(
			ADD,
			{
				this->overflow_guard(s1, s2);
				s1 = s1 + s2;
			}),

		INIT_INSTRUCTION(
			SUB,
			{
				this->overflow_guard(s1, -s2);
				s1 = s1 - s2;
			}),

		INIT_INSTRUCTION(MUL, {}),
		INIT_INSTRUCTION(QUOT, {}),
		INIT_INSTRUCTION(REM, {}),
		INIT_INSTRUCTION(SFTR, {}),
		INIT_INSTRUCTION(SFTL, {}),
		INIT_INSTRUCTION(AND, {}),
		INIT_INSTRUCTION(OR, {}),
		INIT_INSTRUCTION(NOT, {}),
		INIT_INSTRUCTION(XOR, {}),
		INIT_INSTRUCTION(ADDV, {}),
		INIT_INSTRUCTION(SUBV, {}),
		INIT_INSTRUCTION(MULV, {}),
		INIT_INSTRUCTION(DIVV, {}),
		INIT_INSTRUCTION(CMP, {}),
		INIT_INSTRUCTION(CEV, {}),

		/* I type instructions */
		INIT_INSTRUCTION(LOAD, {}),
		INIT_INSTRUCTION(LOADV, {}),
		INIT_INSTRUCTION(ADDI, {}),
		INIT_INSTRUCTION(SUBI, {}),
		INIT_INSTRUCTION(SFTRI, {}),
		INIT_INSTRUCTION(SFTL, {}),
		INIT_INSTRUCTION(ANDI, {}),
		INIT_INSTRUCTION(ORI, {}),
		INIT_INSTRUCTION(XORI, {}),
		INIT_INSTRUCTION(STORE, {}),
		INIT_INSTRUCTION(STOREV, {}),

		/* J type instructions */
		INIT_INSTRUCTION(JMP, {}),
		INIT_INSTRUCTION(JRL, {}),
		INIT_INSTRUCTION(JAL, {}),
		INIT_INSTRUCTION(BEQ, {}),
		INIT_INSTRUCTION(BGT, {}),
		INIT_INSTRUCTION(BUF, {}),
		INIT_INSTRUCTION(BOF, {}),
		INIT_INSTRUCTION(PUSH, {}),
		INIT_INSTRUCTION(POP, {}),

		/* NOP */
		INIT_INSTRUCTION(NOP, (void)s2; (void)s1;),
	};
}

InstrDTO *EX::advance(Response p) { return nullptr; }

void EX::overflow_guard(signed int a, signed int b)
{
	if (a >= 0 && b >= 0 && (a > MAX_INT - b)) {
		this->set_condition(OF, true);
		this->set_condition(UF, false);
	} else if (a < 0 && b < 0 && (a < (-MAX_INT) - 1 - b)) {
		this->set_condition(OF, false);
		this->set_condition(UF, true);
	} else {
		this->set_condition(OF, false);
		this->set_condition(UF, false);
	}
}