michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: // This file should only be compiled if you're on x86 or x86_64. Additionally, michael@0: // you'll need to compile this file with -msse2 if you're using gcc. michael@0: michael@0: #include michael@0: #include "nscore.h" michael@0: #include "nsAlgorithm.h" michael@0: #include "nsTextFragmentImpl.h" michael@0: #include michael@0: michael@0: namespace mozilla { michael@0: namespace SSE2 { michael@0: michael@0: static inline bool michael@0: is_zero (__m128i x) michael@0: { michael@0: return michael@0: _mm_movemask_epi8(_mm_cmpeq_epi8(x, _mm_setzero_si128())) == 0xffff; michael@0: } michael@0: michael@0: int32_t michael@0: FirstNon8Bit(const char16_t *str, const char16_t *end) michael@0: { michael@0: const uint32_t numUnicharsPerVector = 8; michael@0: typedef Non8BitParameters p; michael@0: const size_t mask = p::mask(); michael@0: const uint32_t numUnicharsPerWord = p::numUnicharsPerWord(); michael@0: const int32_t len = end - str; michael@0: int32_t i = 0; michael@0: michael@0: // Align ourselves to a 16-byte boundary, as required by _mm_load_si128 michael@0: // (i.e. MOVDQA). michael@0: int32_t alignLen = michael@0: std::min(len, int32_t(((-NS_PTR_TO_INT32(str)) & 0xf) / sizeof(char16_t))); michael@0: for (; i < alignLen; i++) { michael@0: if (str[i] > 255) michael@0: return i; michael@0: } michael@0: michael@0: // Check one XMM register (16 bytes) at a time. michael@0: const int32_t vectWalkEnd = ((len - i) / numUnicharsPerVector) * numUnicharsPerVector; michael@0: const uint16_t shortMask = 0xff00; michael@0: __m128i vectmask = _mm_set1_epi16(static_cast(shortMask)); michael@0: for(; i < vectWalkEnd; i += numUnicharsPerVector) { michael@0: const __m128i vect = *reinterpret_cast(str + i); michael@0: if (!is_zero(_mm_and_si128(vect, vectmask))) michael@0: return i; michael@0: } michael@0: michael@0: // Check one word at a time. michael@0: const int32_t wordWalkEnd = ((len - i) / numUnicharsPerWord) * numUnicharsPerWord; michael@0: for(; i < wordWalkEnd; i += numUnicharsPerWord) { michael@0: const size_t word = *reinterpret_cast(str + i); michael@0: if (word & mask) michael@0: return i; michael@0: } michael@0: michael@0: // Take care of the remainder one character at a time. michael@0: for (; i < len; i++) { michael@0: if (str[i] > 255) { michael@0: return i; michael@0: } michael@0: } michael@0: michael@0: return -1; michael@0: } michael@0: michael@0: } // namespace SSE2 michael@0: } // namespace mozilla