Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

n64: implement undocumented accesses in FPU half-mode #1364

Merged
merged 3 commits into from
Jan 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions ares/n64/cpu/cpu.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -652,7 +652,7 @@ struct CPU : Thread {

struct Coprocessor {
static constexpr u8 revision = 0x00;
static constexpr u8 implementation = 0x0b;
static constexpr u8 implementation = 0x0a;
} coprocessor;

struct ControlStatus {
Expand Down Expand Up @@ -687,7 +687,9 @@ struct CPU : Thread {
//interpreter-fpu.cpp
float_env fenv;

template<typename T> auto fgr(u32) -> T&;
template<typename T> auto fgr_t(u32) -> T&;
template<typename T> auto fgr_s(u32) -> T&;
template<typename T> auto fgr_d(u32) -> T&;
auto getControlRegisterFPU(n5) -> u32;
auto setControlRegisterFPU(n5, n32) -> void;
template<bool CVT> auto checkFPUExceptions() -> bool;
Expand Down
82 changes: 61 additions & 21 deletions ares/n64/cpu/interpreter-fpu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ auto CPU::FPU::setFloatingPointMode(bool mode) -> void {
}
}

template<> auto CPU::fgr<s32>(u32 index) -> s32& {
template<> auto CPU::fgr_t<s32>(u32 index) -> s32& {
if(scc.status.floatingPointMode) {
return fpu.r[index].s32;
} else if(index & 1) {
Expand All @@ -17,33 +17,73 @@ template<> auto CPU::fgr<s32>(u32 index) -> s32& {
}
}

template<> auto CPU::fgr<u32>(u32 index) -> u32& {
return (u32&)fgr<s32>(index);
template<> auto CPU::fgr_s<s32>(u32 index) -> s32& {
if(scc.status.floatingPointMode) {
return fpu.r[index].s32;
} else {
return fpu.r[index & ~1].s32;
}
}

template<> auto CPU::fgr_d<s32>(u32 index) -> s32& {
fpu.r[index].s32h = 0;
return fpu.r[index].s32;
}

template<> auto CPU::fgr_t<u32>(u32 index) -> u32& {
return (u32&)fgr_t<s32>(index);
}

template<> auto CPU::fgr_t<f32>(u32 index) -> f32& {
return fpu.r[index].f32;
}

template<> auto CPU::fgr_d<f32>(u32 index) -> f32& {
fpu.r[index].f32h = 0;
return fpu.r[index].f32;
}

template<> auto CPU::fgr<f32>(u32 index) -> f32& {
template<> auto CPU::fgr_s<f32>(u32 index) -> f32& {
if(scc.status.floatingPointMode) {
return fpu.r[index].f32;
} else if(index & 1) {
return fpu.r[index & ~1].f32h;
} else {
return fpu.r[index & ~1].f32;
}
}

template<> auto CPU::fgr<s64>(u32 index) -> s64& {
template<> auto CPU::fgr_t<s64>(u32 index) -> s64& {
if(scc.status.floatingPointMode) {
return fpu.r[index].s64;
} else {
return fpu.r[index & ~1].s64;
}
}

template<> auto CPU::fgr<u64>(u32 index) -> u64& {
return (u64&)fgr<s64>(index);
template<> auto CPU::fgr_d<s64>(u32 index) -> s64& {
return fpu.r[index].s64;
}

template<> auto CPU::fgr_s<s64>(u32 index) -> s64& {
return fgr_t<s64>(index);
}

template<> auto CPU::fgr_t<u64>(u32 index) -> u64& {
return (u64&)fgr_t<s64>(index);
}

template<> auto CPU::fgr_s<u64>(u32 index) -> u64& {
return fgr_t<u64>(index);
}

template<> auto CPU::fgr_t<f64>(u32 index) -> f64& {
return fpu.r[index].f64;
}

template<> auto CPU::fgr<f64>(u32 index) -> f64& {
template<> auto CPU::fgr_d<f64>(u32 index) -> f64& {
return fgr_t<f64>(index);
}

template<> auto CPU::fgr_s<f64>(u32 index) -> f64& {
if(scc.status.floatingPointMode) {
return fpu.r[index].f64;
} else {
Expand Down Expand Up @@ -210,8 +250,9 @@ auto CPU::checkFPUExceptions() -> bool {

#define CHECK_FPE_IMPL(type, res, operation, convert) \
fenv.clearExcept(); \
type res = [&]() noinline -> type { return operation; }(); \
if (checkFPUExceptions<convert>()) return;
volatile type v##res = [&]() noinline -> type { return operation; }(); \
if (checkFPUExceptions<convert>()) return; \
type res = v##res;

#define CHECK_FPE(type, res, operation) CHECK_FPE_IMPL(type, res, operation, false)
#define CHECK_FPE_CONV(type, res, operation) CHECK_FPE_IMPL(type, res, operation, true)
Expand Down Expand Up @@ -364,9 +405,9 @@ auto CPU::fpuCheckInputConv<s64>(f64& f) -> bool {
}

#define CF fpu.csr.compare
#define FD(type) fgr<type>(fd)
#define FS(type) fgr<type>(fs)
#define FT(type) fgr<type>(ft)
#define FD(type) fgr_d<type>(fd)
#define FS(type) fgr_s<type>(fs)
#define FT(type) fgr_t<type>(ft)

auto CPU::BC1(bool value, bool likely, s16 imm) -> void {
if(!fpuCheckStart()) return;
Expand Down Expand Up @@ -814,8 +855,7 @@ auto CPU::FFLOOR_W_D(u8 fd, u8 fs) -> void {
}

auto CPU::FMOV_S(u8 fd, u8 fs) -> void {
if(!scc.status.enable.coprocessor1) return exception.coprocessor1();
FD(f32) = FS(f32);
return FMOV_D(fd, fs);
}

auto CPU::FMOV_D(u8 fd, u8 fs) -> void {
Expand Down Expand Up @@ -995,14 +1035,14 @@ auto CPU::LWC1(u8 ft, cr64& rs, s16 imm) -> void {
if(auto data = read<Word>(rs.u64 + imm)) FT(u32) = *data;
}

auto CPU::MFC1(r64& rt, u8 fs) -> void {
auto CPU::MFC1(r64& rt, u8 ft) -> void {
if(!scc.status.enable.coprocessor1) return exception.coprocessor1();
rt.u64 = FS(s32);
rt.u64 = FT(s32);
}

auto CPU::MTC1(cr64& rt, u8 fs) -> void {
auto CPU::MTC1(cr64& rt, u8 ft) -> void {
if(!scc.status.enable.coprocessor1) return exception.coprocessor1();
FS(s32) = rt.u32;
FT(s32) = rt.u32;
}

auto CPU::SDC1(u8 ft, cr64& rs, s16 imm) -> void {
Expand Down
1 change: 1 addition & 0 deletions ares/n64/pi/bus.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ inline auto PI::readWord(u32 address, Thread& thread) -> u32 {
if(address <= 0x046f'ffff) return ioRead(address);

if (unlikely(io.ioBusy)) {
debug(unusual, "[PI::readWord] PI read to 0x", hex(address, 8L), " will not behave as expected because PI writing is in progress");
thread.step(writeForceFinish() * 2);
return io.busLatch;
}
Expand Down
Loading