WolPSX
Loading...
Searching...
No Matches
ins_special.cpp
1#include <sstream>
2
3#include "core/cpu/cpu.hpp"
4
11{
12 if(lookup_special.find(ins.funct()) != lookup_special.end())
13 {
14 (this->*lookup_special[ins.funct()])();
15 return;
16 }
17 //throw unhandled instruction error
18 std::stringstream ss;
19 ss << "Unhandled instruction (SPECIAL): " << std::hex << ir;
20 throw std::runtime_error(ss.str());
21}
22
33{
34 set_reg(ins.rd(), get_reg(ins.rt()) << ins.shamt());
35}
36
47void CPU::OR()
48{
49 set_reg(ins.rd(), get_reg(ins.rs()) | get_reg(ins.rt()));
50}
51
64{
65 set_reg(ins.rd(), get_reg(ins.rs()) < get_reg(ins.rt()));
66}
67
80{
81 set_reg(ins.rd(), get_reg(ins.rs()) + get_reg(ins.rt()));
82}
83
92void CPU::JR()
93{
94 // std::cout << "Jumped to: " << std::hex << get_reg(ins.rs()) << "\n"; //REMOVE
95 pc = get_reg(ins.rs());
96}
97
110{
111 set_reg(ins.rd(), get_reg(ins.rs()) & get_reg(ins.rt()));
112}
113
131{
132 uint32_t extended_op1 = get_reg(ins.rt());
133 uint32_t extended_op2 = get_reg(ins.rs());
134
135 //check for signed overflow
136 //TODO: Handle signed overflow exception
137 if(((extended_op1 & 0x80000000) && (extended_op2 & 0x80000000) && (((extended_op1 + extended_op2) & 0x80000000) == 0))
138 || (((extended_op1 & 0x80000000) == 0) && ((extended_op2 & 0x80000000) == 0) && ((extended_op1 + extended_op2) & 0x80000000)))
139 {
140 //throw signed overflow error
141 std::stringstream ss;
142 ss << "Signed overflow in ADD: " << std::hex << ir;
143 throw std::runtime_error(ss.str());
144 }
145
146 set_reg(ins.rd(), extended_op1 + extended_op2);
147}
148
161{
162 // uint32_t ra = pc + 4;
163 uint32_t ra = pc;
164 pc = get_reg(ins.rs());
165 set_reg(ins.rd(), ra);
166}
167
179{
180 uint32_t data = get_reg(ins.rt());
181 uint32_t shamt = ins.shamt();
182 uint32_t sign_bit = data & 0x80000000;
183 for(uint32_t i = 0; i < shamt; i++)
184 {
185 data >>= 1;
186 data |= sign_bit;
187 }
188 set_reg(ins.rd(), data);
189}
190
203{
204 set_reg(ins.rd(), get_reg(ins.rs()) - get_reg(ins.rt()));
205}
206
221{
222 uint32_t op1 = get_reg(ins.rs());
223 uint32_t op2 = get_reg(ins.rt());
224 if(op2 == 0)
225 {
226 //throw division by zero error
227 if(int32_t(op1) < 0)
228 {
229 lo = 1;
230 hi = op1;
231 }
232 else
233 {
234 lo = 0xffffffff;
235 hi = op1;
236 }
237 std::stringstream ss;
238 ss << "Division by zero in DIV: " << std::hex << ir;
239 throw std::runtime_error(ss.str());
240 }
241 if(op1 == 0x80000000 && op2 == 0xffffffff)
242 {
243 lo = 0x80000000;
244 hi = 0;
245 return;
246 }
247 lo = int32_t(op1) / int32_t(op2);
248 hi = int32_t(op1) % int32_t(op2);
249}
250
263{
264 set_reg(ins.rd(), lo);
265}
266
278{
279 uint32_t data = get_reg(ins.rt()) >> ins.shamt();
280 set_reg(ins.rd(), data);
281}
282
297{
298 uint32_t op1 = get_reg(ins.rs());
299 uint32_t op2 = get_reg(ins.rt());
300
301 if(op2 == 0)
302 {
303 //throw division by zero error
304 lo = 0xffffffff;
305 hi = op1;
306 std::stringstream ss;
307 ss << "Division by zero in DIVU: " << std::hex << ir;
308 throw std::runtime_error(ss.str());
309 }
310
311 lo = op1 / op2;
312 hi = op1 % op2;
313}
314
327{
328 set_reg(ins.rd(), hi);
329}
330
343{
344 int32_t op1 = get_reg(ins.rs());
345 int32_t op2 = get_reg(ins.rt());
346 set_reg(ins.rd(), op1 < op2);
347}
void JR()
Jump Register.
void SLTU()
Set on Less Than Unsigned.
void OR()
Bitwise OR.
void SRA()
Shift Right Arithmetic.
void DIV()
Divide.
void MFHI()
Move From HI.
void ADD()
Add.
void SUBU()
Subtract Unsigned.
uint32_t hi
HI register.
Definition cpu.hpp:219
uint32_t ir
Instruction register.
Definition cpu.hpp:194
void MFLO()
Move From LO.
void SLL()
Shift Left Logical.
void SLT()
Set on Less Than.
void SRL()
Shift Right Logical.
std::map< uint8_t, void(CPU::*)()> lookup_special
Lookup table for special instructions (opcode = 0b000000)
Definition cpu.hpp:299
Instruction ins
Instruction in the form of the Instruction structure.
Definition cpu.hpp:206
void JALR()
Jump and Link Register.
void DIVU()
Divide Unsigned.
uint32_t pc
Program counter.
Definition cpu.hpp:188
void AND()
Bitwise AND.
void ADDU()
Add Unsigned.
void set_reg(uint8_t reg, uint32_t data)
Sets the value of the given register from the general purpose registers.
Definition cpu_utils.cpp:61
uint32_t get_reg(uint8_t reg)
Gets the value of the given register from the general purpose registers.
Definition cpu_utils.cpp:74
void SPECIAL()
Looks up and executes the appropriate SPECIAL instruction.
uint32_t lo
LO register.
Definition cpu.hpp:226
uint32_t rt()
Target register for the instruction. Size: 5 bits [20-16].
Definition cpu.hpp:51
uint32_t rd()
Destination register for the instruction. Size: 5 bits [15-11].
Definition cpu.hpp:58
uint32_t funct()
Function field for the instruction. Size: 6 bits [5-0].
Definition cpu.hpp:74
uint32_t rs()
Source register for the instruction. Size: 5 bits [25-21].
Definition cpu.hpp:44
uint32_t shamt()
Shift amount for the instruction. Size: 5 bits [10-6].
Definition cpu.hpp:66