From be8d37ef3dec3cee993141008baa865ce84c3794 Mon Sep 17 00:00:00 2001 From: Alyssa Rosenzweig Date: Wed, 24 Jan 2024 21:56:33 -0400 Subject: [PATCH] OpcodeDispatcher: optimize 32-bit rol/ror imm Signed-off-by: Alyssa Rosenzweig --- FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp b/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp index 1ccbb272a..3b759bf16 100644 --- a/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp +++ b/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp @@ -1983,7 +1983,8 @@ void OpDispatchBuilder::ROROp(OpcodeArgs) { } void OpDispatchBuilder::RORImmediateOp(OpcodeArgs) { - OrderedNode *Dest = LoadSource(GPRClass, Op, Op->Dest, Op->Flags); + // See ROLImmediateOp for masking explanation + OrderedNode *Dest = LoadSource(GPRClass, Op, Op->Dest, Op->Flags, {.AllowUpperGarbage = true}); LOGMAN_THROW_A_FMT(Op->Src[1].IsLiteral(), "Src1 needs to be literal here"); @@ -2063,7 +2064,8 @@ void OpDispatchBuilder::ROLOp(OpcodeArgs) { } void OpDispatchBuilder::ROLImmediateOp(OpcodeArgs) { - OrderedNode *Dest = LoadSource(GPRClass, Op, Op->Dest, Op->Flags); + // For 32-bit, garbage is ignored in hardware. For < 32, see Bfi comment. + OrderedNode *Dest = LoadSource(GPRClass, Op, Op->Dest, Op->Flags, {.AllowUpperGarbage = true}); LOGMAN_THROW_A_FMT(Op->Src[1].IsLiteral(), "Src1 needs to be literal here"); @@ -2083,7 +2085,8 @@ void OpDispatchBuilder::ROLImmediateOp(OpcodeArgs) { if (Size < 32) { // ARM doesn't support 8/16bit rotates. Emulate with an insert - // StoreResult truncates back to a 8/16 bit value + // StoreResult truncates back to a 8/16 bit value. The inserts have the side + // effect of stomping over any garbage we had in the upper bits. Dest = _Bfi(OpSize::i32Bit, Size, Size, Dest, Dest); if (Size == 8) { // And because the shift size isn't masked to 8 bits, we need to fill the