| 1588 | } |
| 1589 | |
| 1590 | void OpDispatchBuilder::ASHROp(OpcodeArgs, bool Immediate, bool SHR1Bit) { |
| 1591 | const auto Size = OpSizeFromSrc(Op); |
| 1592 | const auto OpSize = std::max(OpSize::i32Bit, OpSizeFromDst(Op)); |
| 1593 | |
| 1594 | // If Size < 4, then we Sbfe the Dest so we can have garbage. |
| 1595 | // Otherwise, if Size = Opsize, then both are 4 or 8 and match the a64 |
| 1596 | // semantics directly, so again we can have garbage. The only case where we |
| 1597 | // need zero-extension here is when the sizes mismatch. |
| 1598 | auto Dest = LoadSource(GPRClass, Op, Op->Dest, Op->Flags, {.AllowUpperGarbage = (OpSize == Size) || (Size < OpSize::i32Bit)}); |
| 1599 | |
| 1600 | if (Size < OpSize::i32Bit) { |
| 1601 | Dest = _Sbfe(OpSize::i64Bit, IR::OpSizeAsBits(Size), 0, Dest); |
| 1602 | } |
| 1603 | |
| 1604 | if (Immediate) { |
| 1605 | uint64_t Shift = LoadConstantShift(Op, SHR1Bit); |
| 1606 | Ref Result = _Ashr(OpSize, Dest, Constant(Shift)); |
| 1607 | |
| 1608 | CalculateFlags_SignShiftRightImmediate(OpSizeFromSrc(Op), Result, Dest, Shift); |
| 1609 | CalculateDeferredFlags(); |
| 1610 | StoreResult(GPRClass, Op, Result, OpSize::iInvalid); |
| 1611 | } else { |
| 1612 | auto Src = LoadSource(GPRClass, Op, Op->Src[1], Op->Flags, {.AllowUpperGarbage = true}); |
| 1613 | Ref Result = _Ashr(OpSize, Dest, Src); |
| 1614 | |
| 1615 | HandleShift(Op, Result, Dest, ShiftType::ASR, Src); |
| 1616 | } |
| 1617 | } |
| 1618 | |
| 1619 | void OpDispatchBuilder::RotateOp(OpcodeArgs, bool Left, bool IsImmediate, bool Is1Bit) { |
| 1620 | CalculateDeferredFlags(); |
nothing calls this directly
no test coverage detected