-
Notifications
You must be signed in to change notification settings - Fork 0
/
GTECoprocessor.cpp
140 lines (115 loc) · 3.8 KB
/
GTECoprocessor.cpp
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
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
#include <stdexcept>
#include <fstream>
#include "GTECoprocessor.hpp"
#include "InstructionTypes.hpp"
#include "InstructionEnums.hpp"
#include "Cpu.hpp"
#include "Bus.hpp"
static GTECoprocessor * instance = nullptr;
GTECoprocessor * GTECoprocessor::get_instance()
{
if (instance == nullptr)
{
instance = new GTECoprocessor();
}
return instance;
}
void GTECoprocessor::save_state(std::stringstream& file)
{
file.write(reinterpret_cast<char*>(&control_registers[0]), sizeof(unsigned int) * 32);
file.write(reinterpret_cast<char*>(&data_registers[0]), sizeof(unsigned int) * 32);
}
void GTECoprocessor::load_state(std::stringstream& file)
{
file.read(reinterpret_cast<char*>(&control_registers[0]), sizeof(unsigned int) * 32);
file.read(reinterpret_cast<char*>(&data_registers[0]), sizeof(unsigned int) * 32);
}
void GTECoprocessor::execute(const instruction_union& instruction)
{
switch (static_cast<cpu_instructions>(instruction.immediate_instruction.op))
{
case cpu_instructions::LWC2:
{
load_word_to_cop(instruction);
} return;
case cpu_instructions::SWC2:
{
store_word_from_cop(instruction);
} return;
}
if (instruction.immediate_instruction.op == 0b0100101)
{
move_control_to_cop_fun(instruction);
return;
}
copz_instructions function = static_cast<copz_instructions>(instruction.register_instruction.rs);
switch (function) {
case copz_instructions::MF:
{
move_from_cop(instruction);
} break;
case copz_instructions::CF:
{
move_control_from_cop(instruction);
} break;
case copz_instructions::MT:
{
move_to_cop(instruction);
} break;
case copz_instructions::CT:
{
move_control_to_cop(instruction);
} break;
}
}
unsigned int GTECoprocessor::get_data_register(unsigned int index)
{
return data_registers[index];
}
void GTECoprocessor::set_data_register(unsigned int index, unsigned int value)
{
data_registers[index] = value;
}
unsigned int GTECoprocessor::get_control_register(unsigned int index)
{
return control_registers[index];
}
void GTECoprocessor::set_control_register(unsigned int index, unsigned int value)
{
control_registers[index] = value;
}
void GTECoprocessor::load_word_to_cop(const instruction_union& instr)
{
unsigned int addr = (short)instr.immediate_instruction.immediate + (int)Cpu::get_instance()->register_file.get_register(instr.immediate_instruction.rs);
unsigned int word = Bus::get_instance()->get_word(addr);
set_data_register(instr.immediate_instruction.rt, word);
}
void GTECoprocessor::store_word_from_cop(const instruction_union& instr)
{
unsigned int addr = (short)instr.immediate_instruction.immediate + (int)Cpu::get_instance()->register_file.get_register(instr.immediate_instruction.rs);
Bus::get_instance()->set_word(addr,get_data_register(instr.immediate_instruction.rt));
}
void GTECoprocessor::move_to_cop(const instruction_union& instr)
{
unsigned int value = Cpu::get_instance()->register_file.get_register(instr.register_instruction.rt);
set_data_register(instr.register_instruction.rd, value);
}
void GTECoprocessor::move_from_cop(const instruction_union& instr)
{
unsigned value = get_data_register(instr.register_instruction.rd);
Cpu::get_instance()->register_file.set_register(instr.register_instruction.rs, value);
}
void GTECoprocessor::move_control_to_cop(const instruction_union& instr)
{
unsigned int value = Cpu::get_instance()->register_file.get_register(instr.register_instruction.rt);
set_control_register(instr.register_instruction.rd, value);
}
void GTECoprocessor::move_control_from_cop(const instruction_union& instr)
{
unsigned int value = get_control_register(instr.register_instruction.rd);
Cpu::get_instance()->register_file.set_register(instr.register_instruction.rt, value);
}
void GTECoprocessor::move_control_to_cop_fun(const instruction_union& instr)
{
throw std::logic_error("not implemented");
}