| 4050 | } |
| 4051 | |
| 4052 | Ref OpDispatchBuilder::DPPOpImpl(IR::OpSize DstSize, Ref Src1, Ref Src2, uint8_t Mask, IR::OpSize ElementSize) { |
| 4053 | const auto SizeMask = [ElementSize]() { |
| 4054 | if (ElementSize == OpSize::i32Bit) { |
| 4055 | return 0b1111; |
| 4056 | } |
| 4057 | return 0b11; |
| 4058 | }(); |
| 4059 | |
| 4060 | const uint8_t SrcMask = (Mask >> 4) & SizeMask; |
| 4061 | const uint8_t DstMask = Mask & SizeMask; |
| 4062 | |
| 4063 | const auto NamedIndexMask = [ElementSize]() { |
| 4064 | if (ElementSize == OpSize::i32Bit) { |
| 4065 | return FEXCore::IR::IndexNamedVectorConstant::INDEXED_NAMED_VECTOR_DPPS_MASK; |
| 4066 | } |
| 4067 | |
| 4068 | return FEXCore::IR::IndexNamedVectorConstant::INDEXED_NAMED_VECTOR_DPPD_MASK; |
| 4069 | }(); |
| 4070 | |
| 4071 | Ref ZeroVec = LoadZeroVector(DstSize); |
| 4072 | if (SrcMask == 0 || DstMask == 0) { |
| 4073 | // What are you even doing here? Go away. |
| 4074 | return ZeroVec; |
| 4075 | } |
| 4076 | |
| 4077 | // First step is to do an FMUL |
| 4078 | Ref Temp = _VFMul(DstSize, ElementSize, Src1, Src2); |
| 4079 | |
| 4080 | // Now mask results based on IndexMask. |
| 4081 | if (SrcMask != SizeMask) { |
| 4082 | auto InputMask = LoadAndCacheIndexedNamedVectorConstant(DstSize, NamedIndexMask, SrcMask * 16); |
| 4083 | Temp = _VAnd(DstSize, ElementSize, Temp, InputMask); |
| 4084 | } |
| 4085 | |
| 4086 | // Now due a float reduction |
| 4087 | Temp = _VFAddV(DstSize, ElementSize, Temp); |
| 4088 | |
| 4089 | // Now using the destination mask we choose where the result ends up |
| 4090 | // It can duplicate and zero results |
| 4091 | if (ElementSize == OpSize::i64Bit) { |
| 4092 | switch (DstMask) { |
| 4093 | case 0b01: |
| 4094 | // Dest[63:0] = Result |
| 4095 | // Dest[127:64] = Zero |
| 4096 | return _VZip(DstSize, ElementSize, Temp, ZeroVec); |
| 4097 | case 0b10: |
| 4098 | // Dest[63:0] = Zero |
| 4099 | // Dest[127:64] = Result |
| 4100 | return _VZip(DstSize, ElementSize, ZeroVec, Temp); |
| 4101 | case 0b11: |
| 4102 | // Broadcast |
| 4103 | // Dest[63:0] = Result |
| 4104 | // Dest[127:64] = Result |
| 4105 | return _VDupElement(DstSize, ElementSize, Temp, 0); |
| 4106 | case 0: |
| 4107 | default: LOGMAN_MSG_A_FMT("Unsupported"); |
| 4108 | } |
| 4109 | } else { |
nothing calls this directly
no test coverage detected