mirror of
https://github.com/FEX-Emu/FEX.git
synced 2026-10-23 14:00:47 +02:00
IR: Implement support for vector load element
Matches Arm64 LD1 semantics.
This commit is contained in:
1 parent
14144523f7
commit
5e57ec94cf
9 files changed
+146
-2
No files matched your search
@@ -154,6 +154,7 @@ constexpr OpHandlerArray InterpreterOpHandlers = [] {
|
||||
REGISTER_OP(STOREMEMTSO, StoreMem);
|
||||
REGISTER_OP(VLOADVECTORMASKED, VLoadVectorMasked);
|
||||
REGISTER_OP(VSTOREVECTORMASKED, VStoreVectorMasked);
|
||||
REGISTER_OP(VLOADVECTORELEMENT, VLoadVectorElement);
|
||||
REGISTER_OP(VBROADCASTFROMMEM, VBroadcastFromMem);
|
||||
REGISTER_OP(PUSH, Push);
|
||||
REGISTER_OP(MEMSET, MemSet);
|
||||
|
||||
@@ -190,6 +190,7 @@ namespace FEXCore::CPU {
|
||||
DEF_OP(StoreMem);
|
||||
DEF_OP(VLoadVectorMasked);
|
||||
DEF_OP(VStoreVectorMasked);
|
||||
DEF_OP(VLoadVectorElement);
|
||||
DEF_OP(VBroadcastFromMem);
|
||||
DEF_OP(Push);
|
||||
DEF_OP(MemSet);
|
||||
|
||||
@@ -418,6 +418,53 @@ DEF_OP(VStoreVectorMasked) {
|
||||
}
|
||||
}
|
||||
|
||||
DEF_OP(VLoadVectorElement) {
|
||||
const auto Op = IROp->C<IR::IROp_VLoadVectorElement>();
|
||||
const auto OpSize = IROp->Size;
|
||||
|
||||
const auto ElementSize = IROp->ElementSize;
|
||||
|
||||
auto *Mem = *GetSrc<uint8_t**>(Data->SSAData, Op->Addr);
|
||||
const auto *DstSrc = GetSrc<uint8_t const*>(Data->SSAData, Op->DstSrc);
|
||||
|
||||
const auto SetElements = []<typename T>(void* Dst, const T* MemPtr, const auto Index) {
|
||||
std::memcpy(static_cast<uint8_t*>(Dst) + (Index * sizeof(T)), MemPtr, sizeof(T));
|
||||
};
|
||||
|
||||
// Copy the source data first.
|
||||
memcpy(GDP, DstSrc, OpSize);
|
||||
|
||||
switch (ElementSize) {
|
||||
case 1: {
|
||||
SetElements(GDP,
|
||||
Mem,
|
||||
Op->Index);
|
||||
return;
|
||||
}
|
||||
case 2: {
|
||||
SetElements(GDP,
|
||||
reinterpret_cast<const uint16_t*>(Mem),
|
||||
Op->Index);
|
||||
return;
|
||||
}
|
||||
case 4: {
|
||||
SetElements(GDP,
|
||||
reinterpret_cast<const uint32_t*>(Mem),
|
||||
Op->Index);
|
||||
return;
|
||||
}
|
||||
case 8: {
|
||||
SetElements(GDP,
|
||||
reinterpret_cast<const uint64_t*>(Mem),
|
||||
Op->Index);
|
||||
return;
|
||||
}
|
||||
default:
|
||||
LOGMAN_MSG_A_FMT("Unhandled {} element size: {}", __func__, ElementSize);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
DEF_OP(VBroadcastFromMem) {
|
||||
const auto Op = IROp->C<IR::IROp_VBroadcastFromMem>();
|
||||
const auto OpSize = IROp->Size;
|
||||
|
||||
@@ -972,6 +972,7 @@ CPUBackend::CompiledCode Arm64JITCore::CompileCode(uint64_t Entry,
|
||||
REGISTER_OP_RT(STOREMEMTSO, StoreMemTSO);
|
||||
REGISTER_OP(VLOADVECTORMASKED, VLoadVectorMasked);
|
||||
REGISTER_OP(VSTOREVECTORMASKED, VStoreVectorMasked);
|
||||
REGISTER_OP(VLOADVECTORELEMENT, VLoadVectorElement);
|
||||
REGISTER_OP(VBROADCASTFROMMEM, VBroadcastFromMem);
|
||||
REGISTER_OP(PUSH, Push);
|
||||
REGISTER_OP(MEMSET, MemSet);
|
||||
|
||||
@@ -343,6 +343,7 @@ private:
|
||||
DEF_OP(StoreMemTSO);
|
||||
DEF_OP(VLoadVectorMasked);
|
||||
DEF_OP(VStoreVectorMasked);
|
||||
DEF_OP(VLoadVectorElement);
|
||||
DEF_OP(VBroadcastFromMem);
|
||||
DEF_OP(Push);
|
||||
DEF_OP(MemSet);
|
||||
|
||||
@@ -1429,6 +1429,55 @@ DEF_OP(VStoreVectorMasked) {
|
||||
}
|
||||
}
|
||||
|
||||
DEF_OP(VLoadVectorElement) {
|
||||
const auto Op = IROp->C<IR::IROp_VLoadVectorElement>();
|
||||
const auto OpSize = IROp->Size;
|
||||
|
||||
const auto Is256Bit = OpSize == Core::CPUState::XMM_AVX_REG_SIZE;
|
||||
const auto ElementSize = IROp->ElementSize;
|
||||
|
||||
const auto Dst = GetVReg(Node);
|
||||
const auto DstSrc = GetVReg(Op->DstSrc.ID());
|
||||
const auto MemReg = GetReg(Op->Addr.ID());
|
||||
|
||||
LOGMAN_THROW_AA_FMT(ElementSize == 1 || ElementSize == 2 ||
|
||||
ElementSize == 4 || ElementSize == 8 ||
|
||||
ElementSize == 16, "Invalid element size");
|
||||
|
||||
if (Is256Bit) {
|
||||
LOGMAN_MSG_A_FMT("Unsupported 256-bit VLoadVectorElement");
|
||||
} else {
|
||||
if (Dst != DstSrc && ElementSize != 16) {
|
||||
mov(Dst.Q(), DstSrc.Q());
|
||||
}
|
||||
switch (ElementSize) {
|
||||
case 1:
|
||||
ld1<ARMEmitter::SubRegSize::i8Bit>(Dst.Q(), Op->Index, MemReg);
|
||||
break;
|
||||
case 2:
|
||||
ld1<ARMEmitter::SubRegSize::i16Bit>(Dst.Q(), Op->Index, MemReg);
|
||||
break;
|
||||
case 4:
|
||||
ld1<ARMEmitter::SubRegSize::i32Bit>(Dst.Q(), Op->Index, MemReg);
|
||||
break;
|
||||
case 8:
|
||||
ld1<ARMEmitter::SubRegSize::i64Bit>(Dst.Q(), Op->Index, MemReg);
|
||||
break;
|
||||
case 16:
|
||||
ldr(Dst.Q(), MemReg);
|
||||
break;
|
||||
default:
|
||||
LOGMAN_MSG_A_FMT("Unhandled {} size: {}", __func__, ElementSize);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Emit a half-barrier if TSO is enabled.
|
||||
if (CTX->IsAtomicTSOEnabled()) {
|
||||
dmb(ARMEmitter::BarrierScope::ISHLD);
|
||||
}
|
||||
}
|
||||
|
||||
DEF_OP(VBroadcastFromMem) {
|
||||
const auto Op = IROp->C<IR::IROp_VBroadcastFromMem>();
|
||||
const auto OpSize = IROp->Size;
|
||||
|
||||
@@ -349,6 +349,7 @@ private:
|
||||
DEF_OP(StoreMem);
|
||||
DEF_OP(VLoadVectorMasked);
|
||||
DEF_OP(VStoreVectorMasked);
|
||||
DEF_OP(VLoadVectorElement);
|
||||
DEF_OP(VBroadcastFromMem);
|
||||
DEF_OP(Push);
|
||||
DEF_OP(MemSet);
|
||||
|
||||
@@ -843,6 +843,43 @@ DEF_OP(VStoreVectorMasked) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
DEF_OP(VLoadVectorElement) {
|
||||
const auto Op = IROp->C<IR::IROp_VLoadVectorElement>();
|
||||
const auto OpSize = IROp->Size;
|
||||
|
||||
const auto Is256Bit = OpSize == Core::CPUState::XMM_AVX_REG_SIZE;
|
||||
const auto ElementSize = IROp->ElementSize;
|
||||
|
||||
const auto Dst = GetDst(Node);
|
||||
const auto DstSrc = GetSrc(Op->DstSrc.ID());
|
||||
const Xbyak::Reg MemReg = GetSrc<RA_64>(Op->Addr.ID());
|
||||
|
||||
if (Is256Bit) {
|
||||
LOGMAN_MSG_A_FMT("Unsupported 256-bit VLoadVectorElement");
|
||||
} else {
|
||||
switch (ElementSize) {
|
||||
case 1:
|
||||
vpinsrb(Dst, DstSrc, byte [MemReg], Op->Index);
|
||||
break;
|
||||
case 2:
|
||||
vpinsrw(Dst, DstSrc, word [MemReg], Op->Index);
|
||||
break;
|
||||
case 4:
|
||||
vpinsrd(Dst, DstSrc, dword [MemReg], Op->Index);
|
||||
break;
|
||||
case 8:
|
||||
vpinsrq(Dst, DstSrc, qword [MemReg], Op->Index);
|
||||
break;
|
||||
case 16:
|
||||
// Normal load
|
||||
vmovups(Dst, xword [MemReg]);
|
||||
break;
|
||||
default:
|
||||
LOGMAN_MSG_A_FMT("Unhandled VBroadcastFromMem size: {}", ElementSize);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DEF_OP(VBroadcastFromMem) {
|
||||
const auto Op = IROp->C<IR::IROp_VBroadcastFromMem>();
|
||||
@@ -1212,6 +1249,7 @@ void X86JITCore::RegisterMemoryHandlers() {
|
||||
REGISTER_OP(STOREMEMTSO, StoreMem);
|
||||
REGISTER_OP(VLOADVECTORMASKED, VLoadVectorMasked);
|
||||
REGISTER_OP(VSTOREVECTORMASKED, VStoreVectorMasked);
|
||||
REGISTER_OP(VLOADVECTORELEMENT, VLoadVectorElement);
|
||||
REGISTER_OP(VBROADCASTFROMMEM, VBroadcastFromMem);
|
||||
REGISTER_OP(PUSH, Push);
|
||||
REGISTER_OP(MEMSET, MemSet);
|
||||
|
||||
@@ -491,7 +491,6 @@
|
||||
"DestSize": "RegisterSize",
|
||||
"NumElements": "RegisterSize / ElementSize"
|
||||
},
|
||||
|
||||
"VStoreVectorMasked u8:#RegisterSize, u8:#ElementSize, FPR:$Mask, FPR:$Data, GPR:$Addr, GPR:$Offset, MemOffsetType:$OffsetType, u8:$OffsetScale": {
|
||||
"Desc": ["Does a masked store similar to VPMASKMOV/VMASKMOV where the upper bit of each element",
|
||||
"determines whether or not that element will be stored to memory"],
|
||||
@@ -499,7 +498,13 @@
|
||||
"DestSize": "RegisterSize",
|
||||
"NumElements": "RegisterSize / ElementSize"
|
||||
},
|
||||
|
||||
"FPR = VLoadVectorElement u8:#RegisterSize, u8:#ElementSize, FPR:$DstSrc, u8:$Index, GPR:$Addr": {
|
||||
"Desc": ["Does a memory load to a single element of a vector.",
|
||||
"Leaves the rest of the vector's data intact.",
|
||||
"Matches arm64 ld1 semantics"],
|
||||
"DestSize": "RegisterSize",
|
||||
"NumElements": "RegisterSize / ElementSize"
|
||||
},
|
||||
"FPR = VBroadcastFromMem u8:#RegisterSize, u8:#ElementSize, GPR:$Address": {
|
||||
"Desc": ["Broadcasts an ElementSize value from memory into each element of a vector."],
|
||||
"DestSize": "RegisterSize",
|
||||
|
||||
Reference in new issue
Block a user