N64 Coprocessors integration
This commit is contained in:
@@ -10,8 +10,6 @@ add_library(cores
|
|||||||
Scheduler.cpp
|
Scheduler.cpp
|
||||||
Scheduler.hpp
|
Scheduler.hpp
|
||||||
common.hpp
|
common.hpp
|
||||||
util.hpp
|
util.hpp)
|
||||||
Audio.hpp
|
|
||||||
Audio.cpp)
|
|
||||||
target_include_directories(cores PUBLIC . ../../external)
|
target_include_directories(cores PUBLIC . ../../external)
|
||||||
target_link_libraries(cores PUBLIC n64)
|
target_link_libraries(cores PUBLIC n64)
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#include <Audio.hpp>
|
#include "Audio.hpp"
|
||||||
#include <SDL2/SDL.h>
|
#include <SDL2/SDL.h>
|
||||||
#include <util.hpp>
|
#include "util.hpp"
|
||||||
|
|
||||||
namespace natsukashii::core {
|
namespace natsukashii::core {
|
||||||
#define AUDIO_SAMPLE_RATE 48000
|
#define AUDIO_SAMPLE_RATE 48000
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <common.hpp>
|
#include "common.hpp"
|
||||||
|
|
||||||
namespace natsukashii::core {
|
namespace natsukashii::core {
|
||||||
void PushSample(s16, s16);
|
void PushSample(s16, s16);
|
||||||
@@ -12,6 +12,8 @@ add_library(n64-core
|
|||||||
Mem.hpp
|
Mem.hpp
|
||||||
RDP.cpp
|
RDP.cpp
|
||||||
RDP.hpp
|
RDP.hpp
|
||||||
|
Audio.cpp
|
||||||
|
Audio.hpp
|
||||||
mmio/AI.cpp
|
mmio/AI.cpp
|
||||||
mmio/AI.hpp
|
mmio/AI.hpp
|
||||||
mmio/Interrupt.cpp
|
mmio/Interrupt.cpp
|
||||||
|
|||||||
@@ -98,5 +98,7 @@ void Cpu::Step(Mem& mem) {
|
|||||||
regs.oldPC = regs.pc;
|
regs.oldPC = regs.pc;
|
||||||
regs.pc = regs.nextPC;
|
regs.pc = regs.nextPC;
|
||||||
regs.nextPC += 4;
|
regs.nextPC += 4;
|
||||||
|
|
||||||
|
Exec(mem, instruction);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -7,6 +7,96 @@ struct Cpu {
|
|||||||
Cpu() = default;
|
Cpu() = default;
|
||||||
void Step(Mem&);
|
void Step(Mem&);
|
||||||
Registers regs;
|
Registers regs;
|
||||||
|
private:
|
||||||
|
friend struct Cop1;
|
||||||
|
void special(Mem&, u32);
|
||||||
|
void regimm(u32);
|
||||||
|
void Exec(Mem&, u32);
|
||||||
|
void add(u32);
|
||||||
|
void addu(u32);
|
||||||
|
void addi(u32);
|
||||||
|
void addiu(u32);
|
||||||
|
void andi(u32);
|
||||||
|
void and_(u32);
|
||||||
|
void branch(bool, s64);
|
||||||
|
void branch_likely(bool, s64);
|
||||||
|
void b(u32, bool);
|
||||||
|
void blink(u32, bool);
|
||||||
|
void bl(u32, bool);
|
||||||
|
void bllink(u32, bool);
|
||||||
|
void dadd(u32);
|
||||||
|
void daddu(u32);
|
||||||
|
void daddi(u32);
|
||||||
|
void daddiu(u32);
|
||||||
|
void ddiv(u32);
|
||||||
|
void ddivu(u32);
|
||||||
|
void div_(u32);
|
||||||
|
void divu(u32);
|
||||||
|
void dmult(u32);
|
||||||
|
void dmultu(u32);
|
||||||
|
void dsll(u32);
|
||||||
|
void dsllv(u32);
|
||||||
|
void dsll32(u32);
|
||||||
|
void dsra(u32);
|
||||||
|
void dsrav(u32);
|
||||||
|
void dsra32(u32);
|
||||||
|
void dsrl(u32);
|
||||||
|
void dsrlv(u32);
|
||||||
|
void dsrl32(u32);
|
||||||
|
void dsub(u32);
|
||||||
|
void dsubu(u32);
|
||||||
|
void j(u32);
|
||||||
|
void jr(u32);
|
||||||
|
void jal(u32);
|
||||||
|
void jalr(u32);
|
||||||
|
void lui(u32);
|
||||||
|
void lbu(Mem&, u32);
|
||||||
|
void lb(Mem&, u32);
|
||||||
|
void ld(Mem&, u32);
|
||||||
|
void ldl(Mem&, u32);
|
||||||
|
void ldr(Mem&, u32);
|
||||||
|
void lh(Mem&, u32);
|
||||||
|
void lhu(Mem&, u32);
|
||||||
|
void ll(Mem&, u32);
|
||||||
|
void lld(Mem&, u32);
|
||||||
|
void lw(Mem&, u32);
|
||||||
|
void lwl(Mem&, u32);
|
||||||
|
void lwu(Mem&, u32);
|
||||||
|
void lwr(Mem&, u32);
|
||||||
|
void mfhi(u32);
|
||||||
|
void mflo(u32);
|
||||||
|
void mult(u32);
|
||||||
|
void multu(u32);
|
||||||
|
void mthi(u32);
|
||||||
|
void mtlo(u32);
|
||||||
|
void nor(u32);
|
||||||
|
void sb(Mem&, u32);
|
||||||
|
void sc(Mem&, u32);
|
||||||
|
void scd(Mem&, u32);
|
||||||
|
void sd(Mem&, u32);
|
||||||
|
void sdl(Mem&, u32);
|
||||||
|
void sdr(Mem&, u32);
|
||||||
|
void sh(Mem&, u32);
|
||||||
|
void sw(Mem&, u32);
|
||||||
|
void swl(Mem&, u32);
|
||||||
|
void swr(Mem&, u32);
|
||||||
|
void slti(u32);
|
||||||
|
void sltiu(u32);
|
||||||
|
void slt(u32);
|
||||||
|
void sltu(u32);
|
||||||
|
void sll(u32);
|
||||||
|
void sllv(u32);
|
||||||
|
void sub(u32);
|
||||||
|
void subu(u32);
|
||||||
|
void sra(u32);
|
||||||
|
void srav(u32);
|
||||||
|
void srl(u32);
|
||||||
|
void srlv(u32);
|
||||||
|
void trap(bool);
|
||||||
|
void or_(u32);
|
||||||
|
void ori(u32);
|
||||||
|
void xor_(u32);
|
||||||
|
void xori(u32);
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class ExceptionCode : u8 {
|
enum class ExceptionCode : u8 {
|
||||||
|
|||||||
@@ -81,6 +81,10 @@ template u8 Mem::Read<u8>(Registers& regs, u32 vaddr, s64 pc);
|
|||||||
template u16 Mem::Read<u16>(Registers& regs, u32 vaddr, s64 pc);
|
template u16 Mem::Read<u16>(Registers& regs, u32 vaddr, s64 pc);
|
||||||
template u32 Mem::Read<u32>(Registers& regs, u32 vaddr, s64 pc);
|
template u32 Mem::Read<u32>(Registers& regs, u32 vaddr, s64 pc);
|
||||||
template u64 Mem::Read<u64>(Registers& regs, u32 vaddr, s64 pc);
|
template u64 Mem::Read<u64>(Registers& regs, u32 vaddr, s64 pc);
|
||||||
|
template u8 Mem::Read<u8, false>(Registers& regs, u32 vaddr, s64 pc);
|
||||||
|
template u16 Mem::Read<u16, false>(Registers& regs, u32 vaddr, s64 pc);
|
||||||
|
template u32 Mem::Read<u32, false>(Registers& regs, u32 vaddr, s64 pc);
|
||||||
|
template u64 Mem::Read<u64, false>(Registers& regs, u32 vaddr, s64 pc);
|
||||||
|
|
||||||
template <class T, bool tlb>
|
template <class T, bool tlb>
|
||||||
void Mem::Write(Registers& regs, u32 vaddr, T val, s64 pc) {
|
void Mem::Write(Registers& regs, u32 vaddr, T val, s64 pc) {
|
||||||
@@ -111,4 +115,8 @@ template void Mem::Write<u8>(Registers& regs, u32 vaddr, u8 val, s64 pc);
|
|||||||
template void Mem::Write<u16>(Registers& regs, u32 vaddr, u16 val, s64 pc);
|
template void Mem::Write<u16>(Registers& regs, u32 vaddr, u16 val, s64 pc);
|
||||||
template void Mem::Write<u32>(Registers& regs, u32 vaddr, u32 val, s64 pc);
|
template void Mem::Write<u32>(Registers& regs, u32 vaddr, u32 val, s64 pc);
|
||||||
template void Mem::Write<u64>(Registers& regs, u32 vaddr, u64 val, s64 pc);
|
template void Mem::Write<u64>(Registers& regs, u32 vaddr, u64 val, s64 pc);
|
||||||
|
template void Mem::Write<u8, false>(Registers& regs, u32 vaddr, u8 val, s64 pc);
|
||||||
|
template void Mem::Write<u16, false>(Registers& regs, u32 vaddr, u16 val, s64 pc);
|
||||||
|
template void Mem::Write<u32, false>(Registers& regs, u32 vaddr, u32 val, s64 pc);
|
||||||
|
template void Mem::Write<u64, false>(Registers& regs, u32 vaddr, u64 val, s64 pc);
|
||||||
}
|
}
|
||||||
@@ -5,7 +5,7 @@ add_library(n64-cpu
|
|||||||
Registers.cpp
|
Registers.cpp
|
||||||
Registers.hpp
|
Registers.hpp
|
||||||
registers/Cop0.cpp
|
registers/Cop0.cpp
|
||||||
registers/Cop0.hpp)
|
registers/Cop0.hpp decode.cpp registers/cop0instructions.cpp registers/Cop1.cpp registers/Cop1.hpp registers/cop1instructions.cpp)
|
||||||
|
|
||||||
target_include_directories(n64-cpu PRIVATE . .. ../../ ../../../)
|
target_include_directories(n64-cpu PRIVATE . .. ../../ ../../../)
|
||||||
target_include_directories(n64-cpu PUBLIC registers ../../../../../external)
|
target_include_directories(n64-cpu PUBLIC registers ../../../../../external)
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <n64/core/cpu/registers/Cop0.hpp>
|
#include <n64/core/cpu/registers/Cop0.hpp>
|
||||||
|
#include <n64/core/cpu/registers/Cop1.hpp>
|
||||||
|
|
||||||
namespace natsukashii::n64::core {
|
namespace natsukashii::n64::core {
|
||||||
struct Registers {
|
struct Registers {
|
||||||
@@ -7,6 +8,7 @@ struct Registers {
|
|||||||
void SetPC(s64);
|
void SetPC(s64);
|
||||||
s64 gpr[32];
|
s64 gpr[32];
|
||||||
Cop0 cop0;
|
Cop0 cop0;
|
||||||
|
Cop1 cop1;
|
||||||
s64 oldPC, pc, nextPC;
|
s64 oldPC, pc, nextPC;
|
||||||
s64 hi, lo;
|
s64 hi, lo;
|
||||||
bool LLBit;
|
bool LLBit;
|
||||||
|
|||||||
143
src/core/n64/core/cpu/decode.cpp
Normal file
143
src/core/n64/core/cpu/decode.cpp
Normal file
@@ -0,0 +1,143 @@
|
|||||||
|
#include <n64/core/Cpu.hpp>
|
||||||
|
#include <util.hpp>
|
||||||
|
|
||||||
|
namespace natsukashii::n64::core {
|
||||||
|
void Cpu::special(Mem& mem, u32 instr) {
|
||||||
|
u8 mask = (instr & 0x3F);
|
||||||
|
// 00rr_rccc
|
||||||
|
switch (mask) { // TODO: named constants for clearer code
|
||||||
|
case 0:
|
||||||
|
if (instr != 0) {
|
||||||
|
sll(instr);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 0x02: srl(instr); break;
|
||||||
|
case 0x03: sra(instr); break;
|
||||||
|
case 0x04: sllv(instr); break;
|
||||||
|
case 0x06: srlv(instr); break;
|
||||||
|
case 0x07: srav(instr); break;
|
||||||
|
case 0x08: jr(instr); break;
|
||||||
|
case 0x09: jalr(instr); break;
|
||||||
|
case 0x0C: FireException(regs, ExceptionCode::Syscall, 0, regs.oldPC); break;
|
||||||
|
case 0x0D: FireException(regs, ExceptionCode::Breakpoint, 0, regs.oldPC); break;
|
||||||
|
case 0x0F: break;
|
||||||
|
case 0x10: mfhi(instr); break;
|
||||||
|
case 0x11: mthi(instr); break;
|
||||||
|
case 0x12: mflo(instr); break;
|
||||||
|
case 0x13: mtlo(instr); break;
|
||||||
|
case 0x14: dsllv(instr); break;
|
||||||
|
case 0x16: dsrlv(instr); break;
|
||||||
|
case 0x17: dsrav(instr); break;
|
||||||
|
case 0x18: mult(instr); break;
|
||||||
|
case 0x19: multu(instr); break;
|
||||||
|
case 0x1A: div_(instr); break;
|
||||||
|
case 0x1B: divu(instr); break;
|
||||||
|
case 0x1C: dmult(instr); break;
|
||||||
|
case 0x1D: dmultu(instr); break;
|
||||||
|
case 0x1E: ddiv(instr); break;
|
||||||
|
case 0x1F: ddivu(instr); break;
|
||||||
|
case 0x20: add(instr); break;
|
||||||
|
case 0x21: addu(instr); break;
|
||||||
|
case 0x22: sub(instr); break;
|
||||||
|
case 0x23: subu(instr); break;
|
||||||
|
case 0x24: and_(instr); break;
|
||||||
|
case 0x25: or_(instr); break;
|
||||||
|
case 0x26: xor_(instr); break;
|
||||||
|
case 0x27: nor(instr); break;
|
||||||
|
case 0x2A: slt(instr); break;
|
||||||
|
case 0x2B: sltu(instr); break;
|
||||||
|
case 0x2C: dadd(instr); break;
|
||||||
|
case 0x2D: daddu(instr); break;
|
||||||
|
case 0x2E: dsub(instr); break;
|
||||||
|
case 0x2F: dsubu(instr); break;
|
||||||
|
case 0x34: trap(regs.gpr[RS(instr)] == regs.gpr[RT(instr)]); break;
|
||||||
|
case 0x38: dsll(instr); break;
|
||||||
|
case 0x3A: dsrl(instr); break;
|
||||||
|
case 0x3B: dsra(instr); break;
|
||||||
|
case 0x3C: dsll32(instr); break;
|
||||||
|
case 0x3E: dsrl32(instr); break;
|
||||||
|
case 0x3F: dsra32(instr); break;
|
||||||
|
default:
|
||||||
|
util::panic("Unimplemented special {} {}", (mask >> 3) & 7, mask & 7);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Cpu::regimm(u32 instr) {
|
||||||
|
u8 mask = ((instr >> 16) & 0x1F);
|
||||||
|
// 000r_rccc
|
||||||
|
switch (mask) { // TODO: named constants for clearer code
|
||||||
|
case 0x00: b(instr, regs.gpr[RS(instr)] < 0); break;
|
||||||
|
case 0x01: b(instr, regs.gpr[RS(instr)] >= 0); break;
|
||||||
|
case 0x02: bl(instr, regs.gpr[RS(instr)] < 0); break;
|
||||||
|
case 0x03: bl(instr, regs.gpr[RS(instr)] >= 0); break;
|
||||||
|
case 0x10: blink(instr, regs.gpr[RS(instr)] < 0); break;
|
||||||
|
case 0x11: blink(instr, regs.gpr[RS(instr)] >= 0); break;
|
||||||
|
case 0x12: bllink(instr, regs.gpr[RS(instr)] < 0); break;
|
||||||
|
case 0x13: bllink(instr, regs.gpr[RS(instr)] >= 0); break;
|
||||||
|
default:
|
||||||
|
util::panic("Unimplemented regimm {} {}", (mask >> 3) & 3, mask & 7);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Cpu::Exec(Mem& mem, u32 instr) {
|
||||||
|
u8 mask = (instr >> 26) & 0x3f;
|
||||||
|
// 00rr_rccc
|
||||||
|
switch(mask) { // TODO: named constants for clearer code
|
||||||
|
case 0x00: special(mem, instr); break;
|
||||||
|
case 0x01: regimm(instr); break;
|
||||||
|
case 0x02: j(instr); break;
|
||||||
|
case 0x03: jal(instr); break;
|
||||||
|
case 0x04: b(instr, regs.gpr[RS(instr)] == regs.gpr[RT(instr)]); break;
|
||||||
|
case 0x05: b(instr, regs.gpr[RS(instr)] != regs.gpr[RT(instr)]); break;
|
||||||
|
case 0x06: b(instr, regs.gpr[RS(instr)] <= 0); break;
|
||||||
|
case 0x07: b(instr, regs.gpr[RS(instr)] > 0); break;
|
||||||
|
case 0x08: addi(instr); break;
|
||||||
|
case 0x09: addiu(instr); break;
|
||||||
|
case 0x0A: slti(instr); break;
|
||||||
|
case 0x0B: sltiu(instr); break;
|
||||||
|
case 0x0C: andi(instr); break;
|
||||||
|
case 0x0D: ori(instr); break;
|
||||||
|
case 0x0E: xori(instr); break;
|
||||||
|
case 0x0F: lui(instr); break;
|
||||||
|
case 0x10: regs.cop0.decode(regs, mem, instr); break;
|
||||||
|
case 0x11: regs.cop1.decode(regs, instr); break;
|
||||||
|
case 0x14: bl(instr, regs.gpr[RS(instr)] == regs.gpr[RT(instr)]); break;
|
||||||
|
case 0x15: bl(instr, regs.gpr[RS(instr)] != regs.gpr[RT(instr)]); break;
|
||||||
|
case 0x16: bl(instr, regs.gpr[RS(instr)] <= 0); break;
|
||||||
|
case 0x17: bl(instr, regs.gpr[RS(instr)] > 0); break;
|
||||||
|
case 0x18: daddi(instr); break;
|
||||||
|
case 0x19: daddiu(instr); break;
|
||||||
|
case 0x1A: ldl(mem, instr); break;
|
||||||
|
case 0x1B: ldr(mem, instr); break;
|
||||||
|
case 0x1F: FireException(regs, ExceptionCode::ReservedInstruction, 0, regs.oldPC); break;
|
||||||
|
case 0x20: lb(mem, instr); break;
|
||||||
|
case 0x21: lh(mem, instr); break;
|
||||||
|
case 0x22: lwl(mem, instr); break;
|
||||||
|
case 0x23: lw(mem, instr); break;
|
||||||
|
case 0x24: lbu(mem, instr); break;
|
||||||
|
case 0x25: lhu(mem, instr); break;
|
||||||
|
case 0x26: lwr(mem, instr); break;
|
||||||
|
case 0x27: lwu(mem, instr); break;
|
||||||
|
case 0x28: sb(mem, instr); break;
|
||||||
|
case 0x29: sh(mem, instr); break;
|
||||||
|
case 0x2A: swl(mem, instr); break;
|
||||||
|
case 0x2B: sw(mem, instr); break;
|
||||||
|
case 0x2C: sdl(mem, instr); break;
|
||||||
|
case 0x2D: sdr(mem, instr); break;
|
||||||
|
case 0x2E: swr(mem, instr); break;
|
||||||
|
case 0x2F: break; // CACHE
|
||||||
|
case 0x30: ll(mem, instr); break;
|
||||||
|
case 0x31: lwc1(mem, instr); break;
|
||||||
|
case 0x34: lld(mem, instr); break;
|
||||||
|
case 0x35: ldc1(mem, instr); break;
|
||||||
|
case 0x37: ld(mem, instr); break;
|
||||||
|
case 0x38: sc(mem, instr); break;
|
||||||
|
case 0x39: swc1(mem, instr); break;
|
||||||
|
case 0x3C: scd(mem, instr); break;
|
||||||
|
case 0x3D: sdc1(mem, instr); break;
|
||||||
|
case 0x3F: sd(mem, instr); break;
|
||||||
|
default:
|
||||||
|
util::panic("Unimplemented instruction {} {}", (mask >> 3) & 7, mask & 7);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -192,4 +192,25 @@ ExceptionCode GetTLBExceptionCode(TLBError error, TLBAccessType accessType) {
|
|||||||
util::panic("Getting TLB exception for unknown error code! ({})\n", error);
|
util::panic("Getting TLB exception for unknown error code! ({})\n", error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Cop0::decode(Registers& regs, Mem& mem, u32 instr) {
|
||||||
|
u8 mask_cop = (instr >> 21) & 0x1F;
|
||||||
|
u8 mask_cop2 = instr & 0x3F;
|
||||||
|
switch(mask_cop) {
|
||||||
|
case 0x00: mfc0(regs, instr); break;
|
||||||
|
case 0x01: dmfc0(regs, instr); break;
|
||||||
|
case 0x04: mtc0(regs, instr); break;
|
||||||
|
case 0x05: dmtc0(regs, instr); break;
|
||||||
|
case 0x10 ... 0x1F:
|
||||||
|
switch(mask_cop2) {
|
||||||
|
case 0x01: tlbr(regs); break;
|
||||||
|
case 0x02: tlbwi(regs); break;
|
||||||
|
case 0x08: tlbp(regs); break;
|
||||||
|
case 0x18: eret(regs); break;
|
||||||
|
default: util::panic("Unimplemented COP0 function {} {} ({:08X}) ({:016lX})", mask_cop2 >> 3, mask_cop2 & 7, instr, regs->old_pc);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default: util::panic("Unimplemented COP0 instruction {} {}", mask_cop >> 4, mask_cop & 7);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -5,6 +5,7 @@ namespace natsukashii::n64::core {
|
|||||||
#define STATUS_MASK 0xFF77FFFF
|
#define STATUS_MASK 0xFF77FFFF
|
||||||
|
|
||||||
struct Cpu;
|
struct Cpu;
|
||||||
|
struct Registers;
|
||||||
struct Mem;
|
struct Mem;
|
||||||
|
|
||||||
union Cop0Cause {
|
union Cop0Cause {
|
||||||
@@ -176,6 +177,17 @@ struct Cop0 {
|
|||||||
u32 r31{};
|
u32 r31{};
|
||||||
TLBEntry tlb[32]{};
|
TLBEntry tlb[32]{};
|
||||||
TLBError tlbError = NONE;
|
TLBError tlbError = NONE;
|
||||||
|
void decode(Registers&, Mem&, u32);
|
||||||
|
private:
|
||||||
|
void mtc0(Registers&, u32);
|
||||||
|
void dmtc0(Registers&, u32);
|
||||||
|
void mfc0(Registers&, u32);
|
||||||
|
void dmfc0(Registers&, u32);
|
||||||
|
void eret(Registers&);
|
||||||
|
|
||||||
|
void tlbr(Registers&);
|
||||||
|
void tlbwi(Registers&);
|
||||||
|
void tlbp(Registers&);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Registers;
|
struct Registers;
|
||||||
|
|||||||
139
src/core/n64/core/cpu/registers/Cop1.cpp
Normal file
139
src/core/n64/core/cpu/registers/Cop1.cpp
Normal file
@@ -0,0 +1,139 @@
|
|||||||
|
#include <n64/core/cpu/registers/Cop1.hpp>
|
||||||
|
#include <n64/core/cpu/Registers.hpp>
|
||||||
|
#include <n64/core/Cpu.hpp>
|
||||||
|
#include <util.hpp>
|
||||||
|
|
||||||
|
namespace natsukashii::n64::core {
|
||||||
|
void Cop1::decode(Cpu& cpu, u32 instr) {
|
||||||
|
Registers& regs = cpu.regs;
|
||||||
|
if(!regs.cop0.status.cu1) {
|
||||||
|
FireException(regs, ExceptionCode::CoprocessorUnusable, 1, regs.oldPC);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
u8 mask_sub = (instr >> 21) & 0x1F;
|
||||||
|
u8 mask_fun = instr & 0x3F;
|
||||||
|
u8 mask_branch = (instr >> 16) & 0x1F;
|
||||||
|
switch(mask_sub) {
|
||||||
|
// 000r_rccc
|
||||||
|
case 0x00: mfc1(regs, instr); break;
|
||||||
|
case 0x01: dmfc1(regs, instr); break;
|
||||||
|
case 0x02: cfc1(regs, instr); break;
|
||||||
|
case 0x04: mtc1(regs, instr); break;
|
||||||
|
case 0x05: dmtc1(regs, instr); break;
|
||||||
|
case 0x06: ctc1(regs, instr); break;
|
||||||
|
case 0x08:
|
||||||
|
switch(mask_branch) {
|
||||||
|
case 0: cpu.b(instr, !regs.cop1.fcr31.compare); break;
|
||||||
|
case 1: cpu.b(instr, regs.cop1.fcr31.compare); break;
|
||||||
|
case 2: cpu.bl(instr, !regs.cop1.fcr31.compare); break;
|
||||||
|
case 3: cpu.bl(instr, regs.cop1.fcr31.compare); break;
|
||||||
|
default: util::panic("Undefined BC COP1 {:02X}\n", mask_branch);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 0x10: // s
|
||||||
|
switch(mask_fun) {
|
||||||
|
case 0x00: adds(regs, instr); break;
|
||||||
|
case 0x01: subs(regs, instr); break;
|
||||||
|
case 0x02: muls(regs, instr); break;
|
||||||
|
case 0x03: divs(regs, instr); break;
|
||||||
|
case 0x04: sqrts(regs, instr); break;
|
||||||
|
case 0x05: abss(regs, instr); break;
|
||||||
|
case 0x06: movs(regs, instr); break;
|
||||||
|
case 0x07: negs(regs, instr); break;
|
||||||
|
case 0x08: roundls(regs, instr); break;
|
||||||
|
case 0x09: truncls(regs, instr); break;
|
||||||
|
case 0x0A: ceills(regs, instr); break;
|
||||||
|
case 0x0B: floorls(regs, instr); break;
|
||||||
|
case 0x0C: roundws(regs, instr); break;
|
||||||
|
case 0x0D: truncws(regs, instr); break;
|
||||||
|
case 0x0E: ceilws(regs, instr); break;
|
||||||
|
case 0x0F: floorws(regs, instr); break;
|
||||||
|
case 0x21: cvtds(regs, instr); break;
|
||||||
|
case 0x24: cvtws(regs, instr); break;
|
||||||
|
case 0x25: cvtls(regs, instr); break;
|
||||||
|
case 0x30: cconds(regs, instr, F); break;
|
||||||
|
case 0x31: cconds(regs, instr, UN); break;
|
||||||
|
case 0x32: cconds(regs, instr, EQ); break;
|
||||||
|
case 0x33: cconds(regs, instr, UEQ); break;
|
||||||
|
case 0x34: cconds(regs, instr, OLT); break;
|
||||||
|
case 0x35: cconds(regs, instr, ULT); break;
|
||||||
|
case 0x36: cconds(regs, instr, OLE); break;
|
||||||
|
case 0x37: cconds(regs, instr, ULE); break;
|
||||||
|
case 0x38: cconds(regs, instr, SF); break;
|
||||||
|
case 0x39: cconds(regs, instr, NGLE); break;
|
||||||
|
case 0x3A: cconds(regs, instr, SEQ); break;
|
||||||
|
case 0x3B: cconds(regs, instr, NGL); break;
|
||||||
|
case 0x3C: cconds(regs, instr, LT); break;
|
||||||
|
case 0x3D: cconds(regs, instr, NGE); break;
|
||||||
|
case 0x3E: cconds(regs, instr, LE); break;
|
||||||
|
case 0x3F: cconds(regs, instr, NGT); break;
|
||||||
|
default: util::panic("Unimplemented COP1 function S[{} {}] ({:08X}) ({:016lX})", mask_fun >> 3, mask_fun & 7, instr, regs.oldPC);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 0x11: // d
|
||||||
|
switch(mask_fun) {
|
||||||
|
case 0x00: addd(regs, instr); break;
|
||||||
|
case 0x01: subd(regs, instr); break;
|
||||||
|
case 0x02: muld(regs, instr); break;
|
||||||
|
case 0x03: divd(regs, instr); break;
|
||||||
|
case 0x04: sqrtd(regs, instr); break;
|
||||||
|
case 0x05: absd(regs, instr); break;
|
||||||
|
case 0x06: movd(regs, instr); break;
|
||||||
|
case 0x07: negd(regs, instr); break;
|
||||||
|
case 0x08: roundld(regs, instr); break;
|
||||||
|
case 0x09: truncld(regs, instr); break;
|
||||||
|
case 0x0A: ceilld(regs, instr); break;
|
||||||
|
case 0x0B: floorld(regs, instr); break;
|
||||||
|
case 0x0C: roundwd(regs, instr); break;
|
||||||
|
case 0x0D: truncwd(regs, instr); break;
|
||||||
|
case 0x0E: ceilwd(regs, instr); break;
|
||||||
|
case 0x0F: floorwd(regs, instr); break;
|
||||||
|
case 0x20: cvtsd(regs, instr); break;
|
||||||
|
case 0x24: cvtwd(regs, instr); break;
|
||||||
|
case 0x25: cvtld(regs, instr); break;
|
||||||
|
case 0x30: ccondd(regs, instr, F); break;
|
||||||
|
case 0x31: ccondd(regs, instr, UN); break;
|
||||||
|
case 0x32: ccondd(regs, instr, EQ); break;
|
||||||
|
case 0x33: ccondd(regs, instr, UEQ); break;
|
||||||
|
case 0x34: ccondd(regs, instr, OLT); break;
|
||||||
|
case 0x35: ccondd(regs, instr, ULT); break;
|
||||||
|
case 0x36: ccondd(regs, instr, OLE); break;
|
||||||
|
case 0x37: ccondd(regs, instr, ULE); break;
|
||||||
|
case 0x38: ccondd(regs, instr, SF); break;
|
||||||
|
case 0x39: ccondd(regs, instr, NGLE); break;
|
||||||
|
case 0x3A: ccondd(regs, instr, SEQ); break;
|
||||||
|
case 0x3B: ccondd(regs, instr, NGL); break;
|
||||||
|
case 0x3C: ccondd(regs, instr, LT); break;
|
||||||
|
case 0x3D: ccondd(regs, instr, NGE); break;
|
||||||
|
case 0x3E: ccondd(regs, instr, LE); break;
|
||||||
|
case 0x3F: ccondd(regs, instr, NGT); break;
|
||||||
|
default: util::panic("Unimplemented COP1 function D[{} {}] ({:08X}) ({:016lX})", mask_fun >> 3, mask_fun & 7, instr, regs.oldPC);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 0x14: // w
|
||||||
|
switch(mask_fun) {
|
||||||
|
case 0x01: subw(regs, instr); break;
|
||||||
|
case 0x05: absw(regs, instr); break;
|
||||||
|
case 0x02: mulw(regs, instr); break;
|
||||||
|
case 0x06: movw(regs, instr); break;
|
||||||
|
case 0x20: cvtsw(regs, instr); break;
|
||||||
|
case 0x21: cvtdw(regs, instr); break;
|
||||||
|
default: util::panic("Unimplemented COP1 function W[{} {}] ({:08X}) ({:016lX})", mask_fun >> 3, mask_fun & 7, instr, regs.oldPC);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 0x15: // l
|
||||||
|
switch(mask_fun) {
|
||||||
|
case 0x01: subl(regs, instr); break;
|
||||||
|
case 0x05: absl(regs, instr); break;
|
||||||
|
case 0x02: mull(regs, instr); break;
|
||||||
|
case 0x06: movl(regs, instr); break;
|
||||||
|
case 0x20: cvtsl(regs, instr); break;
|
||||||
|
case 0x21: cvtdl(regs, instr); break;
|
||||||
|
default: util::panic("Unimplemented COP1 function L[{} {}] ({:08X}) ({:016lX})", mask_fun >> 3, mask_fun & 7, instr, regs.oldPC);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default: util::panic("Unimplemented COP1 instruction {} {}", mask_sub >> 3, mask_sub & 7);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
200
src/core/n64/core/cpu/registers/Cop1.hpp
Normal file
200
src/core/n64/core/cpu/registers/Cop1.hpp
Normal file
@@ -0,0 +1,200 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <n64/core/cpu/registers/Cop0.hpp>
|
||||||
|
|
||||||
|
namespace natsukashii::n64::core {
|
||||||
|
union FCR31 {
|
||||||
|
struct {
|
||||||
|
unsigned rounding_mode:2;
|
||||||
|
unsigned flag_inexact_operation:1;
|
||||||
|
unsigned flag_underflow:1;
|
||||||
|
unsigned flag_overflow:1;
|
||||||
|
unsigned flag_division_by_zero:1;
|
||||||
|
unsigned flag_invalid_operation:1;
|
||||||
|
unsigned enable_inexact_operation:1;
|
||||||
|
unsigned enable_underflow:1;
|
||||||
|
unsigned enable_overflow:1;
|
||||||
|
unsigned enable_division_by_zero:1;
|
||||||
|
unsigned enable_invalid_operation:1;
|
||||||
|
unsigned cause_inexact_operation:1;
|
||||||
|
unsigned cause_underflow:1;
|
||||||
|
unsigned cause_overflow:1;
|
||||||
|
unsigned cause_division_by_zero:1;
|
||||||
|
unsigned cause_invalid_operation:1;
|
||||||
|
unsigned cause_unimplemented_operation:1;
|
||||||
|
unsigned:5;
|
||||||
|
unsigned compare:1;
|
||||||
|
unsigned fs:1;
|
||||||
|
unsigned:7;
|
||||||
|
} __attribute__((__packed__));
|
||||||
|
|
||||||
|
struct {
|
||||||
|
unsigned:7;
|
||||||
|
unsigned enable:5;
|
||||||
|
unsigned cause:6;
|
||||||
|
unsigned:14;
|
||||||
|
} __attribute__((__packed__));
|
||||||
|
|
||||||
|
u32 raw;
|
||||||
|
};
|
||||||
|
|
||||||
|
union FGR {
|
||||||
|
struct {
|
||||||
|
s32 lo:32;
|
||||||
|
s32 hi:32;
|
||||||
|
} __attribute__((__packed__));
|
||||||
|
|
||||||
|
s64 raw;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Cpu;
|
||||||
|
struct Registers;
|
||||||
|
|
||||||
|
struct Cop1 {
|
||||||
|
u32 fcr0;
|
||||||
|
FCR31 fcr31;
|
||||||
|
FGR fgr[32];
|
||||||
|
void decode(Cpu&, u32);
|
||||||
|
private:
|
||||||
|
template <typename T>
|
||||||
|
inline void SetReg(Cop0& cop0, u8 index, T value) {
|
||||||
|
if constexpr(sizeof(T) == 4) {
|
||||||
|
if (cop0.status.fr) {
|
||||||
|
fgr[index].lo = value;
|
||||||
|
} else {
|
||||||
|
if (index & 1) {
|
||||||
|
fgr[index & ~1].hi = value;
|
||||||
|
} else {
|
||||||
|
fgr[index].lo = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if constexpr(sizeof(T) == 8) {
|
||||||
|
if(!cop0.status.fr) {
|
||||||
|
index &= ~1;
|
||||||
|
}
|
||||||
|
|
||||||
|
fgr[index].raw = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
inline T GetReg(Cop0& cop0, u8 index) {
|
||||||
|
if constexpr(sizeof(T) == 4) {
|
||||||
|
if(cop0.status.fr) {
|
||||||
|
return fgr[index].lo;
|
||||||
|
} else {
|
||||||
|
if (index & 1) {
|
||||||
|
return fgr[index & ~1].hi;
|
||||||
|
} else {
|
||||||
|
return fgr[index].lo;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if constexpr(sizeof(T) == 8) {
|
||||||
|
if(!cop0.status.fr) {
|
||||||
|
index &= ~1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return fgr[index].raw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void SetCop1RegDouble(Cop0& cop0, u8 index, double value) {
|
||||||
|
u64 raw;
|
||||||
|
memcpy(&raw, &value, sizeof(double));
|
||||||
|
SetReg<u64>(cop0, index, raw);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline double GetCop1RegDouble(Cop0& cop0, u8 index) {
|
||||||
|
double doublevalue;
|
||||||
|
u64 raw = GetReg<u64>(cop0, index);
|
||||||
|
memcpy(&doublevalue, &raw, sizeof(double));
|
||||||
|
return doublevalue;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void SetCop1RegFloat(Cop0& cop0, u8 index, float value) {
|
||||||
|
u32 raw;
|
||||||
|
memcpy(&raw, &value, sizeof(float));
|
||||||
|
SetReg<u32>(cop0, index, raw);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline float GetCop1RegFloat(Cop0& cop0, u8 index) {
|
||||||
|
u32 raw = GetReg<u32>(cop0, index);
|
||||||
|
float floatvalue;
|
||||||
|
memcpy(&floatvalue, &raw, sizeof(float));
|
||||||
|
return floatvalue;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum CompConds {
|
||||||
|
T, UN, EQ, UEQ,
|
||||||
|
OLT, ULT, OLE, ULE,
|
||||||
|
SF, NGLE, SEQ, NGL,
|
||||||
|
LT, NGE, LE, NGT,
|
||||||
|
F, OR, NEQ, OLG,
|
||||||
|
UGE, OGE, UGT, OGT,
|
||||||
|
ST, GLE, SNE, GL,
|
||||||
|
NLT, GE, NLE, GT
|
||||||
|
};
|
||||||
|
|
||||||
|
void absd(Registers&, u32 instr);
|
||||||
|
void abss(Registers&, u32 instr);
|
||||||
|
void absw(Registers&, u32 instr);
|
||||||
|
void absl(Registers&, u32 instr);
|
||||||
|
void adds(Registers&, u32 instr);
|
||||||
|
void addd(Registers&, u32 instr);
|
||||||
|
void subs(Registers&, u32 instr);
|
||||||
|
void subd(Registers&, u32 instr);
|
||||||
|
void subw(Registers&, u32 instr);
|
||||||
|
void subl(Registers&, u32 instr);
|
||||||
|
void ceills(Registers&, u32 instr);
|
||||||
|
void ceilws(Registers&, u32 instr);
|
||||||
|
void ceilld(Registers&, u32 instr);
|
||||||
|
void ceilwd(Registers&, u32 instr);
|
||||||
|
void cfc1(Registers&, u32 instr);
|
||||||
|
void ctc1(Registers&, u32 instr);
|
||||||
|
void roundls(Registers&, u32 instr);
|
||||||
|
void roundld(Registers&, u32 instr);
|
||||||
|
void roundws(Registers&, u32 instr);
|
||||||
|
void roundwd(Registers&, u32 instr);
|
||||||
|
void floorls(Registers&, u32 instr);
|
||||||
|
void floorld(Registers&, u32 instr);
|
||||||
|
void floorws(Registers&, u32 instr);
|
||||||
|
void floorwd(Registers&, u32 instr);
|
||||||
|
void cvtls(Registers&, u32 instr);
|
||||||
|
void cvtws(Registers&, u32 instr);
|
||||||
|
void cvtds(Registers&, u32 instr);
|
||||||
|
void cvtsw(Registers&, u32 instr);
|
||||||
|
void cvtdw(Registers&, u32 instr);
|
||||||
|
void cvtsd(Registers&, u32 instr);
|
||||||
|
void cvtwd(Registers&, u32 instr);
|
||||||
|
void cvtld(Registers&, u32 instr);
|
||||||
|
void cvtdl(Registers&, u32 instr);
|
||||||
|
void cvtsl(Registers&, u32 instr);
|
||||||
|
void ccondd(Registers&, u32 instr, CompConds);
|
||||||
|
void cconds(Registers&, u32 instr, CompConds);
|
||||||
|
void divs(Registers&, u32 instr);
|
||||||
|
void divd(Registers&, u32 instr);
|
||||||
|
void muls(Registers&, u32 instr);
|
||||||
|
void muld(Registers&, u32 instr);
|
||||||
|
void mulw(Registers&, u32 instr);
|
||||||
|
void mull(Registers&, u32 instr);
|
||||||
|
void movs(Registers&, u32 instr);
|
||||||
|
void movd(Registers&, u32 instr);
|
||||||
|
void movw(Registers&, u32 instr);
|
||||||
|
void movl(Registers&, u32 instr);
|
||||||
|
void negs(Registers&, u32 instr);
|
||||||
|
void negd(Registers&, u32 instr);
|
||||||
|
void sqrts(Registers&, u32 instr);
|
||||||
|
void sqrtd(Registers&, u32 instr);
|
||||||
|
void lwc1(Registers&, Mem&, u32 instr);
|
||||||
|
void swc1(Registers&, Mem&, u32 instr);
|
||||||
|
void ldc1(Registers&, Mem&, u32 instr);
|
||||||
|
void mfc1(Registers&, u32 instr);
|
||||||
|
void dmfc1(Registers&, u32 instr);
|
||||||
|
void mtc1(Registers&, u32 instr);
|
||||||
|
void dmtc1(Registers&, u32 instr);
|
||||||
|
void sdc1(Registers&, Mem&, u32 instr);
|
||||||
|
void truncws(Registers&, u32 instr);
|
||||||
|
void truncwd(Registers&, u32 instr);
|
||||||
|
void truncls(Registers&, u32 instr);
|
||||||
|
void truncld(Registers&, u32 instr);
|
||||||
|
};
|
||||||
|
}
|
||||||
81
src/core/n64/core/cpu/registers/cop0instructions.cpp
Normal file
81
src/core/n64/core/cpu/registers/cop0instructions.cpp
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
#include <n64/core/cpu/registers/Cop0.hpp>
|
||||||
|
#include <n64/core/cpu/Registers.hpp>
|
||||||
|
#include <util.hpp>
|
||||||
|
|
||||||
|
namespace natsukashii::n64::core {
|
||||||
|
void Cop0::mtc0(Registers& regs, u32 instr) {
|
||||||
|
SetReg<u32>(RD(instr), regs.gpr[RT(instr)]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Cop0::dmtc0(Registers& regs, u32 instr) {
|
||||||
|
SetReg(RD(instr), regs.gpr[RT(instr)]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Cop0::mfc0(Registers& regs, u32 instr) {
|
||||||
|
regs.gpr[RT(instr)] = GetReg<s32>(RD(instr));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Cop0::dmfc0(Registers& regs, u32 instr) {
|
||||||
|
regs.gpr[RT(instr)] = GetReg<s64>(RD(instr));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Cop0::eret(Registers& regs) {
|
||||||
|
if(status.erl) {
|
||||||
|
regs.SetPC((s64)ErrorEPC);
|
||||||
|
status.erl = false;
|
||||||
|
} else {
|
||||||
|
regs.SetPC((s64)EPC);
|
||||||
|
status.exl = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Cop0::tlbr(Registers& regs) {
|
||||||
|
int Index = index & 0b111111;
|
||||||
|
if (Index >= 32) {
|
||||||
|
util::panic("TLBR with TLB index {}", index);
|
||||||
|
}
|
||||||
|
|
||||||
|
TLBEntry entry = tlb[Index];
|
||||||
|
|
||||||
|
entryHi.raw = entry.entryHi.raw;
|
||||||
|
entryLo0.raw = entry.entryLo0.raw & 0x3FFFFFFF;
|
||||||
|
entryLo1.raw = entry.entryLo1.raw & 0x3FFFFFFF;
|
||||||
|
|
||||||
|
entryLo0.g = entry.global;
|
||||||
|
entryLo1.g = entry.global;
|
||||||
|
pageMask.raw = entry.pageMask.raw;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Cop0::tlbwi(Registers& regs) {
|
||||||
|
PageMask page_mask;
|
||||||
|
page_mask = pageMask;
|
||||||
|
u32 top = page_mask.mask & 0xAAA;
|
||||||
|
page_mask.mask = top | (top >> 1);
|
||||||
|
|
||||||
|
int Index = index & 0x3F;
|
||||||
|
if(Index >= 32) {
|
||||||
|
util::panic("TLBWI with TLB index {}", Index);
|
||||||
|
}
|
||||||
|
|
||||||
|
tlb[Index].entryHi.raw = entryHi.raw;
|
||||||
|
tlb[Index].entryHi.vpn2 &= ~page_mask.mask;
|
||||||
|
|
||||||
|
tlb[Index].entryLo0.raw = entryLo0.raw & 0x03FFFFFE;
|
||||||
|
tlb[Index].entryLo1.raw = entryLo1.raw & 0x03FFFFFE;
|
||||||
|
tlb[Index].pageMask.raw = page_mask.raw;
|
||||||
|
|
||||||
|
tlb[Index].global = entryLo0.g && entryLo1.g;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Cop0::tlbp(Registers& regs) {
|
||||||
|
int match = -1;
|
||||||
|
TLBEntry* entry = TLBTryMatch(regs, entryHi.raw, &match);
|
||||||
|
if(entry && match >= 0) {
|
||||||
|
index = match;
|
||||||
|
} else {
|
||||||
|
index = 0x80000000;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
255
src/core/n64/core/cpu/registers/cop1instructions.cpp
Normal file
255
src/core/n64/core/cpu/registers/cop1instructions.cpp
Normal file
@@ -0,0 +1,255 @@
|
|||||||
|
#include <n64/core/cpu/registers/Cop1.hpp>
|
||||||
|
#include <n64/core/cpu/Registers.hpp>
|
||||||
|
|
||||||
|
namespace natsukashii::n64::core {
|
||||||
|
void Cop1::absd(Registers& regs, u32 instr) {
|
||||||
|
double fs = GetCop1RegDouble(regs.cop0, FS(instr));
|
||||||
|
SetCop1RegDouble(regs.cop0, FD(instr), fabs(fs));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Cop1::abss(Registers& regs, u32 instr) {
|
||||||
|
float fs = GetCop1RegFloat(regs.cop0, FS(instr));
|
||||||
|
SetCop1RegFloat(regs.cop0, FD(instr), fabsf(fs));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Cop1::absw(Registers& regs, u32 instr) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Cop1::absl(Registers& regs, u32 instr) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Cop1::adds(Registers& regs, u32 instr) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Cop1::addd(Registers& regs, u32 instr) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Cop1::subs(Registers& regs, u32 instr) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Cop1::subd(Registers& regs, u32 instr) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Cop1::subw(Registers& regs, u32 instr) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Cop1::subl(Registers& regs, u32 instr) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Cop1::ceills(Registers& regs, u32 instr) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Cop1::ceilws(Registers& regs, u32 instr) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Cop1::ceilld(Registers& regs, u32 instr) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Cop1::ceilwd(Registers& regs, u32 instr) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Cop1::cfc1(Registers& regs, u32 instr) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Cop1::ctc1(Registers& regs, u32 instr) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Cop1::roundls(Registers& regs, u32 instr) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Cop1::roundld(Registers& regs, u32 instr) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Cop1::roundws(Registers& regs, u32 instr) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Cop1::roundwd(Registers& regs, u32 instr) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Cop1::floorls(Registers& regs, u32 instr) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Cop1::floorld(Registers& regs, u32 instr) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Cop1::floorws(Registers& regs, u32 instr) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Cop1::floorwd(Registers& regs, u32 instr) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Cop1::cvtls(Registers& regs, u32 instr) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Cop1::cvtws(Registers& regs, u32 instr) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Cop1::cvtds(Registers& regs, u32 instr) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Cop1::cvtsw(Registers& regs, u32 instr) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Cop1::cvtdw(Registers& regs, u32 instr) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Cop1::cvtsd(Registers& regs, u32 instr) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Cop1::cvtwd(Registers& regs, u32 instr) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Cop1::cvtld(Registers& regs, u32 instr) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Cop1::cvtdl(Registers& regs, u32 instr) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Cop1::cvtsl(Registers& regs, u32 instr) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Cop1::ccondd(Registers& regs, u32 instr, CompConds cond) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Cop1::cconds(Registers& regs, u32 instr, CompConds cond) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Cop1::divs(Registers& regs, u32 instr) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Cop1::divd(Registers& regs, u32 instr) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Cop1::muls(Registers& regs, u32 instr) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Cop1::muld(Registers& regs, u32 instr) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Cop1::mulw(Registers& regs, u32 instr) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Cop1::mull(Registers& regs, u32 instr) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Cop1::movs(Registers& regs, u32 instr) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Cop1::movd(Registers& regs, u32 instr) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Cop1::movw(Registers& regs, u32 instr) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Cop1::movl(Registers& regs, u32 instr) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Cop1::negs(Registers& regs, u32 instr) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Cop1::negd(Registers& regs, u32 instr) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Cop1::sqrts(Registers& regs, u32 instr) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Cop1::sqrtd(Registers& regs, u32 instr) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Cop1::lwc1(Registers& regs, Mem& mem, u32 instr) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Cop1::swc1(Registers& regs, Mem& mem, u32 instr) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Cop1::ldc1(Registers& regs, Mem& mem, u32 instr) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Cop1::mfc1(Registers& regs, u32 instr) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Cop1::dmfc1(Registers& regs, u32 instr) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Cop1::mtc1(Registers& regs, u32 instr) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Cop1::dmtc1(Registers& regs, u32 instr) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Cop1::sdc1(Registers& regs, Mem&, u32 instr) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Cop1::truncws(Registers& regs, u32 instr) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Cop1::truncwd(Registers& regs, u32 instr) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Cop1::truncls(Registers& regs, u32 instr) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Cop1::truncld(Registers& regs, u32 instr) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
#include <util.hpp>
|
#include <util.hpp>
|
||||||
#include <n64/core/Mem.hpp>
|
#include <n64/core/Mem.hpp>
|
||||||
#include <n64/core/cpu/Registers.hpp>
|
#include <n64/core/cpu/Registers.hpp>
|
||||||
#include <Audio.hpp>
|
#include <n64/core/Audio.hpp>
|
||||||
|
|
||||||
namespace natsukashii::n64::core {
|
namespace natsukashii::n64::core {
|
||||||
auto AI::Read(u32 addr) const -> u32 {
|
auto AI::Read(u32 addr) const -> u32 {
|
||||||
|
|||||||
Reference in New Issue
Block a user