Implements the new IR ops in the CPU backends

This commit is contained in:
Ryan Houdek committed 2020-03-17 13:50:37 -07:00
1 parent 4692a761b6
commit 8ea266e10f
4 files changed
+197

No files matched your search

@@ -304,7 +304,33 @@ void InterpreterCore::ExecuteCode(FEXCore::Core::InternalThreadState *Thread) {
}
break;
}
case IR::OP_VEXTRACTELEMENT: {
auto Op = IROp->C<IR::IROp_VExtractElement>();
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->Index * 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->Index * 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;
@@ -2813,6 +2839,44 @@ void InterpreterCore::ExecuteCode(FEXCore::Core::InternalThreadState *Thread) {
memcpy(GDP, Tmp, Op->RegisterSize);
break;
}
case IR::OP_VINSSCALARELEMENT: {
auto Op = IROp->C<IR::IROp_VInsScalarElement>();
void *Src1 = GetSrc<void*>(Op->Header.Args[0]);
void *Src2 = GetSrc<void*>(Op->Header.Args[1]);
uint8_t Tmp[16];
// Copy src1 in to dest
memcpy(Tmp, Src1, Op->RegisterSize);
switch (Op->ElementSize) {
case 1: {
auto *Dst_d = reinterpret_cast<uint8_t*>(Tmp);
auto Src2_d = *reinterpret_cast<uint8_t*>(Src2);
Dst_d[Op->DestIdx] = Src2_d;
break;
}
case 2: {
auto *Dst_d = reinterpret_cast<uint16_t*>(Tmp);
auto Src2_d = *reinterpret_cast<uint16_t*>(Src2);
Dst_d[Op->DestIdx] = Src2_d;
break;
}
case 4: {
auto *Dst_d = reinterpret_cast<uint32_t*>(Tmp);
auto Src2_d = *reinterpret_cast<uint32_t*>(Src2);
Dst_d[Op->DestIdx] = Src2_d;
break;
}
case 8: {
auto *Dst_d = reinterpret_cast<uint64_t*>(Tmp);
auto Src2_d = *reinterpret_cast<uint64_t*>(Src2);
Dst_d[Op->DestIdx] = Src2_d;
break;
}
default: LogMan::Msg::A("Unknown Element Size: %d", Op->ElementSize); break;
};
memcpy(GDP, Tmp, Op->RegisterSize);
break;
}
case IR::OP_VCMPEQ: {
auto Op = IROp->C<IR::IROp_VCMPEQ>();
void *Src1 = GetSrc<void*>(Op->Header.Args[0]);
@@ -530,6 +530,25 @@ void *JITCore::CompileCode([[maybe_unused]] FEXCore::IR::IRListView<true> const
}
break;
}
case IR::OP_VEXTRACTELEMENT: {
auto Op = IROp->C<IR::IROp_VExtractElement>();
switch (OpSize) {
case 1:
mov(GetDst(Node).B(), GetSrc(Op->Header.Args[0].ID()).V16B(), Op->Index);
break;
case 2:
mov(GetDst(Node).H(), GetSrc(Op->Header.Args[0].ID()).V8H(), Op->Index);
break;
case 4:
mov(GetDst(Node).S(), GetSrc(Op->Header.Args[0].ID()).V4S(), Op->Index);
break;
case 8:
mov(GetDst(Node).D(), GetSrc(Op->Header.Args[0].ID()).V2D(), Op->Index);
break;
default: LogMan::Msg::A("Unhandled ExtractElementSize: %d", OpSize);
}
break;
}
case IR::OP_JUMP: {
auto Op = IROp->C<IR::IROp_Jump>();
@@ -2042,6 +2061,31 @@ void *JITCore::CompileCode([[maybe_unused]] FEXCore::IR::IRListView<true> const
mov(GetDst(Node), VTMP1);
break;
}
case IR::OP_VINSSCALARELEMENT: {
auto Op = IROp->C<IR::IROp_VInsScalarElement>();
mov(VTMP1, GetSrc(Op->Header.Args[0].ID()));
switch (Op->ElementSize) {
case 1: {
mov(VTMP1.V16B(), Op->DestIdx, GetSrc(Op->Header.Args[1].ID()).V16B(), 0);
break;
}
case 2: {
mov(VTMP1.V8H(), Op->DestIdx, GetSrc(Op->Header.Args[1].ID()).V8H(), 0);
break;
}
case 4: {
mov(VTMP1.V4S(), Op->DestIdx, GetSrc(Op->Header.Args[1].ID()).V4S(), 0);
break;
}
case 8: {
mov(VTMP1.V2D(), Op->DestIdx, GetSrc(Op->Header.Args[1].ID()).V2D(), 0);
break;
}
default: LogMan::Msg::A("Unknown Element Size: %d", Op->ElementSize); break;
}
mov(GetDst(Node), VTMP1);
break;
}
case IR::OP_VNOT: {
auto Op = IROp->C<IR::IROp_VNot>();
mvn(GetDst(Node).V16B(), GetSrc(Op->Header.Args[0].ID()).V16B());
@@ -2000,6 +2000,70 @@ void *JITCore::CompileCode([[maybe_unused]] FEXCore::IR::IRListView<true> const
movapd(GetDst(Node), xmm15);
break;
}
case IR::OP_VINSSCALARELEMENT: {
auto Op = IROp->C<IR::IROp_VInsScalarElement>();
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(eax, GetSrc(Op->Header.Args[1].ID()), 0);
pinsrb(xmm15, eax, Op->DestIdx);
break;
}
case 2: {
pextrw(eax, GetSrc(Op->Header.Args[1].ID()), 0);
pinsrw(xmm15, eax, Op->DestIdx);
break;
}
case 4: {
pextrd(eax, GetSrc(Op->Header.Args[1].ID()), 0);
pinsrd(xmm15, eax, Op->DestIdx);
break;
}
case 8: {
pextrq(rax, GetSrc(Op->Header.Args[1].ID()), 0);
pinsrq(xmm15, rax, Op->DestIdx);
break;
}
default: LogMan::Msg::A("Unknown Element Size: %d", Op->ElementSize); break;
}
movapd(GetDst(Node), xmm15);
break;
}
case IR::OP_VEXTRACTELEMENT: {
auto Op = IROp->C<IR::IROp_VExtractElement>();
switch (Op->ElementSize) {
case 1: {
pextrb(eax, GetSrc(Op->Header.Args[1].ID()), Op->Index);
pinsrb(GetDst(Node), eax, 0);
break;
}
case 2: {
pextrw(eax, GetSrc(Op->Header.Args[1].ID()), Op->Index);
pinsrw(GetDst(Node), eax, 0);
break;
}
case 4: {
pextrd(eax, GetSrc(Op->Header.Args[1].ID()), Op->Index);
pinsrd(GetDst(Node), eax, 0);
break;
}
case 8: {
pextrq(rax, GetSrc(Op->Header.Args[1].ID()), Op->Index);
pinsrq(GetDst(Node), rax, 0);
break;
}
default: LogMan::Msg::A("Unknown Element Size: %d", Op->ElementSize); break;
}
break;
}
case IR::OP_VADD: {
auto Op = IROp->C<IR::IROp_VAdd>();
switch (Op->ElementSize) {
@@ -1818,6 +1818,17 @@ void LLVMJITCore::HandleIR(FEXCore::IR::IRListView<true> const *IR, IR::NodeWrap
SetDest(*WrapperOp, Result);
break;
}
case IR::OP_VEXTRACTELEMENT: {
auto Op = IROp->C<IR::IROp_VExtractElement>();
auto Src = GetSrc(Op->Header.Args[0]);
// Cast to the type we want
Src = CastVectorToType(Src, true, Op->RegisterSize, Op->ElementSize);
auto Result = JITState.IRBuilder->CreateExtractElement(Src, JITState.IRBuilder->getInt32(Op->Index));
SetDest(*WrapperOp, Result);
break;
}
case IR::OP_VINSGPR: {
auto Op = IROp->C<IR::IROp_VInsGPR>();
auto Src1 = GetSrc(Op->Header.Args[0]);
@@ -2511,6 +2522,20 @@ void LLVMJITCore::HandleIR(FEXCore::IR::IRListView<true> const *IR, IR::NodeWrap
SetDest(*WrapperOp, Result);
break;
}
case IR::OP_VINSSCALARELEMENT: {
auto Op = IROp->C<IR::IROp_VInsScalarElement>();
auto Src1 = GetSrc(Op->Header.Args[0]);
auto Src2 = GetSrc(Op->Header.Args[1]);
// Cast to the type we want
Src1 = CastVectorToType(Src1, true, Op->RegisterSize, Op->ElementSize);
Src2 = CastScalarToType(Src2, true, Op->RegisterSize, Op->ElementSize);
// Extract our source index
auto Result = JITState.IRBuilder->CreateInsertElement(Src1, Src2, JITState.IRBuilder->getInt32(Op->DestIdx));
SetDest(*WrapperOp, Result);
break;
}
case IR::OP_VECTOR_UTOF: {
auto Op = IROp->C<IR::IROp_Vector_UToF>();
auto Src = GetSrc(Op->Header.Args[0]);