mirror of
https://github.com/FEX-Emu/FEX.git
synced 2026-10-14 09:00:40 +02:00
Adds a couple new IR ops for easy movement of registers between classes.
This commit is contained in:
1 parent
9c873d85ec
commit
e9be5430b9
5 files changed
+148
No files matched your search
@@ -268,6 +268,39 @@ void InterpreterCore::ExecuteCode(FEXCore::Core::InternalThreadState *Thread) {
|
||||
memcpy(GDP, GetSrc<void*>(Op->Header.Args[0]), 16);
|
||||
break;
|
||||
}
|
||||
case IR::OP_VCASTFROMGPR: {
|
||||
auto Op = IROp->C<IR::IROp_VCastFromGPR>();
|
||||
memcpy(GDP, GetSrc<void*>(Op->Header.Args[0]), Op->ElementSize);
|
||||
break;
|
||||
}
|
||||
case IR::OP_VEXTRACTTOGPR: {
|
||||
auto Op = IROp->C<IR::IROp_VExtractToGPR>();
|
||||
LogMan::Throw::A(Op->RegisterSize <= 16, "OpSize is too large for VExtractToGPR: %d", OpSize);
|
||||
if (Op->RegisterSize == 16) {
|
||||
__uint128_t SourceMask = (1ULL << (Op->ElementSize * 8)) - 1;
|
||||
uint64_t Shift = Op->ElementSize * Op->Idx * 8;
|
||||
if (Op->ElementSize == 8)
|
||||
SourceMask = ~0ULL;
|
||||
|
||||
__uint128_t Src = *GetSrc<__uint128_t*>(Op->Header.Args[0]);
|
||||
Src >>= Shift;
|
||||
Src &= SourceMask;
|
||||
memcpy(GDP, &Src, Op->ElementSize);
|
||||
}
|
||||
else {
|
||||
uint64_t SourceMask = (1ULL << (Op->ElementSize * 8)) - 1;
|
||||
uint64_t Shift = Op->ElementSize * Op->Idx * 8;
|
||||
if (Op->ElementSize == 8)
|
||||
SourceMask = ~0ULL;
|
||||
|
||||
uint64_t Src = *GetSrc<uint64_t*>(Op->Header.Args[0]);
|
||||
Src >>= Shift;
|
||||
Src &= SourceMask;
|
||||
GD = Src;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case IR::OP_CONSTANT: {
|
||||
auto Op = IROp->C<IR::IROp_Constant>();
|
||||
GD = Op->Constant;
|
||||
|
||||
@@ -1261,6 +1261,38 @@ void *JITCore::CompileCode([[maybe_unused]] FEXCore::IR::IRListView<true> const
|
||||
mov (GetDst<RA_64>(Node), rax);
|
||||
break;
|
||||
}
|
||||
|
||||
case IR::OP_VEXTRACTTOGPR: {
|
||||
auto Op = IROp->C<IR::IROp_VExtractToGPR>();
|
||||
movapd(xmm15, GetSrc(Op->Header.Args[0].ID()));
|
||||
|
||||
// Dst_d[Op->DestIdx] = Src2_d[Op->SrcIdx];
|
||||
|
||||
// pextrq reg64/mem64, xmm, imm
|
||||
// pinsrq xmm, reg64/mem64, imm8
|
||||
switch (Op->ElementSize) {
|
||||
case 1: {
|
||||
pextrb(GetDst<RA_8>(Node), GetSrc(Op->Header.Args[0].ID()), Op->Idx);
|
||||
break;
|
||||
}
|
||||
case 2: {
|
||||
pextrw(GetDst<RA_16>(Node), GetSrc(Op->Header.Args[0].ID()), Op->Idx);
|
||||
break;
|
||||
}
|
||||
case 4: {
|
||||
pextrd(GetDst<RA_32>(Node), GetSrc(Op->Header.Args[0].ID()), Op->Idx);
|
||||
break;
|
||||
}
|
||||
case 8: {
|
||||
pextrq(GetDst<RA_64>(Node), GetSrc(Op->Header.Args[0].ID()), Op->Idx);
|
||||
break;
|
||||
}
|
||||
default: LogMan::Msg::A("Unknown Element Size: %d", Op->ElementSize); break;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case IR::OP_PRINT: {
|
||||
auto Op = IROp->C<IR::IROp_Print>();
|
||||
|
||||
@@ -1444,6 +1476,27 @@ void *JITCore::CompileCode([[maybe_unused]] FEXCore::IR::IRListView<true> const
|
||||
movaps(GetDst(Node), GetSrc(Op->Header.Args[0].ID()));
|
||||
break;
|
||||
}
|
||||
case IR::OP_VCASTFROMGPR: {
|
||||
auto Op = IROp->C<IR::IROp_VCastFromGPR>();
|
||||
switch (Op->ElementSize) {
|
||||
case 1:
|
||||
movzx(rax, GetSrc<RA_8>(Op->Header.Args[0].ID()));
|
||||
vmovq(GetDst(Node), rax);
|
||||
break;
|
||||
case 2:
|
||||
movzx(rax, GetSrc<RA_16>(Op->Header.Args[0].ID()));
|
||||
vmovq(GetDst(Node), rax);
|
||||
break;
|
||||
case 4:
|
||||
vmovd(GetDst(Node), GetSrc<RA_32>(Op->Header.Args[0].ID()).cvt32());
|
||||
break;
|
||||
case 8:
|
||||
vmovq(GetDst(Node), GetSrc<RA_64>(Op->Header.Args[0].ID()).cvt64());
|
||||
break;
|
||||
default: LogMan::Msg::A("Unknown castGPR element size: %d", Op->ElementSize);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case IR::OP_VCMPEQ: {
|
||||
auto Op = IROp->C<IR::IROp_VCMPEQ>();
|
||||
LogMan::Throw::A(Op->RegisterSize == 16, "Can't handle register size of: %d", Op->RegisterSize);
|
||||
|
||||
@@ -1433,6 +1433,16 @@ void LLVMJITCore::HandleIR(FEXCore::IR::IRListView<true> const *IR, IR::NodeWrap
|
||||
SetDest(*WrapperOp, BSwap(Src));
|
||||
break;
|
||||
}
|
||||
case IR::OP_VCASTFROMGPR: {
|
||||
auto Op = IROp->C<IR::IROp_VCastFromGPR>();
|
||||
LogMan::Throw::A(OpSize <= 16, "Can't handle a vector of size: %d", OpSize);
|
||||
auto Src = GetSrc(Op->Header.Args[0]);
|
||||
|
||||
auto Result = JITState.IRBuilder->CreateVectorSplat(Op->RegisterSize / Op->ElementSize, Src);
|
||||
SetDest(*WrapperOp, Result);
|
||||
break;
|
||||
}
|
||||
|
||||
case IR::OP_CREATEVECTOR2: {
|
||||
auto Op = IROp->C<IR::IROp_CreateVector2>();
|
||||
LogMan::Throw::A(OpSize <= 16, "Can't handle a vector of size: %d", OpSize);
|
||||
@@ -1582,7 +1592,32 @@ void LLVMJITCore::HandleIR(FEXCore::IR::IRListView<true> const *IR, IR::NodeWrap
|
||||
SetDest(*WrapperOp, Result);
|
||||
break;
|
||||
}
|
||||
case IR::OP_VSLI: {
|
||||
auto Op = IROp->C<IR::IROp_VSLI>();
|
||||
auto Src = GetSrc(Op->Header.Args[0]);
|
||||
|
||||
// Cast to the type we want
|
||||
Src = CastToOpaqueStructure(Src, Type::getIntNTy(*Con, Src->getType()->getPrimitiveSizeInBits()));
|
||||
|
||||
// Now we will do a lshr <NumElements x i1> -> <NumElements x ElementSize>
|
||||
auto Result = JITState.IRBuilder->CreateShl(Src, JITState.IRBuilder->getIntN(Src->getType()->getPrimitiveSizeInBits(), Op->ByteShift * 8));
|
||||
|
||||
SetDest(*WrapperOp, Result);
|
||||
break;
|
||||
}
|
||||
case IR::OP_VSRI: {
|
||||
auto Op = IROp->C<IR::IROp_VSRI>();
|
||||
auto Src = GetSrc(Op->Header.Args[0]);
|
||||
|
||||
// Cast to the type we want
|
||||
Src = CastToOpaqueStructure(Src, Type::getIntNTy(*Con, Src->getType()->getPrimitiveSizeInBits()));
|
||||
|
||||
// Now we will do a lshr <NumElements x i1> -> <NumElements x ElementSize>
|
||||
auto Result = JITState.IRBuilder->CreateLShr(Src, JITState.IRBuilder->getIntN(Src->getType()->getPrimitiveSizeInBits(), Op->ByteShift * 8));
|
||||
|
||||
SetDest(*WrapperOp, Result);
|
||||
break;
|
||||
}
|
||||
case IR::OP_VCMPEQ: {
|
||||
auto Op = IROp->C<IR::IROp_VCMPEQ>();
|
||||
auto Src1 = GetSrc(Op->Header.Args[0]);
|
||||
|
||||
@@ -288,6 +288,13 @@ public:
|
||||
IRPair<IROp_VSRI> _VSRI(uint8_t RegisterSize, uint8_t ElementSize, OrderedNode *ssa0, uint8_t ByteShift) {
|
||||
return _VSRI(ssa0, RegisterSize, ElementSize, ByteShift);
|
||||
}
|
||||
IRPair<IROp_VCastFromGPR> _VCastFromGPR(uint8_t RegisterSize, uint8_t ElementSize, OrderedNode *ssa0) {
|
||||
return _VCastFromGPR(ssa0, RegisterSize, ElementSize);
|
||||
}
|
||||
IRPair<IROp_VExtractToGPR> _VExtractToGPR(uint8_t RegisterSize, uint8_t ElementSize, OrderedNode *ssa0, uint8_t Index) {
|
||||
return _VExtractToGPR(ssa0, RegisterSize, ElementSize, Index);
|
||||
}
|
||||
|
||||
IRPair<IROp_Jump> _Jump() {
|
||||
return _Jump(InvalidNode);
|
||||
}
|
||||
|
||||
@@ -381,6 +381,17 @@
|
||||
"SSAArgs": "3"
|
||||
},
|
||||
|
||||
"VExtractToGPR": {
|
||||
"HasDest": true,
|
||||
"SSAArgs": "1",
|
||||
"DestSize": "ElementSize",
|
||||
"Args": [
|
||||
"uint8_t", "RegisterSize",
|
||||
"uint8_t", "ElementSize",
|
||||
"uint8_t", "Idx"
|
||||
]
|
||||
},
|
||||
|
||||
"Print": {
|
||||
"SSAArgs": "1"
|
||||
},
|
||||
@@ -588,6 +599,15 @@
|
||||
"SSAArgs": "1"
|
||||
},
|
||||
|
||||
"VCastFromGPR": {
|
||||
"HasDest": true,
|
||||
"SSAArgs": "1",
|
||||
"Args": [
|
||||
"uint8_t", "RegisterSize",
|
||||
"uint8_t", "ElementSize"
|
||||
]
|
||||
},
|
||||
|
||||
"Last": {
|
||||
"Last": true,
|
||||
"Args": []
|
||||
|
||||
Reference in new issue
Block a user