WolPSX
Loading...
Searching...
No Matches
ins.cpp
1#include <core/cpu/cpu.hpp>
2#include <iostream>
3#include <sstream>
4
14{
15 set_reg(ins.rt(), ins.imm() << 16);
16}
17
27void CPU::ORI() //Bitwise OR Immediate
28{
29 set_reg(ins.rt(), get_reg(ins.rs()) | ins.imm());
30}
31
45void CPU::SW()
46{
47 //if cache is isolated
48 if(cop0_status & 0x00010000)
49 {
50 //TODO: Implement Cache
51 std::cout << "Ignoring SW as cache is isolated.\n";
52 return;
53 }
54
55 uint32_t offset = ins.imm();
56 //pad offset with bit at 16th position
57 if(offset & 0x8000)
58 {
59 offset |= 0xffff0000;
60 }
61 write32(get_reg(ins.rs()) + offset, get_reg(ins.rt()));
62}
63
76{
77 uint32_t data_se = ins.imm();
78 //pad offset with bit at 16th position
79 if(data_se & 0x8000)
80 {
81 data_se |= 0xffff0000;
82 }
83 set_reg(ins.rt(), get_reg(ins.rs()) + data_se);
84
85 // std::cout << "Added " << std::hex << data_se << " to " << get_reg(ins.rs()) << " to get " << get_reg(ins.rt()) << "\n"; //REMOVE
86}
87
94void CPU::J()
95{
96 pc = ((pc - 4) & 0xf0000000) | (ins.addr() << 2);
97}
98
110{
111 uint32_t offset = ins.imm();
112 //pad offset with bit at 16th position
113 if(offset & 0x8000)
114 {
115 offset |= 0xffff0000;
116 }
117 if(get_reg(ins.rs()) != get_reg(ins.rt()))
118 {
119 branch(offset);
120 }
121}
122
138{
139 uint32_t extended_imm = ins.imm();
140 //pad offset with bit at 16th position
141 if(extended_imm & 0x8000)
142 {
143 extended_imm |= 0xffff0000;
144 }
145 //check for signed overflow
146 //TODO: Handle signed overflow exception
147 if(((extended_imm & 0x80000000) && (get_reg(ins.rs()) & 0x80000000) && (((get_reg(ins.rs()) + extended_imm) & 0x80000000) == 0))
148 || (((extended_imm & 0x80000000) == 0) && ((get_reg(ins.rs()) & 0x80000000) == 0) && ((get_reg(ins.rs()) + extended_imm) & 0x80000000)))
149 {
150 //throw signed overflow error
151 std::stringstream ss;
152 ss << "Signed overflow in ADDI: " << std::hex << ir;
153 throw std::runtime_error(ss.str());
154 }
155
156 set_reg(ins.rt(), get_reg(ins.rs()) + extended_imm);
157}
158
174{
175 uint32_t offset = ins.imm();
176 //pad offset with bit at 16th position
177 if(offset & 0x8000)
178 {
179 offset |= 0xffff0000;
180 }
181
182 load_queue.push(RegisterLoad(ins.rt(), read32(get_reg(ins.rs()) + offset), 1));
183}
184
200{
201 //if cache is isolated
202 if(cop0_status & 0x00010000)
203 {
204 //TODO: Implement Cache
205 std::cout << "Ignoring SH as cache is isolated.\n";
206 return;
207 }
208
209 uint32_t offset = ins.imm();
210 //pad offset with bit at 16th position
211 if(offset & 0x8000)
212 {
213 offset |= 0xffff0000;
214 }
215 write16(get_reg(ins.rs()) + offset, get_reg(ins.rt()) & 0xffff);
216}
217
229{
230 // std::cout << "Jumped to: " << std::hex << ((pc & 0xf0000000) | (ins.addr() << 2)) << "\n"; //REMOVE
231 // uint32_t ra = pc + 4;
232 uint32_t ra = pc;
233 pc = ((pc - 4) & 0xf0000000) | (ins.addr() << 2);
234 set_reg(31, ra);
235}
236
249{
250 uint32_t data = ins.imm() & get_reg(ins.rs());
251 set_reg(ins.rt(), data);
252}
253
269{
270 //if cache is isolated
271 if(cop0_status & 0x00010000)
272 {
273 //TODO: Implement Cache
274 std::cout << "Ignoring SB as cache is isolated.\n";
275 return;
276 }
277
278 uint32_t offset = ins.imm();
279 //pad offset with bit at 16th position
280 if(offset & 0x8000)
281 {
282 offset |= 0xffff0000;
283 }
284 write8(get_reg(ins.rs()) + offset, get_reg(ins.rt()) & 0xff);
285}
286
302{
303 uint32_t offset = ins.imm();
304 //pad offset with bit at 16th position
305 if(offset & 0x8000)
306 {
307 offset |= 0xffff0000;
308 }
309 uint32_t data_s = read8(get_reg(ins.rs()) + offset);
310 if(data_s & 0b10000000)
311 {
312 data_s |= 0xffffff00;
313 }
314
315 load_queue.push(RegisterLoad(ins.rt(), data_s, 1));
316}
317
330{
331 uint32_t offset = ins.imm();
332 //pad offset with bit at 16th position
333 if(offset & 0x8000)
334 {
335 offset |= 0xffff0000;
336 }
337 if(get_reg(ins.rs()) == get_reg(ins.rt()))
338 {
339 branch(offset);
340 }
341}
342
354{
355 uint32_t offset = ins.imm();
356 //pad offset with bit at 16th position
357 if(offset & 0x8000)
358 {
359 offset |= 0xffff0000;
360 }
361 if(int32_t(get_reg(ins.rs())) > 0)
362 {
363 branch(offset);
364 }
365}
366
378{
379 uint32_t offset = ins.imm();
380 //pad offset with bit at 16th position
381 if(offset & 0x8000)
382 {
383 offset |= 0xffff0000;
384 }
385 if(int32_t(get_reg(ins.rs())) <= 0)
386 {
387 branch(offset);
388 }
389}
390
406{
407 uint32_t offset = ins.imm();
408 //pad offset with bit at 16th position
409 if(offset & 0x8000)
410 {
411 offset |= 0xffff0000;
412 }
413 uint32_t data = read8(get_reg(ins.rs()) + offset);
414 load_queue.push(RegisterLoad(ins.rt(), data, 1));
415}
416
427void CPU::BLGE() //Choose between BLTZAL, BGEZAL, BLTZ, BGEZ
428{
429 //check if the 16th bit of the instruction is set
430 if(ir & 0x00010000)
431 {
432 //check if the 20th bit of the instruction is set
433 if(ir & 0x00100000)
434 BGEZAL();
435 else
436 BGEZ();
437 }
438 else
439 {
440 //check if the 20th bit of the instruction is set
441 if(ir & 0x00100000)
442 BLTZAL();
443 else
444 BLTZ();
445 }
446}
447
459{
460 uint32_t offset = ins.imm();
461 //pad offset with bit at 16th position
462 if(offset & 0x8000)
463 offset |= 0xffff0000;
464 int32_t op1 = get_reg(ins.rs());
465 uint8_t val = op1 < 0;
466 if(val)
467 branch(offset);
468}
469
482{
483 uint32_t offset = ins.imm();
484 //pad offset with bit at 16th position
485 if(offset & 0x8000)
486 offset |= 0xffff0000;
487 int32_t op1 = get_reg(ins.rs());
488 uint8_t val = op1 < 0;
489 if(val)
490 {
491 // uint32_t ra = pc + 4;
492 uint32_t ra = pc;
493 branch(offset);
494 set_reg(31, ra);
495 }
496}
497
509{
510 uint32_t offset = ins.imm();
511 //pad offset with bit at 16th position
512 if(offset & 0x8000)
513 offset |= 0xffff0000;
514 int32_t op1 = get_reg(ins.rs());
515 uint8_t val = op1 >= 0;
516 if(val)
517 branch(offset);
518}
519
532{
533 uint32_t offset = ins.imm();
534 //pad offset with bit at 16th position
535 if(offset & 0x8000)
536 offset |= 0xffff0000;
537 int32_t op1 = get_reg(ins.rs());
538 uint8_t val = op1 >= 0;
539 if(val)
540 {
541 // uint32_t ra = pc + 4;
542 uint32_t ra = pc;
543 branch(offset);
544 set_reg(31, ra);
545 }
546}
547
560{
561 uint32_t imm_se = ins.imm();
562 //pad offset with bit at 16th position
563 if(imm_se & 0x8000)
564 imm_se |= 0xffff0000;
565 int32_t op1 = get_reg(ins.rs());
566 int32_t op2 = imm_se;
567 set_reg(ins.rt(), op1 < op2);
568}
569
582{
583 uint32_t arg = ins.imm();
584 //pad argument with bit at 16th position
585 if(arg & 0x8000)
586 arg |= 0xffff0000;
587
588 uint32_t val = (get_reg(ins.rs()) < arg);
589 set_reg(ins.rt(), val);
590}
uint8_t read8(uint32_t addr)
Read a 8 bit word from the bus.
Definition cpu_rw.cpp:69
void SLTIU()
Set on Less Than Immediate Unsigned.
Definition ins.cpp:581
void BEQ()
Branch on Equal.
Definition ins.cpp:329
void write16(uint32_t addr, uint16_t data)
Write a 16 bit word to the bus.
Definition cpu_rw.cpp:55
void BLGE()
Choose between BLTZAL, BGEZAL, BLTZ, BGEZ.
Definition ins.cpp:427
void JAL()
Jump and Link.
Definition ins.cpp:228
uint32_t read32(uint32_t addr)
Read a 32 bit word from the bus.
Definition cpu_rw.cpp:13
void LUI()
Load Upper Immediate.
Definition ins.cpp:13
void BLEZ()
Branch on Less Than or Equal to Zero.
Definition ins.cpp:377
void branch(uint32_t offset)
Branches to the given offset.
Definition cpu_utils.cpp:44
uint32_t ir
Instruction register.
Definition cpu.hpp:194
void BGEZAL()
Branch on Greater Than or Equal to Zero And Link.
Definition ins.cpp:531
void SLTI()
Set on Less Than Immediate.
Definition ins.cpp:559
void LBU()
Load Byte Unsigned.
Definition ins.cpp:405
void J()
Unconditional Jump.
Definition ins.cpp:94
Instruction ins
Instruction in the form of the Instruction structure.
Definition cpu.hpp:206
uint32_t cop0_status
COP0 status register.
Definition cpu.hpp:233
void write8(uint32_t addr, uint8_t data)
Write a 8 bit word to the bus.
Definition cpu_rw.cpp:83
void write32(uint32_t addr, uint32_t data)
Write a 32 bit word to the bus.
Definition cpu_rw.cpp:27
void ORI()
Bitwise OR Immediate.
Definition ins.cpp:27
void BLTZAL()
Branch on Less Than Zero And Link.
Definition ins.cpp:481
void LB()
Load Byte.
Definition ins.cpp:301
uint32_t pc
Program counter.
Definition cpu.hpp:188
void ADDIU()
Add Immediate Unsigned.
Definition ins.cpp:75
void BNE()
Branch on Not Equal.
Definition ins.cpp:109
void SW()
Store Word.
Definition ins.cpp:45
void LW()
Load Word.
Definition ins.cpp:173
void ADDI()
Add Immediate.
Definition ins.cpp:137
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 BGEZ()
Branch on Greater Than or Equal to Zero.
Definition ins.cpp:508
void BLTZ()
Branch on Less Than Zero.
Definition ins.cpp:458
void ANDI()
Bitwise AND Immediate.
Definition ins.cpp:248
void SH()
Store Halfword.
Definition ins.cpp:199
std::queue< RegisterLoad > load_queue
Queue to store the loads to the general purpose registers.
Definition cpu.hpp:182
void SB()
Store Byte.
Definition ins.cpp:268
void BGTZ()
Branch on Greater Than Zero.
Definition ins.cpp:353
uint32_t imm()
Immediate value for the instruction. Size: 16 bits [15-0].
Definition cpu.hpp:81
uint32_t rt()
Target register for the instruction. Size: 5 bits [20-16].
Definition cpu.hpp:51
uint32_t addr()
Address value for jump/branch instructions. Size: 26 bits [25-0].
Definition cpu.hpp:88
uint32_t rs()
Source register for the instruction. Size: 5 bits [25-21].
Definition cpu.hpp:44
Struture to store details of loads to the general purpose registers.
Definition cpu.hpp:96