mirror of
https://git.eden-emu.dev/eden-emu/eden
synced 2026-06-29 13:55:32 +02:00
[dynarmic] fix pre-SSE4.1 having errors on CMHI/CMLO, fix extra nuisances and add INTERP testcase (#4025)
does a bit of code dedup fixes pre-SSE4.1 having horrific CMHI/CMLO Signed-off-by: lizzie <lizzie@eden-emu.dev> Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4025 Reviewed-by: crueter <crueter@eden-emu.dev> Reviewed-by: MaranBr <maranbr@eden-emu.dev>
This commit is contained in:
parent
f729dbb3c3
commit
ad9af25027
6 changed files with 158 additions and 115 deletions
|
|
@ -2587,11 +2587,11 @@ TEST_CASE("A64: Manual Vector Min/Max U64 (Optimizer Test)", "[a64]") {
|
|||
|
||||
// MaxU64 pattern: (a > b) ? a : b
|
||||
code.CMHI(V2.D2(), V0.D2(), V1.D2()); // V2 = Mask (A > B)
|
||||
code.BSL(V2.B16(), V0.B16(), V1.B16()); // V2 = Resul
|
||||
code.BSL(V2.B16(), V0.B16(), V1.B16()); // V2 = Result
|
||||
|
||||
// MinU64 pattern: (a > b) ? b : a
|
||||
code.CMHI(V3.D2(), V0.D2(), V1.D2()); // V3 = Mask (A > B)
|
||||
code.BSL(V3.B16(), V1.B16(), V0.B16()); // V3 = Resul
|
||||
code.BSL(V3.B16(), V1.B16(), V0.B16()); // V3 = Result
|
||||
|
||||
jit.SetPC(0);
|
||||
jit.SetVector(0, {100, 20});
|
||||
|
|
@ -2603,3 +2603,32 @@ TEST_CASE("A64: Manual Vector Min/Max U64 (Optimizer Test)", "[a64]") {
|
|||
CHECK(jit.GetVector(2) == Vector{100, 200});
|
||||
CHECK(jit.GetVector(3) == Vector{50, 20});
|
||||
}
|
||||
|
||||
TEST_CASE("A64: Rounding", "[a64]") {
|
||||
A64TestEnv env;
|
||||
A64::UserConfig jit_user_config{};
|
||||
jit_user_config.callbacks = &env;
|
||||
A64::Jit jit{jit_user_config};
|
||||
|
||||
oaknut::VectorCodeGenerator code{env.code_mem, nullptr};
|
||||
|
||||
code.FRINTN(V1.S4(), V0.S4()); // ToNearest_TieEven
|
||||
code.FRINTM(V2.S4(), V0.S4()); // TowardsMinusInfinity
|
||||
code.FRINTP(V3.S4(), V0.S4()); // TowardsPlusInfinity
|
||||
code.FRINTZ(V4.S4(), V0.S4()); // TowardsZero
|
||||
code.FRINTA(V5.S4(), V0.S4()); // ToNearest_TieAwayFromZero
|
||||
code.FRINTX(V6.S4(), V0.S4()); // ToNearest_TieAwayFromZero
|
||||
|
||||
jit.SetPC(0);
|
||||
jit.SetVector(0, {0x4001e17c4001e17c, 0x4001e17c4001e17c});
|
||||
env.ticks_left = env.code_mem.size();
|
||||
CheckedRun([&]() { jit.Run(); });
|
||||
|
||||
CHECK(jit.GetVector(0) == Vector{0x4001e17c4001e17c, 0x4001e17c4001e17c});
|
||||
CHECK(jit.GetVector(1) == Vector{0x4000000040000000, 0x4000000040000000});
|
||||
CHECK(jit.GetVector(2) == Vector{0x4000000040000000, 0x4000000040000000});
|
||||
CHECK(jit.GetVector(3) == Vector{0x4040000040400000, 0x4040000040400000});
|
||||
CHECK(jit.GetVector(4) == Vector{0x4000000040000000, 0x4000000040000000});
|
||||
CHECK(jit.GetVector(5) == Vector{0x4000000040000000, 0x4000000040000000});
|
||||
CHECK(jit.GetVector(6) == Vector{0x4000000040000000, 0x4000000040000000});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,24 +17,19 @@ using Vector = Dynarmic::A64::Vector;
|
|||
|
||||
class A64TestEnv : public Dynarmic::A64::UserCallbacks {
|
||||
public:
|
||||
u64 ticks_left = 0;
|
||||
|
||||
bool code_mem_modified_by_guest = false;
|
||||
u64 code_mem_start_address = 0;
|
||||
std::vector<u32> code_mem;
|
||||
|
||||
ankerl::unordered_dense::map<u64, u8> modified_memory;
|
||||
std::vector<std::string> interrupts;
|
||||
std::vector<u32> code_mem;
|
||||
u64 ticks_left = 0;
|
||||
u64 code_mem_start_address = 0;
|
||||
bool code_mem_modified_by_guest = false;
|
||||
|
||||
bool IsInCodeMem(u64 vaddr) const {
|
||||
return vaddr >= code_mem_start_address && vaddr < code_mem_start_address + code_mem.size() * 4;
|
||||
}
|
||||
|
||||
std::optional<std::uint32_t> MemoryReadCode(u64 vaddr) override {
|
||||
if (!IsInCodeMem(vaddr)) {
|
||||
if (!IsInCodeMem(vaddr))
|
||||
return 0x14000000; // B .
|
||||
}
|
||||
|
||||
const size_t index = (vaddr - code_mem_start_address) / 4;
|
||||
return code_mem[index];
|
||||
}
|
||||
|
|
@ -43,10 +38,9 @@ public:
|
|||
if (IsInCodeMem(vaddr)) {
|
||||
return reinterpret_cast<u8*>(code_mem.data())[vaddr - code_mem_start_address];
|
||||
}
|
||||
if (auto iter = modified_memory.find(vaddr); iter != modified_memory.end()) {
|
||||
return iter->second;
|
||||
}
|
||||
return static_cast<u8>(vaddr);
|
||||
if (auto const it = modified_memory.find(vaddr); it != modified_memory.end())
|
||||
return it->second;
|
||||
return u8(vaddr);
|
||||
}
|
||||
std::uint16_t MemoryRead16(u64 vaddr) override {
|
||||
return u16(MemoryRead8(vaddr)) | u16(MemoryRead8(vaddr + 1)) << 8;
|
||||
|
|
@ -68,16 +62,16 @@ public:
|
|||
modified_memory[vaddr] = value;
|
||||
}
|
||||
void MemoryWrite16(u64 vaddr, std::uint16_t value) override {
|
||||
MemoryWrite8(vaddr, static_cast<u8>(value));
|
||||
MemoryWrite8(vaddr + 1, static_cast<u8>(value >> 8));
|
||||
MemoryWrite8(vaddr, u8(value));
|
||||
MemoryWrite8(vaddr + 1, u8(value >> 8));
|
||||
}
|
||||
void MemoryWrite32(u64 vaddr, std::uint32_t value) override {
|
||||
MemoryWrite16(vaddr, static_cast<u16>(value));
|
||||
MemoryWrite16(vaddr + 2, static_cast<u16>(value >> 16));
|
||||
MemoryWrite16(vaddr, u16(value));
|
||||
MemoryWrite16(vaddr + 2, u16(value >> 16));
|
||||
}
|
||||
void MemoryWrite64(u64 vaddr, std::uint64_t value) override {
|
||||
MemoryWrite32(vaddr, static_cast<u32>(value));
|
||||
MemoryWrite32(vaddr + 4, static_cast<u32>(value >> 32));
|
||||
MemoryWrite32(vaddr, u32(value));
|
||||
MemoryWrite32(vaddr + 4, u32(value >> 32));
|
||||
}
|
||||
void MemoryWrite128(u64 vaddr, Vector value) override {
|
||||
MemoryWrite64(vaddr, value[0]);
|
||||
|
|
@ -139,12 +133,12 @@ public:
|
|||
template<typename T>
|
||||
T read(u64 vaddr) {
|
||||
T value;
|
||||
memcpy(&value, backing_memory + vaddr, sizeof(T));
|
||||
std::memcpy(&value, backing_memory + vaddr, sizeof(T));
|
||||
return value;
|
||||
}
|
||||
template<typename T>
|
||||
void write(u64 vaddr, const T& value) {
|
||||
memcpy(backing_memory + vaddr, &value, sizeof(T));
|
||||
std::memcpy(backing_memory + vaddr, &value, sizeof(T));
|
||||
}
|
||||
|
||||
std::optional<std::uint32_t> MemoryReadCode(u64 vaddr) override {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue