mirror of
https://github.com/smallmain/cocos-enhance-kit.git
synced 2025-01-15 07:21:07 +00:00
74 lines
2.5 KiB
Objective-C
74 lines
2.5 KiB
Objective-C
//
|
|
// Copyright (c) 2016-present, Facebook, Inc.
|
|
// All rights reserved.
|
|
//
|
|
// This source code is licensed under the BSD-style license found in the
|
|
// LICENSE file in the root directory of this source tree. An additional grant
|
|
// of patent rights can be found in the PATENTS file in the same directory.
|
|
//
|
|
|
|
#import "SRSIMDHelpers.h"
|
|
|
|
typedef uint8_t uint8x32_t __attribute__((vector_size(32)));
|
|
|
|
static void SRMaskBytesManual(uint8_t *bytes, size_t length, uint8_t *maskKey) {
|
|
for (size_t i = 0; i < length; i++) {
|
|
bytes[i] = bytes[i] ^ maskKey[i % sizeof(uint32_t)];
|
|
}
|
|
}
|
|
|
|
/**
|
|
Right-shift the elements of a vector, circularly.
|
|
|
|
@param vector The vector to circular shift.
|
|
@param by The number of elements to shift by.
|
|
|
|
@return A shifted vector.
|
|
*/
|
|
static uint8x32_t SRShiftVector(uint8x32_t vector, size_t by) {
|
|
uint8x32_t vectorCopy = vector;
|
|
by = by % _Alignof(uint8x32_t);
|
|
|
|
uint8_t *vectorPointer = (uint8_t *)&vector;
|
|
uint8_t *vectorCopyPointer = (uint8_t *)&vectorCopy;
|
|
|
|
memmove(vectorPointer + by, vectorPointer, sizeof(vector) - by);
|
|
memcpy(vectorPointer, vectorCopyPointer + (sizeof(vector) - by), by);
|
|
|
|
return vector;
|
|
}
|
|
|
|
void SRMaskBytesSIMD(uint8_t *bytes, size_t length, uint8_t *maskKey) {
|
|
size_t alignmentBytes = _Alignof(uint8x32_t) - ((uintptr_t)bytes % _Alignof(uint8x32_t));
|
|
if (alignmentBytes == _Alignof(uint8x32_t)) {
|
|
alignmentBytes = 0;
|
|
}
|
|
|
|
// If the number of bytes that can be processed after aligning is
|
|
// less than the number of bytes we can put into a vector,
|
|
// then there's no work to do with SIMD, just call the manual version.
|
|
if (alignmentBytes > length || (length - alignmentBytes) < sizeof(uint8x32_t)) {
|
|
SRMaskBytesManual(bytes, length, maskKey);
|
|
return;
|
|
}
|
|
|
|
size_t vectorLength = (length - alignmentBytes) / sizeof(uint8x32_t);
|
|
size_t manualStartOffset = alignmentBytes + (vectorLength * sizeof(uint8x32_t));
|
|
size_t manualLength = length - manualStartOffset;
|
|
|
|
uint8x32_t *vector = (uint8x32_t *)(bytes + alignmentBytes);
|
|
uint8x32_t maskVector = { };
|
|
|
|
memset_pattern4(&maskVector, maskKey, sizeof(uint8x32_t));
|
|
maskVector = SRShiftVector(maskVector, alignmentBytes);
|
|
|
|
SRMaskBytesManual(bytes, alignmentBytes, maskKey);
|
|
|
|
for (size_t vectorIndex = 0; vectorIndex < vectorLength; vectorIndex++) {
|
|
vector[vectorIndex] = vector[vectorIndex] ^ maskVector;
|
|
}
|
|
|
|
// Use the shifted mask for the final manual part.
|
|
SRMaskBytesManual(bytes + manualStartOffset, manualLength, (uint8_t *) &maskVector);
|
|
}
|