mirror of
https://github.com/FEX-Emu/FEX.git
synced 2026-10-14 07:00:43 +02:00
IR: Implements new CacheLineZero op
This zeroes out an emulated 64byte cacheline. Writing zeros to memory. This very specifically is only 64bytes to match x86 behaviour. Also specifically non-temporal and weakly ordered. Which matches x86 CLZero behaviour.
This commit is contained in:
1 parent
d2783f2edd
commit
e1d21f0bff
8 files changed
+78
-1
No files matched your search
@@ -157,6 +157,7 @@ constexpr OpHandlerArray InterpreterOpHandlers = [] {
|
||||
REGISTER_OP(VLOADMEMELEMENT, VLoadMemElement);
|
||||
REGISTER_OP(VSTOREMEMELEMENT, VStoreMemElement);
|
||||
REGISTER_OP(CACHELINECLEAR, CacheLineClear);
|
||||
REGISTER_OP(CACHELINEZERO, CacheLineZero);
|
||||
|
||||
// Misc ops
|
||||
REGISTER_OP(DUMMY, NoOp);
|
||||
|
||||
@@ -180,6 +180,7 @@ namespace FEXCore::CPU {
|
||||
DEF_OP(VLoadMemElement);
|
||||
DEF_OP(VStoreMemElement);
|
||||
DEF_OP(CacheLineClear);
|
||||
DEF_OP(CacheLineZero);
|
||||
|
||||
///< Misc ops
|
||||
DEF_OP(EndBlock);
|
||||
|
||||
@@ -264,5 +264,22 @@ DEF_OP(CacheLineClear) {
|
||||
CacheLineFlush(MemData);
|
||||
}
|
||||
|
||||
DEF_OP(CacheLineZero) {
|
||||
auto Op = IROp->C<IR::IROp_CacheLineZero>();
|
||||
|
||||
uintptr_t MemData = *GetSrc<uintptr_t*>(Data->SSAData, Op->Addr);
|
||||
|
||||
// Force cacheline alignment
|
||||
MemData = MemData & ~(CPUIDEmu::CACHELINE_SIZE - 1);
|
||||
|
||||
using DataType = uint64_t;
|
||||
DataType *MemData64 = reinterpret_cast<DataType*>(MemData);
|
||||
|
||||
// 64-byte cache line zero
|
||||
for (size_t i = 0; i < (CPUIDEmu::CACHELINE_SIZE / sizeof(DataType)); ++i) {
|
||||
MemData64[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
#undef DEF_OP
|
||||
} // namespace FEXCore::CPU
|
||||
@@ -321,6 +321,7 @@ private:
|
||||
DEF_OP(VLoadMemElement);
|
||||
DEF_OP(VStoreMemElement);
|
||||
DEF_OP(CacheLineClear);
|
||||
DEF_OP(CacheLineZero);
|
||||
|
||||
///< Misc ops
|
||||
DEF_OP(EndBlock);
|
||||
|
||||
@@ -946,6 +946,28 @@ DEF_OP(CacheLineClear) {
|
||||
dsb(InnerShareable, BarrierAll);
|
||||
}
|
||||
|
||||
DEF_OP(CacheLineZero) {
|
||||
auto Op = IROp->C<IR::IROp_CacheLineZero>();
|
||||
|
||||
auto MemReg = GetReg<RA_64>(Op->Header.Args[0].ID());
|
||||
|
||||
if (CTX->HostFeatures.SupportsCLZERO) {
|
||||
// We can use this instruction directly
|
||||
dc(DataCacheOp::ZVA, MemReg);
|
||||
}
|
||||
else {
|
||||
// We must walk the cacheline ourselves
|
||||
// Force cacheline alignment
|
||||
and_(TMP1, MemReg, ~(CPUIDEmu::CACHELINE_SIZE - 1));
|
||||
// This will end up being four STPs
|
||||
// Depending on uarch it could be slightly more efficient in instructions emitted
|
||||
// and uops to use vector pair STP, but we want the non-temporal bit specifically here
|
||||
for (size_t i = 0; i < CPUIDEmu::CACHELINE_SIZE; i += 16) {
|
||||
stnp(xzr, xzr, MemOperand(TMP1, i, Offset));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#undef DEF_OP
|
||||
void Arm64JITCore::RegisterMemoryHandlers() {
|
||||
#define REGISTER_OP(op, x) OpHandlers[FEXCore::IR::IROps::OP_##op] = &Arm64JITCore::Op_##x
|
||||
@@ -972,6 +994,7 @@ void Arm64JITCore::RegisterMemoryHandlers() {
|
||||
REGISTER_OP(VLOADMEMELEMENT, VLoadMemElement);
|
||||
REGISTER_OP(VSTOREMEMELEMENT, VStoreMemElement);
|
||||
REGISTER_OP(CACHELINECLEAR, CacheLineClear);
|
||||
REGISTER_OP(CACHELINEZERO, CacheLineZero);
|
||||
#undef REGISTER_OP
|
||||
}
|
||||
}
|
||||
|
||||
@@ -315,6 +315,7 @@ private:
|
||||
DEF_OP(VLoadMemElement);
|
||||
DEF_OP(VStoreMemElement);
|
||||
DEF_OP(CacheLineClear);
|
||||
DEF_OP(CacheLineZero);
|
||||
|
||||
///< Misc ops
|
||||
DEF_OP(EndBlock);
|
||||
|
||||
@@ -595,6 +595,23 @@ DEF_OP(CacheLineClear) {
|
||||
clflush(ptr [MemReg]);
|
||||
}
|
||||
|
||||
DEF_OP(CacheLineZero) {
|
||||
auto Op = IROp->C<IR::IROp_CacheLineZero>();
|
||||
|
||||
Xbyak::Reg MemReg = GetSrc<RA_64>(Op->Addr.ID());
|
||||
|
||||
// Align by cacheline
|
||||
mov (TMP1, CPUIDEmu::CACHELINE_SIZE - 1);
|
||||
andn(TMP1, TMP1, MemReg.cvt64());
|
||||
xor_(TMP2, TMP2);
|
||||
|
||||
using DataType = uint64_t;
|
||||
// 64-byte cache line zero
|
||||
for (size_t i = 0; i < CPUIDEmu::CACHELINE_SIZE; i += sizeof(DataType)) {
|
||||
mov (qword [TMP1 + i], TMP2);
|
||||
}
|
||||
}
|
||||
|
||||
#undef DEF_OP
|
||||
void X86JITCore::RegisterMemoryHandlers() {
|
||||
#define REGISTER_OP(op, x) OpHandlers[FEXCore::IR::IROps::OP_##op] = &X86JITCore::Op_##x
|
||||
@@ -615,6 +632,7 @@ void X86JITCore::RegisterMemoryHandlers() {
|
||||
REGISTER_OP(VLOADMEMELEMENT, VLoadMemElement);
|
||||
REGISTER_OP(VSTOREMEMELEMENT, VStoreMemElement);
|
||||
REGISTER_OP(CACHELINECLEAR, CacheLineClear);
|
||||
REGISTER_OP(CACHELINEZERO, CacheLineZero);
|
||||
#undef REGISTER_OP
|
||||
}
|
||||
}
|
||||
|
||||
+16
-1
@@ -858,7 +858,22 @@
|
||||
},
|
||||
|
||||
"CacheLineClear": {
|
||||
"Desc": ["Does a 64 byte cacheline clear at the address specified"
|
||||
"Desc": ["Does a 64 byte cacheline clear at the address specified",
|
||||
"Only clears the data cachelines. Doesn't do any zeroing"
|
||||
],
|
||||
"HasSideEffects": true,
|
||||
"OpClass": "Memory",
|
||||
"SSAArgs": "1",
|
||||
"SSANames": [
|
||||
"Addr"
|
||||
]
|
||||
},
|
||||
|
||||
"CacheLineZero": {
|
||||
"Desc": ["Does a 64 byte zero at the address specified",
|
||||
"Writing zeroes to memory",
|
||||
"It is specifically non-temporal and weakly ordered",
|
||||
"This matches CLZero behaviour"
|
||||
],
|
||||
"HasSideEffects": true,
|
||||
"OpClass": "Memory",
|
||||
|
||||
Reference in new issue
Block a user