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
96
97
98
99
100
101
102
103
104
105
106
|
#include "registers.h"
#include "qtmipsexception.h"
using namespace machine;
// TODO should this be configurable?
//////////////////////////////////////////////////////////////////////////////
/// Program counter initial value
#define PC_INIT 0x80020000
//////////////////////////////////////////////////////////////////////////////
Registers::Registers() : QObject() {
reset();
}
Registers::Registers(const Registers &orig) : QObject() {
this->pc = orig.read_pc();
for (std::uint8_t i = 0; i < 31; i++)
this->gp[i] = orig.read_gp(i + 1);
this->lo = orig.read_hi_lo(false);
this->hi = orig.read_hi_lo(true);
}
std::uint32_t Registers::read_pc() const {
return this->pc;
}
std::uint32_t Registers::pc_inc() {
this->pc += 4;
emit pc_update(this->pc);
return this->pc;
}
std::uint32_t Registers::pc_jmp(std::int32_t offset) {
if (offset % 4)
throw QTMIPS_EXCEPTION(UnalignedJump, "Trying to jump by unaligned offset", QString::number(offset, 16));
this->pc += offset;
emit pc_update(this->pc);
return this->pc;
}
void Registers::pc_abs_jmp(std::uint32_t address) {
if (address % 4)
throw QTMIPS_EXCEPTION(UnalignedJump, "Trying to jump to unaligned address", QString::number(address, 16));
this->pc = address;
emit pc_update(this->pc);
}
void Registers::pc_abs_jmp_28(std::uint32_t address) {
this->pc_abs_jmp((pc & 0xF0000000) | (address & 0x0FFFFFFF));
}
std::uint32_t Registers::read_gp(std::uint8_t i) const {
SANITY_ASSERT(i < 32, QString("Trying to read from register ") + QString(i));
if (!i) // $0 always reads as 0
return 0;
return this->gp[i - 1];
}
void Registers::write_gp(std::uint8_t i, std::uint32_t value) {
SANITY_ASSERT(i < 32, QString("Trying to write to register ") + QString(i));
if (i == 0) // Skip write to $0
return;
emit gp_update(i, value);
this->gp[i - 1] = value;
}
std::uint32_t Registers::read_hi_lo(bool is_hi) const {
if (is_hi)
return hi;
else
return lo;
}
void Registers::write_hi_lo(bool is_hi, std::uint32_t value) {
if (is_hi)
hi = value;
else
lo = value;
emit hi_lo_update(is_hi, value);
}
bool Registers::operator==(const Registers &c) const {
if (read_pc() != c.read_pc())
return false;
for (std::uint8_t i = 0; i < 31; i++)
if (read_gp(i) != c.read_gp(i))
return false;
if (read_hi_lo(false) != c.read_hi_lo(false))
return false;
if (read_hi_lo(true) != c.read_hi_lo(true))
return false;
return true;
}
bool Registers::operator!=(const Registers &c) const {
return ! this->operator==(c);
}
void Registers::reset() {
pc_abs_jmp(PC_INIT); // Initialize to beginning program section
for (int i = 1; i < 32; i++)
write_gp(i, 0);
write_hi_lo(false, 0);
write_hi_lo(true, 0);
}
|