mirror of
https://github.com/FEX-Emu/FEX.git
synced 2026-10-14 07:00:43 +02:00
IR: Implements support for arm64 bfxil
This is useful for extracting a width from a register and inserting in to the lower bits of a destination.
This commit is contained in:
1 parent
6fdf2f963b
commit
90ddee5f8d
9 files changed
+80
No files matched your search
@@ -856,6 +856,18 @@ DEF_OP(Bfi) {
|
||||
GD = Res;
|
||||
}
|
||||
|
||||
DEF_OP(Bfxil) {
|
||||
auto Op = IROp->C<IR::IROp_Bfxil>();
|
||||
uint64_t SourceMask = (1ULL << Op->Width) - 1;
|
||||
if (Op->Width == 64) {
|
||||
SourceMask = ~0ULL;
|
||||
}
|
||||
const uint64_t Src1 = *GetSrc<uint64_t*>(Data->SSAData, Op->Dest);
|
||||
const uint64_t Src2 = *GetSrc<uint64_t*>(Data->SSAData, Op->Src);
|
||||
const uint64_t Res = (Src1 & ~SourceMask) | ((Src2 >> Op->lsb) & SourceMask);
|
||||
GD = Res;
|
||||
}
|
||||
|
||||
DEF_OP(Bfe) {
|
||||
auto Op = IROp->C<IR::IROp_Bfe>();
|
||||
|
||||
|
||||
@@ -84,6 +84,7 @@ constexpr OpHandlerArray InterpreterOpHandlers = [] {
|
||||
REGISTER_OP(COUNTLEADINGZEROES, CountLeadingZeroes);
|
||||
REGISTER_OP(REV, Rev);
|
||||
REGISTER_OP(BFI, Bfi);
|
||||
REGISTER_OP(BFXIL, Bfxil);
|
||||
REGISTER_OP(BFE, Bfe);
|
||||
REGISTER_OP(SBFE, Sbfe);
|
||||
REGISTER_OP(SELECT, Select);
|
||||
|
||||
@@ -121,6 +121,7 @@ namespace FEXCore::CPU {
|
||||
DEF_OP(CountLeadingZeroes);
|
||||
DEF_OP(Rev);
|
||||
DEF_OP(Bfi);
|
||||
DEF_OP(Bfxil);
|
||||
DEF_OP(Bfe);
|
||||
DEF_OP(Sbfe);
|
||||
DEF_OP(Select);
|
||||
|
||||
@@ -1177,6 +1177,29 @@ DEF_OP(Bfi) {
|
||||
}
|
||||
}
|
||||
|
||||
DEF_OP(Bfxil) {
|
||||
auto Op = IROp->C<IR::IROp_Bfxil>();
|
||||
const uint8_t OpSize = IROp->Size;
|
||||
|
||||
const auto EmitSize = OpSize == 8 ? ARMEmitter::Size::i64Bit : ARMEmitter::Size::i32Bit;
|
||||
|
||||
const auto Dst = GetReg(Node);
|
||||
const auto SrcDst = GetReg(Op->Dest.ID());
|
||||
const auto Src = GetReg(Op->Src.ID());
|
||||
|
||||
if (Dst == SrcDst) {
|
||||
// If Dst and SrcDst match then this turns in to a single instruction.
|
||||
bfxil(EmitSize, Dst, Src, Op->lsb, Op->Width);
|
||||
}
|
||||
else {
|
||||
// Destination didn't match the dst source register.
|
||||
// TODO: Inefficient until FEX can have RA constraints here.
|
||||
mov(EmitSize, TMP1, SrcDst);
|
||||
bfxil(EmitSize, TMP1, Src, Op->lsb, Op->Width);
|
||||
mov(EmitSize, Dst, TMP1.R());
|
||||
}
|
||||
}
|
||||
|
||||
DEF_OP(Bfe) {
|
||||
auto Op = IROp->C<IR::IROp_Bfe>();
|
||||
LOGMAN_THROW_AA_FMT(IROp->Size <= 8, "OpSize is too large for BFE: {}", IROp->Size);
|
||||
|
||||
@@ -894,6 +894,7 @@ CPUBackend::CompiledCode Arm64JITCore::CompileCode(uint64_t Entry,
|
||||
REGISTER_OP(COUNTLEADINGZEROES, CountLeadingZeroes);
|
||||
REGISTER_OP(REV, Rev);
|
||||
REGISTER_OP(BFI, Bfi);
|
||||
REGISTER_OP(BFXIL, Bfxil);
|
||||
REGISTER_OP(BFE, Bfe);
|
||||
REGISTER_OP(SBFE, Sbfe);
|
||||
REGISTER_OP(SELECT, Select);
|
||||
|
||||
@@ -272,6 +272,7 @@ private:
|
||||
DEF_OP(CountLeadingZeroes);
|
||||
DEF_OP(Rev);
|
||||
DEF_OP(Bfi);
|
||||
DEF_OP(Bfxil);
|
||||
DEF_OP(Bfe);
|
||||
DEF_OP(Sbfe);
|
||||
DEF_OP(Select);
|
||||
|
||||
@@ -1056,6 +1056,34 @@ DEF_OP(Bfi) {
|
||||
}
|
||||
}
|
||||
|
||||
DEF_OP(Bfxil) {
|
||||
auto Op = IROp->C<IR::IROp_Bfxil>();
|
||||
const uint8_t OpSize = IROp->Size;
|
||||
|
||||
auto Dst = GetDst<RA_64>(Node);
|
||||
|
||||
uint64_t SourceMask = (1ULL << Op->Width) - 1;
|
||||
if (Op->Width == 64) {
|
||||
SourceMask = ~0ULL;
|
||||
}
|
||||
const uint64_t DestMask = ~SourceMask;
|
||||
|
||||
mov(TMP1, GetSrc<RA_64>(Op->Src.ID()));
|
||||
shr(TMP1, Op->lsb);
|
||||
mov(Dst, GetSrc<RA_64>(Op->Dest.ID()));
|
||||
|
||||
mov(TMP2, DestMask);
|
||||
and_(Dst, TMP2);
|
||||
mov(TMP2, SourceMask);
|
||||
and_(TMP1, TMP2);
|
||||
or_(Dst, TMP1);
|
||||
|
||||
if (OpSize != 8) {
|
||||
mov(rcx, uint64_t((1ULL << (OpSize * 8)) - 1));
|
||||
and_(Dst, rcx);
|
||||
}
|
||||
}
|
||||
|
||||
DEF_OP(Bfe) {
|
||||
auto Op = IROp->C<IR::IROp_Bfe>();
|
||||
LOGMAN_THROW_AA_FMT(IROp->Size <= 8, "OpSize is too large for BFE: {}", IROp->Size);
|
||||
@@ -1375,6 +1403,7 @@ void X86JITCore::RegisterALUHandlers() {
|
||||
REGISTER_OP(COUNTLEADINGZEROES, CountLeadingZeroes);
|
||||
REGISTER_OP(REV, Rev);
|
||||
REGISTER_OP(BFI, Bfi);
|
||||
REGISTER_OP(BFXIL, Bfxil);
|
||||
REGISTER_OP(BFE, Bfe);
|
||||
REGISTER_OP(SBFE, Sbfe);
|
||||
REGISTER_OP(SELECT, Select);
|
||||
|
||||
@@ -280,6 +280,7 @@ private:
|
||||
DEF_OP(CountLeadingZeroes);
|
||||
DEF_OP(Rev);
|
||||
DEF_OP(Bfi);
|
||||
DEF_OP(Bfxil);
|
||||
DEF_OP(Bfe);
|
||||
DEF_OP(Sbfe);
|
||||
DEF_OP(Select);
|
||||
|
||||
@@ -1073,6 +1073,17 @@
|
||||
"Size == FEXCore::IR::OpSize::i32Bit || Size == FEXCore::IR::OpSize::i64Bit"
|
||||
]
|
||||
},
|
||||
"GPR = Bfxil OpSize:#Size, u8:$Width, u8:$lsb, GPR:$Dest, GPR:$Src": {
|
||||
"Desc": ["Copies a bitfield from one GPR to another",
|
||||
"Inserting in to the low bits of the destination",
|
||||
"The source bitfield is from Src[(Width + lsb):lsb]",
|
||||
"The bitfield is copied in to Dest[Width:0]"
|
||||
],
|
||||
"DestSize": "Size",
|
||||
"EmitValidation": [
|
||||
"Size == FEXCore::IR::OpSize::i32Bit || Size == FEXCore::IR::OpSize::i64Bit"
|
||||
]
|
||||
},
|
||||
"GPR = Bfe OpSize:#Size, u8:$Width, u8:$lsb, GPR:$Src": {
|
||||
"Desc": ["Extracts a bitfield from one GPR with zext",
|
||||
"The source bitfield is from Src[Width:0]",
|
||||
|
||||
Reference in new issue
Block a user