diff options
Diffstat (limited to 'thirdparty')
212 files changed, 44358 insertions, 21631 deletions
diff --git a/thirdparty/README.md b/thirdparty/README.md index d30b70fede..9c8884fe84 100644 --- a/thirdparty/README.md +++ b/thirdparty/README.md @@ -40,6 +40,17 @@ File extracted from a recent Fedora install: as it's generated on the user's system.) +## cvtt + +- Upstream: https://github.com/elasota/cvtt +- Version: 1.0.0-beta4 +- License: MIT + +Files extracted from upstream source: + +- all .cpp, .h, and .txt files in ConvectionKernels/ + + ## enet - Upstream: http://enet.bespin.org @@ -117,7 +128,7 @@ Files extracted from upstream source: ## glad - Upstream: https://github.com/Dav1dde/glad -- Version: 0.1.20a0 +- Version: 0.1.25 - License: MIT The files we package are automatically generated. @@ -152,7 +163,7 @@ Files extracted from upstream source: ## libpng - Upstream: http://libpng.org/pub/png/libpng.html -- Version: 1.6.34 +- Version: 1.6.35 - License: libpng/zlib Files extracted from upstream source: @@ -161,6 +172,7 @@ Files extracted from upstream source: `example.c` and `pngtest.c` - the arm/ folder - `scripts/pnglibconf.h.prebuilt` as `pnglibconf.h` +- `LICENSE` ## libsimplewebm @@ -262,14 +274,12 @@ Godot build configurations, check them out when updating. ## mbedtls - Upstream: https://tls.mbed.org/ -- Version: 2.8.0 +- Version: 2.12.0 - License: Apache 2.0 -File extracted from upstream release tarball `mbedtls-2.8.0-apache.tgz`: +File extracted from upstream release tarball `mbedtls-2.12.0-apache.tgz`: - All `*.h` from `include/mbedtls/` to `thirdparty/mbedtls/include/mbedtls/` - All `*.c` from `library/` to `thirdparty/mbedtls/library/` -- In file `thirdparty/mbedtls/library/net_sockets.c` mbedTLS overrides the `_WIN32_WINNT` define. - Be sure to check the Godot addition to only redfine it when undefined or `< 0x0501` (PRed upstream). - Applied the patch in `thirdparty/mbedtls/1453.diff` (PR 1453). Soon to be merged upstream. Check it out at next update. @@ -402,15 +412,18 @@ Files extracted from upstream source: ## pcre2 - Upstream: http://www.pcre.org/ -- Version: 10.23 +- Version: 10.31 - License: BSD-3-Clause Files extracted from upstream source: -- Files listed in NON-AUTOTOOLS-BUILD steps 1-4 +- Files listed in the file NON-AUTOTOOLS-BUILD steps 1-4 - All .h files in src/ -- src/pcre2_jit_*.c and src/sljit/* -- AUTHORS and COPYING +- src/pcre2_jit_match.c +- src/pcre2_jit_misc.c +- src/pcre2_jit_maketables.c +- src/sljit/* +- AUTHORS and LICENCE ## pvrtccompressor @@ -481,7 +494,7 @@ changes are marked with `// -- GODOT --` comments. ## tinyexr - Upstream: https://github.com/syoyo/tinyexr -- Version: git (e385dad, 2018) +- Version: git (2d5375f, 2018) - License: BSD-3-Clause Files extracted from upstream source: diff --git a/thirdparty/b2d_convexdecomp/b2Glue.h b/thirdparty/b2d_convexdecomp/b2Glue.h index 425486356e..10c2f62361 100644 --- a/thirdparty/b2d_convexdecomp/b2Glue.h +++ b/thirdparty/b2d_convexdecomp/b2Glue.h @@ -19,7 +19,7 @@ #ifndef B2GLUE_H #define B2GLUE_H -#include "math_2d.h" +#include "vector2.h" #include <limits.h> namespace b2ConvexDecomp { diff --git a/thirdparty/cvtt/ConvectionKernels.cpp b/thirdparty/cvtt/ConvectionKernels.cpp new file mode 100644 index 0000000000..8d379344e1 --- /dev/null +++ b/thirdparty/cvtt/ConvectionKernels.cpp @@ -0,0 +1,7586 @@ +/* +Convection Texture Tools +Copyright (c) 2018 Eric Lasota + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject +to the following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +------------------------------------------------------------------------------------- + +Portions based on DirectX Texture Library (DirectXTex) + +Copyright (c) Microsoft Corporation. All rights reserved. +Licensed under the MIT License. + +http://go.microsoft.com/fwlink/?LinkId=248926 +*/ +#include "ConvectionKernels.h" +#include "ConvectionKernels_BC7_SingleColor.h" + +#if (defined(_M_IX86_FP) && _M_IX86_FP >= 2) || defined(_M_X64) || defined(__SSE2__) +#define CVTT_USE_SSE2 +#endif + +#ifdef CVTT_USE_SSE2 +#include <emmintrin.h> +#endif + +#include <float.h> +#include <assert.h> +#include <string.h> +#include <algorithm> +#include <math.h> + +#define UNREFERENCED_PARAMETER(n) ((void)n) + +namespace cvtt +{ +#ifdef CVTT_USE_SSE2 + // SSE2 version + struct ParallelMath + { + typedef uint16_t ScalarUInt16; + typedef int16_t ScalarSInt16; + + template<unsigned int TRoundingMode> + struct RoundForScope + { + unsigned int m_oldCSR; + + RoundForScope() + { + m_oldCSR = _mm_getcsr(); + _mm_setcsr((m_oldCSR & ~_MM_ROUND_MASK) | (TRoundingMode)); + } + + ~RoundForScope() + { + _mm_setcsr(m_oldCSR); + } + }; + + struct RoundTowardZeroForScope : RoundForScope<_MM_ROUND_TOWARD_ZERO> + { + }; + + struct RoundTowardNearestForScope : RoundForScope<_MM_ROUND_NEAREST> + { + }; + + struct RoundUpForScope : RoundForScope<_MM_ROUND_UP> + { + }; + + struct RoundDownForScope : RoundForScope<_MM_ROUND_DOWN> + { + }; + + static const int ParallelSize = 8; + + enum Int16Subtype + { + IntSubtype_Signed, + IntSubtype_UnsignedFull, + IntSubtype_UnsignedTruncated, + IntSubtype_Abstract, + }; + + template<int TSubtype> + struct VInt16 + { + __m128i m_value; + + inline VInt16 operator+(int16_t other) const + { + VInt16 result; + result.m_value = _mm_add_epi16(m_value, _mm_set1_epi16(static_cast<int16_t>(other))); + return result; + } + + inline VInt16 operator+(const VInt16 &other) const + { + VInt16 result; + result.m_value = _mm_add_epi16(m_value, other.m_value); + return result; + } + + inline VInt16 operator|(const VInt16 &other) const + { + VInt16 result; + result.m_value = _mm_or_si128(m_value, other.m_value); + return result; + } + + inline VInt16 operator&(const VInt16 &other) const + { + VInt16 result; + result.m_value = _mm_and_si128(m_value, other.m_value); + return result; + } + + inline VInt16 operator-(const VInt16 &other) const + { + VInt16 result; + result.m_value = _mm_sub_epi16(m_value, other.m_value); + return result; + } + + inline VInt16 operator<<(int bits) const + { + VInt16 result; + result.m_value = _mm_slli_epi16(m_value, bits); + return result; + } + }; + + typedef VInt16<IntSubtype_Signed> SInt16; + typedef VInt16<IntSubtype_UnsignedFull> UInt16; + typedef VInt16<IntSubtype_UnsignedTruncated> UInt15; + typedef VInt16<IntSubtype_Abstract> AInt16; + + template<int TSubtype> + struct VInt32 + { + __m128i m_values[2]; + + inline VInt32 operator+(const VInt32& other) const + { + VInt32 result; + result.m_values[0] = _mm_add_epi32(m_values[0], other.m_values[0]); + result.m_values[1] = _mm_add_epi32(m_values[1], other.m_values[1]); + return result; + } + + inline VInt32 operator-(const VInt32& other) const + { + VInt32 result; + result.m_values[0] = _mm_sub_epi32(m_values[0], other.m_values[0]); + result.m_values[1] = _mm_sub_epi32(m_values[1], other.m_values[1]); + return result; + } + + inline VInt32 operator<<(const int other) const + { + VInt32 result; + result.m_values[0] = _mm_slli_epi32(m_values[0], other); + result.m_values[1] = _mm_slli_epi32(m_values[1], other); + return result; + } + }; + + typedef VInt32<IntSubtype_Signed> SInt32; + typedef VInt32<IntSubtype_UnsignedTruncated> UInt31; + typedef VInt32<IntSubtype_UnsignedFull> UInt32; + typedef VInt32<IntSubtype_Abstract> AInt32; + + template<class TTargetType> + struct LosslessCast + { +#ifdef CVTT_PERMIT_ALIASING + template<int TSrcSubtype> + static const TTargetType& Cast(const VInt32<TSrcSubtype> &src) + { + return reinterpret_cast<VInt32<TSubtype>&>(src); + } + + template<int TSrcSubtype> + static const TTargetType& Cast(const VInt16<TSrcSubtype> &src) + { + return reinterpret_cast<VInt16<TSubtype>&>(src); + } +#else + template<int TSrcSubtype> + static TTargetType Cast(const VInt32<TSrcSubtype> &src) + { + TTargetType result; + result.m_values[0] = src.m_values[0]; + result.m_values[1] = src.m_values[1]; + return result; + } + + template<int TSrcSubtype> + static TTargetType Cast(const VInt16<TSrcSubtype> &src) + { + TTargetType result; + result.m_value = src.m_value; + return result; + } +#endif + }; + + struct Int64 + { + __m128i m_values[4]; + }; + + struct Float + { + __m128 m_values[2]; + + inline Float operator+(const Float &other) const + { + Float result; + result.m_values[0] = _mm_add_ps(m_values[0], other.m_values[0]); + result.m_values[1] = _mm_add_ps(m_values[1], other.m_values[1]); + return result; + } + + inline Float operator+(float other) const + { + Float result; + result.m_values[0] = _mm_add_ps(m_values[0], _mm_set1_ps(other)); + result.m_values[1] = _mm_add_ps(m_values[1], _mm_set1_ps(other)); + return result; + } + + inline Float operator-(const Float& other) const + { + Float result; + result.m_values[0] = _mm_sub_ps(m_values[0], other.m_values[0]); + result.m_values[1] = _mm_sub_ps(m_values[1], other.m_values[1]); + return result; + } + + inline Float operator-() const + { + Float result; + result.m_values[0] = _mm_sub_ps(_mm_setzero_ps(), m_values[0]); + result.m_values[1] = _mm_sub_ps(_mm_setzero_ps(), m_values[1]); + return result; + } + + inline Float operator*(const Float& other) const + { + Float result; + result.m_values[0] = _mm_mul_ps(m_values[0], other.m_values[0]); + result.m_values[1] = _mm_mul_ps(m_values[1], other.m_values[1]); + return result; + } + + inline Float operator*(float other) const + { + Float result; + result.m_values[0] = _mm_mul_ps(m_values[0], _mm_set1_ps(other)); + result.m_values[1] = _mm_mul_ps(m_values[1], _mm_set1_ps(other)); + return result; + } + + inline Float operator/(const Float &other) const + { + Float result; + result.m_values[0] = _mm_div_ps(m_values[0], other.m_values[0]); + result.m_values[1] = _mm_div_ps(m_values[1], other.m_values[1]); + return result; + } + + inline Float operator/(float other) const + { + Float result; + result.m_values[0] = _mm_div_ps(m_values[0], _mm_set1_ps(other)); + result.m_values[1] = _mm_div_ps(m_values[1], _mm_set1_ps(other)); + return result; + } + }; + + struct Int16CompFlag + { + __m128i m_value; + + inline Int16CompFlag operator&(const Int16CompFlag &other) const + { + Int16CompFlag result; + result.m_value = _mm_and_si128(m_value, other.m_value); + return result; + } + + inline Int16CompFlag operator|(const Int16CompFlag &other) const + { + Int16CompFlag result; + result.m_value = _mm_or_si128(m_value, other.m_value); + return result; + } + }; + + struct FloatCompFlag + { + __m128 m_values[2]; + }; + + template<int TSubtype> + static VInt16<TSubtype> AbstractAdd(const VInt16<TSubtype> &a, const VInt16<TSubtype> &b) + { + VInt16<TSubtype> result; + result.m_value = _mm_add_epi16(a.m_value, b.m_value); + return result; + } + + template<int TSubtype> + static VInt16<TSubtype> AbstractSubtract(const VInt16<TSubtype> &a, const VInt16<TSubtype> &b) + { + VInt16<TSubtype> result; + result.m_value = _mm_sub_epi16(a.m_value, b.m_value); + return result; + } + + static Float Select(const FloatCompFlag &flag, const Float &a, const Float &b) + { + Float result; + for (int i = 0; i < 2; i++) + result.m_values[i] = _mm_or_ps(_mm_and_ps(flag.m_values[i], a.m_values[i]), _mm_andnot_ps(flag.m_values[i], b.m_values[i])); + return result; + } + + template<int TSubtype> + static VInt16<TSubtype> Select(const Int16CompFlag &flag, const VInt16<TSubtype> &a, const VInt16<TSubtype> &b) + { + VInt16<TSubtype> result; + result.m_value = _mm_or_si128(_mm_and_si128(flag.m_value, a.m_value), _mm_andnot_si128(flag.m_value, b.m_value)); + return result; + } + + template<int TSubtype> + static VInt16<TSubtype> SelectOrZero(const Int16CompFlag &flag, const VInt16<TSubtype> &a) + { + VInt16<TSubtype> result; + result.m_value = _mm_and_si128(flag.m_value, a.m_value); + return result; + } + + template<int TSubtype> + static void ConditionalSet(VInt16<TSubtype> &dest, const Int16CompFlag &flag, const VInt16<TSubtype> &src) + { + dest.m_value = _mm_or_si128(_mm_andnot_si128(flag.m_value, dest.m_value), _mm_and_si128(flag.m_value, src.m_value)); + } + + static SInt16 ConditionalNegate(const Int16CompFlag &flag, const SInt16 &v) + { + SInt16 result; + result.m_value = _mm_add_epi16(_mm_xor_si128(flag.m_value, v.m_value), _mm_srli_epi16(flag.m_value, 15)); + return result; + } + + template<int TSubtype> + static void NotConditionalSet(VInt16<TSubtype> &dest, const Int16CompFlag &flag, const VInt16<TSubtype> &src) + { + dest.m_value = _mm_or_si128(_mm_and_si128(flag.m_value, dest.m_value), _mm_andnot_si128(flag.m_value, src.m_value)); + } + + static void ConditionalSet(Float &dest, const FloatCompFlag &flag, const Float &src) + { + for (int i = 0; i < 2; i++) + dest.m_values[i] = _mm_or_ps(_mm_andnot_ps(flag.m_values[i], dest.m_values[i]), _mm_and_ps(flag.m_values[i], src.m_values[i])); + } + + static void NotConditionalSet(Float &dest, const FloatCompFlag &flag, const Float &src) + { + for (int i = 0; i < 2; i++) + dest.m_values[i] = _mm_or_ps(_mm_and_ps(flag.m_values[i], dest.m_values[i]), _mm_andnot_ps(flag.m_values[i], src.m_values[i])); + } + + static void MakeSafeDenominator(Float& v) + { + ConditionalSet(v, Equal(v, MakeFloatZero()), MakeFloat(1.0f)); + } + + static SInt16 TruncateToPrecisionSigned(const SInt16 &v, int precision) + { + int lostBits = 16 - precision; + if (lostBits == 0) + return v; + + SInt16 result; + result.m_value = _mm_srai_epi16(_mm_slli_epi16(v.m_value, lostBits), lostBits); + return result; + } + + static UInt16 TruncateToPrecisionUnsigned(const UInt16 &v, int precision) + { + int lostBits = 16 - precision; + if (lostBits == 0) + return v; + + UInt16 result; + result.m_value = _mm_srli_epi16(_mm_slli_epi16(v.m_value, lostBits), lostBits); + return result; + } + + static UInt16 Min(const UInt16 &a, const UInt16 &b) + { + __m128i bitFlip = _mm_set1_epi16(-32768); + + UInt16 result; + result.m_value = _mm_xor_si128(_mm_min_epi16(_mm_xor_si128(a.m_value, bitFlip), _mm_xor_si128(b.m_value, bitFlip)), bitFlip); + return result; + } + + static SInt16 Min(const SInt16 &a, const SInt16 &b) + { + SInt16 result; + result.m_value = _mm_min_epi16(a.m_value, b.m_value); + return result; + } + + static UInt15 Min(const UInt15 &a, const UInt15 &b) + { + UInt15 result; + result.m_value = _mm_min_epi16(a.m_value, b.m_value); + return result; + } + + static Float Min(const Float &a, const Float &b) + { + Float result; + for (int i = 0; i < 2; i++) + result.m_values[i] = _mm_min_ps(a.m_values[i], b.m_values[i]); + return result; + } + + static UInt16 Max(const UInt16 &a, const UInt16 &b) + { + __m128i bitFlip = _mm_set1_epi16(-32768); + + UInt16 result; + result.m_value = _mm_xor_si128(_mm_max_epi16(_mm_xor_si128(a.m_value, bitFlip), _mm_xor_si128(b.m_value, bitFlip)), bitFlip); + return result; + } + + static SInt16 Max(const SInt16 &a, const SInt16 &b) + { + SInt16 result; + result.m_value = _mm_max_epi16(a.m_value, b.m_value); + return result; + } + + static UInt15 Max(const UInt15 &a, const UInt15 &b) + { + UInt15 result; + result.m_value = _mm_max_epi16(a.m_value, b.m_value); + return result; + } + + static Float Max(const Float &a, const Float &b) + { + Float result; + for (int i = 0; i < 2; i++) + result.m_values[i] = _mm_max_ps(a.m_values[i], b.m_values[i]); + return result; + } + + static Float Clamp(const Float &v, float min, float max) + { + Float result; + for (int i = 0; i < 2; i++) + result.m_values[i] = _mm_max_ps(_mm_min_ps(v.m_values[i], _mm_set1_ps(max)), _mm_set1_ps(min)); + return result; + } + + static Float Reciprocal(const Float &v) + { + Float result; + for (int i = 0; i < 2; i++) + result.m_values[i] = _mm_rcp_ps(v.m_values[i]); + return result; + } + + static void ConvertLDRInputs(const PixelBlockU8* inputBlocks, int pxOffset, int channel, UInt15 &chOut) + { + int16_t values[8]; + for (int i = 0; i < 8; i++) + values[i] = inputBlocks[i].m_pixels[pxOffset][channel]; + + chOut.m_value = _mm_set_epi16(values[7], values[6], values[5], values[4], values[3], values[2], values[1], values[0]); + } + + static void ConvertHDRInputs(const PixelBlockF16* inputBlocks, int pxOffset, int channel, SInt16 &chOut) + { + int16_t values[8]; + for (int i = 0; i < 8; i++) + values[i] = inputBlocks[i].m_pixels[pxOffset][channel]; + + chOut.m_value = _mm_set_epi16(values[7], values[6], values[5], values[4], values[3], values[2], values[1], values[0]); + } + + static Float MakeFloat(float v) + { + Float f; + f.m_values[0] = f.m_values[1] = _mm_set1_ps(v); + return f; + } + + static Float MakeFloatZero() + { + Float f; + f.m_values[0] = f.m_values[1] = _mm_setzero_ps(); + return f; + } + + static UInt16 MakeUInt16(uint16_t v) + { + UInt16 result; + result.m_value = _mm_set1_epi16(static_cast<short>(v)); + return result; + } + + static SInt16 MakeSInt16(int16_t v) + { + SInt16 result; + result.m_value = _mm_set1_epi16(static_cast<short>(v)); + return result; + } + + static AInt16 MakeAInt16(int16_t v) + { + AInt16 result; + result.m_value = _mm_set1_epi16(static_cast<short>(v)); + return result; + } + + static UInt15 MakeUInt15(uint16_t v) + { + UInt15 result; + result.m_value = _mm_set1_epi16(static_cast<short>(v)); + return result; + } + + static SInt32 MakeSInt32(int32_t v) + { + SInt32 result; + result.m_values[0] = _mm_set1_epi32(v); + result.m_values[1] = _mm_set1_epi32(v); + return result; + } + + static UInt31 MakeUInt31(uint32_t v) + { + UInt31 result; + result.m_values[0] = _mm_set1_epi32(v); + result.m_values[1] = _mm_set1_epi32(v); + return result; + } + + static uint16_t Extract(const UInt16 &v, int offset) + { + return reinterpret_cast<const uint16_t*>(&v.m_value)[offset]; + } + + static int16_t Extract(const SInt16 &v, int offset) + { + return reinterpret_cast<const int16_t*>(&v.m_value)[offset]; + } + + static uint16_t Extract(const UInt15 &v, int offset) + { + return reinterpret_cast<const uint16_t*>(&v.m_value)[offset]; + } + + static int16_t Extract(const AInt16 &v, int offset) + { + return reinterpret_cast<const int16_t*>(&v.m_value)[offset]; + } + + static void PutUInt16(UInt16 &dest, int offset, uint16_t v) + { + reinterpret_cast<uint16_t*>(&dest)[offset] = v; + } + + static void PutUInt15(UInt15 &dest, int offset, uint16_t v) + { + reinterpret_cast<uint16_t*>(&dest)[offset] = v; + } + + static void PutSInt16(SInt16 &dest, int offset, int16_t v) + { + reinterpret_cast<int16_t*>(&dest)[offset] = v; + } + + static float ExtractFloat(const Float& v, int offset) + { + return reinterpret_cast<const float*>(&v)[offset]; + } + + static void PutFloat(Float &dest, int offset, float v) + { + reinterpret_cast<float*>(&dest)[offset] = v; + } + + static Int16CompFlag Less(const SInt16 &a, const SInt16 &b) + { + Int16CompFlag result; + result.m_value = _mm_cmplt_epi16(a.m_value, b.m_value); + return result; + } + + static Int16CompFlag Less(const UInt15 &a, const UInt15 &b) + { + Int16CompFlag result; + result.m_value = _mm_cmplt_epi16(a.m_value, b.m_value); + return result; + } + + static Int16CompFlag LessOrEqual(const UInt15 &a, const UInt15 &b) + { + Int16CompFlag result; + result.m_value = _mm_cmplt_epi16(a.m_value, b.m_value); + return result; + } + + static FloatCompFlag Less(const Float &a, const Float &b) + { + FloatCompFlag result; + for (int i = 0; i < 2; i++) + result.m_values[i] = _mm_cmplt_ps(a.m_values[i], b.m_values[i]); + return result; + } + + static FloatCompFlag LessOrEqual(const Float &a, const Float &b) + { + FloatCompFlag result; + for (int i = 0; i < 2; i++) + result.m_values[i] = _mm_cmple_ps(a.m_values[i], b.m_values[i]); + return result; + } + + template<int TSubtype> + static Int16CompFlag Equal(const VInt16<TSubtype> &a, const VInt16<TSubtype> &b) + { + Int16CompFlag result; + result.m_value = _mm_cmpeq_epi16(a.m_value, b.m_value); + return result; + } + + static FloatCompFlag Equal(const Float &a, const Float &b) + { + FloatCompFlag result; + for (int i = 0; i < 2; i++) + result.m_values[i] = _mm_cmpeq_ps(a.m_values[i], b.m_values[i]); + return result; + } + + static Float ToFloat(const UInt16 &v) + { + Float result; + result.m_values[0] = _mm_cvtepi32_ps(_mm_unpacklo_epi16(v.m_value, _mm_setzero_si128())); + result.m_values[1] = _mm_cvtepi32_ps(_mm_unpackhi_epi16(v.m_value, _mm_setzero_si128())); + return result; + } + + static UInt31 ToUInt31(const UInt16 &v) + { + UInt31 result; + result.m_values[0] = _mm_unpacklo_epi16(v.m_value, _mm_setzero_si128()); + result.m_values[1] = _mm_unpackhi_epi16(v.m_value, _mm_setzero_si128()); + return result; + } + + static SInt32 ToInt32(const UInt16 &v) + { + SInt32 result; + result.m_values[0] = _mm_unpacklo_epi16(v.m_value, _mm_setzero_si128()); + result.m_values[1] = _mm_unpackhi_epi16(v.m_value, _mm_setzero_si128()); + return result; + } + + static SInt32 ToInt32(const SInt16 &v) + { + SInt32 result; + result.m_values[0] = _mm_srai_epi32(_mm_unpacklo_epi16(_mm_setzero_si128(), v.m_value), 16); + result.m_values[1] = _mm_srai_epi32(_mm_unpackhi_epi16(_mm_setzero_si128(), v.m_value), 16); + return result; + } + + static Float ToFloat(const SInt16 &v) + { + Float result; + result.m_values[0] = _mm_cvtepi32_ps(_mm_srai_epi32(_mm_unpacklo_epi16(_mm_setzero_si128(), v.m_value), 16)); + result.m_values[1] = _mm_cvtepi32_ps(_mm_srai_epi32(_mm_unpackhi_epi16(_mm_setzero_si128(), v.m_value), 16)); + return result; + } + + static Float ToFloat(const UInt15 &v) + { + Float result; + result.m_values[0] = _mm_cvtepi32_ps(_mm_unpacklo_epi16(v.m_value, _mm_setzero_si128())); + result.m_values[1] = _mm_cvtepi32_ps(_mm_unpackhi_epi16(v.m_value, _mm_setzero_si128())); + return result; + } + + static Float ToFloat(const UInt31 &v) + { + Float result; + result.m_values[0] = _mm_cvtepi32_ps(v.m_values[0]); + result.m_values[1] = _mm_cvtepi32_ps(v.m_values[1]); + return result; + } + + static Int16CompFlag FloatFlagToInt16(const FloatCompFlag &v) + { + __m128i lo = _mm_castps_si128(v.m_values[0]); + __m128i hi = _mm_castps_si128(v.m_values[1]); + + Int16CompFlag result; + result.m_value = _mm_packs_epi32(lo, hi); + return result; + } + + static FloatCompFlag Int16FlagToFloat(const Int16CompFlag &v) + { + __m128i lo = _mm_unpacklo_epi16(v.m_value, v.m_value); + __m128i hi = _mm_unpackhi_epi16(v.m_value, v.m_value); + + FloatCompFlag result; + result.m_values[0] = _mm_castsi128_ps(lo); + result.m_values[1] = _mm_castsi128_ps(hi); + return result; + } + + static Int16CompFlag MakeBoolInt16(bool b) + { + Int16CompFlag result; + if (b) + result.m_value = _mm_set1_epi16(-1); + else + result.m_value = _mm_setzero_si128(); + return result; + } + + static FloatCompFlag MakeBoolFloat(bool b) + { + FloatCompFlag result; + if (b) + result.m_values[0] = result.m_values[1] = _mm_castsi128_ps(_mm_set1_epi32(-1)); + else + result.m_values[0] = result.m_values[1] = _mm_setzero_ps(); + return result; + } + + static Int16CompFlag AndNot(const Int16CompFlag &a, const Int16CompFlag &b) + { + Int16CompFlag result; + result.m_value = _mm_andnot_si128(b.m_value, a.m_value); + return result; + } + + static UInt16 RoundAndConvertToU16(const Float &v, const void* /*roundingMode*/) + { + __m128i lo = _mm_cvtps_epi32(_mm_add_ps(v.m_values[0], _mm_set1_ps(-32768))); + __m128i hi = _mm_cvtps_epi32(_mm_add_ps(v.m_values[1], _mm_set1_ps(-32768))); + + __m128i packed = _mm_packs_epi32(lo, hi); + + UInt16 result; + result.m_value = _mm_xor_si128(packed, _mm_set1_epi16(-32768)); + return result; + } + + static UInt15 RoundAndConvertToU15(const Float &v, const void* /*roundingMode*/) + { + __m128i lo = _mm_cvtps_epi32(v.m_values[0]); + __m128i hi = _mm_cvtps_epi32(v.m_values[1]); + + __m128i packed = _mm_packs_epi32(lo, hi); + + UInt15 result; + result.m_value = _mm_packs_epi32(lo, hi); + return result; + } + + static SInt16 RoundAndConvertToS16(const Float &v, const void* /*roundingMode*/) + { + __m128i lo = _mm_cvtps_epi32(v.m_values[0]); + __m128i hi = _mm_cvtps_epi32(v.m_values[1]); + + __m128i packed = _mm_packs_epi32(lo, hi); + + SInt16 result; + result.m_value = _mm_packs_epi32(lo, hi); + return result; + } + + static Float Sqrt(const Float &f) + { + Float result; + for (int i = 0; i < 2; i++) + result.m_values[i] = _mm_sqrt_ps(f.m_values[i]); + return result; + } + + static UInt16 Abs(const SInt16 &a) + { + __m128i signBitsXor = _mm_srai_epi16(a.m_value, 15); + __m128i signBitsAdd = _mm_srli_epi16(a.m_value, 15); + + UInt16 result; + result.m_value = _mm_add_epi16(_mm_xor_si128(a.m_value, signBitsXor), signBitsAdd); + return result; + } + + static Float Abs(const Float& a) + { + __m128 invMask = _mm_set1_ps(-0.0f); + + Float result; + result.m_values[0] = _mm_andnot_ps(invMask, a.m_values[0]); + result.m_values[1] = _mm_andnot_ps(invMask, a.m_values[1]); + return result; + } + + static UInt16 SqDiffUInt8(const UInt15 &a, const UInt15 &b) + { + __m128i diff = _mm_sub_epi16(a.m_value, b.m_value); + + UInt16 result; + result.m_value = _mm_mullo_epi16(diff, diff); + return result; + } + + static Float SqDiffSInt16(const SInt16 &a, const SInt16 &b) + { + __m128i diffU = _mm_sub_epi16(_mm_max_epi16(a.m_value, b.m_value), _mm_min_epi16(a.m_value, b.m_value)); + + __m128i mulHi = _mm_mulhi_epu16(diffU, diffU); + __m128i mulLo = _mm_mullo_epi16(diffU, diffU); + __m128i sqDiffHi = _mm_unpackhi_epi16(mulLo, mulHi); + __m128i sqDiffLo = _mm_unpacklo_epi16(mulLo, mulHi); + + Float result; + result.m_values[0] = _mm_cvtepi32_ps(sqDiffLo); + result.m_values[1] = _mm_cvtepi32_ps(sqDiffHi); + + return result; + } + + static Float TwosCLHalfToFloat(const SInt16 &v) + { + __m128i absV = _mm_add_epi16(_mm_xor_si128(v.m_value, _mm_srai_epi16(v.m_value, 15)), _mm_srli_epi16(v.m_value, 15)); + + __m128i signBits = _mm_and_si128(v.m_value, _mm_set1_epi16(-32768)); + __m128i mantissa = _mm_and_si128(v.m_value, _mm_set1_epi16(0x03ff)); + __m128i exponent = _mm_and_si128(v.m_value, _mm_set1_epi16(0x7c00)); + + __m128i isDenormal = _mm_cmpeq_epi16(exponent, _mm_setzero_si128()); + + // Convert exponent to high-bits + exponent = _mm_add_epi16(_mm_srli_epi16(exponent, 3), _mm_set1_epi16(14336)); + + __m128i denormalCorrectionHigh = _mm_and_si128(isDenormal, _mm_or_si128(signBits, _mm_set1_epi16(14336))); + + __m128i highBits = _mm_or_si128(signBits, _mm_or_si128(exponent, _mm_srli_epi16(mantissa, 3))); + __m128i lowBits = _mm_slli_epi16(mantissa, 13); + + __m128i flow = _mm_unpacklo_epi16(lowBits, highBits); + __m128i fhigh = _mm_unpackhi_epi16(lowBits, highBits); + + __m128i correctionLow = _mm_unpacklo_epi16(_mm_setzero_si128(), denormalCorrectionHigh); + __m128i correctionHigh = _mm_unpackhi_epi16(_mm_setzero_si128(), denormalCorrectionHigh); + + Float result; + result.m_values[0] = _mm_sub_ps(_mm_castsi128_ps(flow), _mm_castsi128_ps(correctionLow)); + result.m_values[1] = _mm_sub_ps(_mm_castsi128_ps(fhigh), _mm_castsi128_ps(correctionHigh)); + + return result; + } + + static Float SqDiff2CLFloat(const SInt16 &a, const Float &b) + { + Float fa = TwosCLHalfToFloat(a); + + Float diff = fa - b; + return diff * diff; + } + + static Float SqDiff2CL(const SInt16 &a, const SInt16 &b) + { + Float fa = TwosCLHalfToFloat(a); + Float fb = TwosCLHalfToFloat(b); + + Float diff = fa - fb; + return diff * diff; + } + + static Float SqDiff2CLFloat(const SInt16 &a, float aWeight, const Float &b) + { + Float fa = TwosCLHalfToFloat(a) * aWeight; + + Float diff = fa - b; + return diff * diff; + } + + static UInt16 RightShift(const UInt16 &v, int bits) + { + UInt16 result; + result.m_value = _mm_srli_epi16(v.m_value, bits); + return result; + } + + static UInt31 RightShift(const UInt31 &v, int bits) + { + UInt31 result; + result.m_values[0] = _mm_srli_epi32(v.m_values[0], bits); + result.m_values[1] = _mm_srli_epi32(v.m_values[1], bits); + return result; + } + + static SInt16 RightShift(const SInt16 &v, int bits) + { + SInt16 result; + result.m_value = _mm_srai_epi16(v.m_value, bits); + return result; + } + + static UInt15 RightShift(const UInt15 &v, int bits) + { + UInt15 result; + result.m_value = _mm_srli_epi16(v.m_value, bits); + return result; + } + + static SInt32 RightShift(const SInt32 &v, int bits) + { + SInt32 result; + result.m_values[0] = _mm_srai_epi32(v.m_values[0], bits); + result.m_values[1] = _mm_srai_epi32(v.m_values[1], bits); + return result; + } + + static SInt16 ToSInt16(const SInt32 &v) + { + SInt16 result; + result.m_value = _mm_packs_epi32(v.m_values[0], v.m_values[1]); + return result; + } + + static UInt16 ToUInt16(const UInt32 &v) + { + __m128i low = _mm_srai_epi32(_mm_slli_epi32(v.m_values[0], 16), 16); + __m128i high = _mm_srai_epi32(_mm_slli_epi32(v.m_values[1], 16), 16); + + UInt16 result; + result.m_value = _mm_packs_epi32(low, high); + return result; + } + + static UInt16 ToUInt16(const UInt31 &v) + { + __m128i low = _mm_srai_epi32(_mm_slli_epi32(v.m_values[0], 16), 16); + __m128i high = _mm_srai_epi32(_mm_slli_epi32(v.m_values[1], 16), 16); + + UInt16 result; + result.m_value = _mm_packs_epi32(low, high); + return result; + } + + static UInt15 ToUInt15(const UInt31 &v) + { + UInt15 result; + result.m_value = _mm_packs_epi32(v.m_values[0], v.m_values[1]); + return result; + } + + static SInt32 XMultiply(const SInt16 &a, const SInt16 &b) + { + __m128i high = _mm_mulhi_epi16(a.m_value, b.m_value); + __m128i low = _mm_mullo_epi16(a.m_value, b.m_value); + + SInt32 result; + result.m_values[0] = _mm_unpacklo_epi16(low, high); + result.m_values[1] = _mm_unpackhi_epi16(low, high); + return result; + } + + static SInt32 XMultiply(const SInt16 &a, const UInt15 &b) + { + __m128i high = _mm_mulhi_epi16(a.m_value, b.m_value); + __m128i low = _mm_mullo_epi16(a.m_value, b.m_value); + + SInt32 result; + result.m_values[0] = _mm_unpacklo_epi16(low, high); + result.m_values[1] = _mm_unpackhi_epi16(low, high); + return result; + } + + static SInt32 XMultiply(const UInt15 &a, const SInt16 &b) + { + return XMultiply(b, a); + } + + static UInt32 XMultiply(const UInt16 &a, const UInt16 &b) + { + __m128i high = _mm_mulhi_epu16(a.m_value, b.m_value); + __m128i low = _mm_mullo_epi16(a.m_value, b.m_value); + + UInt32 result; + result.m_values[0] = _mm_unpacklo_epi16(low, high); + result.m_values[1] = _mm_unpackhi_epi16(low, high); + return result; + } + + static UInt16 CompactMultiply(const UInt16 &a, const UInt15 &b) + { + UInt16 result; + result.m_value = _mm_mullo_epi16(a.m_value, b.m_value); + return result; + } + + static UInt16 CompactMultiply(const UInt15 &a, const UInt15 &b) + { + UInt16 result; + result.m_value = _mm_mullo_epi16(a.m_value, b.m_value); + return result; + } + + static UInt31 XMultiply(const UInt15 &a, const UInt15 &b) + { + __m128i high = _mm_mulhi_epu16(a.m_value, b.m_value); + __m128i low = _mm_mullo_epi16(a.m_value, b.m_value); + + UInt31 result; + result.m_values[0] = _mm_unpacklo_epi16(low, high); + result.m_values[1] = _mm_unpackhi_epi16(low, high); + return result; + } + + static UInt31 XMultiply(const UInt16 &a, const UInt15 &b) + { + __m128i high = _mm_mulhi_epu16(a.m_value, b.m_value); + __m128i low = _mm_mullo_epi16(a.m_value, b.m_value); + + UInt31 result; + result.m_values[0] = _mm_unpacklo_epi16(low, high); + result.m_values[1] = _mm_unpackhi_epi16(low, high); + return result; + } + + static UInt31 XMultiply(const UInt15 &a, const UInt16 &b) + { + return XMultiply(b, a); + } + + static bool AnySet(const Int16CompFlag &v) + { + return _mm_movemask_epi8(v.m_value) != 0; + } + + static bool AllSet(const Int16CompFlag &v) + { + return _mm_movemask_epi8(v.m_value) == 0xffff; + } + + static bool AnySet(const FloatCompFlag &v) + { + return _mm_movemask_ps(v.m_values[0]) != 0 || _mm_movemask_ps(v.m_values[1]) != 0; + } + + static bool AllSet(const FloatCompFlag &v) + { + return _mm_movemask_ps(v.m_values[0]) == 0xf && _mm_movemask_ps(v.m_values[1]) == 0xf; + } + }; + +#else + // Scalar version + struct ParallelMath + { + struct RoundTowardZeroForScope + { + }; + + struct RoundTowardNearestForScope + { + }; + + struct RoundUpForScope + { + }; + + struct RoundDownForScope + { + }; + + static const int ParallelSize = 1; + + enum Int16Subtype + { + IntSubtype_Signed, + IntSubtype_UnsignedFull, + IntSubtype_UnsignedTruncated, + IntSubtype_Abstract, + }; + + typedef int32_t SInt16; + typedef int32_t UInt15; + typedef int32_t UInt16; + typedef int32_t AInt16; + + typedef int32_t SInt32; + typedef int32_t UInt31; + typedef int32_t UInt32; + typedef int32_t AInt32; + + typedef int32_t ScalarUInt16; + typedef int32_t ScalarSInt16; + + typedef float Float; + + template<class TTargetType> + struct LosslessCast + { + static const int32_t& Cast(const int32_t &src) + { + return src; + } + }; + + typedef bool Int16CompFlag; + typedef bool FloatCompFlag; + + static int32_t AbstractAdd(const int32_t &a, const int32_t &b) + { + return a + b; + } + + static int32_t AbstractSubtract(const int32_t &a, const int32_t &b) + { + return a - b; + } + + static float Select(bool flag, float a, float b) + { + return flag ? a : b; + } + + static int32_t Select(bool flag, int32_t a, int32_t b) + { + return flag ? a : b; + } + + static int32_t SelectOrZero(bool flag, int32_t a) + { + return flag ? a : 0; + } + + static void ConditionalSet(int32_t& dest, bool flag, int32_t src) + { + if (flag) + dest = src; + } + + static int32_t ConditionalNegate(bool flag, int32_t v) + { + return (flag) ? -v : v; + } + + static void NotConditionalSet(int32_t& dest, bool flag, int32_t src) + { + if (!flag) + dest = src; + } + + static void ConditionalSet(float& dest, bool flag, float src) + { + if (flag) + dest = src; + } + + static void NotConditionalSet(float& dest, bool flag, float src) + { + if (!flag) + dest = src; + } + + static void MakeSafeDenominator(float& v) + { + if (v == 0.0f) + v = 1.0f; + } + + static int32_t SignedRightShift(int32_t v, int bits) + { + return v >> bits; + } + + static int32_t TruncateToPrecisionSigned(int32_t v, int precision) + { + v = (v << (32 - precision)) & 0xffffffff; + return SignedRightShift(v, 32 - precision); + } + + static int32_t TruncateToPrecisionUnsigned(int32_t v, int precision) + { + return v & ((1 << precision) - 1); + } + + static int32_t Min(int32_t a, int32_t b) + { + if (a < b) + return a; + return b; + } + + static float Min(float a, float b) + { + if (a < b) + return a; + return b; + } + + static int32_t Max(int32_t a, int32_t b) + { + if (a > b) + return a; + return b; + } + + static float Max(float a, float b) + { + if (a > b) + return a; + return b; + } + + static float Abs(float a) + { + return fabsf(a); + } + + static int32_t Abs(int32_t a) + { + if (a < 0) + return -a; + return a; + } + + static float Clamp(float v, float min, float max) + { + if (v < min) + return min; + if (v > max) + return max; + return v; + } + + static float Reciprocal(float v) + { + return 1.0f / v; + } + + static void ConvertLDRInputs(const PixelBlockU8* inputBlocks, int pxOffset, int channel, int32_t& chOut) + { + chOut = inputBlocks[0].m_pixels[pxOffset][channel]; + } + + static void ConvertHDRInputs(const PixelBlockF16* inputBlocks, int pxOffset, int channel, int32_t& chOut) + { + chOut = inputBlocks[0].m_pixels[pxOffset][channel]; + } + + static float MakeFloat(float v) + { + return v; + } + + static float MakeFloatZero() + { + return 0.0f; + } + + static int32_t MakeUInt16(uint16_t v) + { + return v; + } + + static int32_t MakeSInt16(int16_t v) + { + return v; + } + + static int32_t MakeAInt16(int16_t v) + { + return v; + } + + static int32_t MakeUInt15(uint16_t v) + { + return v; + } + + static int32_t MakeSInt32(int32_t v) + { + return v; + } + + static int32_t MakeUInt31(int32_t v) + { + return v; + } + + static int32_t Extract(int32_t v, int offset) + { + UNREFERENCED_PARAMETER(offset); + return v; + } + + static void PutUInt16(int32_t &dest, int offset, ParallelMath::ScalarUInt16 v) + { + UNREFERENCED_PARAMETER(offset); + dest = v; + } + + static void PutUInt15(int32_t &dest, int offset, ParallelMath::ScalarUInt16 v) + { + UNREFERENCED_PARAMETER(offset); + dest = v; + } + + static void PutSInt16(int32_t &dest, int offset, ParallelMath::ScalarSInt16 v) + { + UNREFERENCED_PARAMETER(offset); + dest = v; + } + + static float ExtractFloat(float v, int offset) + { + UNREFERENCED_PARAMETER(offset); + return v; + } + + static void PutFloat(float &dest, int offset, float v) + { + UNREFERENCED_PARAMETER(offset); + dest = v; + } + + static bool Less(int32_t a, int32_t b) + { + return a < b; + } + + static bool Less(float a, float b) + { + return a < b; + } + + static bool LessOrEqual(int32_t a, int32_t b) + { + return a < b; + } + + static bool LessOrEqual(float a, float b) + { + return a < b; + } + + static bool Equal(int32_t a, int32_t b) + { + return a == b; + } + + static bool Equal(float a, float b) + { + return a == b; + } + + static float ToFloat(int32_t v) + { + return static_cast<float>(v); + } + + static int32_t ToUInt31(int32_t v) + { + return v; + } + + static int32_t ToInt32(int32_t v) + { + return v; + } + + static bool FloatFlagToInt16(bool v) + { + return v; + } + + static bool Int16FlagToFloat(bool v) + { + return v; + } + + static bool MakeBoolInt16(bool b) + { + return b; + } + + static bool MakeBoolFloat(bool b) + { + return b; + } + + static bool AndNot(bool a, bool b) + { + return a && !b; + } + + static int32_t RoundAndConvertToInt(float v, const ParallelMath::RoundTowardZeroForScope *rtz) + { + UNREFERENCED_PARAMETER(rtz); + return static_cast<int>(v); + } + + static int32_t RoundAndConvertToInt(float v, const ParallelMath::RoundUpForScope *ru) + { + UNREFERENCED_PARAMETER(ru); + return static_cast<int>(ceilf(v)); + } + + static int32_t RoundAndConvertToInt(float v, const ParallelMath::RoundDownForScope *rd) + { + UNREFERENCED_PARAMETER(rd); + return static_cast<int>(floorf(v)); + } + + static int32_t RoundAndConvertToInt(float v, const ParallelMath::RoundTowardNearestForScope *rtn) + { + UNREFERENCED_PARAMETER(rtn); + return static_cast<int>(floorf(v + 0.5f)); + } + + template<class TRoundMode> + static int32_t RoundAndConvertToU16(float v, const TRoundMode *roundingMode) + { + return RoundAndConvertToInt(v, roundingMode); + } + + template<class TRoundMode> + static int32_t RoundAndConvertToU15(float v, const TRoundMode *roundingMode) + { + return RoundAndConvertToInt(v, roundingMode); + } + + template<class TRoundMode> + static int32_t RoundAndConvertToS16(float v, const TRoundMode *roundingMode) + { + return RoundAndConvertToInt(v, roundingMode); + } + + static float Sqrt(float f) + { + return sqrtf(f); + } + + static int32_t SqDiffUInt8(int32_t a, int32_t b) + { + int32_t delta = a - b; + return delta * delta; + } + + static int32_t SqDiffInt16(int32_t a, int32_t b) + { + int32_t delta = a - b; + return delta * delta; + } + + static int32_t SqDiffSInt16(int32_t a, int32_t b) + { + int32_t delta = a - b; + return delta * delta; + } + + static float TwosCLHalfToFloat(int32_t v) + { + int32_t absV = (v < 0) ? -v : v; + + int32_t signBits = (absV & -32768); + int32_t mantissa = (absV & 0x03ff); + int32_t exponent = (absV & 0x7c00); + + bool isDenormal = (exponent == 0); + + // Convert exponent to high-bits + exponent = (exponent >> 3) + 14336; + + int32_t denormalCorrection = (isDenormal ? (signBits | 14336) : 0) << 16; + + int32_t fBits = ((exponent | signBits) << 16) | (mantissa << 13); + + float f, correction; + memcpy(&f, &fBits, 4); + memcpy(&correction, &denormalCorrection, 4); + + return f - correction; + } + + static Float SqDiff2CLFloat(const SInt16 &a, const Float &b) + { + Float fa = TwosCLHalfToFloat(a); + + Float diff = fa - b; + return diff * diff; + } + + static Float SqDiff2CL(const SInt16 &a, const SInt16 &b) + { + Float fa = TwosCLHalfToFloat(a); + Float fb = TwosCLHalfToFloat(b); + + Float diff = fa - fb; + return diff * diff; + } + + static Float SqDiff2CLFloat(const SInt16 &a, float aWeight, const Float &b) + { + Float fa = TwosCLHalfToFloat(a) * aWeight; + + Float diff = fa - b; + return diff * diff; + } + + static int32_t RightShift(int32_t v, int bits) + { + return SignedRightShift(v, bits); + } + + static int32_t ToSInt16(int32_t v) + { + return v; + } + + static int32_t ToUInt16(int32_t v) + { + return v; + } + + static int32_t ToUInt15(int32_t v) + { + return v; + } + + static int32_t XMultiply(int32_t a, int32_t b) + { + return a * b; + } + + static int32_t CompactMultiply(int32_t a, int32_t b) + { + return a * b; + } + + static bool AnySet(bool v) + { + return v; + } + + static bool AllSet(bool v) + { + return v; + } + }; + +#endif + + namespace Internal + { + namespace BC7Data + { + enum AlphaMode + { + AlphaMode_Combined, + AlphaMode_Separate, + AlphaMode_None, + }; + + enum PBitMode + { + PBitMode_PerEndpoint, + PBitMode_PerSubset, + PBitMode_None + }; + + struct BC7ModeInfo + { + PBitMode m_pBitMode; + AlphaMode m_alphaMode; + int m_rgbBits; + int m_alphaBits; + int m_partitionBits; + int m_numSubsets; + int m_indexBits; + int m_alphaIndexBits; + bool m_hasIndexSelector; + }; + + BC7ModeInfo g_modes[] = + { + { PBitMode_PerEndpoint, AlphaMode_None, 4, 0, 4, 3, 3, 0, false }, // 0 + { PBitMode_PerSubset, AlphaMode_None, 6, 0, 6, 2, 3, 0, false }, // 1 + { PBitMode_None, AlphaMode_None, 5, 0, 6, 3, 2, 0, false }, // 2 + { PBitMode_PerEndpoint, AlphaMode_None, 7, 0, 6, 2, 2, 0, false }, // 3 (Mode reference has an error, P-bit is really per-endpoint) + + { PBitMode_None, AlphaMode_Separate, 5, 6, 0, 1, 2, 3, true }, // 4 + { PBitMode_None, AlphaMode_Separate, 7, 8, 0, 1, 2, 2, false }, // 5 + { PBitMode_PerEndpoint, AlphaMode_Combined, 7, 7, 0, 1, 4, 0, false }, // 6 + { PBitMode_PerEndpoint, AlphaMode_Combined, 5, 5, 6, 2, 2, 0, false } // 7 + }; + + const int g_weight2[] = { 0, 21, 43, 64 }; + const int g_weight3[] = { 0, 9, 18, 27, 37, 46, 55, 64 }; + const int g_weight4[] = { 0, 4, 9, 13, 17, 21, 26, 30, 34, 38, 43, 47, 51, 55, 60, 64 }; + + const int *g_weightTables[] = + { + NULL, + NULL, + g_weight2, + g_weight3, + g_weight4 + }; + + struct BC6HModeInfo + { + uint16_t m_modeID; + bool m_partitioned; + bool m_transformed; + int m_aPrec; + int m_bPrec[3]; + }; + + // [partitioned][precision] + bool g_hdrModesExistForPrecision[2][17] = + { + //0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 + { false, false, false, false, false, false, false, false, false, false, true, true, true, false, false, false, true }, + { false, false, false, false, false, false, true, true, true, true, true, true, false, false, false, false, false }, + }; + + BC6HModeInfo g_hdrModes[] = + { + { 0x00, true, true, 10,{ 5, 5, 5 } }, + { 0x01, true, true, 7,{ 6, 6, 6 } }, + { 0x02, true, true, 11,{ 5, 4, 4 } }, + { 0x06, true, true, 11,{ 4, 5, 4 } }, + { 0x0a, true, true, 11,{ 4, 4, 5 } }, + { 0x0e, true, true, 9,{ 5, 5, 5 } }, + { 0x12, true, true, 8,{ 6, 5, 5 } }, + { 0x16, true, true, 8,{ 5, 6, 5 } }, + { 0x1a, true, true, 8,{ 5, 5, 6 } }, + { 0x1e, true, false, 6,{ 6, 6, 6 } }, + { 0x03, false, false, 10,{ 10, 10, 10 } }, + { 0x07, false, true, 11,{ 9, 9, 9 } }, + { 0x0b, false, true, 12,{ 8, 8, 8 } }, + { 0x0f, false, true, 16,{ 4, 4, 4 } }, + }; + + const int g_maxHDRPrecision = 16; + + static const size_t g_numHDRModes = sizeof(g_hdrModes) / sizeof(g_hdrModes[0]); + + static uint16_t g_partitionMap[64] = + { + 0xCCCC, 0x8888, 0xEEEE, 0xECC8, + 0xC880, 0xFEEC, 0xFEC8, 0xEC80, + 0xC800, 0xFFEC, 0xFE80, 0xE800, + 0xFFE8, 0xFF00, 0xFFF0, 0xF000, + 0xF710, 0x008E, 0x7100, 0x08CE, + 0x008C, 0x7310, 0x3100, 0x8CCE, + 0x088C, 0x3110, 0x6666, 0x366C, + 0x17E8, 0x0FF0, 0x718E, 0x399C, + 0xaaaa, 0xf0f0, 0x5a5a, 0x33cc, + 0x3c3c, 0x55aa, 0x9696, 0xa55a, + 0x73ce, 0x13c8, 0x324c, 0x3bdc, + 0x6996, 0xc33c, 0x9966, 0x660, + 0x272, 0x4e4, 0x4e40, 0x2720, + 0xc936, 0x936c, 0x39c6, 0x639c, + 0x9336, 0x9cc6, 0x817e, 0xe718, + 0xccf0, 0xfcc, 0x7744, 0xee22, + }; + + static uint32_t g_partitionMap2[64] = + { + 0xaa685050, 0x6a5a5040, 0x5a5a4200, 0x5450a0a8, + 0xa5a50000, 0xa0a05050, 0x5555a0a0, 0x5a5a5050, + 0xaa550000, 0xaa555500, 0xaaaa5500, 0x90909090, + 0x94949494, 0xa4a4a4a4, 0xa9a59450, 0x2a0a4250, + 0xa5945040, 0x0a425054, 0xa5a5a500, 0x55a0a0a0, + 0xa8a85454, 0x6a6a4040, 0xa4a45000, 0x1a1a0500, + 0x0050a4a4, 0xaaa59090, 0x14696914, 0x69691400, + 0xa08585a0, 0xaa821414, 0x50a4a450, 0x6a5a0200, + 0xa9a58000, 0x5090a0a8, 0xa8a09050, 0x24242424, + 0x00aa5500, 0x24924924, 0x24499224, 0x50a50a50, + 0x500aa550, 0xaaaa4444, 0x66660000, 0xa5a0a5a0, + 0x50a050a0, 0x69286928, 0x44aaaa44, 0x66666600, + 0xaa444444, 0x54a854a8, 0x95809580, 0x96969600, + 0xa85454a8, 0x80959580, 0xaa141414, 0x96960000, + 0xaaaa1414, 0xa05050a0, 0xa0a5a5a0, 0x96000000, + 0x40804080, 0xa9a8a9a8, 0xaaaaaa44, 0x2a4a5254, + }; + + static int g_fixupIndexes2[64] = + { + 15,15,15,15, + 15,15,15,15, + 15,15,15,15, + 15,15,15,15, + 15, 2, 8, 2, + 2, 8, 8,15, + 2, 8, 2, 2, + 8, 8, 2, 2, + + 15,15, 6, 8, + 2, 8,15,15, + 2, 8, 2, 2, + 2,15,15, 6, + 6, 2, 6, 8, + 15,15, 2, 2, + 15,15,15,15, + 15, 2, 2,15, + }; + + static int g_fixupIndexes3[64][2] = + { + { 3,15 },{ 3, 8 },{ 15, 8 },{ 15, 3 }, + { 8,15 },{ 3,15 },{ 15, 3 },{ 15, 8 }, + { 8,15 },{ 8,15 },{ 6,15 },{ 6,15 }, + { 6,15 },{ 5,15 },{ 3,15 },{ 3, 8 }, + { 3,15 },{ 3, 8 },{ 8,15 },{ 15, 3 }, + { 3,15 },{ 3, 8 },{ 6,15 },{ 10, 8 }, + { 5, 3 },{ 8,15 },{ 8, 6 },{ 6,10 }, + { 8,15 },{ 5,15 },{ 15,10 },{ 15, 8 }, + + { 8,15 },{ 15, 3 },{ 3,15 },{ 5,10 }, + { 6,10 },{ 10, 8 },{ 8, 9 },{ 15,10 }, + { 15, 6 },{ 3,15 },{ 15, 8 },{ 5,15 }, + { 15, 3 },{ 15, 6 },{ 15, 6 },{ 15, 8 }, + { 3,15 },{ 15, 3 },{ 5,15 },{ 5,15 }, + { 5,15 },{ 8,15 },{ 5,15 },{ 10,15 }, + { 5,15 },{ 10,15 },{ 8,15 },{ 13,15 }, + { 15, 3 },{ 12,15 },{ 3,15 },{ 3, 8 }, + }; + + static const unsigned char g_fragments[] = + { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, // 0, 16 + 0, 1, 2, 3, // 16, 4 + 0, 1, 4, // 20, 3 + 0, 1, 2, 4, // 23, 4 + 2, 3, 7, // 27, 3 + 1, 2, 3, 7, // 30, 4 + 0, 1, 2, 3, 4, 5, 6, 7, // 34, 8 + 0, 1, 4, 8, // 42, 4 + 0, 1, 2, 4, 5, 8, // 46, 6 + 0, 1, 2, 3, 4, 5, 6, 8, // 52, 8 + 1, 4, 5, 6, 9, // 60, 5 + 2, 5, 6, 7, 10, // 65, 5 + 5, 6, 9, 10, // 70, 4 + 2, 3, 7, 11, // 74, 4 + 1, 2, 3, 6, 7, 11, // 78, 6 + 0, 1, 2, 3, 5, 6, 7, 11, // 84, 8 + 0, 1, 2, 3, 8, 9, 10, 11, // 92, 8 + 2, 3, 6, 7, 8, 9, 10, 11, // 100, 8 + 4, 5, 6, 7, 8, 9, 10, 11, // 108, 8 + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, // 116, 12 + 0, 4, 8, 12, // 128, 4 + 0, 2, 3, 4, 6, 7, 8, 12, // 132, 8 + 0, 1, 2, 4, 5, 8, 9, 12, // 140, 8 + 0, 1, 2, 3, 4, 5, 6, 8, 9, 12, // 148, 10 + 3, 6, 7, 8, 9, 12, // 158, 6 + 3, 5, 6, 7, 8, 9, 10, 12, // 164, 8 + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, // 172, 12 + 0, 1, 2, 5, 6, 7, 11, 12, // 184, 8 + 5, 8, 9, 10, 13, // 192, 5 + 8, 12, 13, // 197, 3 + 4, 8, 12, 13, // 200, 4 + 2, 3, 6, 9, 12, 13, // 204, 6 + 0, 1, 2, 3, 8, 9, 12, 13, // 210, 8 + 0, 1, 4, 5, 8, 9, 12, 13, // 218, 8 + 2, 3, 6, 7, 8, 9, 12, 13, // 226, 8 + 2, 3, 5, 6, 9, 10, 12, 13, // 234, 8 + 0, 3, 6, 7, 9, 10, 12, 13, // 242, 8 + 0, 1, 2, 3, 4, 5, 6, 8, 9, 10, 12, 13, // 250, 12 + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 13, // 262, 13 + 2, 3, 4, 7, 8, 11, 12, 13, // 275, 8 + 1, 2, 6, 7, 8, 11, 12, 13, // 283, 8 + 2, 3, 4, 6, 7, 8, 9, 11, 12, 13, // 291, 10 + 2, 3, 4, 5, 10, 11, 12, 13, // 301, 8 + 0, 1, 6, 7, 10, 11, 12, 13, // 309, 8 + 6, 9, 10, 11, 14, // 317, 5 + 0, 2, 4, 6, 8, 10, 12, 14, // 322, 8 + 1, 3, 5, 7, 8, 10, 12, 14, // 330, 8 + 1, 3, 4, 6, 9, 11, 12, 14, // 338, 8 + 0, 2, 5, 7, 9, 11, 12, 14, // 346, 8 + 0, 3, 4, 5, 8, 9, 13, 14, // 354, 8 + 2, 3, 4, 7, 8, 9, 13, 14, // 362, 8 + 1, 2, 5, 6, 9, 10, 13, 14, // 370, 8 + 0, 3, 4, 7, 9, 10, 13, 14, // 378, 8 + 0, 3, 5, 6, 8, 11, 13, 14, // 386, 8 + 1, 2, 4, 7, 8, 11, 13, 14, // 394, 8 + 0, 1, 4, 7, 10, 11, 13, 14, // 402, 8 + 0, 3, 6, 7, 10, 11, 13, 14, // 410, 8 + 8, 12, 13, 14, // 418, 4 + 1, 2, 3, 7, 8, 12, 13, 14, // 422, 8 + 4, 8, 9, 12, 13, 14, // 430, 6 + 0, 4, 5, 8, 9, 12, 13, 14, // 436, 8 + 1, 2, 3, 6, 7, 8, 9, 12, 13, 14, // 444, 10 + 2, 6, 8, 9, 10, 12, 13, 14, // 454, 8 + 0, 1, 2, 4, 5, 6, 8, 9, 10, 12, 13, 14, // 462, 12 + 0, 7, 9, 10, 11, 12, 13, 14, // 474, 8 + 1, 2, 3, 4, 5, 6, 8, 15, // 482, 8 + 3, 7, 11, 15, // 490, 4 + 0, 1, 3, 4, 5, 7, 11, 15, // 494, 8 + 0, 4, 5, 10, 11, 15, // 502, 6 + 1, 2, 3, 6, 7, 10, 11, 15, // 508, 8 + 0, 1, 2, 3, 5, 6, 7, 10, 11, 15, // 516, 10 + 0, 4, 5, 6, 9, 10, 11, 15, // 526, 8 + 0, 1, 2, 3, 4, 5, 6, 7, 9, 10, 11, 15, // 534, 12 + 1, 2, 4, 5, 8, 9, 12, 15, // 546, 8 + 2, 3, 5, 6, 8, 9, 12, 15, // 554, 8 + 0, 3, 5, 6, 9, 10, 12, 15, // 562, 8 + 1, 2, 4, 7, 9, 10, 12, 15, // 570, 8 + 1, 2, 5, 6, 8, 11, 12, 15, // 578, 8 + 0, 3, 4, 7, 8, 11, 12, 15, // 586, 8 + 0, 1, 5, 6, 10, 11, 12, 15, // 594, 8 + 1, 2, 6, 7, 10, 11, 12, 15, // 602, 8 + 1, 3, 4, 6, 8, 10, 13, 15, // 610, 8 + 0, 2, 5, 7, 8, 10, 13, 15, // 618, 8 + 0, 2, 4, 6, 9, 11, 13, 15, // 626, 8 + 1, 3, 5, 7, 9, 11, 13, 15, // 634, 8 + 0, 1, 2, 3, 4, 5, 7, 8, 12, 13, 15, // 642, 11 + 2, 3, 4, 5, 8, 9, 14, 15, // 653, 8 + 0, 1, 6, 7, 8, 9, 14, 15, // 661, 8 + 0, 1, 5, 10, 14, 15, // 669, 6 + 0, 3, 4, 5, 9, 10, 14, 15, // 675, 8 + 0, 1, 5, 6, 9, 10, 14, 15, // 683, 8 + 11, 14, 15, // 691, 3 + 7, 11, 14, 15, // 694, 4 + 1, 2, 4, 5, 8, 11, 14, 15, // 698, 8 + 0, 1, 4, 7, 8, 11, 14, 15, // 706, 8 + 0, 1, 4, 5, 10, 11, 14, 15, // 714, 8 + 2, 3, 6, 7, 10, 11, 14, 15, // 722, 8 + 4, 5, 6, 7, 10, 11, 14, 15, // 730, 8 + 0, 1, 4, 5, 7, 8, 10, 11, 14, 15, // 738, 10 + 0, 1, 2, 3, 5, 6, 7, 9, 10, 11, 14, 15, // 748, 12 + 0, 1, 2, 3, 4, 5, 6, 7, 9, 10, 11, 14, 15, // 760, 13 + 0, 1, 2, 3, 4, 6, 7, 11, 12, 14, 15, // 773, 11 + 3, 4, 8, 9, 10, 13, 14, 15, // 784, 8 + 11, 13, 14, 15, // 792, 4 + 0, 1, 2, 4, 11, 13, 14, 15, // 796, 8 + 0, 1, 2, 4, 5, 10, 11, 13, 14, 15, // 804, 10 + 7, 10, 11, 13, 14, 15, // 814, 6 + 3, 6, 7, 10, 11, 13, 14, 15, // 820, 8 + 1, 5, 9, 10, 11, 13, 14, 15, // 828, 8 + 1, 2, 3, 5, 6, 7, 9, 10, 11, 13, 14, 15, // 836, 12 + 12, 13, 14, 15, // 848, 4 + 0, 1, 2, 3, 12, 13, 14, 15, // 852, 8 + 0, 1, 4, 5, 12, 13, 14, 15, // 860, 8 + 4, 5, 6, 7, 12, 13, 14, 15, // 868, 8 + 4, 8, 9, 10, 12, 13, 14, 15, // 876, 8 + 0, 4, 5, 8, 9, 10, 12, 13, 14, 15, // 884, 10 + 0, 1, 4, 5, 6, 8, 9, 10, 12, 13, 14, 15, // 894, 12 + 0, 1, 2, 3, 4, 7, 8, 11, 12, 13, 14, 15, // 906, 12 + 0, 1, 3, 4, 8, 9, 11, 12, 13, 14, 15, // 918, 11 + 0, 2, 3, 7, 8, 10, 11, 12, 13, 14, 15, // 929, 11 + 7, 9, 10, 11, 12, 13, 14, 15, // 940, 8 + 3, 6, 7, 9, 10, 11, 12, 13, 14, 15, // 948, 10 + 2, 3, 5, 6, 7, 9, 10, 11, 12, 13, 14, 15, // 958, 12 + 8, 9, 10, 11, 12, 13, 14, 15, // 970, 8 + 0, 4, 5, 6, 8, 9, 10, 11, 12, 13, 14, 15, // 978, 12 + 0, 1, 4, 5, 6, 8, 9, 10, 11, 12, 13, 14, 15, // 990, 13 + 3, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, // 1003, 12 + 2, 3, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, // 1015, 13 + 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, // 1028, 12 + 0, 2, // 1040, 2 + 1, 3, // 1042, 2 + 0, 1, 4, 5, // 1044, 4 + 0, 1, 2, 4, 5, // 1048, 5 + 2, 3, 6, // 1053, 3 + 0, 2, 4, 6, // 1056, 4 + 1, 2, 5, 6, // 1060, 4 + 0, 1, 2, 3, 5, 6, // 1064, 6 + 0, 1, 2, 4, 5, 6, // 1070, 6 + 0, 1, 2, 3, 4, 5, 6, // 1076, 7 + 0, 3, 4, 7, // 1083, 4 + 0, 1, 2, 3, 4, 7, // 1087, 6 + 1, 3, 5, 7, // 1093, 4 + 2, 3, 6, 7, // 1097, 4 + 1, 2, 3, 6, 7, // 1101, 5 + 1, 2, 3, 5, 6, 7, // 1106, 6 + 0, 1, 2, 3, 5, 6, 7, // 1112, 7 + 4, 5, 6, 7, // 1119, 4 + 0, 8, // 1123, 2 + 0, 1, 4, 5, 8, // 1125, 5 + 0, 1, 8, 9, // 1130, 4 + 4, 5, 8, 9, // 1134, 4 + 0, 1, 4, 5, 8, 9, // 1138, 6 + 2, 6, 8, 9, // 1144, 4 + 6, 7, 8, 9, // 1148, 4 + 0, 2, 4, 6, 8, 10, // 1152, 6 + 1, 2, 5, 6, 9, 10, // 1158, 6 + 0, 3, 4, 7, 9, 10, // 1164, 6 + 0, 1, 2, 8, 9, 10, // 1170, 6 + 4, 5, 6, 8, 9, 10, // 1176, 6 + 3, 11, // 1182, 2 + 2, 3, 6, 7, 11, // 1184, 5 + 0, 3, 8, 11, // 1189, 4 + 0, 3, 4, 7, 8, 11, // 1193, 6 + 1, 3, 5, 7, 9, 11, // 1199, 6 + 2, 3, 10, 11, // 1205, 4 + 1, 5, 10, 11, // 1209, 4 + 4, 5, 10, 11, // 1213, 4 + 6, 7, 10, 11, // 1217, 4 + 2, 3, 6, 7, 10, 11, // 1221, 6 + 1, 2, 3, 9, 10, 11, // 1227, 6 + 5, 6, 7, 9, 10, 11, // 1233, 6 + 8, 9, 10, 11, // 1239, 4 + 4, 12, // 1243, 2 + 0, 1, 2, 3, 4, 5, 8, 12, // 1245, 8 + 8, 9, 12, // 1253, 3 + 0, 4, 5, 8, 9, 12, // 1256, 6 + 0, 1, 4, 5, 8, 9, 12, // 1262, 7 + 2, 3, 5, 6, 8, 9, 12, // 1269, 7 + 1, 5, 9, 13, // 1276, 4 + 6, 7, 9, 13, // 1280, 4 + 1, 4, 7, 10, 13, // 1284, 5 + 1, 6, 8, 11, 13, // 1289, 5 + 0, 1, 12, 13, // 1294, 4 + 4, 5, 12, 13, // 1298, 4 + 0, 1, 6, 7, 12, 13, // 1302, 6 + 0, 1, 4, 8, 12, 13, // 1308, 6 + 8, 9, 12, 13, // 1314, 4 + 4, 8, 9, 12, 13, // 1318, 5 + 4, 5, 8, 9, 12, 13, // 1323, 6 + 0, 4, 5, 8, 9, 12, 13, // 1329, 7 + 0, 1, 6, 10, 12, 13, // 1336, 6 + 3, 6, 7, 9, 10, 12, 13, // 1342, 7 + 0, 1, 10, 11, 12, 13, // 1349, 6 + 2, 4, 7, 9, 14, // 1355, 5 + 4, 5, 10, 14, // 1360, 4 + 2, 6, 10, 14, // 1364, 4 + 2, 5, 8, 11, 14, // 1368, 5 + 0, 2, 12, 14, // 1373, 4 + 8, 10, 12, 14, // 1377, 4 + 4, 6, 8, 10, 12, 14, // 1381, 6 + 13, 14, // 1387, 2 + 9, 10, 13, 14, // 1389, 4 + 5, 6, 9, 10, 13, 14, // 1393, 6 + 0, 1, 2, 12, 13, 14, // 1399, 6 + 4, 5, 6, 12, 13, 14, // 1405, 6 + 8, 9, 12, 13, 14, // 1411, 5 + 8, 9, 10, 12, 13, 14, // 1416, 6 + 7, 15, // 1422, 2 + 0, 5, 10, 15, // 1424, 4 + 0, 1, 2, 3, 6, 7, 11, 15, // 1428, 8 + 10, 11, 15, // 1436, 3 + 0, 1, 5, 6, 10, 11, 15, // 1439, 7 + 3, 6, 7, 10, 11, 15, // 1446, 6 + 12, 15, // 1452, 2 + 0, 3, 12, 15, // 1454, 4 + 4, 7, 12, 15, // 1458, 4 + 0, 3, 6, 9, 12, 15, // 1462, 6 + 0, 3, 5, 10, 12, 15, // 1468, 6 + 8, 11, 12, 15, // 1474, 4 + 5, 6, 8, 11, 12, 15, // 1478, 6 + 4, 7, 8, 11, 12, 15, // 1484, 6 + 1, 3, 13, 15, // 1490, 4 + 9, 11, 13, 15, // 1494, 4 + 5, 7, 9, 11, 13, 15, // 1498, 6 + 2, 3, 14, 15, // 1504, 4 + 2, 3, 4, 5, 14, 15, // 1508, 6 + 6, 7, 14, 15, // 1514, 4 + 2, 3, 5, 9, 14, 15, // 1518, 6 + 2, 3, 8, 9, 14, 15, // 1524, 6 + 10, 14, 15, // 1530, 3 + 0, 4, 5, 9, 10, 14, 15, // 1533, 7 + 2, 3, 7, 11, 14, 15, // 1540, 6 + 10, 11, 14, 15, // 1546, 4 + 7, 10, 11, 14, 15, // 1550, 5 + 6, 7, 10, 11, 14, 15, // 1555, 6 + 1, 2, 3, 13, 14, 15, // 1561, 6 + 5, 6, 7, 13, 14, 15, // 1567, 6 + 10, 11, 13, 14, 15, // 1573, 5 + 9, 10, 11, 13, 14, 15, // 1578, 6 + 0, 4, 8, 9, 12, 13, 14, 15, // 1584, 8 + 9, 10, 12, 13, 14, 15, // 1592, 6 + 8, 11, 12, 13, 14, 15, // 1598, 6 + 3, 7, 10, 11, 12, 13, 14, 15, // 1604, 8 + }; + static const int g_shapeRanges[][2] = + { + { 0, 16 },{ 16, 4 },{ 20, 3 },{ 23, 4 },{ 27, 3 },{ 30, 4 },{ 34, 8 },{ 42, 4 },{ 46, 6 },{ 52, 8 },{ 60, 5 }, + { 65, 5 },{ 70, 4 },{ 74, 4 },{ 78, 6 },{ 84, 8 },{ 92, 8 },{ 100, 8 },{ 108, 8 },{ 116, 12 },{ 128, 4 },{ 132, 8 }, + { 140, 8 },{ 148, 10 },{ 158, 6 },{ 164, 8 },{ 172, 12 },{ 184, 8 },{ 192, 5 },{ 197, 3 },{ 200, 4 },{ 204, 6 },{ 210, 8 }, + { 218, 8 },{ 226, 8 },{ 234, 8 },{ 242, 8 },{ 250, 12 },{ 262, 13 },{ 275, 8 },{ 283, 8 },{ 291, 10 },{ 301, 8 },{ 309, 8 }, + { 317, 5 },{ 322, 8 },{ 330, 8 },{ 338, 8 },{ 346, 8 },{ 354, 8 },{ 362, 8 },{ 370, 8 },{ 378, 8 },{ 386, 8 },{ 394, 8 }, + { 402, 8 },{ 410, 8 },{ 418, 4 },{ 422, 8 },{ 430, 6 },{ 436, 8 },{ 444, 10 },{ 454, 8 },{ 462, 12 },{ 474, 8 },{ 482, 8 }, + { 490, 4 },{ 494, 8 },{ 502, 6 },{ 508, 8 },{ 516, 10 },{ 526, 8 },{ 534, 12 },{ 546, 8 },{ 554, 8 },{ 562, 8 },{ 570, 8 }, + { 578, 8 },{ 586, 8 },{ 594, 8 },{ 602, 8 },{ 610, 8 },{ 618, 8 },{ 626, 8 },{ 634, 8 },{ 642, 11 },{ 653, 8 },{ 661, 8 }, + { 669, 6 },{ 675, 8 },{ 683, 8 },{ 691, 3 },{ 694, 4 },{ 698, 8 },{ 706, 8 },{ 714, 8 },{ 722, 8 },{ 730, 8 },{ 738, 10 }, + { 748, 12 },{ 760, 13 },{ 773, 11 },{ 784, 8 },{ 792, 4 },{ 796, 8 },{ 804, 10 },{ 814, 6 },{ 820, 8 },{ 828, 8 },{ 836, 12 }, + { 848, 4 },{ 852, 8 },{ 860, 8 },{ 868, 8 },{ 876, 8 },{ 884, 10 },{ 894, 12 },{ 906, 12 },{ 918, 11 },{ 929, 11 },{ 940, 8 }, + { 948, 10 },{ 958, 12 },{ 970, 8 },{ 978, 12 },{ 990, 13 },{ 1003, 12 },{ 1015, 13 },{ 1028, 12 },{ 1040, 2 },{ 1042, 2 },{ 1044, 4 }, + { 1048, 5 },{ 1053, 3 },{ 1056, 4 },{ 1060, 4 },{ 1064, 6 },{ 1070, 6 },{ 1076, 7 },{ 1083, 4 },{ 1087, 6 },{ 1093, 4 },{ 1097, 4 }, + { 1101, 5 },{ 1106, 6 },{ 1112, 7 },{ 1119, 4 },{ 1123, 2 },{ 1125, 5 },{ 1130, 4 },{ 1134, 4 },{ 1138, 6 },{ 1144, 4 },{ 1148, 4 }, + { 1152, 6 },{ 1158, 6 },{ 1164, 6 },{ 1170, 6 },{ 1176, 6 },{ 1182, 2 },{ 1184, 5 },{ 1189, 4 },{ 1193, 6 },{ 1199, 6 },{ 1205, 4 }, + { 1209, 4 },{ 1213, 4 },{ 1217, 4 },{ 1221, 6 },{ 1227, 6 },{ 1233, 6 },{ 1239, 4 },{ 1243, 2 },{ 1245, 8 },{ 1253, 3 },{ 1256, 6 }, + { 1262, 7 },{ 1269, 7 },{ 1276, 4 },{ 1280, 4 },{ 1284, 5 },{ 1289, 5 },{ 1294, 4 },{ 1298, 4 },{ 1302, 6 },{ 1308, 6 },{ 1314, 4 }, + { 1318, 5 },{ 1323, 6 },{ 1329, 7 },{ 1336, 6 },{ 1342, 7 },{ 1349, 6 },{ 1355, 5 },{ 1360, 4 },{ 1364, 4 },{ 1368, 5 },{ 1373, 4 }, + { 1377, 4 },{ 1381, 6 },{ 1387, 2 },{ 1389, 4 },{ 1393, 6 },{ 1399, 6 },{ 1405, 6 },{ 1411, 5 },{ 1416, 6 },{ 1422, 2 },{ 1424, 4 }, + { 1428, 8 },{ 1436, 3 },{ 1439, 7 },{ 1446, 6 },{ 1452, 2 },{ 1454, 4 },{ 1458, 4 },{ 1462, 6 },{ 1468, 6 },{ 1474, 4 },{ 1478, 6 }, + { 1484, 6 },{ 1490, 4 },{ 1494, 4 },{ 1498, 6 },{ 1504, 4 },{ 1508, 6 },{ 1514, 4 },{ 1518, 6 },{ 1524, 6 },{ 1530, 3 },{ 1533, 7 }, + { 1540, 6 },{ 1546, 4 },{ 1550, 5 },{ 1555, 6 },{ 1561, 6 },{ 1567, 6 },{ 1573, 5 },{ 1578, 6 },{ 1584, 8 },{ 1592, 6 },{ 1598, 6 }, + { 1604, 8 }, + }; + static const int g_shapes1[][2] = + { + { 0, 16 } + }; + static const int g_shapes2[64][2] = + { + { 33, 96 },{ 63, 66 },{ 20, 109 },{ 22, 107 },{ 37, 92 },{ 7, 122 },{ 8, 121 },{ 23, 106 }, + { 38, 91 },{ 2, 127 },{ 9, 120 },{ 26, 103 },{ 3, 126 },{ 6, 123 },{ 1, 128 },{ 19, 110 }, + { 15, 114 },{ 124, 5 },{ 72, 57 },{ 115, 14 },{ 125, 4 },{ 70, 59 },{ 100, 29 },{ 60, 69 }, + { 116, 13 },{ 99, 30 },{ 78, 51 },{ 94, 35 },{ 104, 25 },{ 111, 18 },{ 71, 58 },{ 90, 39 }, + { 45, 84 },{ 16, 113 },{ 82, 47 },{ 95, 34 },{ 87, 42 },{ 83, 46 },{ 53, 76 },{ 48, 81 }, + { 68, 61 },{ 105, 24 },{ 98, 31 },{ 88, 41 },{ 75, 54 },{ 43, 86 },{ 52, 77 },{ 117, 12 }, + { 119, 10 },{ 118, 11 },{ 85, 44 },{ 101, 28 },{ 36, 93 },{ 55, 74 },{ 89, 40 },{ 79, 50 }, + { 56, 73 },{ 49, 80 },{ 64, 65 },{ 27, 102 },{ 32, 97 },{ 112, 17 },{ 67, 62 },{ 21, 108 }, + }; + static const int g_shapes3[64][3] = + { + { 148, 160, 240 },{ 132, 212, 205 },{ 136, 233, 187 },{ 175, 237, 143 },{ 6, 186, 232 },{ 33, 142, 232 },{ 131, 123, 142 },{ 131, 96, 186 }, + { 6, 171, 110 },{ 1, 18, 110 },{ 1, 146, 123 },{ 33, 195, 66 },{ 20, 51, 66 },{ 20, 178, 96 },{ 2, 177, 106 },{ 211, 4, 59 }, + { 8, 191, 91 },{ 230, 14, 29 },{ 1, 188, 234 },{ 151, 110, 168 },{ 20, 144, 238 },{ 137, 66, 206 },{ 173, 179, 232 },{ 209, 194, 186 }, + { 239, 165, 142 },{ 131, 152, 242 },{ 214, 54, 12 },{ 140, 219, 201 },{ 190, 150, 231 },{ 156, 135, 241 },{ 185, 227, 167 },{ 145, 210, 59 }, + { 138, 174, 106 },{ 189, 229, 14 },{ 176, 133, 106 },{ 78, 178, 195 },{ 111, 146, 171 },{ 216, 180, 196 },{ 217, 181, 193 },{ 184, 228, 166 }, + { 192, 225, 153 },{ 134, 141, 123 },{ 6, 222, 198 },{ 149, 183, 96 },{ 33, 226, 164 },{ 161, 215, 51 },{ 197, 221, 18 },{ 1, 223, 199 }, + { 154, 163, 110 },{ 20, 236, 169 },{ 157, 204, 66 },{ 1, 202, 220 },{ 20, 170, 235 },{ 203, 158, 66 },{ 162, 155, 110 },{ 6, 201, 218 }, + { 139, 135, 123 },{ 33, 167, 224 },{ 182, 150, 96 },{ 19, 200, 213 },{ 63, 207, 159 },{ 147, 172, 109 },{ 129, 130, 128 },{ 208, 14, 59 }, + }; + + static const int g_shapeList1[] = + { + 0, + }; + + static const int g_shapeList1Collapse[] = + { + 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, + }; + static const int g_shapeList2[] = + { + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, + 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, + 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, + 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, + 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, + 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, + 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, + 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, + 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, + 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, + 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, + 122, 123, 124, 125, 126, 127, 128, + }; + static const int g_shapeList2Collapse[] = + { + -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, + 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, + 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, + 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, + 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, + 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, + 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, + 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, + 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, + 120, 121, 122, 123, 124, 125, 126, 127, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, + }; + + static const int g_shapeList12[] = + { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, + 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, + 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, + 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, + 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, + 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, + 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, + 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, + 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, + 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, + 121, 122, 123, 124, 125, 126, 127, 128, + }; + + static const int g_shapeList12Collapse[] = + { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, + 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, + 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, + 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, + 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, + 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, + 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, + 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, + 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, + 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, + 121, 122, 123, 124, 125, 126, 127, 128, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, + }; + + static const int g_shapeList3[] = + { + 1, 2, 4, 6, 8, 12, 14, 18, 19, 20, 29, + 33, 51, 54, 59, 63, 66, 78, 91, 96, 106, 109, + 110, 111, 123, 128, 129, 130, 131, 132, 133, 134, 135, + 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, + 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, + 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, + 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, + 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, + 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, + 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, + 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, + 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, + 235, 236, 237, 238, 239, 240, 241, 242, + }; + + static const int g_shapeList3Collapse[] = + { + -1, 0, 1, -1, 2, -1, 3, -1, 4, -1, -1, + -1, 5, -1, 6, -1, -1, -1, 7, 8, 9, -1, + -1, -1, -1, -1, -1, -1, -1, 10, -1, -1, -1, + 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 12, -1, -1, 13, + -1, -1, -1, -1, 14, -1, -1, -1, 15, -1, -1, + 16, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 17, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 18, -1, -1, -1, -1, 19, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 20, -1, -1, 21, + 22, 23, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 24, -1, -1, -1, -1, 25, 26, 27, 28, + 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, + 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, + 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, + 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, + 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, + 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, + 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, + 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, + 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, + 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, + 139, + }; + + static const int g_shapeList3Short[] = + { + 1, 2, 4, 6, 18, 20, 33, 51, 59, 66, 96, + 106, 110, 123, 131, 132, 136, 142, 143, 146, 148, 160, + 171, 175, 177, 178, 186, 187, 195, 205, 211, 212, 232, + 233, 237, 240, + }; + + static const int g_shapeList3ShortCollapse[] = + { + -1, 0, 1, -1, 2, -1, 3, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 4, -1, 5, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 7, -1, -1, -1, + -1, -1, -1, -1, 8, -1, -1, -1, -1, -1, -1, + 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 10, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 11, -1, -1, -1, + 12, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 13, -1, -1, -1, -1, -1, -1, -1, 14, + 15, -1, -1, -1, 16, -1, -1, -1, -1, -1, 17, + 18, -1, -1, 19, -1, 20, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 21, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 22, -1, -1, -1, 23, + -1, 24, 25, -1, -1, -1, -1, -1, -1, -1, 26, + 27, -1, -1, -1, -1, -1, -1, -1, 28, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 29, -1, -1, -1, + -1, -1, 30, 31, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 32, 33, -1, -1, -1, 34, -1, -1, 35, -1, + -1, + }; + + static const int g_shapeListAll[] = + { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, + 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, + 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, + 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, + 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, + 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, + 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, + 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, + 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, + 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, + 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, + 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, + 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, + 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, + 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, + 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, + 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, + 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, + 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, + 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, + 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, + 242, + }; + + static const int g_numShapes1 = sizeof(g_shapeList1) / sizeof(g_shapeList1[0]); + static const int g_numShapes2 = sizeof(g_shapeList2) / sizeof(g_shapeList2[0]); + static const int g_numShapes12 = sizeof(g_shapeList12) / sizeof(g_shapeList12[0]); + static const int g_numShapes3 = sizeof(g_shapeList3) / sizeof(g_shapeList3[0]); + static const int g_numShapes3Short = sizeof(g_shapeList3Short) / sizeof(g_shapeList3Short[0]); + static const int g_numShapesAll = sizeof(g_shapeListAll) / sizeof(g_shapeListAll[0]); + static const int g_numFragments = sizeof(g_fragments) / sizeof(g_fragments[0]); + + static const int g_maxFragmentsPerMode = (g_numShapes2 > g_numShapes3) ? g_numShapes2 : g_numShapes3; + } + + namespace BC6HData + { + enum EField + { + NA, // N/A + M, // Mode + D, // Shape + RW, + RX, + RY, + RZ, + GW, + GX, + GY, + GZ, + BW, + BX, + BY, + BZ, + }; + + struct ModeDescriptor + { + EField m_eField; + uint8_t m_uBit; + }; + + const ModeDescriptor g_modeDescriptors[14][82] = + { + { // Mode 1 (0x00) - 10 5 5 5 + { M, 0 },{ M, 1 },{ GY, 4 },{ BY, 4 },{ BZ, 4 },{ RW, 0 },{ RW, 1 },{ RW, 2 },{ RW, 3 },{ RW, 4 }, + { RW, 5 },{ RW, 6 },{ RW, 7 },{ RW, 8 },{ RW, 9 },{ GW, 0 },{ GW, 1 },{ GW, 2 },{ GW, 3 },{ GW, 4 }, + { GW, 5 },{ GW, 6 },{ GW, 7 },{ GW, 8 },{ GW, 9 },{ BW, 0 },{ BW, 1 },{ BW, 2 },{ BW, 3 },{ BW, 4 }, + { BW, 5 },{ BW, 6 },{ BW, 7 },{ BW, 8 },{ BW, 9 },{ RX, 0 },{ RX, 1 },{ RX, 2 },{ RX, 3 },{ RX, 4 }, + { GZ, 4 },{ GY, 0 },{ GY, 1 },{ GY, 2 },{ GY, 3 },{ GX, 0 },{ GX, 1 },{ GX, 2 },{ GX, 3 },{ GX, 4 }, + { BZ, 0 },{ GZ, 0 },{ GZ, 1 },{ GZ, 2 },{ GZ, 3 },{ BX, 0 },{ BX, 1 },{ BX, 2 },{ BX, 3 },{ BX, 4 }, + { BZ, 1 },{ BY, 0 },{ BY, 1 },{ BY, 2 },{ BY, 3 },{ RY, 0 },{ RY, 1 },{ RY, 2 },{ RY, 3 },{ RY, 4 }, + { BZ, 2 },{ RZ, 0 },{ RZ, 1 },{ RZ, 2 },{ RZ, 3 },{ RZ, 4 },{ BZ, 3 },{ D, 0 },{ D, 1 },{ D, 2 }, + { D, 3 },{ D, 4 }, + }, + + { // Mode 2 (0x01) - 7 6 6 6 + { M, 0 },{ M, 1 },{ GY, 5 },{ GZ, 4 },{ GZ, 5 },{ RW, 0 },{ RW, 1 },{ RW, 2 },{ RW, 3 },{ RW, 4 }, + { RW, 5 },{ RW, 6 },{ BZ, 0 },{ BZ, 1 },{ BY, 4 },{ GW, 0 },{ GW, 1 },{ GW, 2 },{ GW, 3 },{ GW, 4 }, + { GW, 5 },{ GW, 6 },{ BY, 5 },{ BZ, 2 },{ GY, 4 },{ BW, 0 },{ BW, 1 },{ BW, 2 },{ BW, 3 },{ BW, 4 }, + { BW, 5 },{ BW, 6 },{ BZ, 3 },{ BZ, 5 },{ BZ, 4 },{ RX, 0 },{ RX, 1 },{ RX, 2 },{ RX, 3 },{ RX, 4 }, + { RX, 5 },{ GY, 0 },{ GY, 1 },{ GY, 2 },{ GY, 3 },{ GX, 0 },{ GX, 1 },{ GX, 2 },{ GX, 3 },{ GX, 4 }, + { GX, 5 },{ GZ, 0 },{ GZ, 1 },{ GZ, 2 },{ GZ, 3 },{ BX, 0 },{ BX, 1 },{ BX, 2 },{ BX, 3 },{ BX, 4 }, + { BX, 5 },{ BY, 0 },{ BY, 1 },{ BY, 2 },{ BY, 3 },{ RY, 0 },{ RY, 1 },{ RY, 2 },{ RY, 3 },{ RY, 4 }, + { RY, 5 },{ RZ, 0 },{ RZ, 1 },{ RZ, 2 },{ RZ, 3 },{ RZ, 4 },{ RZ, 5 },{ D, 0 },{ D, 1 },{ D, 2 }, + { D, 3 },{ D, 4 }, + }, + + { // Mode 3 (0x02) - 11 5 4 4 + { M, 0 },{ M, 1 },{ M, 2 },{ M, 3 },{ M, 4 },{ RW, 0 },{ RW, 1 },{ RW, 2 },{ RW, 3 },{ RW, 4 }, + { RW, 5 },{ RW, 6 },{ RW, 7 },{ RW, 8 },{ RW, 9 },{ GW, 0 },{ GW, 1 },{ GW, 2 },{ GW, 3 },{ GW, 4 }, + { GW, 5 },{ GW, 6 },{ GW, 7 },{ GW, 8 },{ GW, 9 },{ BW, 0 },{ BW, 1 },{ BW, 2 },{ BW, 3 },{ BW, 4 }, + { BW, 5 },{ BW, 6 },{ BW, 7 },{ BW, 8 },{ BW, 9 },{ RX, 0 },{ RX, 1 },{ RX, 2 },{ RX, 3 },{ RX, 4 }, + { RW,10 },{ GY, 0 },{ GY, 1 },{ GY, 2 },{ GY, 3 },{ GX, 0 },{ GX, 1 },{ GX, 2 },{ GX, 3 },{ GW,10 }, + { BZ, 0 },{ GZ, 0 },{ GZ, 1 },{ GZ, 2 },{ GZ, 3 },{ BX, 0 },{ BX, 1 },{ BX, 2 },{ BX, 3 },{ BW,10 }, + { BZ, 1 },{ BY, 0 },{ BY, 1 },{ BY, 2 },{ BY, 3 },{ RY, 0 },{ RY, 1 },{ RY, 2 },{ RY, 3 },{ RY, 4 }, + { BZ, 2 },{ RZ, 0 },{ RZ, 1 },{ RZ, 2 },{ RZ, 3 },{ RZ, 4 },{ BZ, 3 },{ D, 0 },{ D, 1 },{ D, 2 }, + { D, 3 },{ D, 4 }, + }, + + { // Mode 4 (0x06) - 11 4 5 4 + { M, 0 },{ M, 1 },{ M, 2 },{ M, 3 },{ M, 4 },{ RW, 0 },{ RW, 1 },{ RW, 2 },{ RW, 3 },{ RW, 4 }, + { RW, 5 },{ RW, 6 },{ RW, 7 },{ RW, 8 },{ RW, 9 },{ GW, 0 },{ GW, 1 },{ GW, 2 },{ GW, 3 },{ GW, 4 }, + { GW, 5 },{ GW, 6 },{ GW, 7 },{ GW, 8 },{ GW, 9 },{ BW, 0 },{ BW, 1 },{ BW, 2 },{ BW, 3 },{ BW, 4 }, + { BW, 5 },{ BW, 6 },{ BW, 7 },{ BW, 8 },{ BW, 9 },{ RX, 0 },{ RX, 1 },{ RX, 2 },{ RX, 3 },{ RW,10 }, + { GZ, 4 },{ GY, 0 },{ GY, 1 },{ GY, 2 },{ GY, 3 },{ GX, 0 },{ GX, 1 },{ GX, 2 },{ GX, 3 },{ GX, 4 }, + { GW,10 },{ GZ, 0 },{ GZ, 1 },{ GZ, 2 },{ GZ, 3 },{ BX, 0 },{ BX, 1 },{ BX, 2 },{ BX, 3 },{ BW,10 }, + { BZ, 1 },{ BY, 0 },{ BY, 1 },{ BY, 2 },{ BY, 3 },{ RY, 0 },{ RY, 1 },{ RY, 2 },{ RY, 3 },{ BZ, 0 }, + { BZ, 2 },{ RZ, 0 },{ RZ, 1 },{ RZ, 2 },{ RZ, 3 },{ GY, 4 },{ BZ, 3 },{ D, 0 },{ D, 1 },{ D, 2 }, + { D, 3 },{ D, 4 }, + }, + + { // Mode 5 (0x0a) - 11 4 4 5 + { M, 0 },{ M, 1 },{ M, 2 },{ M, 3 },{ M, 4 },{ RW, 0 },{ RW, 1 },{ RW, 2 },{ RW, 3 },{ RW, 4 }, + { RW, 5 },{ RW, 6 },{ RW, 7 },{ RW, 8 },{ RW, 9 },{ GW, 0 },{ GW, 1 },{ GW, 2 },{ GW, 3 },{ GW, 4 }, + { GW, 5 },{ GW, 6 },{ GW, 7 },{ GW, 8 },{ GW, 9 },{ BW, 0 },{ BW, 1 },{ BW, 2 },{ BW, 3 },{ BW, 4 }, + { BW, 5 },{ BW, 6 },{ BW, 7 },{ BW, 8 },{ BW, 9 },{ RX, 0 },{ RX, 1 },{ RX, 2 },{ RX, 3 },{ RW,10 }, + { BY, 4 },{ GY, 0 },{ GY, 1 },{ GY, 2 },{ GY, 3 },{ GX, 0 },{ GX, 1 },{ GX, 2 },{ GX, 3 },{ GW,10 }, + { BZ, 0 },{ GZ, 0 },{ GZ, 1 },{ GZ, 2 },{ GZ, 3 },{ BX, 0 },{ BX, 1 },{ BX, 2 },{ BX, 3 },{ BX, 4 }, + { BW,10 },{ BY, 0 },{ BY, 1 },{ BY, 2 },{ BY, 3 },{ RY, 0 },{ RY, 1 },{ RY, 2 },{ RY, 3 },{ BZ, 1 }, + { BZ, 2 },{ RZ, 0 },{ RZ, 1 },{ RZ, 2 },{ RZ, 3 },{ BZ, 4 },{ BZ, 3 },{ D, 0 },{ D, 1 },{ D, 2 }, + { D, 3 },{ D, 4 }, + }, + + { // Mode 6 (0x0e) - 9 5 5 5 + { M, 0 },{ M, 1 },{ M, 2 },{ M, 3 },{ M, 4 },{ RW, 0 },{ RW, 1 },{ RW, 2 },{ RW, 3 },{ RW, 4 }, + { RW, 5 },{ RW, 6 },{ RW, 7 },{ RW, 8 },{ BY, 4 },{ GW, 0 },{ GW, 1 },{ GW, 2 },{ GW, 3 },{ GW, 4 }, + { GW, 5 },{ GW, 6 },{ GW, 7 },{ GW, 8 },{ GY, 4 },{ BW, 0 },{ BW, 1 },{ BW, 2 },{ BW, 3 },{ BW, 4 }, + { BW, 5 },{ BW, 6 },{ BW, 7 },{ BW, 8 },{ BZ, 4 },{ RX, 0 },{ RX, 1 },{ RX, 2 },{ RX, 3 },{ RX, 4 }, + { GZ, 4 },{ GY, 0 },{ GY, 1 },{ GY, 2 },{ GY, 3 },{ GX, 0 },{ GX, 1 },{ GX, 2 },{ GX, 3 },{ GX, 4 }, + { BZ, 0 },{ GZ, 0 },{ GZ, 1 },{ GZ, 2 },{ GZ, 3 },{ BX, 0 },{ BX, 1 },{ BX, 2 },{ BX, 3 },{ BX, 4 }, + { BZ, 1 },{ BY, 0 },{ BY, 1 },{ BY, 2 },{ BY, 3 },{ RY, 0 },{ RY, 1 },{ RY, 2 },{ RY, 3 },{ RY, 4 }, + { BZ, 2 },{ RZ, 0 },{ RZ, 1 },{ RZ, 2 },{ RZ, 3 },{ RZ, 4 },{ BZ, 3 },{ D, 0 },{ D, 1 },{ D, 2 }, + { D, 3 },{ D, 4 }, + }, + + { // Mode 7 (0x12) - 8 6 5 5 + { M, 0 },{ M, 1 },{ M, 2 },{ M, 3 },{ M, 4 },{ RW, 0 },{ RW, 1 },{ RW, 2 },{ RW, 3 },{ RW, 4 }, + { RW, 5 },{ RW, 6 },{ RW, 7 },{ GZ, 4 },{ BY, 4 },{ GW, 0 },{ GW, 1 },{ GW, 2 },{ GW, 3 },{ GW, 4 }, + { GW, 5 },{ GW, 6 },{ GW, 7 },{ BZ, 2 },{ GY, 4 },{ BW, 0 },{ BW, 1 },{ BW, 2 },{ BW, 3 },{ BW, 4 }, + { BW, 5 },{ BW, 6 },{ BW, 7 },{ BZ, 3 },{ BZ, 4 },{ RX, 0 },{ RX, 1 },{ RX, 2 },{ RX, 3 },{ RX, 4 }, + { RX, 5 },{ GY, 0 },{ GY, 1 },{ GY, 2 },{ GY, 3 },{ GX, 0 },{ GX, 1 },{ GX, 2 },{ GX, 3 },{ GX, 4 }, + { BZ, 0 },{ GZ, 0 },{ GZ, 1 },{ GZ, 2 },{ GZ, 3 },{ BX, 0 },{ BX, 1 },{ BX, 2 },{ BX, 3 },{ BX, 4 }, + { BZ, 1 },{ BY, 0 },{ BY, 1 },{ BY, 2 },{ BY, 3 },{ RY, 0 },{ RY, 1 },{ RY, 2 },{ RY, 3 },{ RY, 4 }, + { RY, 5 },{ RZ, 0 },{ RZ, 1 },{ RZ, 2 },{ RZ, 3 },{ RZ, 4 },{ RZ, 5 },{ D, 0 },{ D, 1 },{ D, 2 }, + { D, 3 },{ D, 4 }, + }, + + { // Mode 8 (0x16) - 8 5 6 5 + { M, 0 },{ M, 1 },{ M, 2 },{ M, 3 },{ M, 4 },{ RW, 0 },{ RW, 1 },{ RW, 2 },{ RW, 3 },{ RW, 4 }, + { RW, 5 },{ RW, 6 },{ RW, 7 },{ BZ, 0 },{ BY, 4 },{ GW, 0 },{ GW, 1 },{ GW, 2 },{ GW, 3 },{ GW, 4 }, + { GW, 5 },{ GW, 6 },{ GW, 7 },{ GY, 5 },{ GY, 4 },{ BW, 0 },{ BW, 1 },{ BW, 2 },{ BW, 3 },{ BW, 4 }, + { BW, 5 },{ BW, 6 },{ BW, 7 },{ GZ, 5 },{ BZ, 4 },{ RX, 0 },{ RX, 1 },{ RX, 2 },{ RX, 3 },{ RX, 4 }, + { GZ, 4 },{ GY, 0 },{ GY, 1 },{ GY, 2 },{ GY, 3 },{ GX, 0 },{ GX, 1 },{ GX, 2 },{ GX, 3 },{ GX, 4 }, + { GX, 5 },{ GZ, 0 },{ GZ, 1 },{ GZ, 2 },{ GZ, 3 },{ BX, 0 },{ BX, 1 },{ BX, 2 },{ BX, 3 },{ BX, 4 }, + { BZ, 1 },{ BY, 0 },{ BY, 1 },{ BY, 2 },{ BY, 3 },{ RY, 0 },{ RY, 1 },{ RY, 2 },{ RY, 3 },{ RY, 4 }, + { BZ, 2 },{ RZ, 0 },{ RZ, 1 },{ RZ, 2 },{ RZ, 3 },{ RZ, 4 },{ BZ, 3 },{ D, 0 },{ D, 1 },{ D, 2 }, + { D, 3 },{ D, 4 }, + }, + + { // Mode 9 (0x1a) - 8 5 5 6 + { M, 0 },{ M, 1 },{ M, 2 },{ M, 3 },{ M, 4 },{ RW, 0 },{ RW, 1 },{ RW, 2 },{ RW, 3 },{ RW, 4 }, + { RW, 5 },{ RW, 6 },{ RW, 7 },{ BZ, 1 },{ BY, 4 },{ GW, 0 },{ GW, 1 },{ GW, 2 },{ GW, 3 },{ GW, 4 }, + { GW, 5 },{ GW, 6 },{ GW, 7 },{ BY, 5 },{ GY, 4 },{ BW, 0 },{ BW, 1 },{ BW, 2 },{ BW, 3 },{ BW, 4 }, + { BW, 5 },{ BW, 6 },{ BW, 7 },{ BZ, 5 },{ BZ, 4 },{ RX, 0 },{ RX, 1 },{ RX, 2 },{ RX, 3 },{ RX, 4 }, + { GZ, 4 },{ GY, 0 },{ GY, 1 },{ GY, 2 },{ GY, 3 },{ GX, 0 },{ GX, 1 },{ GX, 2 },{ GX, 3 },{ GX, 4 }, + { BZ, 0 },{ GZ, 0 },{ GZ, 1 },{ GZ, 2 },{ GZ, 3 },{ BX, 0 },{ BX, 1 },{ BX, 2 },{ BX, 3 },{ BX, 4 }, + { BX, 5 },{ BY, 0 },{ BY, 1 },{ BY, 2 },{ BY, 3 },{ RY, 0 },{ RY, 1 },{ RY, 2 },{ RY, 3 },{ RY, 4 }, + { BZ, 2 },{ RZ, 0 },{ RZ, 1 },{ RZ, 2 },{ RZ, 3 },{ RZ, 4 },{ BZ, 3 },{ D, 0 },{ D, 1 },{ D, 2 }, + { D, 3 },{ D, 4 }, + }, + + { // Mode 10 (0x1e) - 6 6 6 6 + { M, 0 },{ M, 1 },{ M, 2 },{ M, 3 },{ M, 4 },{ RW, 0 },{ RW, 1 },{ RW, 2 },{ RW, 3 },{ RW, 4 }, + { RW, 5 },{ GZ, 4 },{ BZ, 0 },{ BZ, 1 },{ BY, 4 },{ GW, 0 },{ GW, 1 },{ GW, 2 },{ GW, 3 },{ GW, 4 }, + { GW, 5 },{ GY, 5 },{ BY, 5 },{ BZ, 2 },{ GY, 4 },{ BW, 0 },{ BW, 1 },{ BW, 2 },{ BW, 3 },{ BW, 4 }, + { BW, 5 },{ GZ, 5 },{ BZ, 3 },{ BZ, 5 },{ BZ, 4 },{ RX, 0 },{ RX, 1 },{ RX, 2 },{ RX, 3 },{ RX, 4 }, + { RX, 5 },{ GY, 0 },{ GY, 1 },{ GY, 2 },{ GY, 3 },{ GX, 0 },{ GX, 1 },{ GX, 2 },{ GX, 3 },{ GX, 4 }, + { GX, 5 },{ GZ, 0 },{ GZ, 1 },{ GZ, 2 },{ GZ, 3 },{ BX, 0 },{ BX, 1 },{ BX, 2 },{ BX, 3 },{ BX, 4 }, + { BX, 5 },{ BY, 0 },{ BY, 1 },{ BY, 2 },{ BY, 3 },{ RY, 0 },{ RY, 1 },{ RY, 2 },{ RY, 3 },{ RY, 4 }, + { RY, 5 },{ RZ, 0 },{ RZ, 1 },{ RZ, 2 },{ RZ, 3 },{ RZ, 4 },{ RZ, 5 },{ D, 0 },{ D, 1 },{ D, 2 }, + { D, 3 },{ D, 4 }, + }, + + { // Mode 11 (0x03) - 10 10 + { M, 0 },{ M, 1 },{ M, 2 },{ M, 3 },{ M, 4 },{ RW, 0 },{ RW, 1 },{ RW, 2 },{ RW, 3 },{ RW, 4 }, + { RW, 5 },{ RW, 6 },{ RW, 7 },{ RW, 8 },{ RW, 9 },{ GW, 0 },{ GW, 1 },{ GW, 2 },{ GW, 3 },{ GW, 4 }, + { GW, 5 },{ GW, 6 },{ GW, 7 },{ GW, 8 },{ GW, 9 },{ BW, 0 },{ BW, 1 },{ BW, 2 },{ BW, 3 },{ BW, 4 }, + { BW, 5 },{ BW, 6 },{ BW, 7 },{ BW, 8 },{ BW, 9 },{ RX, 0 },{ RX, 1 },{ RX, 2 },{ RX, 3 },{ RX, 4 }, + { RX, 5 },{ RX, 6 },{ RX, 7 },{ RX, 8 },{ RX, 9 },{ GX, 0 },{ GX, 1 },{ GX, 2 },{ GX, 3 },{ GX, 4 }, + { GX, 5 },{ GX, 6 },{ GX, 7 },{ GX, 8 },{ GX, 9 },{ BX, 0 },{ BX, 1 },{ BX, 2 },{ BX, 3 },{ BX, 4 }, + { BX, 5 },{ BX, 6 },{ BX, 7 },{ BX, 8 },{ BX, 9 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 }, + { NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 }, + { NA, 0 },{ NA, 0 }, + }, + + { // Mode 12 (0x07) - 11 9 + { M, 0 },{ M, 1 },{ M, 2 },{ M, 3 },{ M, 4 },{ RW, 0 },{ RW, 1 },{ RW, 2 },{ RW, 3 },{ RW, 4 }, + { RW, 5 },{ RW, 6 },{ RW, 7 },{ RW, 8 },{ RW, 9 },{ GW, 0 },{ GW, 1 },{ GW, 2 },{ GW, 3 },{ GW, 4 }, + { GW, 5 },{ GW, 6 },{ GW, 7 },{ GW, 8 },{ GW, 9 },{ BW, 0 },{ BW, 1 },{ BW, 2 },{ BW, 3 },{ BW, 4 }, + { BW, 5 },{ BW, 6 },{ BW, 7 },{ BW, 8 },{ BW, 9 },{ RX, 0 },{ RX, 1 },{ RX, 2 },{ RX, 3 },{ RX, 4 }, + { RX, 5 },{ RX, 6 },{ RX, 7 },{ RX, 8 },{ RW,10 },{ GX, 0 },{ GX, 1 },{ GX, 2 },{ GX, 3 },{ GX, 4 }, + { GX, 5 },{ GX, 6 },{ GX, 7 },{ GX, 8 },{ GW,10 },{ BX, 0 },{ BX, 1 },{ BX, 2 },{ BX, 3 },{ BX, 4 }, + { BX, 5 },{ BX, 6 },{ BX, 7 },{ BX, 8 },{ BW,10 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 }, + { NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 }, + { NA, 0 },{ NA, 0 }, + }, + + { // Mode 13 (0x0b) - 12 8 + { M, 0 },{ M, 1 },{ M, 2 },{ M, 3 },{ M, 4 },{ RW, 0 },{ RW, 1 },{ RW, 2 },{ RW, 3 },{ RW, 4 }, + { RW, 5 },{ RW, 6 },{ RW, 7 },{ RW, 8 },{ RW, 9 },{ GW, 0 },{ GW, 1 },{ GW, 2 },{ GW, 3 },{ GW, 4 }, + { GW, 5 },{ GW, 6 },{ GW, 7 },{ GW, 8 },{ GW, 9 },{ BW, 0 },{ BW, 1 },{ BW, 2 },{ BW, 3 },{ BW, 4 }, + { BW, 5 },{ BW, 6 },{ BW, 7 },{ BW, 8 },{ BW, 9 },{ RX, 0 },{ RX, 1 },{ RX, 2 },{ RX, 3 },{ RX, 4 }, + { RX, 5 },{ RX, 6 },{ RX, 7 },{ RW,11 },{ RW,10 },{ GX, 0 },{ GX, 1 },{ GX, 2 },{ GX, 3 },{ GX, 4 }, + { GX, 5 },{ GX, 6 },{ GX, 7 },{ GW,11 },{ GW,10 },{ BX, 0 },{ BX, 1 },{ BX, 2 },{ BX, 3 },{ BX, 4 }, + { BX, 5 },{ BX, 6 },{ BX, 7 },{ BW,11 },{ BW,10 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 }, + { NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 }, + { NA, 0 },{ NA, 0 }, + }, + + { // Mode 14 (0x0f) - 16 4 + { M, 0 },{ M, 1 },{ M, 2 },{ M, 3 },{ M, 4 },{ RW, 0 },{ RW, 1 },{ RW, 2 },{ RW, 3 },{ RW, 4 }, + { RW, 5 },{ RW, 6 },{ RW, 7 },{ RW, 8 },{ RW, 9 },{ GW, 0 },{ GW, 1 },{ GW, 2 },{ GW, 3 },{ GW, 4 }, + { GW, 5 },{ GW, 6 },{ GW, 7 },{ GW, 8 },{ GW, 9 },{ BW, 0 },{ BW, 1 },{ BW, 2 },{ BW, 3 },{ BW, 4 }, + { BW, 5 },{ BW, 6 },{ BW, 7 },{ BW, 8 },{ BW, 9 },{ RX, 0 },{ RX, 1 },{ RX, 2 },{ RX, 3 },{ RW,15 }, + { RW,14 },{ RW,13 },{ RW,12 },{ RW,11 },{ RW,10 },{ GX, 0 },{ GX, 1 },{ GX, 2 },{ GX, 3 },{ GW,15 }, + { GW,14 },{ GW,13 },{ GW,12 },{ GW,11 },{ GW,10 },{ BX, 0 },{ BX, 1 },{ BX, 2 },{ BX, 3 },{ BW,15 }, + { BW,14 },{ BW,13 },{ BW,12 },{ BW,11 },{ BW,10 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 }, + { NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 }, + { NA, 0 },{ NA, 0 }, + }, + }; + } + + struct PackingVector + { + uint32_t m_vector[4]; + int m_offset; + + void Init() + { + for (int i = 0; i < 4; i++) + m_vector[i] = 0; + + m_offset = 0; + } + + inline void Pack(ParallelMath::ScalarUInt16 value, int bits) + { + int vOffset = m_offset >> 5; + int bitOffset = m_offset & 0x1f; + + m_vector[vOffset] |= (static_cast<uint32_t>(value) << bitOffset) & static_cast<uint32_t>(0xffffffff); + + int overflowBits = bitOffset + bits - 32; + if (overflowBits > 0) + m_vector[vOffset + 1] |= (static_cast<uint32_t>(value) >> (bits - overflowBits)); + + m_offset += bits; + } + + inline void Flush(uint8_t* output) + { + assert(m_offset == 128); + + for (int v = 0; v < 4; v++) + { + uint32_t chunk = m_vector[v]; + for (int b = 0; b < 4; b++) + output[v * 4 + b] = static_cast<uint8_t>((chunk >> (b * 8)) & 0xff); + } + } + }; + + + struct UnpackingVector + { + uint32_t m_vector[4]; + + void Init(const uint8_t *bytes) + { + for (int i = 0; i < 4; i++) + m_vector[i] = 0; + + for (int b = 0; b < 16; b++) + m_vector[b / 4] |= (bytes[b] << ((b % 4) * 8)); + } + + inline ParallelMath::ScalarUInt16 Unpack(int bits) + { + uint32_t bitMask = (1 << bits) - 1; + + ParallelMath::ScalarUInt16 result = static_cast<ParallelMath::ScalarUInt16>(m_vector[0] & bitMask); + + for (int i = 0; i < 4; i++) + { + m_vector[i] >>= bits; + if (i != 3) + m_vector[i] |= (m_vector[i + 1] & bitMask) << (32 - bits); + } + + return result; + } + }; + + void ComputeTweakFactors(int tweak, int range, float *outFactors) + { + int totalUnits = range - 1; + int minOutsideUnits = ((tweak >> 1) & 1); + int maxOutsideUnits = (tweak & 1); + int insideUnits = totalUnits - minOutsideUnits - maxOutsideUnits; + + outFactors[0] = -static_cast<float>(minOutsideUnits) / static_cast<float>(insideUnits); + outFactors[1] = static_cast<float>(maxOutsideUnits) / static_cast<float>(insideUnits) + 1.0f; + } + + ParallelMath::Float ScaleHDRValue(const ParallelMath::Float &v, bool isSigned) + { + if (isSigned) + { + ParallelMath::Float offset = ParallelMath::Select(ParallelMath::Less(v, ParallelMath::MakeFloatZero()), ParallelMath::MakeFloat(-30.0f), ParallelMath::MakeFloat(30.0f)); + return (v * 32.0f + offset) / 31.0f; + } + else + return (v * 64.0f + 30.0f) / 31.0f; + } + + ParallelMath::SInt16 UnscaleHDRValueSigned(const ParallelMath::SInt16 &v) + { +#ifdef CVTT_ENABLE_ASSERTS + for (int i = 0; i < ParallelMath::ParallelSize; i++) + assert(ParallelMath::Extract(v, i) != -32768) +#endif + + ParallelMath::Int16CompFlag negative = ParallelMath::Less(v, ParallelMath::MakeSInt16(0)); + ParallelMath::UInt15 absComp = ParallelMath::LosslessCast<ParallelMath::UInt15>::Cast(ParallelMath::Select(negative, ParallelMath::SInt16(ParallelMath::MakeSInt16(0) - v), v)); + + ParallelMath::UInt31 multiplied = ParallelMath::XMultiply(absComp, ParallelMath::MakeUInt15(31)); + ParallelMath::UInt31 shifted = ParallelMath::RightShift(multiplied, 5); + ParallelMath::UInt15 absCompScaled = ParallelMath::ToUInt15(shifted); + ParallelMath::SInt16 signBits = ParallelMath::SelectOrZero(negative, ParallelMath::MakeSInt16(-32768)); + + return ParallelMath::LosslessCast<ParallelMath::SInt16>::Cast(absCompScaled) | signBits; + } + + ParallelMath::UInt15 UnscaleHDRValueUnsigned(const ParallelMath::UInt16 &v) + { + return ParallelMath::ToUInt15(ParallelMath::RightShift(ParallelMath::XMultiply(v, ParallelMath::MakeUInt15(31)), 6)); + } + + void UnscaleHDREndpoints(const ParallelMath::AInt16 inEP[2][3], ParallelMath::AInt16 outEP[2][3], bool isSigned) + { + for (int epi = 0; epi < 2; epi++) + { + for (int ch = 0; ch < 3; ch++) + { + if (isSigned) + outEP[epi][ch] = ParallelMath::LosslessCast<ParallelMath::AInt16>::Cast(UnscaleHDRValueSigned(ParallelMath::LosslessCast<ParallelMath::SInt16>::Cast(inEP[epi][ch]))); + else + outEP[epi][ch] = ParallelMath::LosslessCast<ParallelMath::AInt16>::Cast(UnscaleHDRValueUnsigned(ParallelMath::LosslessCast<ParallelMath::UInt16>::Cast(inEP[epi][ch]))); + } + } + } + + template<int TVectorSize> + class UnfinishedEndpoints + { + public: + typedef ParallelMath::Float MFloat; + typedef ParallelMath::UInt16 MUInt16; + typedef ParallelMath::UInt15 MUInt15; + typedef ParallelMath::SInt16 MSInt16; + typedef ParallelMath::SInt32 MSInt32; + + UnfinishedEndpoints() + { + } + + UnfinishedEndpoints(const MFloat *base, const MFloat *offset) + { + for (int ch = 0; ch < TVectorSize; ch++) + m_base[ch] = base[ch]; + for (int ch = 0; ch < TVectorSize; ch++) + m_offset[ch] = offset[ch]; + } + + UnfinishedEndpoints(const UnfinishedEndpoints& other) + { + for (int ch = 0; ch < TVectorSize; ch++) + m_base[ch] = other.m_base[ch]; + for (int ch = 0; ch < TVectorSize; ch++) + m_offset[ch] = other.m_offset[ch]; + } + + void FinishHDRUnsigned(int tweak, int range, MSInt16 *outEP0, MSInt16 *outEP1, ParallelMath::RoundTowardNearestForScope *roundingMode) + { + float tweakFactors[2]; + ComputeTweakFactors(tweak, range, tweakFactors); + + for (int ch = 0; ch < TVectorSize; ch++) + { + MUInt15 channelEPs[2]; + for (int epi = 0; epi < 2; epi++) + { + MFloat f = ParallelMath::Clamp(m_base[ch] + m_offset[ch] * tweakFactors[epi], 0.0f, 31743.0f); + channelEPs[epi] = ParallelMath::RoundAndConvertToU15(f, roundingMode); + } + + outEP0[ch] = ParallelMath::LosslessCast<MSInt16>::Cast(channelEPs[0]); + outEP1[ch] = ParallelMath::LosslessCast<MSInt16>::Cast(channelEPs[1]); + } + } + + void FinishHDRSigned(int tweak, int range, MSInt16* outEP0, MSInt16* outEP1, ParallelMath::RoundTowardNearestForScope* roundingMode) + { + float tweakFactors[2]; + ComputeTweakFactors(tweak, range, tweakFactors); + + for (int ch = 0; ch < TVectorSize; ch++) + { + MSInt16 channelEPs[2]; + for (int epi = 0; epi < 2; epi++) + { + MFloat f = ParallelMath::Clamp(m_base[ch] + m_offset[ch] * tweakFactors[epi], -31743.0f, 31743.0f); + channelEPs[epi] = ParallelMath::RoundAndConvertToS16(f, roundingMode); + } + + outEP0[ch] = channelEPs[0]; + outEP1[ch] = channelEPs[1]; + } + } + + void FinishLDR(int tweak, int range, MUInt15* outEP0, MUInt15* outEP1) + { + ParallelMath::RoundTowardNearestForScope roundingMode; + + float tweakFactors[2]; + ComputeTweakFactors(tweak, range, tweakFactors); + + for (int ch = 0; ch < TVectorSize; ch++) + { + MFloat ep0f = ParallelMath::Clamp(m_base[ch] + m_offset[ch] * tweakFactors[0], 0.0f, 255.0f); + MFloat ep1f = ParallelMath::Clamp(m_base[ch] + m_offset[ch] * tweakFactors[1], 0.0f, 255.0f); + outEP0[ch] = ParallelMath::RoundAndConvertToU15(ep0f, &roundingMode); + outEP1[ch] = ParallelMath::RoundAndConvertToU15(ep1f, &roundingMode); + } + } + + template<int TNewVectorSize> + UnfinishedEndpoints<TNewVectorSize> ExpandTo(float filler) + { + MFloat newBase[TNewVectorSize]; + MFloat newOffset[TNewVectorSize]; + + for (int ch = 0; ch < TNewVectorSize && ch < TVectorSize; ch++) + { + newBase[ch] = m_base[ch]; + newOffset[ch] = m_offset[ch]; + } + + MFloat fillerV = ParallelMath::MakeFloat(filler); + + for (int ch = TVectorSize; ch < TNewVectorSize; ch++) + { + newBase[ch] = fillerV; + newOffset[ch] = ParallelMath::MakeFloatZero(); + } + + return UnfinishedEndpoints<TNewVectorSize>(newBase, newOffset); + } + + private: + MFloat m_base[TVectorSize]; + MFloat m_offset[TVectorSize]; + }; + + template<int TMatrixSize> + class PackedCovarianceMatrix + { + public: + // 0: xx, + // 1: xy, yy + // 3: xz, yz, zz + // 6: xw, yw, zw, ww + // ... etc. + static const int PyramidSize = (TMatrixSize * (TMatrixSize + 1)) / 2; + + typedef ParallelMath::Float MFloat; + + PackedCovarianceMatrix() + { + for (int i = 0; i < PyramidSize; i++) + m_values[i] = ParallelMath::MakeFloatZero(); + } + + void Add(const ParallelMath::Float *vec, const ParallelMath::Float &weight) + { + int index = 0; + for (int row = 0; row < TMatrixSize; row++) + { + for (int col = 0; col <= row; col++) + { + m_values[index] = m_values[index] + vec[row] * vec[col] * weight; + index++; + } + } + } + + void Product(MFloat *outVec, const MFloat *inVec) + { + for (int row = 0; row < TMatrixSize; row++) + { + MFloat sum = ParallelMath::MakeFloatZero(); + + int index = (row * (row + 1)) >> 1; + for (int col = 0; col < TMatrixSize; col++) + { + sum = sum + inVec[col] * m_values[index]; + if (col >= row) + index += col + 1; + else + index++; + } + + outVec[row] = sum; + } + } + + private: + ParallelMath::Float m_values[PyramidSize]; + }; + + static const int NumEndpointSelectorPasses = 3; + + template<int TVectorSize, int TIterationCount> + class EndpointSelector + { + public: + typedef ParallelMath::Float MFloat; + + EndpointSelector() + { + for (int ch = 0; ch < TVectorSize; ch++) + { + m_centroid[ch] = ParallelMath::MakeFloatZero(); + m_direction[ch] = ParallelMath::MakeFloatZero(); + } + m_weightTotal = ParallelMath::MakeFloatZero(); + m_minDist = ParallelMath::MakeFloat(FLT_MAX); + m_maxDist = ParallelMath::MakeFloat(-FLT_MAX); + } + + void ContributePass(const MFloat *value, int pass, const MFloat &weight) + { + if (pass == 0) + ContributeCentroid(value, weight); + else if (pass == 1) + ContributeDirection(value, weight); + else if (pass == 2) + ContributeMinMax(value); + } + + void FinishPass(int pass) + { + if (pass == 0) + FinishCentroid(); + else if (pass == 1) + FinishDirection(); + } + + UnfinishedEndpoints<TVectorSize> GetEndpoints(const float channelWeights[TVectorSize]) const + { + MFloat unweightedBase[TVectorSize]; + MFloat unweightedOffset[TVectorSize]; + + for (int ch = 0; ch < TVectorSize; ch++) + { + MFloat min = m_centroid[ch] + m_direction[ch] * m_minDist; + MFloat max = m_centroid[ch] + m_direction[ch] * m_maxDist; + + float safeWeight = channelWeights[ch]; + if (safeWeight == 0.f) + safeWeight = 1.0f; + + unweightedBase[ch] = min / channelWeights[ch]; + unweightedOffset[ch] = (max - min) / channelWeights[ch]; + } + + return UnfinishedEndpoints<TVectorSize>(unweightedBase, unweightedOffset); + } + + private: + void ContributeCentroid(const MFloat *value, const MFloat &weight) + { + for (int ch = 0; ch < TVectorSize; ch++) + m_centroid[ch] = m_centroid[ch] + value[ch] * weight; + m_weightTotal = m_weightTotal + weight; + } + + void FinishCentroid() + { + MFloat denom = m_weightTotal; + ParallelMath::MakeSafeDenominator(denom); + + for (int ch = 0; ch < TVectorSize; ch++) + m_centroid[ch] = m_centroid[ch] / denom; + } + + void ContributeDirection(const MFloat *value, const MFloat &weight) + { + MFloat diff[TVectorSize]; + for (int ch = 0; ch < TVectorSize; ch++) + diff[ch] = value[ch] - m_centroid[ch]; + + m_covarianceMatrix.Add(diff, weight); + } + + void FinishDirection() + { + MFloat approx[TVectorSize]; + for (int ch = 0; ch < TVectorSize; ch++) + approx[ch] = ParallelMath::MakeFloat(1.0f); + + for (int i = 0; i < TIterationCount; i++) + { + MFloat product[TVectorSize]; + m_covarianceMatrix.Product(product, approx); + + MFloat largestComponent = product[0]; + for (int ch = 1; ch < TVectorSize; ch++) + largestComponent = ParallelMath::Max(largestComponent, product[ch]); + + // product = largestComponent*newApprox + ParallelMath::MakeSafeDenominator(largestComponent); + for (int ch = 0; ch < TVectorSize; ch++) + approx[ch] = product[ch] / largestComponent; + } + + // Normalize + MFloat approxLen = ParallelMath::MakeFloatZero(); + for (int ch = 0; ch < TVectorSize; ch++) + approxLen = approxLen + approx[ch] * approx[ch]; + + approxLen = ParallelMath::Sqrt(approxLen); + + ParallelMath::MakeSafeDenominator(approxLen); + + for (int ch = 0; ch < TVectorSize; ch++) + m_direction[ch] = approx[ch] / approxLen; + } + + void ContributeMinMax(const MFloat *value) + { + MFloat dist = ParallelMath::MakeFloatZero(); + for (int ch = 0; ch < TVectorSize; ch++) + dist = dist + m_direction[ch] * (value[ch] - m_centroid[ch]); + + m_minDist = ParallelMath::Min(m_minDist, dist); + m_maxDist = ParallelMath::Max(m_maxDist, dist); + } + + ParallelMath::Float m_centroid[TVectorSize]; + ParallelMath::Float m_direction[TVectorSize]; + PackedCovarianceMatrix<TVectorSize> m_covarianceMatrix; + ParallelMath::Float m_weightTotal; + + ParallelMath::Float m_minDist; + ParallelMath::Float m_maxDist; + }; + + static const ParallelMath::UInt16 g_weightReciprocals[] = + { + ParallelMath::MakeUInt16(0), // -1 + ParallelMath::MakeUInt16(0), // 0 + ParallelMath::MakeUInt16(32768), // 1 + ParallelMath::MakeUInt16(16384), // 2 + ParallelMath::MakeUInt16(10923), // 3 + ParallelMath::MakeUInt16(8192), // 4 + ParallelMath::MakeUInt16(6554), // 5 + ParallelMath::MakeUInt16(5461), // 6 + ParallelMath::MakeUInt16(4681), // 7 + ParallelMath::MakeUInt16(4096), // 8 + ParallelMath::MakeUInt16(3641), // 9 + ParallelMath::MakeUInt16(3277), // 10 + ParallelMath::MakeUInt16(2979), // 11 + ParallelMath::MakeUInt16(2731), // 12 + ParallelMath::MakeUInt16(2521), // 13 + ParallelMath::MakeUInt16(2341), // 14 + ParallelMath::MakeUInt16(2185), // 15 + }; + + template<int TVectorSize> + class IndexSelector + { + public: + typedef ParallelMath::Float MFloat; + typedef ParallelMath::UInt16 MUInt16; + typedef ParallelMath::UInt15 MUInt15; + typedef ParallelMath::SInt16 MSInt16; + typedef ParallelMath::AInt16 MAInt16; + typedef ParallelMath::SInt32 MSInt32; + typedef ParallelMath::UInt31 MUInt31; + + template<class TInterpolationEPType, class TColorEPType> + void Init(const float *channelWeights, const TInterpolationEPType interpolationEndPoints[2][TVectorSize], const TColorEPType colorSpaceEndpoints[2][TVectorSize], int range) + { + // In BC6H, the interpolation endpoints are higher-precision than the endpoints in color space. + // We need to select indexes using the color-space endpoints. + + m_isUniform = true; + for (int ch = 1; ch < TVectorSize; ch++) + { + if (channelWeights[ch] != channelWeights[0]) + m_isUniform = false; + } + + // To work with channel weights, we need something where: + // pxDiff = px - ep[0] + // epDiff = ep[1] - ep[0] + // + // weightedEPDiff = epDiff * channelWeights + // normalizedWeightedAxis = weightedEPDiff / len(weightedEPDiff) + // normalizedIndex = dot(pxDiff * channelWeights, normalizedWeightedAxis) / len(weightedEPDiff) + // index = normalizedIndex * maxValue + // + // Equivalent to: + // axis = channelWeights * maxValue * epDiff * channelWeights / lenSquared(epDiff * channelWeights) + // index = dot(axis, pxDiff) + + for (int ep = 0; ep < 2; ep++) + for (int ch = 0; ch < TVectorSize; ch++) + m_endPoint[ep][ch] = ParallelMath::LosslessCast<MAInt16>::Cast(interpolationEndPoints[ep][ch]); + + m_range = range; + m_maxValue = static_cast<float>(range - 1); + + MFloat epDiffWeighted[TVectorSize]; + for (int ch = 0; ch < TVectorSize; ch++) + { + m_origin[ch] = ParallelMath::ToFloat(colorSpaceEndpoints[0][ch]); + MFloat opposingOriginCh = ParallelMath::ToFloat(colorSpaceEndpoints[1][ch]); + epDiffWeighted[ch] = (opposingOriginCh - m_origin[ch]) * channelWeights[ch]; + } + + MFloat lenSquared = epDiffWeighted[0] * epDiffWeighted[0]; + for (int ch = 1; ch < TVectorSize; ch++) + lenSquared = lenSquared + epDiffWeighted[ch] * epDiffWeighted[ch]; + + ParallelMath::MakeSafeDenominator(lenSquared); + + MFloat maxValueDividedByLengthSquared = ParallelMath::MakeFloat(m_maxValue) / lenSquared; + + for (int ch = 0; ch < TVectorSize; ch++) + m_axis[ch] = epDiffWeighted[ch] * channelWeights[ch] * maxValueDividedByLengthSquared; + } + + template<bool TSigned> + void Init(const float channelWeights[TVectorSize], const MUInt15 endPoints[2][TVectorSize], int range) + { + MAInt16 converted[2][TVectorSize]; + for (int epi = 0; epi < 2; epi++) + for (int ch = 0; ch < TVectorSize; ch++) + converted[epi][ch] = ParallelMath::LosslessCast<MAInt16>::Cast(endPoints[epi][ch]); + + Init<MUInt15, MUInt15>(channelWeights, endPoints, endPoints, range); + } + + void ReconstructLDR_BC7(const MUInt15 &index, MUInt15* pixel, int numRealChannels) + { + MUInt15 weight = ParallelMath::LosslessCast<MUInt15>::Cast(ParallelMath::RightShift(ParallelMath::CompactMultiply(g_weightReciprocals[m_range], index) + 256, 9)); + + for (int ch = 0; ch < numRealChannels; ch++) + { + MUInt15 ep0f = ParallelMath::LosslessCast<MUInt15>::Cast(ParallelMath::CompactMultiply((ParallelMath::MakeUInt15(64) - weight), ParallelMath::LosslessCast<MUInt15>::Cast(m_endPoint[0][ch]))); + MUInt15 ep1f = ParallelMath::LosslessCast<MUInt15>::Cast(ParallelMath::CompactMultiply(weight, ParallelMath::LosslessCast<MUInt15>::Cast(m_endPoint[1][ch]))); + pixel[ch] = ParallelMath::LosslessCast<MUInt15>::Cast(ParallelMath::RightShift(ep0f + ep1f + ParallelMath::MakeUInt15(32), 6)); + } + } + + void ReconstructLDRPrecise(const MUInt15 &index, MUInt15* pixel, int numRealChannels) + { + MUInt15 weight = ParallelMath::LosslessCast<MUInt15>::Cast(ParallelMath::RightShift(ParallelMath::CompactMultiply(g_weightReciprocals[m_range], index) + 64, 7)); + + for (int ch = 0; ch < numRealChannels; ch++) + { + MUInt15 ep0f = ParallelMath::LosslessCast<MUInt15>::Cast(ParallelMath::CompactMultiply((ParallelMath::MakeUInt15(256) - weight), ParallelMath::LosslessCast<MUInt15>::Cast(m_endPoint[0][ch]))); + MUInt15 ep1f = ParallelMath::LosslessCast<MUInt15>::Cast(ParallelMath::CompactMultiply(weight, ParallelMath::LosslessCast<MUInt15>::Cast(m_endPoint[1][ch]))); + pixel[ch] = ParallelMath::LosslessCast<MUInt15>::Cast(ParallelMath::RightShift(ep0f + ep1f + ParallelMath::MakeUInt15(128), 8)); + } + } + + void ReconstructLDR_BC7(const MUInt15 &index, MUInt15* pixel) + { + ReconstructLDR_BC7(index, pixel, TVectorSize); + } + + void ReconstructLDRPrecise(const MUInt15 &index, MUInt15* pixel) + { + ReconstructLDRPrecise(index, pixel, TVectorSize); + } + + MUInt15 SelectIndexLDR(const MFloat* pixel, const ParallelMath::RoundTowardNearestForScope* rtn) const + { + MFloat dist = (pixel[0] - m_origin[0]) * m_axis[0]; + for (int ch = 1; ch < TVectorSize; ch++) + dist = dist + (pixel[ch] - m_origin[ch]) * m_axis[ch]; + + return ParallelMath::RoundAndConvertToU15(ParallelMath::Clamp(dist, 0.0f, m_maxValue), rtn); + } + + protected: + MAInt16 m_endPoint[2][TVectorSize]; + + private: + MFloat m_origin[TVectorSize]; + MFloat m_axis[TVectorSize]; + int m_range; + float m_maxValue; + bool m_isUniform; + }; + + + template<int TVectorSize> + class IndexSelectorHDR : public IndexSelector<TVectorSize> + { + public: + typedef ParallelMath::UInt15 MUInt15; + typedef ParallelMath::UInt16 MUInt16; + typedef ParallelMath::UInt31 MUInt31; + typedef ParallelMath::SInt16 MSInt16; + typedef ParallelMath::SInt32 MSInt32; + typedef ParallelMath::Float MFloat; + + private: + + MUInt15 InvertSingle(const MUInt15& anIndex) const + { + MUInt15 inverted = m_maxValueMinusOne - anIndex; + return ParallelMath::Select(m_isInverted, inverted, anIndex); + } + + void ReconstructHDRSignedUninverted(const MUInt15 &index, MSInt16* pixel) const + { + MUInt15 weight = ParallelMath::LosslessCast<MUInt15>::Cast(ParallelMath::RightShift(ParallelMath::CompactMultiply(g_weightReciprocals[m_range], index) + 256, 9)); + + for (int ch = 0; ch < TVectorSize; ch++) + { + MSInt16 ep0 = ParallelMath::LosslessCast<MSInt16>::Cast(this->m_endPoint[0][ch]); + MSInt16 ep1 = ParallelMath::LosslessCast<MSInt16>::Cast(this->m_endPoint[1][ch]); + + MSInt32 pixel32 = ParallelMath::XMultiply((ParallelMath::MakeUInt15(64) - weight), ep0) + ParallelMath::XMultiply(weight, ep1); + + pixel32 = ParallelMath::RightShift(pixel32 + ParallelMath::MakeSInt32(32), 6); + + pixel[ch] = UnscaleHDRValueSigned(ParallelMath::ToSInt16(pixel32)); + } + } + + void ReconstructHDRUnsignedUninverted(const MUInt15 &index, MSInt16* pixel) const + { + MUInt15 weight = ParallelMath::LosslessCast<MUInt15>::Cast(ParallelMath::RightShift(ParallelMath::CompactMultiply(g_weightReciprocals[m_range], index) + 256, 9)); + + for (int ch = 0; ch < TVectorSize; ch++) + { + MUInt16 ep0 = ParallelMath::LosslessCast<MUInt16>::Cast(this->m_endPoint[0][ch]); + MUInt16 ep1 = ParallelMath::LosslessCast<MUInt16>::Cast(this->m_endPoint[1][ch]); + + MUInt31 pixel31 = ParallelMath::XMultiply((ParallelMath::MakeUInt15(64) - weight), ep0) + ParallelMath::XMultiply(weight, ep1); + + pixel31 = ParallelMath::RightShift(pixel31 + ParallelMath::MakeUInt31(32), 6); + + pixel[ch] = ParallelMath::LosslessCast<MSInt16>::Cast(UnscaleHDRValueUnsigned(ParallelMath::ToUInt16(pixel31))); + } + } + + MFloat ErrorForInterpolatorComponent(int index, int ch, const MFloat *pixel) const + { + MFloat diff = pixel[ch] - m_reconstructedInterpolators[index][ch]; + return diff * diff; + } + + MFloat ErrorForInterpolator(int index, const MFloat *pixel) const + { + MFloat error = ErrorForInterpolatorComponent(index, 0, pixel); + for (int ch = 1; ch < TVectorSize; ch++) + error = error + ErrorForInterpolatorComponent(index, ch, pixel); + return error; + } + + public: + + void InitHDR(int range, bool isSigned, bool fastIndexing, const float *channelWeights) + { + assert(range <= 16); + + m_range = range; + + m_isInverted = ParallelMath::MakeBoolInt16(false); + m_maxValueMinusOne = ParallelMath::MakeUInt15(static_cast<uint16_t>(range - 1)); + + if (!fastIndexing) + { + for (int i = 0; i < range; i++) + { + MSInt16 recon2CL[TVectorSize]; + + if (isSigned) + ReconstructHDRSignedUninverted(ParallelMath::MakeUInt15(static_cast<uint16_t>(i)), recon2CL); + else + ReconstructHDRUnsignedUninverted(ParallelMath::MakeUInt15(static_cast<uint16_t>(i)), recon2CL); + + for (int ch = 0; ch < TVectorSize; ch++) + m_reconstructedInterpolators[i][ch] = ParallelMath::TwosCLHalfToFloat(recon2CL[ch]) * channelWeights[ch]; + } + } + } + + void ReconstructHDRSigned(const MUInt15 &index, MSInt16* pixel) const + { + ReconstructHDRSignedUninverted(InvertSingle(index), pixel); + } + + void ReconstructHDRUnsigned(const MUInt15 &index, MSInt16* pixel) const + { + ReconstructHDRUnsignedUninverted(InvertSingle(index), pixel); + } + + void ConditionalInvert(const ParallelMath::Int16CompFlag &invert) + { + m_isInverted = invert; + } + + MUInt15 SelectIndexHDRSlow(const MFloat* pixel, const ParallelMath::RoundTowardNearestForScope*) const + { + MUInt15 index = ParallelMath::MakeUInt15(0); + + MFloat bestError = ErrorForInterpolator(0, pixel); + for (int i = 1; i < m_range; i++) + { + MFloat error = ErrorForInterpolator(i, pixel); + ParallelMath::FloatCompFlag errorBetter = ParallelMath::Less(error, bestError); + ParallelMath::ConditionalSet(index, ParallelMath::FloatFlagToInt16(errorBetter), ParallelMath::MakeUInt15(static_cast<uint16_t>(i))); + bestError = ParallelMath::Min(bestError, error); + } + + return InvertSingle(index); + } + + MUInt15 SelectIndexHDRFast(const MFloat* pixel, const ParallelMath::RoundTowardNearestForScope* rtn) const + { + return InvertSingle(this->SelectIndexLDR(pixel, rtn)); + } + + private: + MFloat m_reconstructedInterpolators[16][TVectorSize]; + ParallelMath::Int16CompFlag m_isInverted; + MUInt15 m_maxValueMinusOne; + int m_range; + }; + + // Solve for a, b where v = a*t + b + // This allows endpoints to be mapped to where T=0 and T=1 + // Least squares from totals: + // a = (tv - t*v/w)/(tt - t*t/w) + // b = (v - a*t)/w + template<int TVectorSize> + class EndpointRefiner + { + public: + typedef ParallelMath::Float MFloat; + typedef ParallelMath::UInt16 MUInt16; + typedef ParallelMath::UInt15 MUInt15; + typedef ParallelMath::AInt16 MAInt16; + typedef ParallelMath::SInt16 MSInt16; + typedef ParallelMath::SInt32 MSInt32; + + MFloat m_tv[TVectorSize]; + MFloat m_v[TVectorSize]; + MFloat m_tt; + MFloat m_t; + MFloat m_w; + int m_wu; + + float m_rcpMaxIndex; + float m_channelWeights[TVectorSize]; + float m_rcpChannelWeights[TVectorSize]; + + void Init(int indexRange, const float channelWeights[TVectorSize]) + { + for (int ch = 0; ch < TVectorSize; ch++) + { + m_tv[ch] = ParallelMath::MakeFloatZero(); + m_v[ch] = ParallelMath::MakeFloatZero(); + } + m_tt = ParallelMath::MakeFloatZero(); + m_t = ParallelMath::MakeFloatZero(); + m_w = ParallelMath::MakeFloatZero(); + + m_rcpMaxIndex = 1.0f / static_cast<float>(indexRange - 1); + + for (int ch = 0; ch < TVectorSize; ch++) + { + m_channelWeights[ch] = channelWeights[ch]; + m_rcpChannelWeights[ch] = 1.0f; + if (m_channelWeights[ch] != 0.0f) + m_rcpChannelWeights[ch] = 1.0f / channelWeights[ch]; + } + + m_wu = 0; + } + + void ContributePW(const MFloat *pwFloatPixel, const MUInt15 &index, const MFloat &weight) + { + MFloat t = ParallelMath::ToFloat(index) * m_rcpMaxIndex; + + for (int ch = 0; ch < TVectorSize; ch++) + { + MFloat v = pwFloatPixel[ch] * weight; + + m_tv[ch] = m_tv[ch] + t * v; + m_v[ch] = m_v[ch] + v; + } + m_tt = m_tt + weight * t * t; + m_t = m_t + weight * t; + m_w = m_w + weight; + } + + void ContributeUnweightedPW(const MFloat *pwFloatPixel, const MUInt15 &index, int numRealChannels) + { + MFloat t = ParallelMath::ToFloat(index) * m_rcpMaxIndex; + + for (int ch = 0; ch < numRealChannels; ch++) + { + MFloat v = pwFloatPixel[ch]; + + m_tv[ch] = m_tv[ch] + t * v; + m_v[ch] = m_v[ch] + v; + } + m_tt = m_tt + t * t; + m_t = m_t + t; + m_wu++; + } + + void ContributeUnweightedPW(const MFloat *floatPixel, const MUInt15 &index) + { + ContributeUnweightedPW(floatPixel, index, TVectorSize); + } + + void GetRefinedEndpoints(MFloat endPoint[2][TVectorSize]) + { + // a = (tv - t*v/w)/(tt - t*t/w) + // b = (v - a*t)/w + MFloat w = m_w + ParallelMath::MakeFloat(static_cast<float>(m_wu)); + + ParallelMath::MakeSafeDenominator(w); + MFloat wRcp = ParallelMath::Reciprocal(w); + + MFloat adenom = (m_tt * w - m_t * m_t) * wRcp; + + ParallelMath::FloatCompFlag adenomZero = ParallelMath::Equal(adenom, ParallelMath::MakeFloatZero()); + ParallelMath::ConditionalSet(adenom, adenomZero, ParallelMath::MakeFloat(1.0f)); + + for (int ch = 0; ch < TVectorSize; ch++) + { + /* + if (adenom == 0.0) + p1 = p2 = er.v / er.w; + else + { + float4 a = (er.tv - er.t*er.v / er.w) / adenom; + float4 b = (er.v - a * er.t) / er.w; + p1 = b; + p2 = a + b; + } + */ + + MFloat a = (m_tv[ch] - m_t * m_v[ch] * wRcp) / adenom; + MFloat b = (m_v[ch] - a * m_t) * wRcp; + + MFloat p1 = b; + MFloat p2 = a + b; + + ParallelMath::ConditionalSet(p1, adenomZero, (m_v[ch] * wRcp)); + ParallelMath::ConditionalSet(p2, adenomZero, p1); + + // Unweight + float inverseWeight = m_rcpChannelWeights[ch]; + + endPoint[0][ch] = p1 * inverseWeight; + endPoint[1][ch] = p2 * inverseWeight; + } + } + + void GetRefinedEndpointsLDR(MUInt15 endPoint[2][TVectorSize], int numRealChannels, const ParallelMath::RoundTowardNearestForScope *roundingMode) + { + MFloat floatEndPoint[2][TVectorSize]; + GetRefinedEndpoints(floatEndPoint); + + for (int epi = 0; epi < 2; epi++) + for (int ch = 0; ch < TVectorSize; ch++) + endPoint[epi][ch] = ParallelMath::RoundAndConvertToU15(ParallelMath::Clamp(floatEndPoint[epi][ch], 0.0f, 255.0f), roundingMode); + } + + void GetRefinedEndpointsLDR(MUInt15 endPoint[2][TVectorSize], const ParallelMath::RoundTowardNearestForScope *roundingMode) + { + GetRefinedEndpointsLDR(endPoint, TVectorSize, roundingMode); + } + + void GetRefinedEndpointsHDR(MSInt16 endPoint[2][TVectorSize], bool isSigned, const ParallelMath::RoundTowardNearestForScope *roundingMode) + { + MFloat floatEndPoint[2][TVectorSize]; + GetRefinedEndpoints(floatEndPoint); + + for (int epi = 0; epi < 2; epi++) + { + for (int ch = 0; ch < TVectorSize; ch++) + { + MFloat f = floatEndPoint[epi][ch]; + if (isSigned) + endPoint[epi][ch] = ParallelMath::LosslessCast<MSInt16>::Cast(ParallelMath::RoundAndConvertToS16(ParallelMath::Clamp(f, -31743.0f, 31743.0f), roundingMode)); + else + endPoint[epi][ch] = ParallelMath::LosslessCast<MSInt16>::Cast(ParallelMath::RoundAndConvertToU15(ParallelMath::Clamp(f, 0.0f, 31743.0f), roundingMode)); + } + } + } + }; + + template<int TVectorSize> + class AggregatedError + { + public: + typedef ParallelMath::UInt16 MUInt16; + typedef ParallelMath::UInt31 MUInt31; + typedef ParallelMath::Float MFloat; + + AggregatedError() + { + for (int ch = 0; ch < TVectorSize; ch++) + m_errorUnweighted[ch] = ParallelMath::MakeUInt31(0); + } + + void Add(const MUInt16 &channelErrorUnweighted, int ch) + { + m_errorUnweighted[ch] = m_errorUnweighted[ch] + ParallelMath::ToUInt31(channelErrorUnweighted); + } + + MFloat Finalize(uint32_t flags, const float channelWeightsSq[TVectorSize]) const + { + if (flags & cvtt::Flags::Uniform) + { + MUInt31 total = m_errorUnweighted[0]; + for (int ch = 1; ch < TVectorSize; ch++) + total = total + m_errorUnweighted[ch]; + return ParallelMath::ToFloat(total); + } + else + { + MFloat total = ParallelMath::ToFloat(m_errorUnweighted[0]) * channelWeightsSq[0]; + for (int ch = 1; ch < TVectorSize; ch++) + total = total + ParallelMath::ToFloat(m_errorUnweighted[ch]) * channelWeightsSq[ch]; + return total; + } + } + + private: + MUInt31 m_errorUnweighted[TVectorSize]; + }; + + class BCCommon + { + public: + typedef ParallelMath::Float MFloat; + typedef ParallelMath::UInt16 MUInt16; + typedef ParallelMath::UInt15 MUInt15; + typedef ParallelMath::AInt16 MAInt16; + typedef ParallelMath::SInt16 MSInt16; + typedef ParallelMath::SInt32 MSInt32; + + static int TweakRoundsForRange(int range) + { + if (range == 3) + return 3; + return 4; + } + + template<int TVectorSize> + static void ComputeErrorLDR(uint32_t flags, const MUInt15 reconstructed[TVectorSize], const MUInt15 original[TVectorSize], int numRealChannels, AggregatedError<TVectorSize> &aggError) + { + for (int ch = 0; ch < numRealChannels; ch++) + aggError.Add(ParallelMath::SqDiffUInt8(reconstructed[ch], original[ch]), ch); + } + + template<int TVectorSize> + static void ComputeErrorLDR(uint32_t flags, const MUInt15 reconstructed[TVectorSize], const MUInt15 original[TVectorSize], AggregatedError<TVectorSize> &aggError) + { + ComputeErrorLDR<TVectorSize>(flags, reconstructed, original, TVectorSize, aggError); + } + + template<int TVectorSize> + static MFloat ComputeErrorLDRSimple(uint32_t flags, const MUInt15 reconstructed[TVectorSize], const MUInt15 original[TVectorSize], int numRealChannels, const float *channelWeightsSq) + { + AggregatedError<TVectorSize> aggError; + ComputeErrorLDR<TVectorSize>(flags, reconstructed, original, numRealChannels, aggError); + return aggError.Finalize(flags, channelWeightsSq); + } + + template<int TVectorSize> + static MFloat ComputeErrorHDRFast(uint32_t flags, const MSInt16 reconstructed[TVectorSize], const MSInt16 original[TVectorSize], const float channelWeightsSq[TVectorSize]) + { + MFloat error = ParallelMath::MakeFloatZero(); + if (flags & Flags::Uniform) + { + for (int ch = 0; ch < TVectorSize; ch++) + error = error + ParallelMath::SqDiffSInt16(reconstructed[ch], original[ch]); + } + else + { + for (int ch = 0; ch < TVectorSize; ch++) + error = error + ParallelMath::SqDiffSInt16(reconstructed[ch], original[ch]) * ParallelMath::MakeFloat(channelWeightsSq[ch]); + } + + return error; + } + + template<int TVectorSize> + static MFloat ComputeErrorHDRSlow(uint32_t flags, const MSInt16 reconstructed[TVectorSize], const MSInt16 original[TVectorSize], const float channelWeightsSq[TVectorSize]) + { + MFloat error = ParallelMath::MakeFloatZero(); + if (flags & Flags::Uniform) + { + for (int ch = 0; ch < TVectorSize; ch++) + error = error + ParallelMath::SqDiff2CL(reconstructed[ch], original[ch]); + } + else + { + for (int ch = 0; ch < TVectorSize; ch++) + error = error + ParallelMath::SqDiff2CL(reconstructed[ch], original[ch]) * ParallelMath::MakeFloat(channelWeightsSq[ch]); + } + + return error; + } + + template<int TChannelCount> + static void PreWeightPixelsLDR(MFloat preWeightedPixels[16][TChannelCount], const MUInt15 pixels[16][TChannelCount], const float channelWeights[TChannelCount]) + { + for (int px = 0; px < 16; px++) + { + for (int ch = 0; ch < TChannelCount; ch++) + preWeightedPixels[px][ch] = ParallelMath::ToFloat(pixels[px][ch]) * channelWeights[ch]; + } + } + + template<int TChannelCount> + static void PreWeightPixelsHDR(MFloat preWeightedPixels[16][TChannelCount], const MSInt16 pixels[16][TChannelCount], const float channelWeights[TChannelCount]) + { + for (int px = 0; px < 16; px++) + { + for (int ch = 0; ch < TChannelCount; ch++) + preWeightedPixels[px][ch] = ParallelMath::ToFloat(pixels[px][ch]) * channelWeights[ch]; + } + } + }; + + class BC7Computer + { + public: + static const int MaxTweakRounds = 4; + + typedef ParallelMath::SInt16 MSInt16; + typedef ParallelMath::UInt15 MUInt15; + typedef ParallelMath::UInt16 MUInt16; + typedef ParallelMath::SInt32 MSInt32; + typedef ParallelMath::Float MFloat; + + struct WorkInfo + { + MUInt15 m_mode; + MFloat m_error; + MUInt15 m_ep[3][2][4]; + MUInt15 m_indexes[16]; + MUInt15 m_indexes2[16]; + + union + { + MUInt15 m_partition; + struct IndexSelectorAndRotation + { + MUInt15 m_indexSelector; + MUInt15 m_rotation; + } m_isr; + } m_u; + }; + + static void TweakAlpha(const MUInt15 original[2], int tweak, int range, MUInt15 result[2]) + { + ParallelMath::RoundTowardNearestForScope roundingMode; + + float tf[2]; + ComputeTweakFactors(tweak, range, tf); + + MFloat base = ParallelMath::ToFloat(original[0]); + MFloat offs = ParallelMath::ToFloat(original[1]) - base; + + result[0] = ParallelMath::RoundAndConvertToU15(ParallelMath::Clamp(base + offs * tf[0], 0.0f, 255.0f), &roundingMode); + result[1] = ParallelMath::RoundAndConvertToU15(ParallelMath::Clamp(base + offs * tf[1], 0.0f, 255.0f), &roundingMode); + } + + static void Quantize(MUInt15* color, int bits, int channels, const ParallelMath::RoundTowardNearestForScope *roundingMode) + { + float maxColor = static_cast<float>((1 << bits) - 1); + + for (int i = 0; i < channels; i++) + color[i] = ParallelMath::RoundAndConvertToU15(ParallelMath::Clamp(ParallelMath::ToFloat(color[i]) * ParallelMath::MakeFloat(1.0f / 255.0f) * maxColor, 0.f, 255.f), roundingMode); + } + + static void QuantizeP(MUInt15* color, int bits, uint16_t p, int channels, const ParallelMath::RoundTowardNearestForScope *roundingMode) + { + uint16_t pShift = static_cast<uint16_t>(1 << (7 - bits)); + MUInt15 pShiftV = ParallelMath::MakeUInt15(pShift); + + float maxColorF = static_cast<float>(255 - (1 << (7 - bits))); + + float maxQuantized = static_cast<float>((1 << bits) - 1); + + for (int ch = 0; ch < channels; ch++) + { + MUInt15 clr = color[ch]; + if (p) + clr = ParallelMath::Max(clr, pShiftV) - pShiftV; + + MFloat rerangedColor = ParallelMath::ToFloat(clr) * maxQuantized / maxColorF; + + clr = ParallelMath::RoundAndConvertToU15(ParallelMath::Clamp(rerangedColor, 0.0f, maxQuantized), roundingMode) << 1; + if (p) + clr = clr | ParallelMath::MakeUInt15(1); + + color[ch] = clr; + } + } + + static void Unquantize(MUInt15* color, int bits, int channels) + { + for (int ch = 0; ch < channels; ch++) + { + MUInt15 clr = color[ch]; + clr = clr << (8 - bits); + color[ch] = clr | ParallelMath::RightShift(clr, bits); + } + } + + static void CompressEndpoints0(MUInt15 ep[2][4], uint16_t p[2], const ParallelMath::RoundTowardNearestForScope *roundingMode) + { + for (int j = 0; j < 2; j++) + { + QuantizeP(ep[j], 4, p[j], 3, roundingMode); + Unquantize(ep[j], 5, 3); + ep[j][3] = ParallelMath::MakeUInt15(255); + } + } + + static void CompressEndpoints1(MUInt15 ep[2][4], uint16_t p, const ParallelMath::RoundTowardNearestForScope *roundingMode) + { + for (int j = 0; j < 2; j++) + { + QuantizeP(ep[j], 6, p, 3, roundingMode); + Unquantize(ep[j], 7, 3); + ep[j][3] = ParallelMath::MakeUInt15(255); + } + } + + static void CompressEndpoints2(MUInt15 ep[2][4], const ParallelMath::RoundTowardNearestForScope *roundingMode) + { + for (int j = 0; j < 2; j++) + { + Quantize(ep[j], 5, 3, roundingMode); + Unquantize(ep[j], 5, 3); + ep[j][3] = ParallelMath::MakeUInt15(255); + } + } + + static void CompressEndpoints3(MUInt15 ep[2][4], uint16_t p[2], const ParallelMath::RoundTowardNearestForScope *roundingMode) + { + for (int j = 0; j < 2; j++) + { + QuantizeP(ep[j], 7, p[j], 3, roundingMode); + ep[j][3] = ParallelMath::MakeUInt15(255); + } + } + + static void CompressEndpoints4(MUInt15 epRGB[2][3], MUInt15 epA[2], const ParallelMath::RoundTowardNearestForScope *roundingMode) + { + for (int j = 0; j < 2; j++) + { + Quantize(epRGB[j], 5, 3, roundingMode); + Unquantize(epRGB[j], 5, 3); + + Quantize(epA + j, 6, 1, roundingMode); + Unquantize(epA + j, 6, 1); + } + } + + static void CompressEndpoints5(MUInt15 epRGB[2][3], MUInt15 epA[2], const ParallelMath::RoundTowardNearestForScope *roundingMode) + { + for (int j = 0; j < 2; j++) + { + Quantize(epRGB[j], 7, 3, roundingMode); + Unquantize(epRGB[j], 7, 3); + } + + // Alpha is full precision + (void)epA; + } + + static void CompressEndpoints6(MUInt15 ep[2][4], uint16_t p[2], const ParallelMath::RoundTowardNearestForScope *roundingMode) + { + for (int j = 0; j < 2; j++) + QuantizeP(ep[j], 7, p[j], 4, roundingMode); + } + + static void CompressEndpoints7(MUInt15 ep[2][4], uint16_t p[2], const ParallelMath::RoundTowardNearestForScope *roundingMode) + { + for (int j = 0; j < 2; j++) + { + QuantizeP(ep[j], 5, p[j], 4, roundingMode); + Unquantize(ep[j], 6, 4); + } + } + + struct SinglePlaneTemporaries + { + UnfinishedEndpoints<3> unfinishedRGB[BC7Data::g_numShapesAll]; + UnfinishedEndpoints<4> unfinishedRGBA[BC7Data::g_numShapes12]; + + MUInt15 fragmentBestIndexes[BC7Data::g_numFragments]; + MUInt15 shapeBestEP[BC7Data::g_maxFragmentsPerMode][2][4]; + MFloat shapeBestError[BC7Data::g_maxFragmentsPerMode]; + }; + + static void TrySingleColorRGBAMultiTable(uint32_t flags, const MUInt15 pixels[16][4], const MFloat average[4], int numRealChannels, const uint8_t *fragmentStart, int shapeLength, const MFloat &staticAlphaError, const ParallelMath::Int16CompFlag punchThroughInvalid[4], MFloat& shapeBestError, MUInt15 shapeBestEP[2][4], MUInt15 *fragmentBestIndexes, const float *channelWeightsSq, const cvtt::Tables::BC7SC::Table*const* tables, int numTables, const ParallelMath::RoundTowardNearestForScope *rtn) + { + MFloat bestAverageError = ParallelMath::MakeFloat(FLT_MAX); + + MUInt15 intAverage[4]; + for (int ch = 0; ch < 4; ch++) + intAverage[ch] = ParallelMath::RoundAndConvertToU15(average[ch], rtn); + + MUInt15 eps[2][4]; + MUInt15 reconstructed[4]; + MUInt15 index = ParallelMath::MakeUInt15(0); + + for (int epi = 0; epi < 2; epi++) + { + for (int ch = 0; ch < 3; ch++) + eps[epi][ch] = ParallelMath::MakeUInt15(0); + eps[epi][3] = ParallelMath::MakeUInt15(255); + } + + for (int ch = 0; ch < 3; ch++) + reconstructed[ch] = ParallelMath::MakeUInt15(0); + reconstructed[3] = ParallelMath::MakeUInt15(255); + + // Depending on the target index and parity bits, there are multiple valid solid colors. + // We want to find the one closest to the actual average. + MFloat epsAverageDiff = ParallelMath::MakeFloat(FLT_MAX); + for (int t = 0; t < numTables; t++) + { + const cvtt::Tables::BC7SC::Table& table = *(tables[t]); + + ParallelMath::Int16CompFlag pti = punchThroughInvalid[table.m_pBits]; + + MUInt15 candidateReconstructed[4]; + MUInt15 candidateEPs[2][4]; + + for (int i = 0; i < ParallelMath::ParallelSize; i++) + { + for (int ch = 0; ch < numRealChannels; ch++) + { + ParallelMath::ScalarUInt16 avgValue = ParallelMath::Extract(intAverage[ch], i); + assert(avgValue >= 0 && avgValue <= 255); + + const cvtt::Tables::BC7SC::TableEntry &entry = table.m_entries[avgValue]; + + ParallelMath::PutUInt15(candidateEPs[0][ch], i, entry.m_min); + ParallelMath::PutUInt15(candidateEPs[1][ch], i, entry.m_max); + ParallelMath::PutUInt15(candidateReconstructed[ch], i, entry.m_actualColor); + } + } + + MFloat avgError = ParallelMath::MakeFloatZero(); + for (int ch = 0; ch < numRealChannels; ch++) + { + MFloat delta = ParallelMath::ToFloat(candidateReconstructed[ch]) - average[ch]; + avgError = avgError + delta * delta * channelWeightsSq[ch]; + } + + ParallelMath::Int16CompFlag better = ParallelMath::FloatFlagToInt16(ParallelMath::Less(avgError, bestAverageError)); + better = ParallelMath::AndNot(pti, better); // Mask out punch-through invalidations + + if (ParallelMath::AnySet(better)) + { + ParallelMath::ConditionalSet(bestAverageError, ParallelMath::Int16FlagToFloat(better), avgError); + + MUInt15 candidateIndex = ParallelMath::MakeUInt15(table.m_index); + + ParallelMath::ConditionalSet(index, better, candidateIndex); + + for (int ch = 0; ch < numRealChannels; ch++) + ParallelMath::ConditionalSet(reconstructed[ch], better, candidateReconstructed[ch]); + + for (int epi = 0; epi < 2; epi++) + for (int ch = 0; ch < numRealChannels; ch++) + ParallelMath::ConditionalSet(eps[epi][ch], better, candidateEPs[epi][ch]); + } + } + + AggregatedError<4> aggError; + for (int pxi = 0; pxi < shapeLength; pxi++) + { + int px = fragmentStart[pxi]; + + BCCommon::ComputeErrorLDR<4>(flags, reconstructed, pixels[px], numRealChannels, aggError); + } + + MFloat error = aggError.Finalize(flags, channelWeightsSq) + staticAlphaError; + + ParallelMath::Int16CompFlag better = ParallelMath::FloatFlagToInt16(ParallelMath::Less(error, shapeBestError)); + if (ParallelMath::AnySet(better)) + { + shapeBestError = ParallelMath::Min(shapeBestError, error); + for (int epi = 0; epi < 2; epi++) + { + for (int ch = 0; ch < numRealChannels; ch++) + ParallelMath::ConditionalSet(shapeBestEP[epi][ch], better, eps[epi][ch]); + } + + for (int pxi = 0; pxi < shapeLength; pxi++) + ParallelMath::ConditionalSet(fragmentBestIndexes[pxi], better, index); + } + } + + + static void TrySinglePlane(uint32_t flags, const MUInt15 pixels[16][4], const MFloat floatPixels[16][4], const float channelWeights[4], int numTweakRounds, int numRefineRounds, WorkInfo& work, const ParallelMath::RoundTowardNearestForScope *rtn) + { + if (numRefineRounds < 1) + numRefineRounds = 1; + + if (numTweakRounds < 1) + numTweakRounds = 1; + else if (numTweakRounds > MaxTweakRounds) + numTweakRounds = MaxTweakRounds; + + float channelWeightsSq[4]; + + for (int ch = 0; ch < 4; ch++) + channelWeightsSq[ch] = channelWeights[ch] * channelWeights[ch]; + + SinglePlaneTemporaries temps; + + MUInt15 maxAlpha = ParallelMath::MakeUInt15(0); + MUInt15 minAlpha = ParallelMath::MakeUInt15(255); + ParallelMath::Int16CompFlag isPunchThrough = ParallelMath::MakeBoolInt16(true); + for (int px = 0; px < 16; px++) + { + MUInt15 a = pixels[px][3]; + maxAlpha = ParallelMath::Max(maxAlpha, a); + minAlpha = ParallelMath::Min(minAlpha, a); + + isPunchThrough = (isPunchThrough & (ParallelMath::Equal(a, ParallelMath::MakeUInt15(0)) | ParallelMath::Equal(a, ParallelMath::MakeUInt15(255)))); + } + + ParallelMath::Int16CompFlag blockHasNonMaxAlpha = ParallelMath::Less(minAlpha, ParallelMath::MakeUInt15(255)); + ParallelMath::Int16CompFlag blockHasNonZeroAlpha = ParallelMath::Less(ParallelMath::MakeUInt15(0), maxAlpha); + + bool anyBlockHasAlpha = ParallelMath::AnySet(blockHasNonMaxAlpha); + + // Try RGB modes if any block has a min alpha 251 or higher + bool allowRGBModes = ParallelMath::AnySet(ParallelMath::Less(ParallelMath::MakeUInt15(250), minAlpha)); + + // Try mode 7 if any block has alpha. + // Mode 7 is almost never selected for RGB blocks because mode 4 has very accurate 7.7.7.1 endpoints + // and its parity bit doesn't affect alpha, meaning mode 7 can only be better in extremely specific + // situations, and only by at most 1 unit of error per pixel. + bool allowMode7 = anyBlockHasAlpha; + + MFloat preWeightedPixels[16][4]; + + BCCommon::PreWeightPixelsLDR<4>(preWeightedPixels, pixels, channelWeights); + + const int *rgbInitialEPCollapseList = NULL; + + // Get initial RGB endpoints + if (allowRGBModes) + { + const int *shapeList; + int numShapesToEvaluate; + + if (flags & Flags::BC7_EnablePartitioning) + { + if (flags & Flags::BC7_Enable3Subsets) + { + shapeList = BC7Data::g_shapeListAll; + rgbInitialEPCollapseList = BC7Data::g_shapeListAll; + numShapesToEvaluate = BC7Data::g_numShapesAll; + } + else + { + shapeList = BC7Data::g_shapeList12; + rgbInitialEPCollapseList = BC7Data::g_shapeList12Collapse; + numShapesToEvaluate = BC7Data::g_numShapes12; + } + } + else + { + shapeList = BC7Data::g_shapeList1; + rgbInitialEPCollapseList = BC7Data::g_shapeList1Collapse; + numShapesToEvaluate = BC7Data::g_numShapes1; + } + + for (int shapeIter = 0; shapeIter < numShapesToEvaluate; shapeIter++) + { + int shape = shapeList[shapeIter]; + + int shapeStart = BC7Data::g_shapeRanges[shape][0]; + int shapeSize = BC7Data::g_shapeRanges[shape][1]; + + EndpointSelector<3, 8> epSelector; + + for (int epPass = 0; epPass < NumEndpointSelectorPasses; epPass++) + { + for (int spx = 0; spx < shapeSize; spx++) + { + int px = BC7Data::g_fragments[shapeStart + spx]; + epSelector.ContributePass(preWeightedPixels[px], epPass, ParallelMath::MakeFloat(1.0f)); + } + epSelector.FinishPass(epPass); + } + temps.unfinishedRGB[shapeIter] = epSelector.GetEndpoints(channelWeights); + } + } + + const int *rgbaInitialEPCollapseList = BC7Data::g_shapeList12Collapse; + + // Get initial RGBA endpoints + { + const int *shapeList = BC7Data::g_shapeList12; + int numShapesToEvaluate = BC7Data::g_numShapes12; + + for (int shapeIter = 0; shapeIter < numShapesToEvaluate; shapeIter++) + { + int shape = shapeList[shapeIter]; + + if (anyBlockHasAlpha || !allowRGBModes) + { + int shapeStart = BC7Data::g_shapeRanges[shape][0]; + int shapeSize = BC7Data::g_shapeRanges[shape][1]; + + EndpointSelector<4, 8> epSelector; + + for (int epPass = 0; epPass < NumEndpointSelectorPasses; epPass++) + { + for (int spx = 0; spx < shapeSize; spx++) + { + int px = BC7Data::g_fragments[shapeStart + spx]; + epSelector.ContributePass(preWeightedPixels[px], epPass, ParallelMath::MakeFloat(1.0f)); + } + epSelector.FinishPass(epPass); + } + temps.unfinishedRGBA[shapeIter] = epSelector.GetEndpoints(channelWeights); + } + else + { + temps.unfinishedRGBA[shapeIter] = temps.unfinishedRGB[rgbInitialEPCollapseList[shape]].ExpandTo<4>(255); + } + } + } + + for (uint16_t mode = 0; mode <= 7; mode++) + { + if (!(flags & Flags::BC7_EnablePartitioning) && BC7Data::g_modes[mode].m_numSubsets != 1) + continue; + + if (!(flags & Flags::BC7_Enable3Subsets) && BC7Data::g_modes[mode].m_numSubsets == 3) + continue; + + if (mode == 4 || mode == 5) + continue; + + if (mode < 4 && !allowRGBModes) + continue; + + if (mode == 7 && !allowMode7) + continue; + + bool isRGB = (mode < 4); + + unsigned int numPartitions = 1 << BC7Data::g_modes[mode].m_partitionBits; + int numSubsets = BC7Data::g_modes[mode].m_numSubsets; + int indexPrec = BC7Data::g_modes[mode].m_indexBits; + + int parityBitMax = 1; + if (BC7Data::g_modes[mode].m_pBitMode == BC7Data::PBitMode_PerEndpoint) + parityBitMax = 4; + else if (BC7Data::g_modes[mode].m_pBitMode == BC7Data::PBitMode_PerSubset) + parityBitMax = 2; + + int numRealChannels = isRGB ? 3 : 4; + + int numShapes; + const int *shapeList; + const int *shapeCollapseList; + + if (numSubsets == 1) + { + numShapes = BC7Data::g_numShapes1; + shapeList = BC7Data::g_shapeList1; + shapeCollapseList = BC7Data::g_shapeList1Collapse; + } + else if (numSubsets == 2) + { + numShapes = BC7Data::g_numShapes2; + shapeList = BC7Data::g_shapeList2; + shapeCollapseList = BC7Data::g_shapeList2Collapse; + } + else + { + assert(numSubsets == 3); + if (numPartitions == 16) + { + numShapes = BC7Data::g_numShapes3Short; + shapeList = BC7Data::g_shapeList3Short; + shapeCollapseList = BC7Data::g_shapeList3ShortCollapse; + } + else + { + assert(numPartitions == 64); + numShapes = BC7Data::g_numShapes3; + shapeList = BC7Data::g_shapeList3; + shapeCollapseList = BC7Data::g_shapeList3Collapse; + } + } + + for (int slot = 0; slot < BC7Data::g_maxFragmentsPerMode; slot++) + temps.shapeBestError[slot] = ParallelMath::MakeFloat(FLT_MAX); + + for (int shapeIter = 0; shapeIter < numShapes; shapeIter++) + { + int shape = shapeList[shapeIter]; + int shapeStart = BC7Data::g_shapeRanges[shape][0]; + int shapeLength = BC7Data::g_shapeRanges[shape][1]; + int shapeCollapsedEvalIndex = shapeCollapseList[shape]; + + AggregatedError<1> alphaAggError; + if (isRGB && anyBlockHasAlpha) + { + MUInt15 filledAlpha[1] = { ParallelMath::MakeUInt15(255) }; + + for (int pxi = 0; pxi < shapeLength; pxi++) + { + int px = BC7Data::g_fragments[shapeStart + pxi]; + MUInt15 original[1] = { pixels[px][3] }; + BCCommon::ComputeErrorLDR<1>(flags, filledAlpha, original, alphaAggError); + } + } + + float alphaWeightsSq[1] = { channelWeightsSq[3] }; + MFloat staticAlphaError = alphaAggError.Finalize(flags, alphaWeightsSq); + + assert(shapeCollapsedEvalIndex >= 0); + + MUInt15 tweakBaseEP[MaxTweakRounds][2][4]; + + for (int tweak = 0; tweak < numTweakRounds; tweak++) + { + if (isRGB) + { + temps.unfinishedRGB[rgbInitialEPCollapseList[shape]].FinishLDR(tweak, 1 << indexPrec, tweakBaseEP[tweak][0], tweakBaseEP[tweak][1]); + tweakBaseEP[tweak][0][3] = tweakBaseEP[tweak][1][3] = ParallelMath::MakeUInt15(255); + } + else + { + temps.unfinishedRGBA[rgbaInitialEPCollapseList[shape]].FinishLDR(tweak, 1 << indexPrec, tweakBaseEP[tweak][0], tweakBaseEP[tweak][1]); + } + } + + ParallelMath::Int16CompFlag punchThroughInvalid[4]; + for (int pIter = 0; pIter < parityBitMax; pIter++) + { + punchThroughInvalid[pIter] = ParallelMath::MakeBoolInt16(false); + + if ((flags & Flags::BC7_RespectPunchThrough) && (mode == 6 || mode == 7)) + { + // Modes 6 and 7 have parity bits that affect alpha + if (pIter == 0) + punchThroughInvalid[pIter] = (isPunchThrough & blockHasNonZeroAlpha); + else if (pIter == parityBitMax - 1) + punchThroughInvalid[pIter] = (isPunchThrough & blockHasNonMaxAlpha); + else + punchThroughInvalid[pIter] = isPunchThrough; + } + } + + for (int pIter = 0; pIter < parityBitMax; pIter++) + { + if (ParallelMath::AllSet(punchThroughInvalid[pIter])) + continue; + + bool needPunchThroughCheck = ParallelMath::AnySet(punchThroughInvalid[pIter]); + + for (int tweak = 0; tweak < numTweakRounds; tweak++) + { + uint16_t p[2]; + p[0] = (pIter & 1); + p[1] = ((pIter >> 1) & 1); + + MUInt15 ep[2][4]; + + for (int epi = 0; epi < 2; epi++) + for (int ch = 0; ch < 4; ch++) + ep[epi][ch] = tweakBaseEP[tweak][epi][ch]; + + for (int refine = 0; refine < numRefineRounds; refine++) + { + switch (mode) + { + case 0: + CompressEndpoints0(ep, p, rtn); + break; + case 1: + CompressEndpoints1(ep, p[0], rtn); + break; + case 2: + CompressEndpoints2(ep, rtn); + break; + case 3: + CompressEndpoints3(ep, p, rtn); + break; + case 6: + CompressEndpoints6(ep, p, rtn); + break; + case 7: + CompressEndpoints7(ep, p, rtn); + break; + default: + assert(false); + break; + }; + + MFloat shapeError = ParallelMath::MakeFloatZero(); + + IndexSelector<4> indexSelector; + indexSelector.Init<false>(channelWeights, ep, 1 << indexPrec); + + EndpointRefiner<4> epRefiner; + epRefiner.Init(1 << indexPrec, channelWeights); + + MUInt15 indexes[16]; + + AggregatedError<4> aggError; + for (int pxi = 0; pxi < shapeLength; pxi++) + { + int px = BC7Data::g_fragments[shapeStart + pxi]; + + MUInt15 index; + MUInt15 reconstructed[4]; + + index = indexSelector.SelectIndexLDR(floatPixels[px], rtn); + indexSelector.ReconstructLDR_BC7(index, reconstructed, numRealChannels); + + if (flags & cvtt::Flags::BC7_FastIndexing) + BCCommon::ComputeErrorLDR<4>(flags, reconstructed, pixels[px], numRealChannels, aggError); + else + { + MFloat error = BCCommon::ComputeErrorLDRSimple<4>(flags, reconstructed, pixels[px], numRealChannels, channelWeightsSq); + + MUInt15 altIndexes[2]; + altIndexes[0] = ParallelMath::Max(index, ParallelMath::MakeUInt15(1)) - ParallelMath::MakeUInt15(1); + altIndexes[1] = ParallelMath::Min(index + ParallelMath::MakeUInt15(1), ParallelMath::MakeUInt15(static_cast<uint16_t>((1 << indexPrec) - 1))); + + for (int ii = 0; ii < 2; ii++) + { + indexSelector.ReconstructLDR_BC7(altIndexes[ii], reconstructed, numRealChannels); + + MFloat altError = BCCommon::ComputeErrorLDRSimple<4>(flags, reconstructed, pixels[px], numRealChannels, channelWeightsSq); + ParallelMath::Int16CompFlag better = ParallelMath::FloatFlagToInt16(ParallelMath::Less(altError, error)); + error = ParallelMath::Min(error, altError); + ParallelMath::ConditionalSet(index, better, altIndexes[ii]); + } + + shapeError = shapeError + error; + } + + if (refine != numRefineRounds - 1) + epRefiner.ContributeUnweightedPW(preWeightedPixels[px], index, numRealChannels); + + indexes[pxi] = index; + } + + if (flags & cvtt::Flags::BC7_FastIndexing) + shapeError = aggError.Finalize(flags, channelWeightsSq); + + if (isRGB) + shapeError = shapeError + staticAlphaError; + + ParallelMath::FloatCompFlag shapeErrorBetter; + ParallelMath::Int16CompFlag shapeErrorBetter16; + + shapeErrorBetter = ParallelMath::Less(shapeError, temps.shapeBestError[shapeCollapsedEvalIndex]); + shapeErrorBetter16 = ParallelMath::FloatFlagToInt16(shapeErrorBetter); + + if (ParallelMath::AnySet(shapeErrorBetter16)) + { + bool punchThroughOK = true; + if (needPunchThroughCheck) + { + shapeErrorBetter16 = ParallelMath::AndNot(punchThroughInvalid[pIter], shapeErrorBetter16); + shapeErrorBetter = ParallelMath::Int16FlagToFloat(shapeErrorBetter16); + + if (!ParallelMath::AnySet(shapeErrorBetter16)) + punchThroughOK = false; + } + + if (punchThroughOK) + { + ParallelMath::ConditionalSet(temps.shapeBestError[shapeCollapsedEvalIndex], shapeErrorBetter, shapeError); + for (int epi = 0; epi < 2; epi++) + for (int ch = 0; ch < numRealChannels; ch++) + ParallelMath::ConditionalSet(temps.shapeBestEP[shapeCollapsedEvalIndex][epi][ch], shapeErrorBetter16, ep[epi][ch]); + + for (int pxi = 0; pxi < shapeLength; pxi++) + ParallelMath::ConditionalSet(temps.fragmentBestIndexes[shapeStart + pxi], shapeErrorBetter16, indexes[pxi]); + } + } + + if (refine != numRefineRounds - 1) + epRefiner.GetRefinedEndpointsLDR(ep, numRealChannels, rtn); + } // refine + } // tweak + } // p + + if (flags & cvtt::Flags::BC7_TrySingleColor) + { + MUInt15 total[4]; + for (int ch = 0; ch < 4; ch++) + total[ch] = ParallelMath::MakeUInt15(0); + + for (int pxi = 0; pxi < shapeLength; pxi++) + { + int px = BC7Data::g_fragments[shapeStart + pxi]; + for (int ch = 0; ch < 4; ch++) + total[ch] = total[ch] + pixels[pxi][ch]; + } + + MFloat rcpShapeLength = ParallelMath::MakeFloat(1.0f / static_cast<float>(shapeLength)); + MFloat average[4]; + for (int ch = 0; ch < 4; ch++) + average[ch] = ParallelMath::ToFloat(total[ch]) * rcpShapeLength; + + const uint8_t *fragment = BC7Data::g_fragments + shapeStart; + MFloat &shapeBestError = temps.shapeBestError[shapeCollapsedEvalIndex]; + MUInt15(&shapeBestEP)[2][4] = temps.shapeBestEP[shapeCollapsedEvalIndex]; + MUInt15 *fragmentBestIndexes = temps.fragmentBestIndexes + shapeStart; + + const cvtt::Tables::BC7SC::Table **scTables = NULL; + int numSCTables = 0; + + switch (mode) + { + case 0: + { + const cvtt::Tables::BC7SC::Table *tables[] = + { + &cvtt::Tables::BC7SC::g_mode0_p00_i1, + &cvtt::Tables::BC7SC::g_mode0_p00_i2, + &cvtt::Tables::BC7SC::g_mode0_p00_i3, + &cvtt::Tables::BC7SC::g_mode0_p01_i1, + &cvtt::Tables::BC7SC::g_mode0_p01_i2, + &cvtt::Tables::BC7SC::g_mode0_p01_i3, + &cvtt::Tables::BC7SC::g_mode0_p10_i1, + &cvtt::Tables::BC7SC::g_mode0_p10_i2, + &cvtt::Tables::BC7SC::g_mode0_p10_i3, + &cvtt::Tables::BC7SC::g_mode0_p11_i1, + &cvtt::Tables::BC7SC::g_mode0_p11_i2, + &cvtt::Tables::BC7SC::g_mode0_p11_i3, + }; + scTables = tables; + numSCTables = sizeof(tables) / sizeof(tables[0]); + } + break; + case 1: + { + const cvtt::Tables::BC7SC::Table *tables[] = + { + &cvtt::Tables::BC7SC::g_mode1_p0_i1, + &cvtt::Tables::BC7SC::g_mode1_p0_i2, + &cvtt::Tables::BC7SC::g_mode1_p0_i3, + &cvtt::Tables::BC7SC::g_mode1_p1_i1, + &cvtt::Tables::BC7SC::g_mode1_p1_i2, + &cvtt::Tables::BC7SC::g_mode1_p1_i3, + }; + scTables = tables; + numSCTables = sizeof(tables) / sizeof(tables[0]); + } + break; + case 2: + { + const cvtt::Tables::BC7SC::Table *tables[] = + { + &cvtt::Tables::BC7SC::g_mode2, + }; + scTables = tables; + numSCTables = sizeof(tables) / sizeof(tables[0]); + } + break; + case 3: + { + const cvtt::Tables::BC7SC::Table *tables[] = + { + &cvtt::Tables::BC7SC::g_mode3_p0, + &cvtt::Tables::BC7SC::g_mode3_p1, + }; + scTables = tables; + numSCTables = sizeof(tables) / sizeof(tables[0]); + } + break; + case 6: + { + const cvtt::Tables::BC7SC::Table *tables[] = + { + &cvtt::Tables::BC7SC::g_mode6_p0_i1, + &cvtt::Tables::BC7SC::g_mode6_p0_i2, + &cvtt::Tables::BC7SC::g_mode6_p0_i3, + &cvtt::Tables::BC7SC::g_mode6_p0_i4, + &cvtt::Tables::BC7SC::g_mode6_p0_i5, + &cvtt::Tables::BC7SC::g_mode6_p0_i6, + &cvtt::Tables::BC7SC::g_mode6_p0_i7, + &cvtt::Tables::BC7SC::g_mode6_p1_i1, + &cvtt::Tables::BC7SC::g_mode6_p1_i2, + &cvtt::Tables::BC7SC::g_mode6_p1_i3, + &cvtt::Tables::BC7SC::g_mode6_p1_i4, + &cvtt::Tables::BC7SC::g_mode6_p1_i5, + &cvtt::Tables::BC7SC::g_mode6_p1_i6, + &cvtt::Tables::BC7SC::g_mode6_p1_i7, + }; + scTables = tables; + numSCTables = sizeof(tables) / sizeof(tables[0]); + } + break; + case 7: + { + const cvtt::Tables::BC7SC::Table *tables[] = + { + &cvtt::Tables::BC7SC::g_mode7_p00, + &cvtt::Tables::BC7SC::g_mode7_p01, + &cvtt::Tables::BC7SC::g_mode7_p10, + &cvtt::Tables::BC7SC::g_mode7_p11, + }; + scTables = tables; + numSCTables = sizeof(tables) / sizeof(tables[0]); + } + break; + default: + assert(false); + break; + } + + TrySingleColorRGBAMultiTable(flags, pixels, average, numRealChannels, fragment, shapeLength, staticAlphaError, punchThroughInvalid, shapeBestError, shapeBestEP, fragmentBestIndexes, channelWeightsSq, scTables, numSCTables, rtn); + } + } // shapeIter + + for (uint16_t partition = 0; partition < numPartitions; partition++) + { + const int *partitionShapes; + if (numSubsets == 1) + partitionShapes = BC7Data::g_shapes1[partition]; + else if (numSubsets == 2) + partitionShapes = BC7Data::g_shapes2[partition]; + else + { + assert(numSubsets == 3); + partitionShapes = BC7Data::g_shapes3[partition]; + } + + MFloat totalError = ParallelMath::MakeFloatZero(); + for (int subset = 0; subset < numSubsets; subset++) + totalError = totalError + temps.shapeBestError[shapeCollapseList[partitionShapes[subset]]]; + + ParallelMath::FloatCompFlag errorBetter = ParallelMath::Less(totalError, work.m_error); + ParallelMath::Int16CompFlag errorBetter16 = ParallelMath::FloatFlagToInt16(errorBetter); + + if (ParallelMath::AnySet(errorBetter16)) + { + for (int subset = 0; subset < numSubsets; subset++) + { + int shape = partitionShapes[subset]; + int shapeStart = BC7Data::g_shapeRanges[shape][0]; + int shapeLength = BC7Data::g_shapeRanges[shape][1]; + int shapeCollapsedEvalIndex = shapeCollapseList[shape]; + + for (int epi = 0; epi < 2; epi++) + for (int ch = 0; ch < 4; ch++) + ParallelMath::ConditionalSet(work.m_ep[subset][epi][ch], errorBetter16, temps.shapeBestEP[shapeCollapsedEvalIndex][epi][ch]); + + for (int pxi = 0; pxi < shapeLength; pxi++) + { + int px = BC7Data::g_fragments[shapeStart + pxi]; + ParallelMath::ConditionalSet(work.m_indexes[px], errorBetter16, temps.fragmentBestIndexes[shapeStart + pxi]); + } + } + + work.m_error = ParallelMath::Min(totalError, work.m_error); + ParallelMath::ConditionalSet(work.m_mode, errorBetter16, ParallelMath::MakeUInt15(mode)); + ParallelMath::ConditionalSet(work.m_u.m_partition, errorBetter16, ParallelMath::MakeUInt15(partition)); + } + } + } + } + + static void TryDualPlane(uint32_t flags, const MUInt15 pixels[16][4], const MFloat floatPixels[16][4], const float channelWeights[4], int numTweakRounds, int numRefineRounds, WorkInfo& work, const ParallelMath::RoundTowardNearestForScope *rtn) + { + // TODO: These error calculations are not optimal for weight-by-alpha, but this routine needs to be mostly rewritten for that. + // The alpha/color solutions are co-dependent in that case, but a good way to solve it would probably be to + // solve the alpha channel first, then solve the RGB channels, which in turn breaks down into two cases: + // - Separate alpha channel, then weighted RGB + // - Alpha+2 other channels, then the independent channel + + if (!(flags & Flags::BC7_EnableDualPlane)) + return; + + if (numRefineRounds < 1) + numRefineRounds = 1; + + if (numTweakRounds < 1) + numTweakRounds = 1; + else if (numTweakRounds > MaxTweakRounds) + numTweakRounds = MaxTweakRounds; + + float channelWeightsSq[4]; + for (int ch = 0; ch < 4; ch++) + channelWeightsSq[ch] = channelWeights[ch] * channelWeights[ch]; + + for (uint16_t mode = 4; mode <= 5; mode++) + { + for (uint16_t rotation = 0; rotation < 4; rotation++) + { + int alphaChannel = (rotation + 3) & 3; + int redChannel = (rotation == 1) ? 3 : 0; + int greenChannel = (rotation == 2) ? 3 : 1; + int blueChannel = (rotation == 3) ? 3 : 2; + + MUInt15 rotatedRGB[16][3]; + MFloat floatRotatedRGB[16][3]; + + for (int px = 0; px < 16; px++) + { + rotatedRGB[px][0] = pixels[px][redChannel]; + rotatedRGB[px][1] = pixels[px][greenChannel]; + rotatedRGB[px][2] = pixels[px][blueChannel]; + + for (int ch = 0; ch < 3; ch++) + floatRotatedRGB[px][ch] = ParallelMath::ToFloat(rotatedRGB[px][ch]); + } + + uint16_t maxIndexSelector = (mode == 4) ? 2 : 1; + + float rotatedRGBWeights[3] = { channelWeights[redChannel], channelWeights[greenChannel], channelWeights[blueChannel] }; + float rotatedRGBWeightsSq[3] = { channelWeightsSq[redChannel], channelWeightsSq[greenChannel], channelWeightsSq[blueChannel] }; + float rotatedAlphaWeight[1] = { channelWeights[alphaChannel] }; + float rotatedAlphaWeightSq[1] = { channelWeightsSq[alphaChannel] }; + + float uniformWeight[1] = { 1.0f }; // Since the alpha channel is independent, there's no need to bother with weights when doing refinement or selection, only error + + MFloat preWeightedRotatedRGB[16][3]; + BCCommon::PreWeightPixelsLDR<3>(preWeightedRotatedRGB, rotatedRGB, rotatedRGBWeights); + + for (uint16_t indexSelector = 0; indexSelector < maxIndexSelector; indexSelector++) + { + EndpointSelector<3, 8> rgbSelector; + + for (int epPass = 0; epPass < NumEndpointSelectorPasses; epPass++) + { + for (int px = 0; px < 16; px++) + rgbSelector.ContributePass(preWeightedRotatedRGB[px], epPass, ParallelMath::MakeFloat(1.0f)); + + rgbSelector.FinishPass(epPass); + } + + MUInt15 alphaRange[2]; + + alphaRange[0] = alphaRange[1] = pixels[0][alphaChannel]; + for (int px = 1; px < 16; px++) + { + alphaRange[0] = ParallelMath::Min(pixels[px][alphaChannel], alphaRange[0]); + alphaRange[1] = ParallelMath::Max(pixels[px][alphaChannel], alphaRange[1]); + } + + int rgbPrec = 0; + int alphaPrec = 0; + + if (mode == 4) + { + rgbPrec = indexSelector ? 3 : 2; + alphaPrec = indexSelector ? 2 : 3; + } + else + rgbPrec = alphaPrec = 2; + + UnfinishedEndpoints<3> unfinishedRGB = rgbSelector.GetEndpoints(rotatedRGBWeights); + + MFloat bestRGBError = ParallelMath::MakeFloat(FLT_MAX); + MFloat bestAlphaError = ParallelMath::MakeFloat(FLT_MAX); + + MUInt15 bestRGBIndexes[16]; + MUInt15 bestAlphaIndexes[16]; + MUInt15 bestEP[2][4]; + + for (int px = 0; px < 16; px++) + bestRGBIndexes[px] = bestAlphaIndexes[px] = ParallelMath::MakeUInt15(0); + + for (int tweak = 0; tweak < numTweakRounds; tweak++) + { + MUInt15 rgbEP[2][3]; + MUInt15 alphaEP[2]; + + unfinishedRGB.FinishLDR(tweak, 1 << rgbPrec, rgbEP[0], rgbEP[1]); + + TweakAlpha(alphaRange, tweak, 1 << alphaPrec, alphaEP); + + for (int refine = 0; refine < numRefineRounds; refine++) + { + if (mode == 4) + CompressEndpoints4(rgbEP, alphaEP, rtn); + else + CompressEndpoints5(rgbEP, alphaEP, rtn); + + + IndexSelector<1> alphaIndexSelector; + IndexSelector<3> rgbIndexSelector; + + { + MUInt15 alphaEPTemp[2][1] = { { alphaEP[0] },{ alphaEP[1] } }; + alphaIndexSelector.Init<false>(uniformWeight, alphaEPTemp, 1 << alphaPrec); + } + rgbIndexSelector.Init<false>(rotatedRGBWeights, rgbEP, 1 << rgbPrec); + + EndpointRefiner<3> rgbRefiner; + EndpointRefiner<1> alphaRefiner; + + rgbRefiner.Init(1 << rgbPrec, rotatedRGBWeights); + alphaRefiner.Init(1 << alphaPrec, uniformWeight); + + MFloat errorRGB = ParallelMath::MakeFloatZero(); + MFloat errorA = ParallelMath::MakeFloatZero(); + + MUInt15 rgbIndexes[16]; + MUInt15 alphaIndexes[16]; + + AggregatedError<3> rgbAggError; + AggregatedError<1> alphaAggError; + + for (int px = 0; px < 16; px++) + { + MUInt15 rgbIndex = rgbIndexSelector.SelectIndexLDR(floatRotatedRGB[px], rtn); + MUInt15 alphaIndex = alphaIndexSelector.SelectIndexLDR(floatPixels[px] + alphaChannel, rtn); + + MUInt15 reconstructedRGB[3]; + MUInt15 reconstructedAlpha[1]; + + rgbIndexSelector.ReconstructLDR_BC7(rgbIndex, reconstructedRGB); + alphaIndexSelector.ReconstructLDR_BC7(alphaIndex, reconstructedAlpha); + + if (flags & cvtt::Flags::BC7_FastIndexing) + { + BCCommon::ComputeErrorLDR<3>(flags, reconstructedRGB, rotatedRGB[px], rgbAggError); + BCCommon::ComputeErrorLDR<1>(flags, reconstructedAlpha, pixels[px] + alphaChannel, alphaAggError); + } + else + { + AggregatedError<3> baseRGBAggError; + AggregatedError<1> baseAlphaAggError; + + BCCommon::ComputeErrorLDR<3>(flags, reconstructedRGB, rotatedRGB[px], baseRGBAggError); + BCCommon::ComputeErrorLDR<1>(flags, reconstructedAlpha, pixels[px] + alphaChannel, baseAlphaAggError); + + MFloat rgbError = baseRGBAggError.Finalize(flags, rotatedRGBWeightsSq); + MFloat alphaError = baseAlphaAggError.Finalize(flags, rotatedAlphaWeightSq); + + MUInt15 altRGBIndexes[2]; + MUInt15 altAlphaIndexes[2]; + + altRGBIndexes[0] = ParallelMath::Max(rgbIndex, ParallelMath::MakeUInt15(1)) - ParallelMath::MakeUInt15(1); + altRGBIndexes[1] = ParallelMath::Min(rgbIndex + ParallelMath::MakeUInt15(1), ParallelMath::MakeUInt15(static_cast<uint16_t>((1 << rgbPrec) - 1))); + + altAlphaIndexes[0] = ParallelMath::Max(alphaIndex, ParallelMath::MakeUInt15(1)) - ParallelMath::MakeUInt15(1); + altAlphaIndexes[1] = ParallelMath::Min(alphaIndex + ParallelMath::MakeUInt15(1), ParallelMath::MakeUInt15(static_cast<uint16_t>((1 << alphaPrec) - 1))); + + for (int ii = 0; ii < 2; ii++) + { + rgbIndexSelector.ReconstructLDR_BC7(altRGBIndexes[ii], reconstructedRGB); + alphaIndexSelector.ReconstructLDR_BC7(altAlphaIndexes[ii], reconstructedAlpha); + + AggregatedError<3> altRGBAggError; + AggregatedError<1> altAlphaAggError; + + BCCommon::ComputeErrorLDR<3>(flags, reconstructedRGB, rotatedRGB[px], altRGBAggError); + BCCommon::ComputeErrorLDR<1>(flags, reconstructedAlpha, pixels[px] + alphaChannel, altAlphaAggError); + + MFloat altRGBError = altRGBAggError.Finalize(flags, rotatedRGBWeightsSq); + MFloat altAlphaError = altAlphaAggError.Finalize(flags, rotatedAlphaWeightSq); + + ParallelMath::Int16CompFlag rgbBetter = ParallelMath::FloatFlagToInt16(ParallelMath::Less(altRGBError, rgbError)); + ParallelMath::Int16CompFlag alphaBetter = ParallelMath::FloatFlagToInt16(ParallelMath::Less(altAlphaError, alphaError)); + + rgbError = ParallelMath::Min(altRGBError, rgbError); + alphaError = ParallelMath::Min(altAlphaError, alphaError); + + ParallelMath::ConditionalSet(rgbIndex, rgbBetter, altRGBIndexes[ii]); + ParallelMath::ConditionalSet(alphaIndex, alphaBetter, altAlphaIndexes[ii]); + } + + errorRGB = errorRGB + rgbError; + errorA = errorA + alphaError; + } + + if (refine != numRefineRounds - 1) + { + rgbRefiner.ContributeUnweightedPW(preWeightedRotatedRGB[px], rgbIndex); + alphaRefiner.ContributeUnweightedPW(floatPixels[px] + alphaChannel, alphaIndex); + } + + if (flags & Flags::BC7_FastIndexing) + { + errorRGB = rgbAggError.Finalize(flags, rotatedRGBWeightsSq); + errorA = rgbAggError.Finalize(flags, rotatedAlphaWeightSq); + } + + rgbIndexes[px] = rgbIndex; + alphaIndexes[px] = alphaIndex; + } + + ParallelMath::FloatCompFlag rgbBetter = ParallelMath::Less(errorRGB, bestRGBError); + ParallelMath::FloatCompFlag alphaBetter = ParallelMath::Less(errorA, bestAlphaError); + + ParallelMath::Int16CompFlag rgbBetterInt16 = ParallelMath::FloatFlagToInt16(rgbBetter); + ParallelMath::Int16CompFlag alphaBetterInt16 = ParallelMath::FloatFlagToInt16(alphaBetter); + + if (ParallelMath::AnySet(rgbBetterInt16)) + { + bestRGBError = ParallelMath::Min(errorRGB, bestRGBError); + + for (int px = 0; px < 16; px++) + ParallelMath::ConditionalSet(bestRGBIndexes[px], rgbBetterInt16, rgbIndexes[px]); + + for (int ep = 0; ep < 2; ep++) + { + for (int ch = 0; ch < 3; ch++) + ParallelMath::ConditionalSet(bestEP[ep][ch], rgbBetterInt16, rgbEP[ep][ch]); + } + } + + if (ParallelMath::AnySet(alphaBetterInt16)) + { + bestAlphaError = ParallelMath::Min(errorA, bestAlphaError); + + for (int px = 0; px < 16; px++) + ParallelMath::ConditionalSet(bestAlphaIndexes[px], alphaBetterInt16, alphaIndexes[px]); + + for (int ep = 0; ep < 2; ep++) + ParallelMath::ConditionalSet(bestEP[ep][3], alphaBetterInt16, alphaEP[ep]); + } + + if (refine != numRefineRounds - 1) + { + rgbRefiner.GetRefinedEndpointsLDR(rgbEP, rtn); + + MUInt15 alphaEPTemp[2][1]; + alphaRefiner.GetRefinedEndpointsLDR(alphaEPTemp, rtn); + + for (int i = 0; i < 2; i++) + alphaEP[i] = alphaEPTemp[i][0]; + } + } // refine + } // tweak + + MFloat combinedError = bestRGBError + bestAlphaError; + + ParallelMath::FloatCompFlag errorBetter = ParallelMath::Less(combinedError, work.m_error); + ParallelMath::Int16CompFlag errorBetter16 = ParallelMath::FloatFlagToInt16(errorBetter); + + work.m_error = ParallelMath::Min(combinedError, work.m_error); + + ParallelMath::ConditionalSet(work.m_mode, errorBetter16, ParallelMath::MakeUInt15(mode)); + ParallelMath::ConditionalSet(work.m_u.m_isr.m_rotation, errorBetter16, ParallelMath::MakeUInt15(rotation)); + ParallelMath::ConditionalSet(work.m_u.m_isr.m_indexSelector, errorBetter16, ParallelMath::MakeUInt15(indexSelector)); + + for (int px = 0; px < 16; px++) + { + ParallelMath::ConditionalSet(work.m_indexes[px], errorBetter16, indexSelector ? bestAlphaIndexes[px] : bestRGBIndexes[px]); + ParallelMath::ConditionalSet(work.m_indexes2[px], errorBetter16, indexSelector ? bestRGBIndexes[px] : bestAlphaIndexes[px]); + } + + for (int ep = 0; ep < 2; ep++) + for (int ch = 0; ch < 4; ch++) + ParallelMath::ConditionalSet(work.m_ep[0][ep][ch], errorBetter16, bestEP[ep][ch]); + } + } + } + } + + template<class T> + static void Swap(T& a, T& b) + { + T temp = a; + a = b; + b = temp; + } + + static void Pack(uint32_t flags, const PixelBlockU8* inputs, uint8_t* packedBlocks, const float channelWeights[4], int numTweakRounds, int numRefineRounds) + { + MUInt15 pixels[16][4]; + MFloat floatPixels[16][4]; + + for (int px = 0; px < 16; px++) + { + for (int ch = 0; ch < 4; ch++) + ParallelMath::ConvertLDRInputs(inputs, px, ch, pixels[px][ch]); + } + + for (int px = 0; px < 16; px++) + { + for (int ch = 0; ch < 4; ch++) + floatPixels[px][ch] = ParallelMath::ToFloat(pixels[px][ch]); + } + + WorkInfo work; + memset(&work, 0, sizeof(work)); + + work.m_error = ParallelMath::MakeFloat(FLT_MAX); + + { + ParallelMath::RoundTowardNearestForScope rtn; + TrySinglePlane(flags, pixels, floatPixels, channelWeights, numTweakRounds, numRefineRounds, work, &rtn); + TryDualPlane(flags, pixels, floatPixels, channelWeights, numTweakRounds, numRefineRounds, work, &rtn); + } + + for (int block = 0; block < ParallelMath::ParallelSize; block++) + { + PackingVector pv; + pv.Init(); + + ParallelMath::ScalarUInt16 mode = ParallelMath::Extract(work.m_mode, block); + ParallelMath::ScalarUInt16 partition = ParallelMath::Extract(work.m_u.m_partition, block); + ParallelMath::ScalarUInt16 indexSelector = ParallelMath::Extract(work.m_u.m_isr.m_indexSelector, block); + + const BC7Data::BC7ModeInfo& modeInfo = BC7Data::g_modes[mode]; + + ParallelMath::ScalarUInt16 indexes[16]; + ParallelMath::ScalarUInt16 indexes2[16]; + ParallelMath::ScalarUInt16 endPoints[3][2][4]; + + for (int i = 0; i < 16; i++) + { + indexes[i] = ParallelMath::Extract(work.m_indexes[i], block); + if (modeInfo.m_alphaMode == BC7Data::AlphaMode_Separate) + indexes2[i] = ParallelMath::Extract(work.m_indexes2[i], block); + } + + for (int subset = 0; subset < 3; subset++) + { + for (int ep = 0; ep < 2; ep++) + { + for (int ch = 0; ch < 4; ch++) + endPoints[subset][ep][ch] = ParallelMath::Extract(work.m_ep[subset][ep][ch], block); + } + } + + int fixups[3] = { 0, 0, 0 }; + + if (modeInfo.m_alphaMode == BC7Data::AlphaMode_Separate) + { + bool flipRGB = ((indexes[0] & (1 << (modeInfo.m_indexBits - 1))) != 0); + bool flipAlpha = ((indexes2[0] & (1 << (modeInfo.m_alphaIndexBits - 1))) != 0); + + if (flipRGB) + { + uint16_t highIndex = (1 << modeInfo.m_indexBits) - 1; + for (int px = 0; px < 16; px++) + indexes[px] = highIndex - indexes[px]; + } + + if (flipAlpha) + { + uint16_t highIndex = (1 << modeInfo.m_alphaIndexBits) - 1; + for (int px = 0; px < 16; px++) + indexes2[px] = highIndex - indexes2[px]; + } + + if (indexSelector) + Swap(flipRGB, flipAlpha); + + if (flipRGB) + { + for (int ch = 0; ch < 3; ch++) + Swap(endPoints[0][0][ch], endPoints[0][1][ch]); + } + if (flipAlpha) + Swap(endPoints[0][0][3], endPoints[0][1][3]); + + } + else + { + if (modeInfo.m_numSubsets == 2) + fixups[1] = BC7Data::g_fixupIndexes2[partition]; + else if (modeInfo.m_numSubsets == 3) + { + fixups[1] = BC7Data::g_fixupIndexes3[partition][0]; + fixups[2] = BC7Data::g_fixupIndexes3[partition][1]; + } + + bool flip[3] = { false, false, false }; + for (int subset = 0; subset < modeInfo.m_numSubsets; subset++) + flip[subset] = ((indexes[fixups[subset]] & (1 << (modeInfo.m_indexBits - 1))) != 0); + + if (flip[0] || flip[1] || flip[2]) + { + uint16_t highIndex = (1 << modeInfo.m_indexBits) - 1; + for (int px = 0; px < 16; px++) + { + int subset = 0; + if (modeInfo.m_numSubsets == 2) + subset = (BC7Data::g_partitionMap[partition] >> px) & 1; + else if (modeInfo.m_numSubsets == 3) + subset = (BC7Data::g_partitionMap2[partition] >> (px * 2)) & 3; + + if (flip[subset]) + indexes[px] = highIndex - indexes[px]; + } + + int maxCH = (modeInfo.m_alphaMode == BC7Data::AlphaMode_Combined) ? 4 : 3; + for (int subset = 0; subset < modeInfo.m_numSubsets; subset++) + { + if (flip[subset]) + for (int ch = 0; ch < maxCH; ch++) + Swap(endPoints[subset][0][ch], endPoints[subset][1][ch]); + } + } + } + + pv.Pack(static_cast<uint8_t>(1 << mode), mode + 1); + + if (modeInfo.m_partitionBits) + pv.Pack(partition, modeInfo.m_partitionBits); + + if (modeInfo.m_alphaMode == BC7Data::AlphaMode_Separate) + { + ParallelMath::ScalarUInt16 rotation = ParallelMath::Extract(work.m_u.m_isr.m_rotation, block); + pv.Pack(rotation, 2); + } + + if (modeInfo.m_hasIndexSelector) + pv.Pack(indexSelector, 1); + + // Encode RGB + for (int ch = 0; ch < 3; ch++) + { + for (int subset = 0; subset < modeInfo.m_numSubsets; subset++) + { + for (int ep = 0; ep < 2; ep++) + { + ParallelMath::ScalarUInt16 epPart = endPoints[subset][ep][ch]; + epPart >>= (8 - modeInfo.m_rgbBits); + + pv.Pack(epPart, modeInfo.m_rgbBits); + } + } + } + + // Encode alpha + if (modeInfo.m_alphaMode != BC7Data::AlphaMode_None) + { + for (int subset = 0; subset < modeInfo.m_numSubsets; subset++) + { + for (int ep = 0; ep < 2; ep++) + { + ParallelMath::ScalarUInt16 epPart = endPoints[subset][ep][3]; + epPart >>= (8 - modeInfo.m_alphaBits); + + pv.Pack(epPart, modeInfo.m_alphaBits); + } + } + } + + // Encode parity bits + if (modeInfo.m_pBitMode == BC7Data::PBitMode_PerSubset) + { + for (int subset = 0; subset < modeInfo.m_numSubsets; subset++) + { + ParallelMath::ScalarUInt16 epPart = endPoints[subset][0][0]; + epPart >>= (7 - modeInfo.m_rgbBits); + epPart &= 1; + + pv.Pack(epPart, 1); + } + } + else if (modeInfo.m_pBitMode == BC7Data::PBitMode_PerEndpoint) + { + for (int subset = 0; subset < modeInfo.m_numSubsets; subset++) + { + for (int ep = 0; ep < 2; ep++) + { + ParallelMath::ScalarUInt16 epPart = endPoints[subset][ep][0]; + epPart >>= (7 - modeInfo.m_rgbBits); + epPart &= 1; + + pv.Pack(epPart, 1); + } + } + } + + // Encode indexes + for (int px = 0; px < 16; px++) + { + int bits = modeInfo.m_indexBits; + if ((px == 0) || (px == fixups[1]) || (px == fixups[2])) + bits--; + + pv.Pack(indexes[px], bits); + } + + // Encode secondary indexes + if (modeInfo.m_alphaMode == BC7Data::AlphaMode_Separate) + { + for (int px = 0; px < 16; px++) + { + int bits = modeInfo.m_alphaIndexBits; + if (px == 0) + bits--; + + pv.Pack(indexes2[px], bits); + } + } + + pv.Flush(packedBlocks); + + packedBlocks += 16; + } + } + + static void UnpackOne(PixelBlockU8 &output, const uint8_t* packedBlock) + { + UnpackingVector pv; + pv.Init(packedBlock); + + int mode = 8; + for (int i = 0; i < 8; i++) + { + if (pv.Unpack(1) == 1) + { + mode = i; + break; + } + } + + if (mode > 7) + { + for (int px = 0; px < 16; px++) + for (int ch = 0; ch < 4; ch++) + output.m_pixels[px][ch] = 0; + + return; + } + + const BC7Data::BC7ModeInfo &modeInfo = BC7Data::g_modes[mode]; + + int partition = 0; + if (modeInfo.m_partitionBits) + partition = pv.Unpack(modeInfo.m_partitionBits); + + int rotation = 0; + if (modeInfo.m_alphaMode == BC7Data::AlphaMode_Separate) + rotation = pv.Unpack(2); + + int indexSelector = 0; + if (modeInfo.m_hasIndexSelector) + indexSelector = pv.Unpack(1); + + // Resolve fixups + int fixups[3] = { 0, 0, 0 }; + + if (modeInfo.m_alphaMode != BC7Data::AlphaMode_Separate) + { + if (modeInfo.m_numSubsets == 2) + fixups[1] = BC7Data::g_fixupIndexes2[partition]; + else if (modeInfo.m_numSubsets == 3) + { + fixups[1] = BC7Data::g_fixupIndexes3[partition][0]; + fixups[2] = BC7Data::g_fixupIndexes3[partition][1]; + } + } + + int endPoints[3][2][4]; + + // Decode RGB + for (int ch = 0; ch < 3; ch++) + { + for (int subset = 0; subset < modeInfo.m_numSubsets; subset++) + { + for (int ep = 0; ep < 2; ep++) + endPoints[subset][ep][ch] = (pv.Unpack(modeInfo.m_rgbBits) << (8 - modeInfo.m_rgbBits)); + } + } + + // Decode alpha + if (modeInfo.m_alphaMode != BC7Data::AlphaMode_None) + { + for (int subset = 0; subset < modeInfo.m_numSubsets; subset++) + { + for (int ep = 0; ep < 2; ep++) + endPoints[subset][ep][3] = (pv.Unpack(modeInfo.m_alphaBits) << (8 - modeInfo.m_alphaBits)); + } + } + else + { + for (int subset = 0; subset < modeInfo.m_numSubsets; subset++) + { + for (int ep = 0; ep < 2; ep++) + endPoints[subset][ep][3] = 255; + } + } + + int parityBits = 0; + + // Decode parity bits + if (modeInfo.m_pBitMode == BC7Data::PBitMode_PerSubset) + { + for (int subset = 0; subset < modeInfo.m_numSubsets; subset++) + { + int p = pv.Unpack(1); + + for (int ep = 0; ep < 2; ep++) + { + for (int ch = 0; ch < 3; ch++) + endPoints[subset][ep][ch] |= p << (7 - modeInfo.m_rgbBits); + + if (modeInfo.m_alphaMode != BC7Data::AlphaMode_None) + endPoints[subset][ep][3] |= p << (7 - modeInfo.m_alphaBits); + } + } + + parityBits = 1; + } + else if (modeInfo.m_pBitMode == BC7Data::PBitMode_PerEndpoint) + { + for (int subset = 0; subset < modeInfo.m_numSubsets; subset++) + { + for (int ep = 0; ep < 2; ep++) + { + int p = pv.Unpack(1); + + for (int ch = 0; ch < 3; ch++) + endPoints[subset][ep][ch] |= p << (7 - modeInfo.m_rgbBits); + + if (modeInfo.m_alphaMode != BC7Data::AlphaMode_None) + endPoints[subset][ep][3] |= p << (7 - modeInfo.m_alphaBits); + } + } + + parityBits = 1; + } + + // Fill endpoint bits + for (int subset = 0; subset < modeInfo.m_numSubsets; subset++) + { + for (int ep = 0; ep < 2; ep++) + { + for (int ch = 0; ch < 3; ch++) + endPoints[subset][ep][ch] |= (endPoints[subset][ep][ch] >> (modeInfo.m_rgbBits + parityBits)); + + if (modeInfo.m_alphaMode != BC7Data::AlphaMode_None) + endPoints[subset][ep][3] |= (endPoints[subset][ep][3] >> (modeInfo.m_alphaBits + parityBits)); + } + } + + int indexes[16]; + int indexes2[16]; + + // Decode indexes + for (int px = 0; px < 16; px++) + { + int bits = modeInfo.m_indexBits; + if ((px == 0) || (px == fixups[1]) || (px == fixups[2])) + bits--; + + indexes[px] = pv.Unpack(bits); + } + + // Decode secondary indexes + if (modeInfo.m_alphaMode == BC7Data::AlphaMode_Separate) + { + for (int px = 0; px < 16; px++) + { + int bits = modeInfo.m_alphaIndexBits; + if (px == 0) + bits--; + + indexes2[px] = pv.Unpack(bits); + } + } + else + { + for (int px = 0; px < 16; px++) + indexes2[px] = 0; + } + + const int *alphaWeights = BC7Data::g_weightTables[modeInfo.m_alphaIndexBits]; + const int *rgbWeights = BC7Data::g_weightTables[modeInfo.m_indexBits]; + + // Decode each pixel + for (int px = 0; px < 16; px++) + { + int rgbWeight = 0; + int alphaWeight = 0; + + int rgbIndex = indexes[px]; + + rgbWeight = rgbWeights[indexes[px]]; + + if (modeInfo.m_alphaMode == BC7Data::AlphaMode_Combined) + alphaWeight = rgbWeight; + else if (modeInfo.m_alphaMode == BC7Data::AlphaMode_Separate) + alphaWeight = alphaWeights[indexes2[px]]; + + if (indexSelector == 1) + { + int temp = rgbWeight; + rgbWeight = alphaWeight; + alphaWeight = temp; + } + + int pixel[4] = { 0, 0, 0, 255 }; + + int subset = 0; + + if (modeInfo.m_numSubsets == 2) + subset = (BC7Data::g_partitionMap[partition] >> px) & 1; + else if (modeInfo.m_numSubsets == 3) + subset = (BC7Data::g_partitionMap2[partition] >> (px * 2)) & 3; + + for (int ch = 0; ch < 3; ch++) + pixel[ch] = ((64 - rgbWeight) * endPoints[subset][0][ch] + rgbWeight * endPoints[subset][1][ch] + 32) >> 6; + + if (modeInfo.m_alphaMode != BC7Data::AlphaMode_None) + pixel[3] = ((64 - alphaWeight) * endPoints[subset][0][3] + alphaWeight * endPoints[subset][1][3] + 32) >> 6; + + if (rotation != 0) + { + int ch = rotation - 1; + int temp = pixel[ch]; + pixel[ch] = pixel[3]; + pixel[3] = temp; + } + + for (int ch = 0; ch < 4; ch++) + output.m_pixels[px][ch] = static_cast<uint8_t>(pixel[ch]); + } + } + }; + + class BC6HComputer + { + public: + typedef ParallelMath::Float MFloat; + typedef ParallelMath::SInt16 MSInt16; + typedef ParallelMath::UInt16 MUInt16; + typedef ParallelMath::UInt15 MUInt15; + typedef ParallelMath::AInt16 MAInt16; + typedef ParallelMath::SInt32 MSInt32; + typedef ParallelMath::UInt31 MUInt31; + + static const int MaxTweakRounds = 4; + static const int MaxRefineRounds = 3; + + static MSInt16 QuantizeSingleEndpointElementSigned(const MSInt16 &elem2CL, int precision, const ParallelMath::RoundUpForScope* ru) + { + assert(ParallelMath::AllSet(ParallelMath::Less(elem2CL, ParallelMath::MakeSInt16(31744)))); + assert(ParallelMath::AllSet(ParallelMath::Less(ParallelMath::MakeSInt16(-31744), elem2CL))); + + // Expand to full range + ParallelMath::Int16CompFlag isNegative = ParallelMath::Less(elem2CL, ParallelMath::MakeSInt16(0)); + MUInt15 absElem = ParallelMath::LosslessCast<MUInt15>::Cast(ParallelMath::Select(isNegative, ParallelMath::MakeSInt16(0) - elem2CL, elem2CL)); + + absElem = ParallelMath::RightShift(ParallelMath::RoundAndConvertToU15(ParallelMath::ToFloat(absElem) * 32.0f / 31.0f, ru), 16 - precision); + + MSInt16 absElemS16 = ParallelMath::LosslessCast<MSInt16>::Cast(absElem); + + return ParallelMath::Select(isNegative, ParallelMath::MakeSInt16(0) - absElemS16, absElemS16); + } + + static MUInt15 QuantizeSingleEndpointElementUnsigned(const MUInt15 &elem, int precision, const ParallelMath::RoundUpForScope* ru) + { + MUInt16 expandedElem = ParallelMath::RoundAndConvertToU16(ParallelMath::Min(ParallelMath::ToFloat(elem) * 64.0f / 31.0f, ParallelMath::MakeFloat(65535.0f)), ru); + return ParallelMath::LosslessCast<MUInt15>::Cast(ParallelMath::RightShift(expandedElem, 16 - precision)); + } + + static void UnquantizeSingleEndpointElementSigned(const MSInt16 &comp, int precision, MSInt16 &outUnquantized, MSInt16 &outUnquantizedFinished2CL) + { + MSInt16 zero = ParallelMath::MakeSInt16(0); + + ParallelMath::Int16CompFlag negative = ParallelMath::Less(comp, zero); + MUInt15 absComp = ParallelMath::LosslessCast<MUInt15>::Cast(ParallelMath::Select(negative, MSInt16(zero - comp), comp)); + + MSInt16 unq; + MUInt15 absUnq; + + if (precision >= 16) + { + unq = comp; + absUnq = absComp; + } + else + { + MSInt16 maxCompMinusOne = ParallelMath::MakeSInt16(static_cast<int16_t>((1 << (precision - 1)) - 2)); + ParallelMath::Int16CompFlag isZero = ParallelMath::Equal(comp, zero); + ParallelMath::Int16CompFlag isMax = ParallelMath::Less(maxCompMinusOne, comp); + + absUnq = (absComp << (16 - precision)) + ParallelMath::MakeUInt15(static_cast<uint16_t>(0x4000 >> (precision - 1))); + ParallelMath::ConditionalSet(absUnq, isZero, ParallelMath::MakeUInt15(0)); + ParallelMath::ConditionalSet(absUnq, isMax, ParallelMath::MakeUInt15(0x7fff)); + + unq = ParallelMath::ConditionalNegate(negative, ParallelMath::LosslessCast<MSInt16>::Cast(absUnq)); + } + + outUnquantized = unq; + + MUInt15 funq = ParallelMath::ToUInt15(ParallelMath::RightShift(ParallelMath::XMultiply(absUnq, ParallelMath::MakeUInt15(31)), 5)); + + outUnquantizedFinished2CL = ParallelMath::ConditionalNegate(negative, ParallelMath::LosslessCast<MSInt16>::Cast(funq)); + } + + static void UnquantizeSingleEndpointElementUnsigned(const MUInt15 &comp, int precision, MUInt16 &outUnquantized, MUInt16 &outUnquantizedFinished) + { + MUInt16 unq = ParallelMath::LosslessCast<MUInt16>::Cast(comp); + if (precision < 15) + { + MUInt15 zero = ParallelMath::MakeUInt15(0); + MUInt15 maxCompMinusOne = ParallelMath::MakeUInt15(static_cast<uint16_t>((1 << precision) - 2)); + + ParallelMath::Int16CompFlag isZero = ParallelMath::Equal(comp, zero); + ParallelMath::Int16CompFlag isMax = ParallelMath::Less(maxCompMinusOne, comp); + + unq = (ParallelMath::LosslessCast<MUInt16>::Cast(comp) << (16 - precision)) + ParallelMath::MakeUInt16(static_cast<uint16_t>(0x8000 >> precision)); + + ParallelMath::ConditionalSet(unq, isZero, ParallelMath::MakeUInt16(0)); + ParallelMath::ConditionalSet(unq, isMax, ParallelMath::MakeUInt16(0xffff)); + } + + outUnquantized = unq; + outUnquantizedFinished = ParallelMath::ToUInt16(ParallelMath::RightShift(ParallelMath::XMultiply(unq, ParallelMath::MakeUInt15(31)), 6)); + } + + static void QuantizeEndpointsSigned(const MSInt16 endPoints[2][3], const MFloat floatPixelsColorSpace[16][3], const MFloat floatPixelsLinearWeighted[16][3], MAInt16 quantizedEndPoints[2][3], MUInt15 indexes[16], IndexSelectorHDR<3> &indexSelector, int fixupIndex, int precision, int indexRange, const float *channelWeights, bool fastIndexing, const ParallelMath::RoundTowardNearestForScope *rtn) + { + MSInt16 unquantizedEP[2][3]; + MSInt16 finishedUnquantizedEP[2][3]; + + { + ParallelMath::RoundUpForScope ru; + + for (int epi = 0; epi < 2; epi++) + { + for (int ch = 0; ch < 3; ch++) + { + MSInt16 qee = QuantizeSingleEndpointElementSigned(endPoints[epi][ch], precision, &ru); + UnquantizeSingleEndpointElementSigned(qee, precision, unquantizedEP[epi][ch], finishedUnquantizedEP[epi][ch]); + quantizedEndPoints[epi][ch] = ParallelMath::LosslessCast<MAInt16>::Cast(qee); + } + } + } + + indexSelector.Init(channelWeights, unquantizedEP, finishedUnquantizedEP, indexRange); + indexSelector.InitHDR(indexRange, true, fastIndexing, channelWeights); + + MUInt15 halfRangeMinusOne = ParallelMath::MakeUInt15(static_cast<uint16_t>(indexRange / 2) - 1); + + MUInt15 index = fastIndexing ? indexSelector.SelectIndexHDRFast(floatPixelsColorSpace[fixupIndex], rtn) : indexSelector.SelectIndexHDRSlow(floatPixelsLinearWeighted[fixupIndex], rtn); + + ParallelMath::Int16CompFlag invert = ParallelMath::Less(halfRangeMinusOne, index); + + if (ParallelMath::AnySet(invert)) + { + ParallelMath::ConditionalSet(index, invert, MUInt15(ParallelMath::MakeUInt15(static_cast<uint16_t>(indexRange - 1)) - index)); + + indexSelector.ConditionalInvert(invert); + + for (int ch = 0; ch < 3; ch++) + { + MAInt16 firstEP = quantizedEndPoints[0][ch]; + MAInt16 secondEP = quantizedEndPoints[1][ch]; + + quantizedEndPoints[0][ch] = ParallelMath::Select(invert, secondEP, firstEP); + quantizedEndPoints[1][ch] = ParallelMath::Select(invert, firstEP, secondEP); + } + } + + indexes[fixupIndex] = index; + } + + static void QuantizeEndpointsUnsigned(const MSInt16 endPoints[2][3], const MFloat floatPixelsColorSpace[16][3], const MFloat floatPixelsLinearWeighted[16][3], MAInt16 quantizedEndPoints[2][3], MUInt15 indexes[16], IndexSelectorHDR<3> &indexSelector, int fixupIndex, int precision, int indexRange, const float *channelWeights, bool fastIndexing, const ParallelMath::RoundTowardNearestForScope *rtn) + { + MUInt16 unquantizedEP[2][3]; + MUInt16 finishedUnquantizedEP[2][3]; + + { + ParallelMath::RoundUpForScope ru; + + for (int epi = 0; epi < 2; epi++) + { + for (int ch = 0; ch < 3; ch++) + { + MUInt15 qee = QuantizeSingleEndpointElementUnsigned(ParallelMath::LosslessCast<MUInt15>::Cast(endPoints[epi][ch]), precision, &ru); + UnquantizeSingleEndpointElementUnsigned(qee, precision, unquantizedEP[epi][ch], finishedUnquantizedEP[epi][ch]); + quantizedEndPoints[epi][ch] = ParallelMath::LosslessCast<MAInt16>::Cast(qee); + } + } + } + + indexSelector.Init(channelWeights, unquantizedEP, finishedUnquantizedEP, indexRange); + indexSelector.InitHDR(indexRange, false, fastIndexing, channelWeights); + + MUInt15 halfRangeMinusOne = ParallelMath::MakeUInt15(static_cast<uint16_t>(indexRange / 2) - 1); + + MUInt15 index = fastIndexing ? indexSelector.SelectIndexHDRFast(floatPixelsColorSpace[fixupIndex], rtn) : indexSelector.SelectIndexHDRSlow(floatPixelsLinearWeighted[fixupIndex], rtn); + + ParallelMath::Int16CompFlag invert = ParallelMath::Less(halfRangeMinusOne, index); + + if (ParallelMath::AnySet(invert)) + { + ParallelMath::ConditionalSet(index, invert, MUInt15(ParallelMath::MakeUInt15(static_cast<uint16_t>(indexRange - 1)) - index)); + + indexSelector.ConditionalInvert(invert); + + for (int ch = 0; ch < 3; ch++) + { + MAInt16 firstEP = quantizedEndPoints[0][ch]; + MAInt16 secondEP = quantizedEndPoints[1][ch]; + + quantizedEndPoints[0][ch] = ParallelMath::Select(invert, secondEP, firstEP); + quantizedEndPoints[1][ch] = ParallelMath::Select(invert, firstEP, secondEP); + } + } + + indexes[fixupIndex] = index; + } + + static void EvaluatePartitionedLegality(const MAInt16 ep0[2][3], const MAInt16 ep1[2][3], int aPrec, const int bPrec[3], bool isTransformed, MAInt16 outEncodedEPs[2][2][3], ParallelMath::Int16CompFlag& outIsLegal) + { + ParallelMath::Int16CompFlag allLegal = ParallelMath::MakeBoolInt16(true); + + MAInt16 aSignificantMask = ParallelMath::MakeAInt16(static_cast<int16_t>((1 << aPrec) - 1)); + + for (int ch = 0; ch < 3; ch++) + { + outEncodedEPs[0][0][ch] = ep0[0][ch]; + outEncodedEPs[0][1][ch] = ep0[1][ch]; + outEncodedEPs[1][0][ch] = ep1[0][ch]; + outEncodedEPs[1][1][ch] = ep1[1][ch]; + + if (isTransformed) + { + for (int subset = 0; subset < 2; subset++) + { + for (int epi = 0; epi < 2; epi++) + { + if (epi == 0 && subset == 0) + continue; + + MAInt16 bReduced = (outEncodedEPs[subset][epi][ch] & aSignificantMask); + + MSInt16 delta = ParallelMath::TruncateToPrecisionSigned(ParallelMath::LosslessCast<MSInt16>::Cast(ParallelMath::AbstractSubtract(outEncodedEPs[subset][epi][ch], outEncodedEPs[0][0][ch])), bPrec[ch]); + + outEncodedEPs[subset][epi][ch] = ParallelMath::LosslessCast<MAInt16>::Cast(delta); + + MAInt16 reconstructed = (ParallelMath::AbstractAdd(outEncodedEPs[subset][epi][ch], outEncodedEPs[0][0][ch]) & aSignificantMask); + allLegal = allLegal & ParallelMath::Equal(reconstructed, bReduced); + } + } + } + + if (!ParallelMath::AnySet(allLegal)) + break; + } + + outIsLegal = allLegal; + } + + static void EvaluateSingleLegality(const MAInt16 ep[2][3], int aPrec, const int bPrec[3], bool isTransformed, MAInt16 outEncodedEPs[2][3], ParallelMath::Int16CompFlag& outIsLegal) + { + ParallelMath::Int16CompFlag allLegal = ParallelMath::MakeBoolInt16(true); + + MAInt16 aSignificantMask = ParallelMath::MakeAInt16(static_cast<int16_t>((1 << aPrec) - 1)); + + for (int ch = 0; ch < 3; ch++) + { + outEncodedEPs[0][ch] = ep[0][ch]; + outEncodedEPs[1][ch] = ep[1][ch]; + + if (isTransformed) + { + MAInt16 bReduced = (outEncodedEPs[1][ch] & aSignificantMask); + + MSInt16 delta = ParallelMath::TruncateToPrecisionSigned(ParallelMath::LosslessCast<MSInt16>::Cast(ParallelMath::AbstractSubtract(outEncodedEPs[1][ch], outEncodedEPs[0][ch])), bPrec[ch]); + + outEncodedEPs[1][ch] = ParallelMath::LosslessCast<MAInt16>::Cast(delta); + + MAInt16 reconstructed = (ParallelMath::AbstractAdd(outEncodedEPs[1][ch], outEncodedEPs[0][ch]) & aSignificantMask); + allLegal = allLegal & ParallelMath::Equal(reconstructed, bReduced); + } + } + + outIsLegal = allLegal; + } + + static void Pack(uint32_t flags, const PixelBlockF16* inputs, uint8_t* packedBlocks, const float channelWeights[4], bool isSigned, int numTweakRounds, int numRefineRounds) + { + if (numTweakRounds < 1) + numTweakRounds = 1; + else if (numTweakRounds > MaxTweakRounds) + numTweakRounds = MaxTweakRounds; + + if (numRefineRounds < 1) + numRefineRounds = 1; + else if (numRefineRounds > MaxRefineRounds) + numRefineRounds = MaxRefineRounds; + + bool fastIndexing = ((flags & cvtt::Flags::BC6H_FastIndexing) != 0); + float channelWeightsSq[3]; + + ParallelMath::RoundTowardNearestForScope rtn; + + MSInt16 pixels[16][3]; + MFloat floatPixels2CL[16][3]; + MFloat floatPixelsLinearWeighted[16][3]; + + MSInt16 low15Bits = ParallelMath::MakeSInt16(32767); + + for (int ch = 0; ch < 3; ch++) + channelWeightsSq[ch] = channelWeights[ch] * channelWeights[ch]; + + for (int px = 0; px < 16; px++) + { + for (int ch = 0; ch < 3; ch++) + { + MSInt16 pixelValue; + ParallelMath::ConvertHDRInputs(inputs, px, ch, pixelValue); + + // Convert from sign+magnitude to 2CL + if (isSigned) + { + ParallelMath::Int16CompFlag negative = ParallelMath::Less(pixelValue, ParallelMath::MakeSInt16(0)); + MSInt16 magnitude = (pixelValue & low15Bits); + ParallelMath::ConditionalSet(pixelValue, negative, ParallelMath::MakeSInt16(0) - magnitude); + pixelValue = ParallelMath::Max(pixelValue, ParallelMath::MakeSInt16(-31743)); + } + else + pixelValue = ParallelMath::Max(pixelValue, ParallelMath::MakeSInt16(0)); + + pixelValue = ParallelMath::Min(pixelValue, ParallelMath::MakeSInt16(31743)); + + pixels[px][ch] = pixelValue; + floatPixels2CL[px][ch] = ParallelMath::ToFloat(pixelValue); + floatPixelsLinearWeighted[px][ch] = ParallelMath::TwosCLHalfToFloat(pixelValue) * channelWeights[ch]; + } + } + + MFloat preWeightedPixels[16][3]; + + BCCommon::PreWeightPixelsHDR<3>(preWeightedPixels, pixels, channelWeights); + + MAInt16 bestEndPoints[2][2][3]; + MUInt15 bestIndexes[16]; + MFloat bestError = ParallelMath::MakeFloat(FLT_MAX); + MUInt15 bestMode = ParallelMath::MakeUInt15(0); + MUInt15 bestPartition = ParallelMath::MakeUInt15(0); + + for (int px = 0; px < 16; px++) + bestIndexes[px] = ParallelMath::MakeUInt15(0); + + for (int subset = 0; subset < 2; subset++) + for (int epi = 0; epi < 2; epi++) + for (int ch = 0; ch < 3; ch++) + bestEndPoints[subset][epi][ch] = ParallelMath::MakeAInt16(0); + + UnfinishedEndpoints<3> partitionedUFEP[32][2]; + UnfinishedEndpoints<3> singleUFEP; + + // Generate UFEP for partitions + for (int p = 0; p < 32; p++) + { + int partitionMask = BC7Data::g_partitionMap[p]; + + EndpointSelector<3, 8> epSelectors[2]; + + for (int pass = 0; pass < NumEndpointSelectorPasses; pass++) + { + for (int px = 0; px < 16; px++) + { + int subset = (partitionMask >> px) & 1; + epSelectors[subset].ContributePass(preWeightedPixels[px], pass, ParallelMath::MakeFloat(1.0f)); + } + + for (int subset = 0; subset < 2; subset++) + epSelectors[subset].FinishPass(pass); + } + + for (int subset = 0; subset < 2; subset++) + partitionedUFEP[p][subset] = epSelectors[subset].GetEndpoints(channelWeights); + } + + // Generate UFEP for single + { + EndpointSelector<3, 8> epSelector; + + for (int pass = 0; pass < NumEndpointSelectorPasses; pass++) + { + for (int px = 0; px < 16; px++) + epSelector.ContributePass(preWeightedPixels[px], pass, ParallelMath::MakeFloat(1.0f)); + + epSelector.FinishPass(pass); + } + + singleUFEP = epSelector.GetEndpoints(channelWeights); + } + + for (int partitionedInt = 0; partitionedInt < 2; partitionedInt++) + { + bool partitioned = (partitionedInt == 1); + + for (int aPrec = BC7Data::g_maxHDRPrecision; aPrec >= 0; aPrec--) + { + if (!BC7Data::g_hdrModesExistForPrecision[partitionedInt][aPrec]) + continue; + + int numPartitions = partitioned ? 32 : 1; + int numSubsets = partitioned ? 2 : 1; + int indexBits = partitioned ? 3 : 4; + int indexRange = (1 << indexBits); + + for (int p = 0; p < numPartitions; p++) + { + int partitionMask = partitioned ? BC7Data::g_partitionMap[p] : 0; + + const int MaxMetaRounds = MaxTweakRounds * MaxRefineRounds; + + MAInt16 metaEndPointsQuantized[MaxMetaRounds][2][2][3]; + MUInt15 metaIndexes[MaxMetaRounds][16]; + MFloat metaError[MaxMetaRounds][2]; + + bool roundValid[MaxMetaRounds][2]; + + for (int r = 0; r < MaxMetaRounds; r++) + for (int subset = 0; subset < 2; subset++) + roundValid[r][subset] = true; + + for (int subset = 0; subset < numSubsets; subset++) + { + for (int tweak = 0; tweak < MaxTweakRounds; tweak++) + { + EndpointRefiner<3> refiners[2]; + + bool abortRemainingRefines = false; + for (int refinePass = 0; refinePass < MaxRefineRounds; refinePass++) + { + int metaRound = tweak * MaxRefineRounds + refinePass; + + if (tweak >= numTweakRounds || refinePass >= numRefineRounds) + abortRemainingRefines = true; + + if (abortRemainingRefines) + { + roundValid[metaRound][subset] = false; + continue; + } + + MAInt16(&mrQuantizedEndPoints)[2][2][3] = metaEndPointsQuantized[metaRound]; + MUInt15(&mrIndexes)[16] = metaIndexes[metaRound]; + + MSInt16 endPointsColorSpace[2][3]; + + if (refinePass == 0) + { + UnfinishedEndpoints<3> ufep = partitioned ? partitionedUFEP[p][subset] : singleUFEP; + + if (isSigned) + ufep.FinishHDRSigned(tweak, indexRange, endPointsColorSpace[0], endPointsColorSpace[1], &rtn); + else + ufep.FinishHDRUnsigned(tweak, indexRange, endPointsColorSpace[0], endPointsColorSpace[1], &rtn); + } + else + refiners[subset].GetRefinedEndpointsHDR(endPointsColorSpace, isSigned, &rtn); + + refiners[subset].Init(indexRange, channelWeights); + + int fixupIndex = (subset == 0) ? 0 : BC7Data::g_fixupIndexes2[p]; + + IndexSelectorHDR<3> indexSelector; + if (isSigned) + QuantizeEndpointsSigned(endPointsColorSpace, floatPixels2CL, floatPixelsLinearWeighted, mrQuantizedEndPoints[subset], mrIndexes, indexSelector, fixupIndex, aPrec, indexRange, channelWeights, fastIndexing, &rtn); + else + QuantizeEndpointsUnsigned(endPointsColorSpace, floatPixels2CL, floatPixelsLinearWeighted, mrQuantizedEndPoints[subset], mrIndexes, indexSelector, fixupIndex, aPrec, indexRange, channelWeights, fastIndexing, &rtn); + + if (metaRound > 0) + { + ParallelMath::Int16CompFlag anySame = ParallelMath::MakeBoolInt16(false); + + for (int prevRound = 0; prevRound < metaRound; prevRound++) + { + MAInt16(&prevRoundEPs)[2][3] = metaEndPointsQuantized[prevRound][subset]; + + ParallelMath::Int16CompFlag same = ParallelMath::MakeBoolInt16(true); + + for (int epi = 0; epi < 2; epi++) + for (int ch = 0; ch < 3; ch++) + same = (same & ParallelMath::Equal(prevRoundEPs[epi][ch], mrQuantizedEndPoints[subset][epi][ch])); + + anySame = (anySame | same); + if (ParallelMath::AllSet(anySame)) + break; + } + + if (ParallelMath::AllSet(anySame)) + { + roundValid[metaRound][subset] = false; + continue; + } + } + + MFloat subsetError = ParallelMath::MakeFloatZero(); + + { + for (int px = 0; px < 16; px++) + { + if (subset != ((partitionMask >> px) & 1)) + continue; + + MUInt15 index; + if (px == fixupIndex) + index = mrIndexes[px]; + else + { + index = fastIndexing ? indexSelector.SelectIndexHDRFast(floatPixels2CL[px], &rtn) : indexSelector.SelectIndexHDRSlow(floatPixelsLinearWeighted[px], &rtn); + mrIndexes[px] = index; + } + + MSInt16 reconstructed[3]; + if (isSigned) + indexSelector.ReconstructHDRSigned(mrIndexes[px], reconstructed); + else + indexSelector.ReconstructHDRUnsigned(mrIndexes[px], reconstructed); + + subsetError = subsetError + (fastIndexing ? BCCommon::ComputeErrorHDRFast<3>(flags, reconstructed, pixels[px], channelWeightsSq) : BCCommon::ComputeErrorHDRSlow<3>(flags, reconstructed, pixels[px], channelWeightsSq)); + + if (refinePass != numRefineRounds - 1) + refiners[subset].ContributeUnweightedPW(preWeightedPixels[px], index); + } + } + + metaError[metaRound][subset] = subsetError; + } + } + } + + // Now we have a bunch of attempts, but not all of them will fit in the delta coding scheme + int numMeta1 = partitioned ? MaxMetaRounds : 1; + for (int meta0 = 0; meta0 < MaxMetaRounds; meta0++) + { + if (!roundValid[meta0][0]) + continue; + + for (int meta1 = 0; meta1 < numMeta1; meta1++) + { + MFloat combinedError = metaError[meta0][0]; + if (partitioned) + { + if (!roundValid[meta1][1]) + continue; + + combinedError = combinedError + metaError[meta1][1]; + } + + ParallelMath::FloatCompFlag errorBetter = ParallelMath::Less(combinedError, bestError); + if (!ParallelMath::AnySet(errorBetter)) + continue; + + ParallelMath::Int16CompFlag needsCommit = ParallelMath::FloatFlagToInt16(errorBetter); + + // Figure out if this is encodable + for (int mode = 0; mode < BC7Data::g_numHDRModes; mode++) + { + const BC7Data::BC6HModeInfo &modeInfo = BC7Data::g_hdrModes[mode]; + + if (modeInfo.m_partitioned != partitioned || modeInfo.m_aPrec != aPrec) + continue; + + MAInt16 encodedEPs[2][2][3]; + ParallelMath::Int16CompFlag isLegal; + if (partitioned) + EvaluatePartitionedLegality(metaEndPointsQuantized[meta0][0], metaEndPointsQuantized[meta1][1], modeInfo.m_aPrec, modeInfo.m_bPrec, modeInfo.m_transformed, encodedEPs, isLegal); + else + EvaluateSingleLegality(metaEndPointsQuantized[meta0][0], modeInfo.m_aPrec, modeInfo.m_bPrec, modeInfo.m_transformed, encodedEPs[0], isLegal); + + ParallelMath::Int16CompFlag isLegalAndBetter = (ParallelMath::FloatFlagToInt16(errorBetter) & isLegal); + if (!ParallelMath::AnySet(isLegalAndBetter)) + continue; + + ParallelMath::FloatCompFlag isLegalAndBetterFloat = ParallelMath::Int16FlagToFloat(isLegalAndBetter); + + ParallelMath::ConditionalSet(bestError, isLegalAndBetterFloat, combinedError); + ParallelMath::ConditionalSet(bestMode, isLegalAndBetter, ParallelMath::MakeUInt15(static_cast<uint16_t>(mode))); + ParallelMath::ConditionalSet(bestPartition, isLegalAndBetter, ParallelMath::MakeUInt15(static_cast<uint16_t>(p))); + + for (int subset = 0; subset < numSubsets; subset++) + { + for (int epi = 0; epi < 2; epi++) + { + for (int ch = 0; ch < 3; ch++) + ParallelMath::ConditionalSet(bestEndPoints[subset][epi][ch], isLegalAndBetter, encodedEPs[subset][epi][ch]); + } + } + + for (int px = 0; px < 16; px++) + { + int subset = ((partitionMask >> px) & 1); + if (subset == 0) + ParallelMath::ConditionalSet(bestIndexes[px], isLegalAndBetter, metaIndexes[meta0][px]); + else + ParallelMath::ConditionalSet(bestIndexes[px], isLegalAndBetter, metaIndexes[meta1][px]); + } + + needsCommit = ParallelMath::AndNot(needsCommit, isLegalAndBetter); + if (!ParallelMath::AnySet(needsCommit)) + break; + } + } + } + } + } + } + + // At this point, everything should be set + for (int block = 0; block < ParallelMath::ParallelSize; block++) + { + ParallelMath::ScalarUInt16 mode = ParallelMath::Extract(bestMode, block); + ParallelMath::ScalarUInt16 partition = ParallelMath::Extract(bestPartition, block); + int32_t eps[2][2][3]; + ParallelMath::ScalarUInt16 indexes[16]; + + const BC7Data::BC6HModeInfo& modeInfo = BC7Data::g_hdrModes[mode]; + + const BC6HData::ModeDescriptor* desc = BC6HData::g_modeDescriptors[mode]; + + const size_t headerBits = modeInfo.m_partitioned ? 82 : 65; + + for (int subset = 0; subset < 2; subset++) + { + for (int epi = 0; epi < 2; epi++) + { + for (int ch = 0; ch < 3; ch++) + eps[subset][epi][ch] = ParallelMath::Extract(bestEndPoints[subset][epi][ch], block); + } + } + + for (int px = 0; px < 16; px++) + indexes[px] = ParallelMath::Extract(bestIndexes[px], block); + + uint16_t modeID = modeInfo.m_modeID; + + PackingVector pv; + pv.Init(); + + for (size_t i = 0; i < headerBits; i++) + { + int32_t codedValue = 0; + switch (desc[i].m_eField) + { + case BC6HData::M: codedValue = modeID; break; + case BC6HData::D: codedValue = partition; break; + case BC6HData::RW: codedValue = eps[0][0][0]; break; + case BC6HData::RX: codedValue = eps[0][1][0]; break; + case BC6HData::RY: codedValue = eps[1][0][0]; break; + case BC6HData::RZ: codedValue = eps[1][1][0]; break; + case BC6HData::GW: codedValue = eps[0][0][1]; break; + case BC6HData::GX: codedValue = eps[0][1][1]; break; + case BC6HData::GY: codedValue = eps[1][0][1]; break; + case BC6HData::GZ: codedValue = eps[1][1][1]; break; + case BC6HData::BW: codedValue = eps[0][0][2]; break; + case BC6HData::BX: codedValue = eps[0][1][2]; break; + case BC6HData::BY: codedValue = eps[1][0][2]; break; + case BC6HData::BZ: codedValue = eps[1][1][2]; break; + default: assert(false); break; + } + + pv.Pack(static_cast<uint16_t>((codedValue >> desc[i].m_uBit) & 1), 1); + } + + int fixupIndex1 = 0; + int indexBits = 4; + if (modeInfo.m_partitioned) + { + fixupIndex1 = BC7Data::g_fixupIndexes2[partition]; + indexBits = 3; + } + + for (int px = 0; px < 16; px++) + { + ParallelMath::ScalarUInt16 index = ParallelMath::Extract(bestIndexes[px], block); + if (px == 0 || px == fixupIndex1) + pv.Pack(index, indexBits - 1); + else + pv.Pack(index, indexBits); + } + + pv.Flush(packedBlocks + 16 * block); + } + } + + static void SignExtendSingle(int &v, int bits) + { + if (v & (1 << (bits - 1))) + v |= -(1 << bits); + } + + static void UnpackOne(PixelBlockF16 &output, const uint8_t *pBC, bool isSigned) + { + UnpackingVector pv; + pv.Init(pBC); + + int numModeBits = 2; + int modeBits = pv.Unpack(2); + if (modeBits != 0 && modeBits != 1) + { + modeBits |= pv.Unpack(3) << 2; + numModeBits += 3; + } + + int mode = -1; + for (int possibleMode = 0; possibleMode < BC7Data::g_numHDRModes; possibleMode++) + { + if (BC7Data::g_hdrModes[possibleMode].m_modeID == modeBits) + { + mode = possibleMode; + break; + } + } + + if (mode < 0) + { + for (int px = 0; px < 16; px++) + { + for (int ch = 0; ch < 3; ch++) + output.m_pixels[px][ch] = 0; + output.m_pixels[px][3] = 0x3c00; // 1.0 + } + return; + } + + const BC7Data::BC6HModeInfo& modeInfo = BC7Data::g_hdrModes[mode]; + const size_t headerBits = modeInfo.m_partitioned ? 82 : 65; + const BC6HData::ModeDescriptor* desc = BC6HData::g_modeDescriptors[mode]; + + int32_t partition = 0; + int32_t eps[2][2][3]; + + for (int subset = 0; subset < 2; subset++) + for (int epi = 0; epi < 2; epi++) + for (int ch = 0; ch < 3; ch++) + eps[subset][epi][ch] = 0; + + for (size_t i = numModeBits; i < headerBits; i++) + { + int32_t *pCodedValue = NULL; + + switch (desc[i].m_eField) + { + case BC6HData::D: pCodedValue = &partition; break; + case BC6HData::RW: pCodedValue = &eps[0][0][0]; break; + case BC6HData::RX: pCodedValue = &eps[0][1][0]; break; + case BC6HData::RY: pCodedValue = &eps[1][0][0]; break; + case BC6HData::RZ: pCodedValue = &eps[1][1][0]; break; + case BC6HData::GW: pCodedValue = &eps[0][0][1]; break; + case BC6HData::GX: pCodedValue = &eps[0][1][1]; break; + case BC6HData::GY: pCodedValue = &eps[1][0][1]; break; + case BC6HData::GZ: pCodedValue = &eps[1][1][1]; break; + case BC6HData::BW: pCodedValue = &eps[0][0][2]; break; + case BC6HData::BX: pCodedValue = &eps[0][1][2]; break; + case BC6HData::BY: pCodedValue = &eps[1][0][2]; break; + case BC6HData::BZ: pCodedValue = &eps[1][1][2]; break; + default: assert(false); break; + } + + (*pCodedValue) |= pv.Unpack(1) << desc[i].m_uBit; + } + + + uint16_t modeID = modeInfo.m_modeID; + + int fixupIndex1 = 0; + int indexBits = 4; + int numSubsets = 1; + if (modeInfo.m_partitioned) + { + fixupIndex1 = BC7Data::g_fixupIndexes2[partition]; + indexBits = 3; + numSubsets = 2; + } + + int indexes[16]; + for (int px = 0; px < 16; px++) + { + if (px == 0 || px == fixupIndex1) + indexes[px] = pv.Unpack(indexBits - 1); + else + indexes[px] = pv.Unpack(indexBits); + } + + if (modeInfo.m_partitioned) + { + for (int ch = 0; ch < 3; ch++) + { + if (isSigned) + SignExtendSingle(eps[0][0][ch], modeInfo.m_aPrec); + if (modeInfo.m_transformed || isSigned) + { + SignExtendSingle(eps[0][1][ch], modeInfo.m_bPrec[ch]); + SignExtendSingle(eps[1][0][ch], modeInfo.m_bPrec[ch]); + SignExtendSingle(eps[1][1][ch], modeInfo.m_bPrec[ch]); + } + } + } + else + { + for (int ch = 0; ch < 3; ch++) + { + if (isSigned) + SignExtendSingle(eps[0][0][ch], modeInfo.m_aPrec); + if (modeInfo.m_transformed || isSigned) + SignExtendSingle(eps[0][1][ch], modeInfo.m_bPrec[ch]); + } + } + + int aPrec = modeInfo.m_aPrec; + + if (modeInfo.m_transformed) + { + for (int ch = 0; ch < 3; ch++) + { + int wrapMask = (1 << aPrec) - 1; + + eps[0][1][ch] = ((eps[0][0][ch] + eps[0][1][ch]) & wrapMask); + if (isSigned) + SignExtendSingle(eps[0][1][ch], aPrec); + + if (modeInfo.m_partitioned) + { + eps[1][0][ch] = ((eps[0][0][ch] + eps[1][0][ch]) & wrapMask); + eps[1][1][ch] = ((eps[0][0][ch] + eps[1][1][ch]) & wrapMask); + + if (isSigned) + { + SignExtendSingle(eps[1][0][ch], aPrec); + SignExtendSingle(eps[1][1][ch], aPrec); + } + } + } + } + + // Unquantize endpoints + for (int subset = 0; subset < numSubsets; subset++) + { + for (int epi = 0; epi < 2; epi++) + { + for (int ch = 0; ch < 3; ch++) + { + int &v = eps[subset][epi][ch]; + + if (isSigned) + { + if (aPrec >= 16) + { + // Nothing + } + else + { + bool s = false; + int comp = v; + if (v < 0) + { + s = true; + comp = -comp; + } + + int unq = 0; + if (comp == 0) + unq = 0; + else if (comp >= ((1 << (aPrec - 1)) - 1)) + unq = 0x7fff; + else + unq = ((comp << 15) + 0x4000) >> (aPrec - 1); + + if (s) + unq = -unq; + + v = unq; + } + } + else + { + if (aPrec >= 15) + { + // Nothing + } + else if (v == 0) + { + // Nothing + } + else if (v == ((1 << aPrec) - 1)) + v = 0xffff; + else + v = ((v << 16) + 0x8000) >> aPrec; + } + } + } + } + + const int *weights = BC7Data::g_weightTables[indexBits]; + + for (int px = 0; px < 16; px++) + { + int subset = 0; + if (modeInfo.m_partitioned) + subset = (BC7Data::g_partitionMap[partition] >> px) & 1; + + int w = weights[indexes[px]]; + for (int ch = 0; ch < 3; ch++) + { + int comp = ((64 - w) * eps[subset][0][ch] + w * eps[subset][1][ch] + 32) >> 6; + + if (isSigned) + { + if (comp < 0) + comp = -(((-comp) * 31) >> 5); + else + comp = (comp * 31) >> 5; + + int s = 0; + if (comp < 0) + { + s = 0x8000; + comp = -comp; + } + + output.m_pixels[px][ch] = static_cast<uint16_t>(s | comp); + } + else + { + comp = (comp * 31) >> 6; + output.m_pixels[px][ch] = static_cast<uint16_t>(comp); + } + } + output.m_pixels[px][3] = 0x3c00; // 1.0 + } + } + }; + + namespace S3TCSingleColorTables + { + struct SingleColorTableEntry + { + uint8_t m_min; + uint8_t m_max; + uint8_t m_actualColor; + uint8_t m_span; + }; + + SingleColorTableEntry g_singleColor5_3[256] = + { + { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 8, 0, 2, 8 }, { 8, 0, 2, 8 }, { 0, 8, 5, 8 }, { 0, 8, 5, 8 }, { 0, 8, 5, 8 }, { 8, 8, 8, 0 }, + { 8, 8, 8, 0 }, { 8, 8, 8, 0 }, { 16, 8, 10, 8 }, { 33, 0, 11, 33 }, { 8, 16, 13, 8 }, { 8, 16, 13, 8 }, { 8, 16, 13, 8 }, { 16, 16, 16, 0 }, + { 16, 16, 16, 0 }, { 16, 16, 16, 0 }, { 24, 16, 18, 8 }, { 41, 8, 19, 33 }, { 16, 24, 21, 8 }, { 16, 24, 21, 8 }, { 0, 33, 22, 33 }, { 24, 24, 24, 0 }, + { 24, 24, 24, 0 }, { 24, 24, 24, 0 }, { 33, 24, 27, 9 }, { 33, 24, 27, 9 }, { 33, 24, 27, 9 }, { 41, 24, 29, 17 }, { 24, 33, 30, 9 }, { 24, 33, 30, 9 }, + { 16, 41, 32, 25 }, { 33, 33, 33, 0 }, { 33, 33, 33, 0 }, { 41, 33, 35, 8 }, { 41, 33, 35, 8 }, { 33, 41, 38, 8 }, { 33, 41, 38, 8 }, { 33, 41, 38, 8 }, + { 24, 49, 40, 25 }, { 41, 41, 41, 0 }, { 41, 41, 41, 0 }, { 49, 41, 43, 8 }, { 66, 33, 44, 33 }, { 41, 49, 46, 8 }, { 41, 49, 46, 8 }, { 41, 49, 46, 8 }, + { 49, 49, 49, 0 }, { 49, 49, 49, 0 }, { 49, 49, 49, 0 }, { 57, 49, 51, 8 }, { 74, 41, 52, 33 }, { 49, 57, 54, 8 }, { 49, 57, 54, 8 }, { 33, 66, 55, 33 }, + { 57, 57, 57, 0 }, { 57, 57, 57, 0 }, { 57, 57, 57, 0 }, { 66, 57, 60, 9 }, { 66, 57, 60, 9 }, { 66, 57, 60, 9 }, { 74, 57, 62, 17 }, { 57, 66, 63, 9 }, + { 57, 66, 63, 9 }, { 49, 74, 65, 25 }, { 66, 66, 66, 0 }, { 66, 66, 66, 0 }, { 74, 66, 68, 8 }, { 74, 66, 68, 8 }, { 66, 74, 71, 8 }, { 66, 74, 71, 8 }, + { 66, 74, 71, 8 }, { 57, 82, 73, 25 }, { 74, 74, 74, 0 }, { 74, 74, 74, 0 }, { 82, 74, 76, 8 }, { 99, 66, 77, 33 }, { 74, 82, 79, 8 }, { 74, 82, 79, 8 }, + { 74, 82, 79, 8 }, { 82, 82, 82, 0 }, { 82, 82, 82, 0 }, { 82, 82, 82, 0 }, { 90, 82, 84, 8 }, { 107, 74, 85, 33 }, { 82, 90, 87, 8 }, { 82, 90, 87, 8 }, + { 66, 99, 88, 33 }, { 90, 90, 90, 0 }, { 90, 90, 90, 0 }, { 90, 90, 90, 0 }, { 99, 90, 93, 9 }, { 99, 90, 93, 9 }, { 99, 90, 93, 9 }, { 107, 90, 95, 17 }, + { 90, 99, 96, 9 }, { 90, 99, 96, 9 }, { 82, 107, 98, 25 }, { 99, 99, 99, 0 }, { 99, 99, 99, 0 }, { 107, 99, 101, 8 }, { 107, 99, 101, 8 }, { 99, 107, 104, 8 }, + { 99, 107, 104, 8 }, { 99, 107, 104, 8 }, { 90, 115, 106, 25 }, { 107, 107, 107, 0 }, { 107, 107, 107, 0 }, { 115, 107, 109, 8 }, { 132, 99, 110, 33 }, { 107, 115, 112, 8 }, + { 107, 115, 112, 8 }, { 107, 115, 112, 8 }, { 115, 115, 115, 0 }, { 115, 115, 115, 0 }, { 115, 115, 115, 0 }, { 123, 115, 117, 8 }, { 140, 107, 118, 33 }, { 115, 123, 120, 8 }, + { 115, 123, 120, 8 }, { 99, 132, 121, 33 }, { 123, 123, 123, 0 }, { 123, 123, 123, 0 }, { 123, 123, 123, 0 }, { 132, 123, 126, 9 }, { 132, 123, 126, 9 }, { 132, 123, 126, 9 }, + { 140, 123, 128, 17 }, { 123, 132, 129, 9 }, { 123, 132, 129, 9 }, { 115, 140, 131, 25 }, { 132, 132, 132, 0 }, { 132, 132, 132, 0 }, { 140, 132, 134, 8 }, { 140, 132, 134, 8 }, + { 132, 140, 137, 8 }, { 132, 140, 137, 8 }, { 132, 140, 137, 8 }, { 123, 148, 139, 25 }, { 140, 140, 140, 0 }, { 140, 140, 140, 0 }, { 148, 140, 142, 8 }, { 165, 132, 143, 33 }, + { 140, 148, 145, 8 }, { 140, 148, 145, 8 }, { 140, 148, 145, 8 }, { 148, 148, 148, 0 }, { 148, 148, 148, 0 }, { 148, 148, 148, 0 }, { 156, 148, 150, 8 }, { 173, 140, 151, 33 }, + { 148, 156, 153, 8 }, { 148, 156, 153, 8 }, { 132, 165, 154, 33 }, { 156, 156, 156, 0 }, { 156, 156, 156, 0 }, { 156, 156, 156, 0 }, { 165, 156, 159, 9 }, { 165, 156, 159, 9 }, + { 165, 156, 159, 9 }, { 173, 156, 161, 17 }, { 156, 165, 162, 9 }, { 156, 165, 162, 9 }, { 148, 173, 164, 25 }, { 165, 165, 165, 0 }, { 165, 165, 165, 0 }, { 173, 165, 167, 8 }, + { 173, 165, 167, 8 }, { 165, 173, 170, 8 }, { 165, 173, 170, 8 }, { 165, 173, 170, 8 }, { 156, 181, 172, 25 }, { 173, 173, 173, 0 }, { 173, 173, 173, 0 }, { 181, 173, 175, 8 }, + { 198, 165, 176, 33 }, { 173, 181, 178, 8 }, { 173, 181, 178, 8 }, { 173, 181, 178, 8 }, { 181, 181, 181, 0 }, { 181, 181, 181, 0 }, { 181, 181, 181, 0 }, { 189, 181, 183, 8 }, + { 206, 173, 184, 33 }, { 181, 189, 186, 8 }, { 181, 189, 186, 8 }, { 165, 198, 187, 33 }, { 189, 189, 189, 0 }, { 189, 189, 189, 0 }, { 189, 189, 189, 0 }, { 198, 189, 192, 9 }, + { 198, 189, 192, 9 }, { 198, 189, 192, 9 }, { 206, 189, 194, 17 }, { 189, 198, 195, 9 }, { 189, 198, 195, 9 }, { 181, 206, 197, 25 }, { 198, 198, 198, 0 }, { 198, 198, 198, 0 }, + { 206, 198, 200, 8 }, { 206, 198, 200, 8 }, { 198, 206, 203, 8 }, { 198, 206, 203, 8 }, { 198, 206, 203, 8 }, { 189, 214, 205, 25 }, { 206, 206, 206, 0 }, { 206, 206, 206, 0 }, + { 214, 206, 208, 8 }, { 231, 198, 209, 33 }, { 206, 214, 211, 8 }, { 206, 214, 211, 8 }, { 206, 214, 211, 8 }, { 214, 214, 214, 0 }, { 214, 214, 214, 0 }, { 214, 214, 214, 0 }, + { 222, 214, 216, 8 }, { 239, 206, 217, 33 }, { 214, 222, 219, 8 }, { 214, 222, 219, 8 }, { 198, 231, 220, 33 }, { 222, 222, 222, 0 }, { 222, 222, 222, 0 }, { 222, 222, 222, 0 }, + { 231, 222, 225, 9 }, { 231, 222, 225, 9 }, { 231, 222, 225, 9 }, { 239, 222, 227, 17 }, { 222, 231, 228, 9 }, { 222, 231, 228, 9 }, { 214, 239, 230, 25 }, { 231, 231, 231, 0 }, + { 231, 231, 231, 0 }, { 239, 231, 233, 8 }, { 239, 231, 233, 8 }, { 231, 239, 236, 8 }, { 231, 239, 236, 8 }, { 231, 239, 236, 8 }, { 222, 247, 238, 25 }, { 239, 239, 239, 0 }, + { 239, 239, 239, 0 }, { 247, 239, 241, 8 }, { 247, 239, 241, 8 }, { 239, 247, 244, 8 }, { 239, 247, 244, 8 }, { 239, 247, 244, 8 }, { 247, 247, 247, 0 }, { 247, 247, 247, 0 }, + { 247, 247, 247, 0 }, { 255, 247, 249, 8 }, { 255, 247, 249, 8 }, { 247, 255, 252, 8 }, { 247, 255, 252, 8 }, { 247, 255, 252, 8 }, { 255, 255, 255, 0 }, { 255, 255, 255, 0 }, + }; + + SingleColorTableEntry g_singleColor6_3[256] = + { + { 0, 0, 0, 0 }, { 4, 0, 1, 4 }, { 0, 4, 2, 4 }, { 4, 4, 4, 0 }, { 4, 4, 4, 0 }, { 8, 4, 5, 4 }, { 4, 8, 6, 4 }, { 8, 8, 8, 0 }, + { 8, 8, 8, 0 }, { 12, 8, 9, 4 }, { 8, 12, 10, 4 }, { 12, 12, 12, 0 }, { 12, 12, 12, 0 }, { 16, 12, 13, 4 }, { 12, 16, 14, 4 }, { 16, 16, 16, 0 }, + { 16, 16, 16, 0 }, { 20, 16, 17, 4 }, { 16, 20, 18, 4 }, { 20, 20, 20, 0 }, { 20, 20, 20, 0 }, { 24, 20, 21, 4 }, { 20, 24, 22, 4 }, { 69, 0, 23, 69 }, + { 24, 24, 24, 0 }, { 28, 24, 25, 4 }, { 24, 28, 26, 4 }, { 65, 8, 27, 57 }, { 28, 28, 28, 0 }, { 32, 28, 29, 4 }, { 28, 32, 30, 4 }, { 69, 12, 31, 57 }, + { 32, 32, 32, 0 }, { 36, 32, 33, 4 }, { 32, 36, 34, 4 }, { 65, 20, 35, 45 }, { 36, 36, 36, 0 }, { 40, 36, 37, 4 }, { 36, 40, 38, 4 }, { 69, 24, 39, 45 }, + { 40, 40, 40, 0 }, { 44, 40, 41, 4 }, { 40, 44, 42, 4 }, { 65, 32, 43, 33 }, { 44, 44, 44, 0 }, { 48, 44, 45, 4 }, { 44, 48, 46, 4 }, { 69, 36, 47, 33 }, + { 48, 48, 48, 0 }, { 52, 48, 49, 4 }, { 48, 52, 50, 4 }, { 65, 44, 51, 21 }, { 52, 52, 52, 0 }, { 56, 52, 53, 4 }, { 52, 56, 54, 4 }, { 69, 48, 55, 21 }, + { 56, 56, 56, 0 }, { 60, 56, 57, 4 }, { 56, 60, 58, 4 }, { 65, 56, 59, 9 }, { 60, 60, 60, 0 }, { 65, 60, 61, 5 }, { 56, 65, 62, 9 }, { 60, 65, 63, 5 }, + { 56, 69, 64, 13 }, { 65, 65, 65, 0 }, { 69, 65, 66, 4 }, { 65, 69, 67, 4 }, { 60, 73, 68, 13 }, { 69, 69, 69, 0 }, { 73, 69, 70, 4 }, { 69, 73, 71, 4 }, + { 56, 81, 72, 25 }, { 73, 73, 73, 0 }, { 77, 73, 74, 4 }, { 73, 77, 75, 4 }, { 60, 85, 76, 25 }, { 77, 77, 77, 0 }, { 81, 77, 78, 4 }, { 77, 81, 79, 4 }, + { 56, 93, 80, 37 }, { 81, 81, 81, 0 }, { 85, 81, 82, 4 }, { 81, 85, 83, 4 }, { 60, 97, 84, 37 }, { 85, 85, 85, 0 }, { 89, 85, 86, 4 }, { 85, 89, 87, 4 }, + { 56, 105, 88, 49 }, { 89, 89, 89, 0 }, { 93, 89, 90, 4 }, { 89, 93, 91, 4 }, { 60, 109, 92, 49 }, { 93, 93, 93, 0 }, { 97, 93, 94, 4 }, { 93, 97, 95, 4 }, + { 134, 77, 96, 57 }, { 97, 97, 97, 0 }, { 101, 97, 98, 4 }, { 97, 101, 99, 4 }, { 130, 85, 100, 45 }, { 101, 101, 101, 0 }, { 105, 101, 102, 4 }, { 101, 105, 103, 4 }, + { 134, 89, 104, 45 }, { 105, 105, 105, 0 }, { 109, 105, 106, 4 }, { 105, 109, 107, 4 }, { 130, 97, 108, 33 }, { 109, 109, 109, 0 }, { 113, 109, 110, 4 }, { 109, 113, 111, 4 }, + { 134, 101, 112, 33 }, { 113, 113, 113, 0 }, { 117, 113, 114, 4 }, { 113, 117, 115, 4 }, { 130, 109, 116, 21 }, { 117, 117, 117, 0 }, { 121, 117, 118, 4 }, { 117, 121, 119, 4 }, + { 134, 113, 120, 21 }, { 121, 121, 121, 0 }, { 125, 121, 122, 4 }, { 121, 125, 123, 4 }, { 130, 121, 124, 9 }, { 125, 125, 125, 0 }, { 130, 125, 126, 5 }, { 121, 130, 127, 9 }, + { 125, 130, 128, 5 }, { 121, 134, 129, 13 }, { 130, 130, 130, 0 }, { 134, 130, 131, 4 }, { 130, 134, 132, 4 }, { 125, 138, 133, 13 }, { 134, 134, 134, 0 }, { 138, 134, 135, 4 }, + { 134, 138, 136, 4 }, { 121, 146, 137, 25 }, { 138, 138, 138, 0 }, { 142, 138, 139, 4 }, { 138, 142, 140, 4 }, { 125, 150, 141, 25 }, { 142, 142, 142, 0 }, { 146, 142, 143, 4 }, + { 142, 146, 144, 4 }, { 121, 158, 145, 37 }, { 146, 146, 146, 0 }, { 150, 146, 147, 4 }, { 146, 150, 148, 4 }, { 125, 162, 149, 37 }, { 150, 150, 150, 0 }, { 154, 150, 151, 4 }, + { 150, 154, 152, 4 }, { 121, 170, 153, 49 }, { 154, 154, 154, 0 }, { 158, 154, 155, 4 }, { 154, 158, 156, 4 }, { 125, 174, 157, 49 }, { 158, 158, 158, 0 }, { 162, 158, 159, 4 }, + { 158, 162, 160, 4 }, { 199, 142, 161, 57 }, { 162, 162, 162, 0 }, { 166, 162, 163, 4 }, { 162, 166, 164, 4 }, { 195, 150, 165, 45 }, { 166, 166, 166, 0 }, { 170, 166, 167, 4 }, + { 166, 170, 168, 4 }, { 199, 154, 169, 45 }, { 170, 170, 170, 0 }, { 174, 170, 171, 4 }, { 170, 174, 172, 4 }, { 195, 162, 173, 33 }, { 174, 174, 174, 0 }, { 178, 174, 175, 4 }, + { 174, 178, 176, 4 }, { 199, 166, 177, 33 }, { 178, 178, 178, 0 }, { 182, 178, 179, 4 }, { 178, 182, 180, 4 }, { 195, 174, 181, 21 }, { 182, 182, 182, 0 }, { 186, 182, 183, 4 }, + { 182, 186, 184, 4 }, { 199, 178, 185, 21 }, { 186, 186, 186, 0 }, { 190, 186, 187, 4 }, { 186, 190, 188, 4 }, { 195, 186, 189, 9 }, { 190, 190, 190, 0 }, { 195, 190, 191, 5 }, + { 186, 195, 192, 9 }, { 190, 195, 193, 5 }, { 186, 199, 194, 13 }, { 195, 195, 195, 0 }, { 199, 195, 196, 4 }, { 195, 199, 197, 4 }, { 190, 203, 198, 13 }, { 199, 199, 199, 0 }, + { 203, 199, 200, 4 }, { 199, 203, 201, 4 }, { 186, 211, 202, 25 }, { 203, 203, 203, 0 }, { 207, 203, 204, 4 }, { 203, 207, 205, 4 }, { 190, 215, 206, 25 }, { 207, 207, 207, 0 }, + { 211, 207, 208, 4 }, { 207, 211, 209, 4 }, { 186, 223, 210, 37 }, { 211, 211, 211, 0 }, { 215, 211, 212, 4 }, { 211, 215, 213, 4 }, { 190, 227, 214, 37 }, { 215, 215, 215, 0 }, + { 219, 215, 216, 4 }, { 215, 219, 217, 4 }, { 186, 235, 218, 49 }, { 219, 219, 219, 0 }, { 223, 219, 220, 4 }, { 219, 223, 221, 4 }, { 190, 239, 222, 49 }, { 223, 223, 223, 0 }, + { 227, 223, 224, 4 }, { 223, 227, 225, 4 }, { 186, 247, 226, 61 }, { 227, 227, 227, 0 }, { 231, 227, 228, 4 }, { 227, 231, 229, 4 }, { 190, 251, 230, 61 }, { 231, 231, 231, 0 }, + { 235, 231, 232, 4 }, { 231, 235, 233, 4 }, { 235, 235, 235, 0 }, { 235, 235, 235, 0 }, { 239, 235, 236, 4 }, { 235, 239, 237, 4 }, { 239, 239, 239, 0 }, { 239, 239, 239, 0 }, + { 243, 239, 240, 4 }, { 239, 243, 241, 4 }, { 243, 243, 243, 0 }, { 243, 243, 243, 0 }, { 247, 243, 244, 4 }, { 243, 247, 245, 4 }, { 247, 247, 247, 0 }, { 247, 247, 247, 0 }, + { 251, 247, 248, 4 }, { 247, 251, 249, 4 }, { 251, 251, 251, 0 }, { 251, 251, 251, 0 }, { 255, 251, 252, 4 }, { 251, 255, 253, 4 }, { 255, 255, 255, 0 }, { 255, 255, 255, 0 }, + }; + + SingleColorTableEntry g_singleColor5_2[256] = + { + { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 8, 4, 8 }, { 0, 8, 4, 8 }, { 0, 8, 4, 8 }, { 8, 8, 8, 0 }, { 8, 8, 8, 0 }, + { 8, 8, 8, 0 }, { 8, 8, 8, 0 }, { 8, 8, 8, 0 }, { 8, 16, 12, 8 }, { 8, 16, 12, 8 }, { 8, 16, 12, 8 }, { 16, 16, 16, 0 }, { 16, 16, 16, 0 }, + { 16, 16, 16, 0 }, { 16, 16, 16, 0 }, { 16, 16, 16, 0 }, { 16, 24, 20, 8 }, { 16, 24, 20, 8 }, { 16, 24, 20, 8 }, { 24, 24, 24, 0 }, { 24, 24, 24, 0 }, + { 24, 24, 24, 0 }, { 24, 24, 24, 0 }, { 24, 24, 24, 0 }, { 24, 33, 28, 9 }, { 24, 33, 28, 9 }, { 24, 33, 28, 9 }, { 24, 33, 28, 9 }, { 24, 41, 32, 17 }, + { 24, 41, 32, 17 }, { 33, 33, 33, 0 }, { 33, 33, 33, 0 }, { 24, 49, 36, 25 }, { 24, 49, 36, 25 }, { 33, 41, 37, 8 }, { 33, 41, 37, 8 }, { 24, 57, 40, 33 }, + { 24, 57, 40, 33 }, { 41, 41, 41, 0 }, { 41, 41, 41, 0 }, { 41, 41, 41, 0 }, { 41, 49, 45, 8 }, { 41, 49, 45, 8 }, { 41, 49, 45, 8 }, { 49, 49, 49, 0 }, + { 49, 49, 49, 0 }, { 49, 49, 49, 0 }, { 49, 49, 49, 0 }, { 49, 49, 49, 0 }, { 49, 57, 53, 8 }, { 49, 57, 53, 8 }, { 49, 57, 53, 8 }, { 57, 57, 57, 0 }, + { 57, 57, 57, 0 }, { 57, 57, 57, 0 }, { 57, 57, 57, 0 }, { 57, 57, 57, 0 }, { 57, 66, 61, 9 }, { 57, 66, 61, 9 }, { 57, 66, 61, 9 }, { 57, 66, 61, 9 }, + { 57, 74, 65, 17 }, { 57, 74, 65, 17 }, { 66, 66, 66, 0 }, { 66, 66, 66, 0 }, { 57, 82, 69, 25 }, { 57, 82, 69, 25 }, { 66, 74, 70, 8 }, { 66, 74, 70, 8 }, + { 57, 90, 73, 33 }, { 57, 90, 73, 33 }, { 74, 74, 74, 0 }, { 74, 74, 74, 0 }, { 74, 74, 74, 0 }, { 74, 82, 78, 8 }, { 74, 82, 78, 8 }, { 74, 82, 78, 8 }, + { 82, 82, 82, 0 }, { 82, 82, 82, 0 }, { 82, 82, 82, 0 }, { 82, 82, 82, 0 }, { 82, 82, 82, 0 }, { 82, 90, 86, 8 }, { 82, 90, 86, 8 }, { 82, 90, 86, 8 }, + { 90, 90, 90, 0 }, { 90, 90, 90, 0 }, { 90, 90, 90, 0 }, { 90, 90, 90, 0 }, { 90, 90, 90, 0 }, { 90, 99, 94, 9 }, { 90, 99, 94, 9 }, { 90, 99, 94, 9 }, + { 90, 99, 94, 9 }, { 90, 107, 98, 17 }, { 90, 107, 98, 17 }, { 99, 99, 99, 0 }, { 99, 99, 99, 0 }, { 90, 115, 102, 25 }, { 90, 115, 102, 25 }, { 99, 107, 103, 8 }, + { 99, 107, 103, 8 }, { 90, 123, 106, 33 }, { 90, 123, 106, 33 }, { 107, 107, 107, 0 }, { 107, 107, 107, 0 }, { 107, 107, 107, 0 }, { 107, 115, 111, 8 }, { 107, 115, 111, 8 }, + { 107, 115, 111, 8 }, { 115, 115, 115, 0 }, { 115, 115, 115, 0 }, { 115, 115, 115, 0 }, { 115, 115, 115, 0 }, { 115, 115, 115, 0 }, { 115, 123, 119, 8 }, { 115, 123, 119, 8 }, + { 115, 123, 119, 8 }, { 123, 123, 123, 0 }, { 123, 123, 123, 0 }, { 123, 123, 123, 0 }, { 123, 123, 123, 0 }, { 123, 123, 123, 0 }, { 123, 132, 127, 9 }, { 123, 132, 127, 9 }, + { 123, 132, 127, 9 }, { 123, 132, 127, 9 }, { 123, 140, 131, 17 }, { 123, 140, 131, 17 }, { 132, 132, 132, 0 }, { 132, 132, 132, 0 }, { 123, 148, 135, 25 }, { 123, 148, 135, 25 }, + { 132, 140, 136, 8 }, { 132, 140, 136, 8 }, { 123, 156, 139, 33 }, { 123, 156, 139, 33 }, { 140, 140, 140, 0 }, { 140, 140, 140, 0 }, { 140, 140, 140, 0 }, { 140, 148, 144, 8 }, + { 140, 148, 144, 8 }, { 140, 148, 144, 8 }, { 148, 148, 148, 0 }, { 148, 148, 148, 0 }, { 148, 148, 148, 0 }, { 148, 148, 148, 0 }, { 148, 148, 148, 0 }, { 148, 156, 152, 8 }, + { 148, 156, 152, 8 }, { 148, 156, 152, 8 }, { 156, 156, 156, 0 }, { 156, 156, 156, 0 }, { 156, 156, 156, 0 }, { 156, 156, 156, 0 }, { 156, 156, 156, 0 }, { 156, 165, 160, 9 }, + { 156, 165, 160, 9 }, { 156, 165, 160, 9 }, { 156, 165, 160, 9 }, { 156, 173, 164, 17 }, { 156, 173, 164, 17 }, { 165, 165, 165, 0 }, { 165, 165, 165, 0 }, { 156, 181, 168, 25 }, + { 156, 181, 168, 25 }, { 165, 173, 169, 8 }, { 165, 173, 169, 8 }, { 156, 189, 172, 33 }, { 156, 189, 172, 33 }, { 173, 173, 173, 0 }, { 173, 173, 173, 0 }, { 173, 173, 173, 0 }, + { 173, 181, 177, 8 }, { 173, 181, 177, 8 }, { 173, 181, 177, 8 }, { 181, 181, 181, 0 }, { 181, 181, 181, 0 }, { 181, 181, 181, 0 }, { 181, 181, 181, 0 }, { 181, 181, 181, 0 }, + { 181, 189, 185, 8 }, { 181, 189, 185, 8 }, { 181, 189, 185, 8 }, { 189, 189, 189, 0 }, { 189, 189, 189, 0 }, { 189, 189, 189, 0 }, { 189, 189, 189, 0 }, { 189, 189, 189, 0 }, + { 189, 198, 193, 9 }, { 189, 198, 193, 9 }, { 189, 198, 193, 9 }, { 189, 198, 193, 9 }, { 189, 206, 197, 17 }, { 189, 206, 197, 17 }, { 198, 198, 198, 0 }, { 198, 198, 198, 0 }, + { 189, 214, 201, 25 }, { 189, 214, 201, 25 }, { 198, 206, 202, 8 }, { 198, 206, 202, 8 }, { 189, 222, 205, 33 }, { 189, 222, 205, 33 }, { 206, 206, 206, 0 }, { 206, 206, 206, 0 }, + { 206, 206, 206, 0 }, { 206, 214, 210, 8 }, { 206, 214, 210, 8 }, { 206, 214, 210, 8 }, { 214, 214, 214, 0 }, { 214, 214, 214, 0 }, { 214, 214, 214, 0 }, { 214, 214, 214, 0 }, + { 214, 214, 214, 0 }, { 214, 222, 218, 8 }, { 214, 222, 218, 8 }, { 214, 222, 218, 8 }, { 222, 222, 222, 0 }, { 222, 222, 222, 0 }, { 222, 222, 222, 0 }, { 222, 222, 222, 0 }, + { 222, 222, 222, 0 }, { 222, 231, 226, 9 }, { 222, 231, 226, 9 }, { 222, 231, 226, 9 }, { 222, 231, 226, 9 }, { 222, 239, 230, 17 }, { 222, 239, 230, 17 }, { 231, 231, 231, 0 }, + { 231, 231, 231, 0 }, { 222, 247, 234, 25 }, { 222, 247, 234, 25 }, { 231, 239, 235, 8 }, { 231, 239, 235, 8 }, { 222, 255, 238, 33 }, { 222, 255, 238, 33 }, { 239, 239, 239, 0 }, + { 239, 239, 239, 0 }, { 239, 239, 239, 0 }, { 239, 247, 243, 8 }, { 239, 247, 243, 8 }, { 239, 247, 243, 8 }, { 247, 247, 247, 0 }, { 247, 247, 247, 0 }, { 247, 247, 247, 0 }, + { 247, 247, 247, 0 }, { 247, 247, 247, 0 }, { 247, 255, 251, 8 }, { 247, 255, 251, 8 }, { 247, 255, 251, 8 }, { 255, 255, 255, 0 }, { 255, 255, 255, 0 }, { 255, 255, 255, 0 }, + }; + + SingleColorTableEntry g_singleColor6_2[256] = + { + { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 4, 2, 4 }, { 4, 4, 4, 0 }, { 4, 4, 4, 0 }, { 4, 4, 4, 0 }, { 4, 8, 6, 4 }, { 8, 8, 8, 0 }, + { 8, 8, 8, 0 }, { 8, 8, 8, 0 }, { 8, 12, 10, 4 }, { 12, 12, 12, 0 }, { 12, 12, 12, 0 }, { 12, 12, 12, 0 }, { 12, 16, 14, 4 }, { 16, 16, 16, 0 }, + { 16, 16, 16, 0 }, { 16, 16, 16, 0 }, { 16, 20, 18, 4 }, { 20, 20, 20, 0 }, { 20, 20, 20, 0 }, { 20, 20, 20, 0 }, { 20, 24, 22, 4 }, { 24, 24, 24, 0 }, + { 24, 24, 24, 0 }, { 24, 24, 24, 0 }, { 24, 28, 26, 4 }, { 28, 28, 28, 0 }, { 28, 28, 28, 0 }, { 28, 28, 28, 0 }, { 28, 32, 30, 4 }, { 32, 32, 32, 0 }, + { 32, 32, 32, 0 }, { 32, 32, 32, 0 }, { 32, 36, 34, 4 }, { 36, 36, 36, 0 }, { 36, 36, 36, 0 }, { 36, 36, 36, 0 }, { 36, 40, 38, 4 }, { 40, 40, 40, 0 }, + { 40, 40, 40, 0 }, { 40, 40, 40, 0 }, { 40, 44, 42, 4 }, { 44, 44, 44, 0 }, { 44, 44, 44, 0 }, { 44, 44, 44, 0 }, { 44, 48, 46, 4 }, { 48, 48, 48, 0 }, + { 48, 48, 48, 0 }, { 48, 48, 48, 0 }, { 48, 52, 50, 4 }, { 52, 52, 52, 0 }, { 52, 52, 52, 0 }, { 52, 52, 52, 0 }, { 52, 56, 54, 4 }, { 56, 56, 56, 0 }, + { 56, 56, 56, 0 }, { 56, 56, 56, 0 }, { 56, 60, 58, 4 }, { 60, 60, 60, 0 }, { 60, 60, 60, 0 }, { 60, 60, 60, 0 }, { 60, 65, 62, 5 }, { 60, 65, 62, 5 }, + { 60, 69, 64, 9 }, { 65, 65, 65, 0 }, { 60, 73, 66, 13 }, { 65, 69, 67, 4 }, { 60, 77, 68, 17 }, { 69, 69, 69, 0 }, { 60, 81, 70, 21 }, { 69, 73, 71, 4 }, + { 60, 85, 72, 25 }, { 73, 73, 73, 0 }, { 60, 89, 74, 29 }, { 73, 77, 75, 4 }, { 60, 93, 76, 33 }, { 77, 77, 77, 0 }, { 60, 97, 78, 37 }, { 77, 81, 79, 4 }, + { 60, 101, 80, 41 }, { 81, 81, 81, 0 }, { 60, 105, 82, 45 }, { 81, 85, 83, 4 }, { 60, 109, 84, 49 }, { 85, 85, 85, 0 }, { 60, 113, 86, 53 }, { 85, 89, 87, 4 }, + { 60, 117, 88, 57 }, { 89, 89, 89, 0 }, { 60, 121, 90, 61 }, { 89, 93, 91, 4 }, { 60, 125, 92, 65 }, { 93, 93, 93, 0 }, { 93, 93, 93, 0 }, { 93, 97, 95, 4 }, + { 97, 97, 97, 0 }, { 97, 97, 97, 0 }, { 97, 97, 97, 0 }, { 97, 101, 99, 4 }, { 101, 101, 101, 0 }, { 101, 101, 101, 0 }, { 101, 101, 101, 0 }, { 101, 105, 103, 4 }, + { 105, 105, 105, 0 }, { 105, 105, 105, 0 }, { 105, 105, 105, 0 }, { 105, 109, 107, 4 }, { 109, 109, 109, 0 }, { 109, 109, 109, 0 }, { 109, 109, 109, 0 }, { 109, 113, 111, 4 }, + { 113, 113, 113, 0 }, { 113, 113, 113, 0 }, { 113, 113, 113, 0 }, { 113, 117, 115, 4 }, { 117, 117, 117, 0 }, { 117, 117, 117, 0 }, { 117, 117, 117, 0 }, { 117, 121, 119, 4 }, + { 121, 121, 121, 0 }, { 121, 121, 121, 0 }, { 121, 121, 121, 0 }, { 121, 125, 123, 4 }, { 125, 125, 125, 0 }, { 125, 125, 125, 0 }, { 125, 125, 125, 0 }, { 125, 130, 127, 5 }, + { 125, 130, 127, 5 }, { 125, 134, 129, 9 }, { 130, 130, 130, 0 }, { 125, 138, 131, 13 }, { 130, 134, 132, 4 }, { 125, 142, 133, 17 }, { 134, 134, 134, 0 }, { 125, 146, 135, 21 }, + { 134, 138, 136, 4 }, { 125, 150, 137, 25 }, { 138, 138, 138, 0 }, { 125, 154, 139, 29 }, { 138, 142, 140, 4 }, { 125, 158, 141, 33 }, { 142, 142, 142, 0 }, { 125, 162, 143, 37 }, + { 142, 146, 144, 4 }, { 125, 166, 145, 41 }, { 146, 146, 146, 0 }, { 125, 170, 147, 45 }, { 146, 150, 148, 4 }, { 125, 174, 149, 49 }, { 150, 150, 150, 0 }, { 125, 178, 151, 53 }, + { 150, 154, 152, 4 }, { 125, 182, 153, 57 }, { 154, 154, 154, 0 }, { 125, 186, 155, 61 }, { 154, 158, 156, 4 }, { 125, 190, 157, 65 }, { 158, 158, 158, 0 }, { 158, 158, 158, 0 }, + { 158, 162, 160, 4 }, { 162, 162, 162, 0 }, { 162, 162, 162, 0 }, { 162, 162, 162, 0 }, { 162, 166, 164, 4 }, { 166, 166, 166, 0 }, { 166, 166, 166, 0 }, { 166, 166, 166, 0 }, + { 166, 170, 168, 4 }, { 170, 170, 170, 0 }, { 170, 170, 170, 0 }, { 170, 170, 170, 0 }, { 170, 174, 172, 4 }, { 174, 174, 174, 0 }, { 174, 174, 174, 0 }, { 174, 174, 174, 0 }, + { 174, 178, 176, 4 }, { 178, 178, 178, 0 }, { 178, 178, 178, 0 }, { 178, 178, 178, 0 }, { 178, 182, 180, 4 }, { 182, 182, 182, 0 }, { 182, 182, 182, 0 }, { 182, 182, 182, 0 }, + { 182, 186, 184, 4 }, { 186, 186, 186, 0 }, { 186, 186, 186, 0 }, { 186, 186, 186, 0 }, { 186, 190, 188, 4 }, { 190, 190, 190, 0 }, { 190, 190, 190, 0 }, { 190, 190, 190, 0 }, + { 190, 195, 192, 5 }, { 190, 195, 192, 5 }, { 190, 199, 194, 9 }, { 195, 195, 195, 0 }, { 190, 203, 196, 13 }, { 195, 199, 197, 4 }, { 190, 207, 198, 17 }, { 199, 199, 199, 0 }, + { 190, 211, 200, 21 }, { 199, 203, 201, 4 }, { 190, 215, 202, 25 }, { 203, 203, 203, 0 }, { 190, 219, 204, 29 }, { 203, 207, 205, 4 }, { 190, 223, 206, 33 }, { 207, 207, 207, 0 }, + { 190, 227, 208, 37 }, { 207, 211, 209, 4 }, { 190, 231, 210, 41 }, { 211, 211, 211, 0 }, { 190, 235, 212, 45 }, { 211, 215, 213, 4 }, { 190, 239, 214, 49 }, { 215, 215, 215, 0 }, + { 190, 243, 216, 53 }, { 215, 219, 217, 4 }, { 190, 247, 218, 57 }, { 219, 219, 219, 0 }, { 190, 251, 220, 61 }, { 219, 223, 221, 4 }, { 190, 255, 222, 65 }, { 223, 223, 223, 0 }, + { 223, 223, 223, 0 }, { 223, 227, 225, 4 }, { 227, 227, 227, 0 }, { 227, 227, 227, 0 }, { 227, 227, 227, 0 }, { 227, 231, 229, 4 }, { 231, 231, 231, 0 }, { 231, 231, 231, 0 }, + { 231, 231, 231, 0 }, { 231, 235, 233, 4 }, { 235, 235, 235, 0 }, { 235, 235, 235, 0 }, { 235, 235, 235, 0 }, { 235, 239, 237, 4 }, { 239, 239, 239, 0 }, { 239, 239, 239, 0 }, + { 239, 239, 239, 0 }, { 239, 243, 241, 4 }, { 243, 243, 243, 0 }, { 243, 243, 243, 0 }, { 243, 243, 243, 0 }, { 243, 247, 245, 4 }, { 247, 247, 247, 0 }, { 247, 247, 247, 0 }, + { 247, 247, 247, 0 }, { 247, 251, 249, 4 }, { 251, 251, 251, 0 }, { 251, 251, 251, 0 }, { 251, 251, 251, 0 }, { 251, 255, 253, 4 }, { 255, 255, 255, 0 }, { 255, 255, 255, 0 }, + }; + + SingleColorTableEntry g_singleColor5_3_p[256] = + { + { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 8, 0, 2, 8 }, { 8, 0, 2, 8 }, { 0, 8, 5, 8 }, { 0, 8, 5, 8 }, { 0, 8, 5, 8 }, { 8, 8, 8, 0 }, + { 8, 8, 8, 0 }, { 8, 8, 8, 0 }, { 16, 8, 10, 8 }, { 33, 0, 11, 33 }, { 8, 16, 13, 8 }, { 8, 16, 13, 8 }, { 8, 16, 13, 8 }, { 16, 16, 16, 0 }, + { 16, 16, 16, 0 }, { 16, 16, 16, 0 }, { 24, 16, 18, 8 }, { 41, 8, 19, 33 }, { 16, 24, 21, 8 }, { 16, 24, 21, 8 }, { 0, 33, 22, 33 }, { 24, 24, 24, 0 }, + { 24, 24, 24, 0 }, { 24, 24, 24, 0 }, { 33, 24, 27, 9 }, { 33, 24, 27, 9 }, { 33, 24, 27, 9 }, { 41, 24, 29, 17 }, { 24, 33, 30, 9 }, { 24, 33, 30, 9 }, + { 16, 41, 32, 25 }, { 33, 33, 33, 0 }, { 33, 33, 33, 0 }, { 41, 33, 35, 8 }, { 41, 33, 35, 8 }, { 33, 41, 38, 8 }, { 33, 41, 38, 8 }, { 33, 41, 38, 8 }, + { 24, 49, 40, 25 }, { 41, 41, 41, 0 }, { 41, 41, 41, 0 }, { 49, 41, 43, 8 }, { 66, 33, 44, 33 }, { 41, 49, 46, 8 }, { 41, 49, 46, 8 }, { 41, 49, 46, 8 }, + { 49, 49, 49, 0 }, { 49, 49, 49, 0 }, { 49, 49, 49, 0 }, { 57, 49, 51, 8 }, { 74, 41, 52, 33 }, { 49, 57, 54, 8 }, { 49, 57, 54, 8 }, { 33, 66, 55, 33 }, + { 57, 57, 57, 0 }, { 57, 57, 57, 0 }, { 57, 57, 57, 0 }, { 66, 57, 60, 9 }, { 66, 57, 60, 9 }, { 66, 57, 60, 9 }, { 74, 57, 62, 17 }, { 57, 66, 63, 9 }, + { 57, 66, 63, 9 }, { 49, 74, 65, 25 }, { 66, 66, 66, 0 }, { 66, 66, 66, 0 }, { 74, 66, 68, 8 }, { 74, 66, 68, 8 }, { 66, 74, 71, 8 }, { 66, 74, 71, 8 }, + { 66, 74, 71, 8 }, { 57, 82, 73, 25 }, { 74, 74, 74, 0 }, { 74, 74, 74, 0 }, { 82, 74, 76, 8 }, { 99, 66, 77, 33 }, { 74, 82, 79, 8 }, { 74, 82, 79, 8 }, + { 74, 82, 79, 8 }, { 82, 82, 82, 0 }, { 82, 82, 82, 0 }, { 82, 82, 82, 0 }, { 90, 82, 84, 8 }, { 107, 74, 85, 33 }, { 82, 90, 87, 8 }, { 82, 90, 87, 8 }, + { 66, 99, 88, 33 }, { 90, 90, 90, 0 }, { 90, 90, 90, 0 }, { 90, 90, 90, 0 }, { 99, 90, 93, 9 }, { 99, 90, 93, 9 }, { 99, 90, 93, 9 }, { 107, 90, 95, 17 }, + { 90, 99, 96, 9 }, { 90, 99, 96, 9 }, { 82, 107, 98, 25 }, { 99, 99, 99, 0 }, { 99, 99, 99, 0 }, { 107, 99, 101, 8 }, { 107, 99, 101, 8 }, { 99, 107, 104, 8 }, + { 99, 107, 104, 8 }, { 99, 107, 104, 8 }, { 90, 115, 106, 25 }, { 107, 107, 107, 0 }, { 107, 107, 107, 0 }, { 115, 107, 109, 8 }, { 132, 99, 110, 33 }, { 107, 115, 112, 8 }, + { 107, 115, 112, 8 }, { 107, 115, 112, 8 }, { 115, 115, 115, 0 }, { 115, 115, 115, 0 }, { 115, 115, 115, 0 }, { 123, 115, 117, 8 }, { 140, 107, 118, 33 }, { 115, 123, 120, 8 }, + { 115, 123, 120, 8 }, { 99, 132, 121, 33 }, { 123, 123, 123, 0 }, { 123, 123, 123, 0 }, { 123, 123, 123, 0 }, { 132, 123, 126, 9 }, { 132, 123, 126, 9 }, { 132, 123, 126, 9 }, + { 140, 123, 128, 17 }, { 123, 132, 129, 9 }, { 123, 132, 129, 9 }, { 115, 140, 131, 25 }, { 132, 132, 132, 0 }, { 132, 132, 132, 0 }, { 140, 132, 134, 8 }, { 140, 132, 134, 8 }, + { 132, 140, 137, 8 }, { 132, 140, 137, 8 }, { 132, 140, 137, 8 }, { 123, 148, 139, 25 }, { 140, 140, 140, 0 }, { 140, 140, 140, 0 }, { 148, 140, 142, 8 }, { 165, 132, 143, 33 }, + { 140, 148, 145, 8 }, { 140, 148, 145, 8 }, { 140, 148, 145, 8 }, { 148, 148, 148, 0 }, { 148, 148, 148, 0 }, { 148, 148, 148, 0 }, { 156, 148, 150, 8 }, { 173, 140, 151, 33 }, + { 148, 156, 153, 8 }, { 148, 156, 153, 8 }, { 132, 165, 154, 33 }, { 156, 156, 156, 0 }, { 156, 156, 156, 0 }, { 156, 156, 156, 0 }, { 165, 156, 159, 9 }, { 165, 156, 159, 9 }, + { 165, 156, 159, 9 }, { 173, 156, 161, 17 }, { 156, 165, 162, 9 }, { 156, 165, 162, 9 }, { 148, 173, 164, 25 }, { 165, 165, 165, 0 }, { 165, 165, 165, 0 }, { 173, 165, 167, 8 }, + { 173, 165, 167, 8 }, { 165, 173, 170, 8 }, { 165, 173, 170, 8 }, { 165, 173, 170, 8 }, { 156, 181, 172, 25 }, { 173, 173, 173, 0 }, { 173, 173, 173, 0 }, { 181, 173, 175, 8 }, + { 198, 165, 176, 33 }, { 173, 181, 178, 8 }, { 173, 181, 178, 8 }, { 173, 181, 178, 8 }, { 181, 181, 181, 0 }, { 181, 181, 181, 0 }, { 181, 181, 181, 0 }, { 189, 181, 183, 8 }, + { 206, 173, 184, 33 }, { 181, 189, 186, 8 }, { 181, 189, 186, 8 }, { 165, 198, 187, 33 }, { 189, 189, 189, 0 }, { 189, 189, 189, 0 }, { 189, 189, 189, 0 }, { 198, 189, 192, 9 }, + { 198, 189, 192, 9 }, { 198, 189, 192, 9 }, { 206, 189, 194, 17 }, { 189, 198, 195, 9 }, { 189, 198, 195, 9 }, { 181, 206, 197, 25 }, { 198, 198, 198, 0 }, { 198, 198, 198, 0 }, + { 206, 198, 200, 8 }, { 206, 198, 200, 8 }, { 198, 206, 203, 8 }, { 198, 206, 203, 8 }, { 198, 206, 203, 8 }, { 189, 214, 205, 25 }, { 206, 206, 206, 0 }, { 206, 206, 206, 0 }, + { 214, 206, 208, 8 }, { 231, 198, 209, 33 }, { 206, 214, 211, 8 }, { 206, 214, 211, 8 }, { 206, 214, 211, 8 }, { 214, 214, 214, 0 }, { 214, 214, 214, 0 }, { 214, 214, 214, 0 }, + { 222, 214, 216, 8 }, { 239, 206, 217, 33 }, { 214, 222, 219, 8 }, { 214, 222, 219, 8 }, { 198, 231, 220, 33 }, { 222, 222, 222, 0 }, { 222, 222, 222, 0 }, { 222, 222, 222, 0 }, + { 231, 222, 225, 9 }, { 231, 222, 225, 9 }, { 231, 222, 225, 9 }, { 239, 222, 227, 17 }, { 222, 231, 228, 9 }, { 222, 231, 228, 9 }, { 214, 239, 230, 25 }, { 231, 231, 231, 0 }, + { 231, 231, 231, 0 }, { 239, 231, 233, 8 }, { 239, 231, 233, 8 }, { 231, 239, 236, 8 }, { 231, 239, 236, 8 }, { 231, 239, 236, 8 }, { 222, 247, 238, 25 }, { 239, 239, 239, 0 }, + { 239, 239, 239, 0 }, { 247, 239, 241, 8 }, { 247, 239, 241, 8 }, { 239, 247, 244, 8 }, { 239, 247, 244, 8 }, { 239, 247, 244, 8 }, { 247, 247, 247, 0 }, { 247, 247, 247, 0 }, + { 247, 247, 247, 0 }, { 255, 247, 249, 8 }, { 255, 247, 249, 8 }, { 247, 255, 252, 8 }, { 247, 255, 252, 8 }, { 247, 255, 252, 8 }, { 255, 255, 255, 0 }, { 255, 255, 255, 0 }, + }; + + SingleColorTableEntry g_singleColor6_3_p[256] = + { + { 0, 0, 0, 0 }, { 4, 0, 1, 4 }, { 0, 4, 2, 4 }, { 4, 4, 4, 0 }, { 4, 4, 4, 0 }, { 8, 4, 5, 4 }, { 4, 8, 6, 4 }, { 8, 8, 8, 0 }, + { 8, 8, 8, 0 }, { 12, 8, 9, 4 }, { 8, 12, 10, 4 }, { 12, 12, 12, 0 }, { 12, 12, 12, 0 }, { 16, 12, 13, 4 }, { 12, 16, 14, 4 }, { 16, 16, 16, 0 }, + { 16, 16, 16, 0 }, { 20, 16, 17, 4 }, { 16, 20, 18, 4 }, { 20, 20, 20, 0 }, { 20, 20, 20, 0 }, { 24, 20, 21, 4 }, { 20, 24, 22, 4 }, { 24, 24, 24, 0 }, + { 24, 24, 24, 0 }, { 28, 24, 25, 4 }, { 24, 28, 26, 4 }, { 28, 28, 28, 0 }, { 28, 28, 28, 0 }, { 32, 28, 29, 4 }, { 28, 32, 30, 4 }, { 32, 32, 32, 0 }, + { 32, 32, 32, 0 }, { 36, 32, 33, 4 }, { 32, 36, 34, 4 }, { 36, 36, 36, 0 }, { 36, 36, 36, 0 }, { 40, 36, 37, 4 }, { 36, 40, 38, 4 }, { 40, 40, 40, 0 }, + { 40, 40, 40, 0 }, { 44, 40, 41, 4 }, { 40, 44, 42, 4 }, { 65, 32, 43, 33 }, { 44, 44, 44, 0 }, { 48, 44, 45, 4 }, { 44, 48, 46, 4 }, { 69, 36, 47, 33 }, + { 48, 48, 48, 0 }, { 52, 48, 49, 4 }, { 48, 52, 50, 4 }, { 65, 44, 51, 21 }, { 52, 52, 52, 0 }, { 56, 52, 53, 4 }, { 52, 56, 54, 4 }, { 69, 48, 55, 21 }, + { 56, 56, 56, 0 }, { 60, 56, 57, 4 }, { 56, 60, 58, 4 }, { 65, 56, 59, 9 }, { 60, 60, 60, 0 }, { 65, 60, 61, 5 }, { 56, 65, 62, 9 }, { 60, 65, 63, 5 }, + { 56, 69, 64, 13 }, { 65, 65, 65, 0 }, { 69, 65, 66, 4 }, { 65, 69, 67, 4 }, { 60, 73, 68, 13 }, { 69, 69, 69, 0 }, { 73, 69, 70, 4 }, { 69, 73, 71, 4 }, + { 56, 81, 72, 25 }, { 73, 73, 73, 0 }, { 77, 73, 74, 4 }, { 73, 77, 75, 4 }, { 60, 85, 76, 25 }, { 77, 77, 77, 0 }, { 81, 77, 78, 4 }, { 77, 81, 79, 4 }, + { 81, 81, 81, 0 }, { 81, 81, 81, 0 }, { 85, 81, 82, 4 }, { 81, 85, 83, 4 }, { 85, 85, 85, 0 }, { 85, 85, 85, 0 }, { 89, 85, 86, 4 }, { 85, 89, 87, 4 }, + { 89, 89, 89, 0 }, { 89, 89, 89, 0 }, { 93, 89, 90, 4 }, { 89, 93, 91, 4 }, { 93, 93, 93, 0 }, { 93, 93, 93, 0 }, { 97, 93, 94, 4 }, { 93, 97, 95, 4 }, + { 97, 97, 97, 0 }, { 97, 97, 97, 0 }, { 101, 97, 98, 4 }, { 97, 101, 99, 4 }, { 101, 101, 101, 0 }, { 101, 101, 101, 0 }, { 105, 101, 102, 4 }, { 101, 105, 103, 4 }, + { 105, 105, 105, 0 }, { 105, 105, 105, 0 }, { 109, 105, 106, 4 }, { 105, 109, 107, 4 }, { 130, 97, 108, 33 }, { 109, 109, 109, 0 }, { 113, 109, 110, 4 }, { 109, 113, 111, 4 }, + { 134, 101, 112, 33 }, { 113, 113, 113, 0 }, { 117, 113, 114, 4 }, { 113, 117, 115, 4 }, { 130, 109, 116, 21 }, { 117, 117, 117, 0 }, { 121, 117, 118, 4 }, { 117, 121, 119, 4 }, + { 134, 113, 120, 21 }, { 121, 121, 121, 0 }, { 125, 121, 122, 4 }, { 121, 125, 123, 4 }, { 130, 121, 124, 9 }, { 125, 125, 125, 0 }, { 130, 125, 126, 5 }, { 121, 130, 127, 9 }, + { 125, 130, 128, 5 }, { 121, 134, 129, 13 }, { 130, 130, 130, 0 }, { 134, 130, 131, 4 }, { 130, 134, 132, 4 }, { 125, 138, 133, 13 }, { 134, 134, 134, 0 }, { 138, 134, 135, 4 }, + { 134, 138, 136, 4 }, { 121, 146, 137, 25 }, { 138, 138, 138, 0 }, { 142, 138, 139, 4 }, { 138, 142, 140, 4 }, { 125, 150, 141, 25 }, { 142, 142, 142, 0 }, { 146, 142, 143, 4 }, + { 142, 146, 144, 4 }, { 146, 146, 146, 0 }, { 146, 146, 146, 0 }, { 150, 146, 147, 4 }, { 146, 150, 148, 4 }, { 150, 150, 150, 0 }, { 150, 150, 150, 0 }, { 154, 150, 151, 4 }, + { 150, 154, 152, 4 }, { 154, 154, 154, 0 }, { 154, 154, 154, 0 }, { 158, 154, 155, 4 }, { 154, 158, 156, 4 }, { 158, 158, 158, 0 }, { 158, 158, 158, 0 }, { 162, 158, 159, 4 }, + { 158, 162, 160, 4 }, { 162, 162, 162, 0 }, { 162, 162, 162, 0 }, { 166, 162, 163, 4 }, { 162, 166, 164, 4 }, { 166, 166, 166, 0 }, { 166, 166, 166, 0 }, { 170, 166, 167, 4 }, + { 166, 170, 168, 4 }, { 170, 170, 170, 0 }, { 170, 170, 170, 0 }, { 174, 170, 171, 4 }, { 170, 174, 172, 4 }, { 195, 162, 173, 33 }, { 174, 174, 174, 0 }, { 178, 174, 175, 4 }, + { 174, 178, 176, 4 }, { 199, 166, 177, 33 }, { 178, 178, 178, 0 }, { 182, 178, 179, 4 }, { 178, 182, 180, 4 }, { 195, 174, 181, 21 }, { 182, 182, 182, 0 }, { 186, 182, 183, 4 }, + { 182, 186, 184, 4 }, { 199, 178, 185, 21 }, { 186, 186, 186, 0 }, { 190, 186, 187, 4 }, { 186, 190, 188, 4 }, { 195, 186, 189, 9 }, { 190, 190, 190, 0 }, { 195, 190, 191, 5 }, + { 186, 195, 192, 9 }, { 190, 195, 193, 5 }, { 186, 199, 194, 13 }, { 195, 195, 195, 0 }, { 199, 195, 196, 4 }, { 195, 199, 197, 4 }, { 190, 203, 198, 13 }, { 199, 199, 199, 0 }, + { 203, 199, 200, 4 }, { 199, 203, 201, 4 }, { 186, 211, 202, 25 }, { 203, 203, 203, 0 }, { 207, 203, 204, 4 }, { 203, 207, 205, 4 }, { 190, 215, 206, 25 }, { 207, 207, 207, 0 }, + { 211, 207, 208, 4 }, { 207, 211, 209, 4 }, { 211, 211, 211, 0 }, { 211, 211, 211, 0 }, { 215, 211, 212, 4 }, { 211, 215, 213, 4 }, { 215, 215, 215, 0 }, { 215, 215, 215, 0 }, + { 219, 215, 216, 4 }, { 215, 219, 217, 4 }, { 219, 219, 219, 0 }, { 219, 219, 219, 0 }, { 223, 219, 220, 4 }, { 219, 223, 221, 4 }, { 223, 223, 223, 0 }, { 223, 223, 223, 0 }, + { 227, 223, 224, 4 }, { 223, 227, 225, 4 }, { 227, 227, 227, 0 }, { 227, 227, 227, 0 }, { 231, 227, 228, 4 }, { 227, 231, 229, 4 }, { 231, 231, 231, 0 }, { 231, 231, 231, 0 }, + { 235, 231, 232, 4 }, { 231, 235, 233, 4 }, { 235, 235, 235, 0 }, { 235, 235, 235, 0 }, { 239, 235, 236, 4 }, { 235, 239, 237, 4 }, { 239, 239, 239, 0 }, { 239, 239, 239, 0 }, + { 243, 239, 240, 4 }, { 239, 243, 241, 4 }, { 243, 243, 243, 0 }, { 243, 243, 243, 0 }, { 247, 243, 244, 4 }, { 243, 247, 245, 4 }, { 247, 247, 247, 0 }, { 247, 247, 247, 0 }, + { 251, 247, 248, 4 }, { 247, 251, 249, 4 }, { 251, 251, 251, 0 }, { 251, 251, 251, 0 }, { 255, 251, 252, 4 }, { 251, 255, 253, 4 }, { 255, 255, 255, 0 }, { 255, 255, 255, 0 }, + }; + + SingleColorTableEntry g_singleColor5_2_p[256] = + { + { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 8, 4, 8 }, { 0, 8, 4, 8 }, { 0, 8, 4, 8 }, { 8, 8, 8, 0 }, { 8, 8, 8, 0 }, + { 8, 8, 8, 0 }, { 8, 8, 8, 0 }, { 8, 8, 8, 0 }, { 8, 16, 12, 8 }, { 8, 16, 12, 8 }, { 8, 16, 12, 8 }, { 16, 16, 16, 0 }, { 16, 16, 16, 0 }, + { 16, 16, 16, 0 }, { 16, 16, 16, 0 }, { 16, 16, 16, 0 }, { 16, 24, 20, 8 }, { 16, 24, 20, 8 }, { 16, 24, 20, 8 }, { 24, 24, 24, 0 }, { 24, 24, 24, 0 }, + { 24, 24, 24, 0 }, { 24, 24, 24, 0 }, { 24, 24, 24, 0 }, { 24, 33, 28, 9 }, { 24, 33, 28, 9 }, { 24, 33, 28, 9 }, { 24, 33, 28, 9 }, { 24, 41, 32, 17 }, + { 24, 41, 32, 17 }, { 33, 33, 33, 0 }, { 33, 33, 33, 0 }, { 24, 49, 36, 25 }, { 24, 49, 36, 25 }, { 33, 41, 37, 8 }, { 33, 41, 37, 8 }, { 24, 57, 40, 33 }, + { 24, 57, 40, 33 }, { 41, 41, 41, 0 }, { 41, 41, 41, 0 }, { 41, 41, 41, 0 }, { 41, 49, 45, 8 }, { 41, 49, 45, 8 }, { 41, 49, 45, 8 }, { 49, 49, 49, 0 }, + { 49, 49, 49, 0 }, { 49, 49, 49, 0 }, { 49, 49, 49, 0 }, { 49, 49, 49, 0 }, { 49, 57, 53, 8 }, { 49, 57, 53, 8 }, { 49, 57, 53, 8 }, { 57, 57, 57, 0 }, + { 57, 57, 57, 0 }, { 57, 57, 57, 0 }, { 57, 57, 57, 0 }, { 57, 57, 57, 0 }, { 57, 66, 61, 9 }, { 57, 66, 61, 9 }, { 57, 66, 61, 9 }, { 57, 66, 61, 9 }, + { 57, 74, 65, 17 }, { 57, 74, 65, 17 }, { 66, 66, 66, 0 }, { 66, 66, 66, 0 }, { 57, 82, 69, 25 }, { 57, 82, 69, 25 }, { 66, 74, 70, 8 }, { 66, 74, 70, 8 }, + { 57, 90, 73, 33 }, { 57, 90, 73, 33 }, { 74, 74, 74, 0 }, { 74, 74, 74, 0 }, { 74, 74, 74, 0 }, { 74, 82, 78, 8 }, { 74, 82, 78, 8 }, { 74, 82, 78, 8 }, + { 82, 82, 82, 0 }, { 82, 82, 82, 0 }, { 82, 82, 82, 0 }, { 82, 82, 82, 0 }, { 82, 82, 82, 0 }, { 82, 90, 86, 8 }, { 82, 90, 86, 8 }, { 82, 90, 86, 8 }, + { 90, 90, 90, 0 }, { 90, 90, 90, 0 }, { 90, 90, 90, 0 }, { 90, 90, 90, 0 }, { 90, 90, 90, 0 }, { 90, 99, 94, 9 }, { 90, 99, 94, 9 }, { 90, 99, 94, 9 }, + { 90, 99, 94, 9 }, { 90, 107, 98, 17 }, { 90, 107, 98, 17 }, { 99, 99, 99, 0 }, { 99, 99, 99, 0 }, { 90, 115, 102, 25 }, { 90, 115, 102, 25 }, { 99, 107, 103, 8 }, + { 99, 107, 103, 8 }, { 90, 123, 106, 33 }, { 90, 123, 106, 33 }, { 107, 107, 107, 0 }, { 107, 107, 107, 0 }, { 107, 107, 107, 0 }, { 107, 115, 111, 8 }, { 107, 115, 111, 8 }, + { 107, 115, 111, 8 }, { 115, 115, 115, 0 }, { 115, 115, 115, 0 }, { 115, 115, 115, 0 }, { 115, 115, 115, 0 }, { 115, 115, 115, 0 }, { 115, 123, 119, 8 }, { 115, 123, 119, 8 }, + { 115, 123, 119, 8 }, { 123, 123, 123, 0 }, { 123, 123, 123, 0 }, { 123, 123, 123, 0 }, { 123, 123, 123, 0 }, { 123, 123, 123, 0 }, { 123, 132, 127, 9 }, { 123, 132, 127, 9 }, + { 123, 132, 127, 9 }, { 123, 132, 127, 9 }, { 123, 140, 131, 17 }, { 123, 140, 131, 17 }, { 132, 132, 132, 0 }, { 132, 132, 132, 0 }, { 123, 148, 135, 25 }, { 123, 148, 135, 25 }, + { 132, 140, 136, 8 }, { 132, 140, 136, 8 }, { 123, 156, 139, 33 }, { 123, 156, 139, 33 }, { 140, 140, 140, 0 }, { 140, 140, 140, 0 }, { 140, 140, 140, 0 }, { 140, 148, 144, 8 }, + { 140, 148, 144, 8 }, { 140, 148, 144, 8 }, { 148, 148, 148, 0 }, { 148, 148, 148, 0 }, { 148, 148, 148, 0 }, { 148, 148, 148, 0 }, { 148, 148, 148, 0 }, { 148, 156, 152, 8 }, + { 148, 156, 152, 8 }, { 148, 156, 152, 8 }, { 156, 156, 156, 0 }, { 156, 156, 156, 0 }, { 156, 156, 156, 0 }, { 156, 156, 156, 0 }, { 156, 156, 156, 0 }, { 156, 165, 160, 9 }, + { 156, 165, 160, 9 }, { 156, 165, 160, 9 }, { 156, 165, 160, 9 }, { 156, 173, 164, 17 }, { 156, 173, 164, 17 }, { 165, 165, 165, 0 }, { 165, 165, 165, 0 }, { 156, 181, 168, 25 }, + { 156, 181, 168, 25 }, { 165, 173, 169, 8 }, { 165, 173, 169, 8 }, { 156, 189, 172, 33 }, { 156, 189, 172, 33 }, { 173, 173, 173, 0 }, { 173, 173, 173, 0 }, { 173, 173, 173, 0 }, + { 173, 181, 177, 8 }, { 173, 181, 177, 8 }, { 173, 181, 177, 8 }, { 181, 181, 181, 0 }, { 181, 181, 181, 0 }, { 181, 181, 181, 0 }, { 181, 181, 181, 0 }, { 181, 181, 181, 0 }, + { 181, 189, 185, 8 }, { 181, 189, 185, 8 }, { 181, 189, 185, 8 }, { 189, 189, 189, 0 }, { 189, 189, 189, 0 }, { 189, 189, 189, 0 }, { 189, 189, 189, 0 }, { 189, 189, 189, 0 }, + { 189, 198, 193, 9 }, { 189, 198, 193, 9 }, { 189, 198, 193, 9 }, { 189, 198, 193, 9 }, { 189, 206, 197, 17 }, { 189, 206, 197, 17 }, { 198, 198, 198, 0 }, { 198, 198, 198, 0 }, + { 189, 214, 201, 25 }, { 189, 214, 201, 25 }, { 198, 206, 202, 8 }, { 198, 206, 202, 8 }, { 189, 222, 205, 33 }, { 189, 222, 205, 33 }, { 206, 206, 206, 0 }, { 206, 206, 206, 0 }, + { 206, 206, 206, 0 }, { 206, 214, 210, 8 }, { 206, 214, 210, 8 }, { 206, 214, 210, 8 }, { 214, 214, 214, 0 }, { 214, 214, 214, 0 }, { 214, 214, 214, 0 }, { 214, 214, 214, 0 }, + { 214, 214, 214, 0 }, { 214, 222, 218, 8 }, { 214, 222, 218, 8 }, { 214, 222, 218, 8 }, { 222, 222, 222, 0 }, { 222, 222, 222, 0 }, { 222, 222, 222, 0 }, { 222, 222, 222, 0 }, + { 222, 222, 222, 0 }, { 222, 231, 226, 9 }, { 222, 231, 226, 9 }, { 222, 231, 226, 9 }, { 222, 231, 226, 9 }, { 222, 239, 230, 17 }, { 222, 239, 230, 17 }, { 231, 231, 231, 0 }, + { 231, 231, 231, 0 }, { 222, 247, 234, 25 }, { 222, 247, 234, 25 }, { 231, 239, 235, 8 }, { 231, 239, 235, 8 }, { 222, 255, 238, 33 }, { 222, 255, 238, 33 }, { 239, 239, 239, 0 }, + { 239, 239, 239, 0 }, { 239, 239, 239, 0 }, { 239, 247, 243, 8 }, { 239, 247, 243, 8 }, { 239, 247, 243, 8 }, { 247, 247, 247, 0 }, { 247, 247, 247, 0 }, { 247, 247, 247, 0 }, + { 247, 247, 247, 0 }, { 247, 247, 247, 0 }, { 247, 255, 251, 8 }, { 247, 255, 251, 8 }, { 247, 255, 251, 8 }, { 255, 255, 255, 0 }, { 255, 255, 255, 0 }, { 255, 255, 255, 0 }, + }; + + SingleColorTableEntry g_singleColor6_2_p[256] = + { + { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 4, 2, 4 }, { 4, 4, 4, 0 }, { 4, 4, 4, 0 }, { 4, 4, 4, 0 }, { 4, 8, 6, 4 }, { 8, 8, 8, 0 }, + { 8, 8, 8, 0 }, { 8, 8, 8, 0 }, { 8, 12, 10, 4 }, { 12, 12, 12, 0 }, { 12, 12, 12, 0 }, { 12, 12, 12, 0 }, { 12, 16, 14, 4 }, { 16, 16, 16, 0 }, + { 16, 16, 16, 0 }, { 16, 16, 16, 0 }, { 16, 20, 18, 4 }, { 20, 20, 20, 0 }, { 20, 20, 20, 0 }, { 20, 20, 20, 0 }, { 20, 24, 22, 4 }, { 24, 24, 24, 0 }, + { 24, 24, 24, 0 }, { 24, 24, 24, 0 }, { 24, 28, 26, 4 }, { 28, 28, 28, 0 }, { 28, 28, 28, 0 }, { 28, 28, 28, 0 }, { 28, 32, 30, 4 }, { 32, 32, 32, 0 }, + { 32, 32, 32, 0 }, { 32, 32, 32, 0 }, { 32, 36, 34, 4 }, { 36, 36, 36, 0 }, { 36, 36, 36, 0 }, { 36, 36, 36, 0 }, { 36, 40, 38, 4 }, { 40, 40, 40, 0 }, + { 40, 40, 40, 0 }, { 40, 40, 40, 0 }, { 40, 44, 42, 4 }, { 44, 44, 44, 0 }, { 44, 44, 44, 0 }, { 44, 44, 44, 0 }, { 44, 48, 46, 4 }, { 48, 48, 48, 0 }, + { 48, 48, 48, 0 }, { 48, 48, 48, 0 }, { 48, 52, 50, 4 }, { 52, 52, 52, 0 }, { 52, 52, 52, 0 }, { 52, 52, 52, 0 }, { 52, 56, 54, 4 }, { 56, 56, 56, 0 }, + { 56, 56, 56, 0 }, { 56, 56, 56, 0 }, { 56, 60, 58, 4 }, { 60, 60, 60, 0 }, { 60, 60, 60, 0 }, { 60, 60, 60, 0 }, { 60, 65, 62, 5 }, { 60, 65, 62, 5 }, + { 60, 69, 64, 9 }, { 65, 65, 65, 0 }, { 60, 73, 66, 13 }, { 65, 69, 67, 4 }, { 60, 77, 68, 17 }, { 69, 69, 69, 0 }, { 60, 81, 70, 21 }, { 69, 73, 71, 4 }, + { 60, 85, 72, 25 }, { 73, 73, 73, 0 }, { 60, 89, 74, 29 }, { 73, 77, 75, 4 }, { 60, 93, 76, 33 }, { 77, 77, 77, 0 }, { 77, 77, 77, 0 }, { 77, 81, 79, 4 }, + { 81, 81, 81, 0 }, { 81, 81, 81, 0 }, { 81, 81, 81, 0 }, { 81, 85, 83, 4 }, { 85, 85, 85, 0 }, { 85, 85, 85, 0 }, { 85, 85, 85, 0 }, { 85, 89, 87, 4 }, + { 89, 89, 89, 0 }, { 89, 89, 89, 0 }, { 89, 89, 89, 0 }, { 89, 93, 91, 4 }, { 93, 93, 93, 0 }, { 93, 93, 93, 0 }, { 93, 93, 93, 0 }, { 93, 97, 95, 4 }, + { 97, 97, 97, 0 }, { 97, 97, 97, 0 }, { 97, 97, 97, 0 }, { 97, 101, 99, 4 }, { 101, 101, 101, 0 }, { 101, 101, 101, 0 }, { 101, 101, 101, 0 }, { 101, 105, 103, 4 }, + { 105, 105, 105, 0 }, { 105, 105, 105, 0 }, { 105, 105, 105, 0 }, { 105, 109, 107, 4 }, { 109, 109, 109, 0 }, { 109, 109, 109, 0 }, { 109, 109, 109, 0 }, { 109, 113, 111, 4 }, + { 113, 113, 113, 0 }, { 113, 113, 113, 0 }, { 113, 113, 113, 0 }, { 113, 117, 115, 4 }, { 117, 117, 117, 0 }, { 117, 117, 117, 0 }, { 117, 117, 117, 0 }, { 117, 121, 119, 4 }, + { 121, 121, 121, 0 }, { 121, 121, 121, 0 }, { 121, 121, 121, 0 }, { 121, 125, 123, 4 }, { 125, 125, 125, 0 }, { 125, 125, 125, 0 }, { 125, 125, 125, 0 }, { 125, 130, 127, 5 }, + { 125, 130, 127, 5 }, { 125, 134, 129, 9 }, { 130, 130, 130, 0 }, { 125, 138, 131, 13 }, { 130, 134, 132, 4 }, { 125, 142, 133, 17 }, { 134, 134, 134, 0 }, { 125, 146, 135, 21 }, + { 134, 138, 136, 4 }, { 125, 150, 137, 25 }, { 138, 138, 138, 0 }, { 125, 154, 139, 29 }, { 138, 142, 140, 4 }, { 125, 158, 141, 33 }, { 142, 142, 142, 0 }, { 142, 142, 142, 0 }, + { 142, 146, 144, 4 }, { 146, 146, 146, 0 }, { 146, 146, 146, 0 }, { 146, 146, 146, 0 }, { 146, 150, 148, 4 }, { 150, 150, 150, 0 }, { 150, 150, 150, 0 }, { 150, 150, 150, 0 }, + { 150, 154, 152, 4 }, { 154, 154, 154, 0 }, { 154, 154, 154, 0 }, { 154, 154, 154, 0 }, { 154, 158, 156, 4 }, { 158, 158, 158, 0 }, { 158, 158, 158, 0 }, { 158, 158, 158, 0 }, + { 158, 162, 160, 4 }, { 162, 162, 162, 0 }, { 162, 162, 162, 0 }, { 162, 162, 162, 0 }, { 162, 166, 164, 4 }, { 166, 166, 166, 0 }, { 166, 166, 166, 0 }, { 166, 166, 166, 0 }, + { 166, 170, 168, 4 }, { 170, 170, 170, 0 }, { 170, 170, 170, 0 }, { 170, 170, 170, 0 }, { 170, 174, 172, 4 }, { 174, 174, 174, 0 }, { 174, 174, 174, 0 }, { 174, 174, 174, 0 }, + { 174, 178, 176, 4 }, { 178, 178, 178, 0 }, { 178, 178, 178, 0 }, { 178, 178, 178, 0 }, { 178, 182, 180, 4 }, { 182, 182, 182, 0 }, { 182, 182, 182, 0 }, { 182, 182, 182, 0 }, + { 182, 186, 184, 4 }, { 186, 186, 186, 0 }, { 186, 186, 186, 0 }, { 186, 186, 186, 0 }, { 186, 190, 188, 4 }, { 190, 190, 190, 0 }, { 190, 190, 190, 0 }, { 190, 190, 190, 0 }, + { 190, 195, 192, 5 }, { 190, 195, 192, 5 }, { 190, 199, 194, 9 }, { 195, 195, 195, 0 }, { 190, 203, 196, 13 }, { 195, 199, 197, 4 }, { 190, 207, 198, 17 }, { 199, 199, 199, 0 }, + { 190, 211, 200, 21 }, { 199, 203, 201, 4 }, { 190, 215, 202, 25 }, { 203, 203, 203, 0 }, { 190, 219, 204, 29 }, { 203, 207, 205, 4 }, { 190, 223, 206, 33 }, { 207, 207, 207, 0 }, + { 207, 207, 207, 0 }, { 207, 211, 209, 4 }, { 211, 211, 211, 0 }, { 211, 211, 211, 0 }, { 211, 211, 211, 0 }, { 211, 215, 213, 4 }, { 215, 215, 215, 0 }, { 215, 215, 215, 0 }, + { 215, 215, 215, 0 }, { 215, 219, 217, 4 }, { 219, 219, 219, 0 }, { 219, 219, 219, 0 }, { 219, 219, 219, 0 }, { 219, 223, 221, 4 }, { 223, 223, 223, 0 }, { 223, 223, 223, 0 }, + { 223, 223, 223, 0 }, { 223, 227, 225, 4 }, { 227, 227, 227, 0 }, { 227, 227, 227, 0 }, { 227, 227, 227, 0 }, { 227, 231, 229, 4 }, { 231, 231, 231, 0 }, { 231, 231, 231, 0 }, + { 231, 231, 231, 0 }, { 231, 235, 233, 4 }, { 235, 235, 235, 0 }, { 235, 235, 235, 0 }, { 235, 235, 235, 0 }, { 235, 239, 237, 4 }, { 239, 239, 239, 0 }, { 239, 239, 239, 0 }, + { 239, 239, 239, 0 }, { 239, 243, 241, 4 }, { 243, 243, 243, 0 }, { 243, 243, 243, 0 }, { 243, 243, 243, 0 }, { 243, 247, 245, 4 }, { 247, 247, 247, 0 }, { 247, 247, 247, 0 }, + { 247, 247, 247, 0 }, { 247, 251, 249, 4 }, { 251, 251, 251, 0 }, { 251, 251, 251, 0 }, { 251, 251, 251, 0 }, { 251, 255, 253, 4 }, { 255, 255, 255, 0 }, { 255, 255, 255, 0 }, + }; + } + + class S3TCComputer + { + public: + typedef ParallelMath::Float MFloat; + typedef ParallelMath::SInt16 MSInt16; + typedef ParallelMath::UInt15 MUInt15; + typedef ParallelMath::UInt16 MUInt16; + typedef ParallelMath::SInt32 MSInt32; + + static void Init(MFloat& error) + { + error = ParallelMath::MakeFloat(FLT_MAX); + } + + static void QuantizeTo6Bits(MUInt15& v) + { + MUInt15 reduced = ParallelMath::LosslessCast<MUInt15>::Cast(ParallelMath::RightShift(ParallelMath::CompactMultiply(v, ParallelMath::MakeUInt15(253)) + ParallelMath::MakeUInt16(512), 10)); + v = (reduced << 2) | ParallelMath::RightShift(reduced, 4); + } + + static void QuantizeTo5Bits(MUInt15& v) + { + MUInt15 reduced = ParallelMath::LosslessCast<MUInt15>::Cast(ParallelMath::RightShift(ParallelMath::CompactMultiply(v, ParallelMath::MakeUInt15(249)) + ParallelMath::MakeUInt16(1024), 11)); + v = (reduced << 3) | ParallelMath::RightShift(reduced, 2); + } + + static void QuantizeTo565(MUInt15 endPoint[3]) + { + QuantizeTo5Bits(endPoint[0]); + QuantizeTo6Bits(endPoint[1]); + QuantizeTo5Bits(endPoint[2]); + } + + static MFloat ParanoidFactorForSpan(const MSInt16& span) + { + return ParallelMath::Abs(ParallelMath::ToFloat(span)) * 0.03f; + } + + static MFloat ParanoidDiff(const MUInt15& a, const MUInt15& b, const MFloat& d) + { + MFloat absDiff = ParallelMath::Abs(ParallelMath::ToFloat(ParallelMath::LosslessCast<MSInt16>::Cast(a) - ParallelMath::LosslessCast<MSInt16>::Cast(b))); + absDiff = absDiff + d; + return absDiff * absDiff; + } + + static void TestSingleColor(uint32_t flags, const MUInt15 pixels[16][4], const MFloat floatPixels[16][4], int range, const float* channelWeights, + MFloat &bestError, MUInt15 bestEndpoints[2][3], MUInt15 bestIndexes[16], MUInt15 &bestRange, const ParallelMath::RoundTowardNearestForScope *rtn) + { + float channelWeightsSq[3]; + + for (int ch = 0; ch < 3; ch++) + channelWeightsSq[ch] = channelWeights[ch] * channelWeights[ch]; + + MUInt15 totals[3] = { ParallelMath::MakeUInt15(0), ParallelMath::MakeUInt15(0), ParallelMath::MakeUInt15(0) }; + + for (int px = 0; px < 16; px++) + { + for (int ch = 0; ch < 3; ch++) + totals[ch] = totals[ch] + pixels[px][ch]; + } + + MUInt15 average[3]; + for (int ch = 0; ch < 3; ch++) + average[ch] = ParallelMath::RightShift(totals[ch] + ParallelMath::MakeUInt15(8), 4); + + const S3TCSingleColorTables::SingleColorTableEntry* rbTable = NULL; + const S3TCSingleColorTables::SingleColorTableEntry* gTable = NULL; + if (flags & cvtt::Flags::S3TC_Paranoid) + { + if (range == 4) + { + rbTable = S3TCSingleColorTables::g_singleColor5_3_p; + gTable = S3TCSingleColorTables::g_singleColor6_3_p; + } + else + { + assert(range == 3); + rbTable = S3TCSingleColorTables::g_singleColor5_2_p; + gTable = S3TCSingleColorTables::g_singleColor6_2_p; + } + } + else + { + if (range == 4) + { + rbTable = S3TCSingleColorTables::g_singleColor5_3; + gTable = S3TCSingleColorTables::g_singleColor6_3; + } + else + { + assert(range == 3); + rbTable = S3TCSingleColorTables::g_singleColor5_2; + gTable = S3TCSingleColorTables::g_singleColor6_2; + } + } + + MUInt15 interpolated[3]; + MUInt15 eps[2][3]; + MSInt16 spans[3]; + for (int i = 0; i < ParallelMath::ParallelSize; i++) + { + for (int ch = 0; ch < 3; ch++) + { + uint16_t avg = ParallelMath::Extract(average[ch], i); + const S3TCSingleColorTables::SingleColorTableEntry& tableEntry = ((ch == 1) ? gTable[avg] : rbTable[avg]); + ParallelMath::PutUInt15(eps[0][ch], i, tableEntry.m_min); + ParallelMath::PutUInt15(eps[1][ch], i, tableEntry.m_max); + ParallelMath::PutUInt15(interpolated[ch], i, tableEntry.m_actualColor); + ParallelMath::PutSInt16(spans[ch], i, tableEntry.m_span); + } + } + + MFloat error = ParallelMath::MakeFloatZero(); + if (flags & cvtt::Flags::S3TC_Paranoid) + { + MFloat spanParanoidFactors[3]; + for (int ch = 0; ch < 3; ch++) + spanParanoidFactors[ch] = ParanoidFactorForSpan(spans[ch]); + + for (int px = 0; px < 16; px++) + { + for (int ch = 0; ch < 3; ch++) + error = error + ParanoidDiff(interpolated[ch], pixels[px][ch], spanParanoidFactors[ch]) * channelWeightsSq[ch]; + } + } + else + { + for (int px = 0; px < 16; px++) + { + for (int ch = 0; ch < 3; ch++) + error = error + ParallelMath::ToFloat(ParallelMath::SqDiffUInt8(interpolated[ch], pixels[px][ch])) * channelWeightsSq[ch]; + } + } + + ParallelMath::FloatCompFlag better = ParallelMath::Less(error, bestError); + ParallelMath::Int16CompFlag better16 = ParallelMath::FloatFlagToInt16(better); + + if (ParallelMath::AnySet(better16)) + { + bestError = ParallelMath::Min(bestError, error); + for (int epi = 0; epi < 2; epi++) + for (int ch = 0; ch < 3; ch++) + ParallelMath::ConditionalSet(bestEndpoints[epi][ch], better16, eps[epi][ch]); + + MUInt15 vindexes = ParallelMath::MakeUInt15(1); + for (int px = 0; px < 16; px++) + ParallelMath::ConditionalSet(bestIndexes[px], better16, vindexes); + + ParallelMath::ConditionalSet(bestRange, better16, ParallelMath::MakeUInt15(range)); + } + } + + static void TestEndpoints(uint32_t flags, const MUInt15 pixels[16][4], const MFloat floatPixels[16][4], const MFloat preWeightedPixels[16][4], const MUInt15 unquantizedEndPoints[2][3], int range, const float* channelWeights, + MFloat &bestError, MUInt15 bestEndpoints[2][3], MUInt15 bestIndexes[16], MUInt15 &bestRange, EndpointRefiner<3> *refiner, const ParallelMath::RoundTowardNearestForScope *rtn) + { + float channelWeightsSq[3]; + + for (int ch = 0; ch < 3; ch++) + channelWeightsSq[ch] = channelWeights[ch] * channelWeights[ch]; + + MUInt15 endPoints[2][3]; + + for (int ep = 0; ep < 2; ep++) + for (int ch = 0; ch < 3; ch++) + endPoints[ep][ch] = unquantizedEndPoints[ep][ch]; + + QuantizeTo565(endPoints[0]); + QuantizeTo565(endPoints[1]); + + IndexSelector<3> selector; + selector.Init<false>(channelWeights, endPoints, range); + + MUInt15 indexes[16]; + + MFloat paranoidFactors[3]; + for (int ch = 0; ch < 3; ch++) + paranoidFactors[ch] = ParanoidFactorForSpan(ParallelMath::LosslessCast<MSInt16>::Cast(endPoints[0][ch]) - ParallelMath::LosslessCast<MSInt16>::Cast(endPoints[1][ch])); + + MFloat error = ParallelMath::MakeFloatZero(); + AggregatedError<3> aggError; + for (int px = 0; px < 16; px++) + { + MUInt15 index = selector.SelectIndexLDR(floatPixels[px], rtn); + indexes[px] = index; + + if (refiner) + refiner->ContributeUnweightedPW(preWeightedPixels[px], index); + + MUInt15 reconstructed[3]; + selector.ReconstructLDRPrecise(index, reconstructed); + + if (flags & Flags::S3TC_Paranoid) + { + for (int ch = 0; ch < 3; ch++) + error = error + ParanoidDiff(reconstructed[ch], pixels[px][ch], paranoidFactors[ch]) * channelWeightsSq[ch]; + } + else + BCCommon::ComputeErrorLDR<3>(flags, reconstructed, pixels[px], aggError); + } + + if (!(flags & Flags::S3TC_Paranoid)) + error = aggError.Finalize(flags, channelWeightsSq); + + ParallelMath::FloatCompFlag better = ParallelMath::Less(error, bestError); + + if (ParallelMath::AnySet(better)) + { + ParallelMath::Int16CompFlag betterInt16 = ParallelMath::FloatFlagToInt16(better); + + ParallelMath::ConditionalSet(bestError, better, error); + + for (int ep = 0; ep < 2; ep++) + for (int ch = 0; ch < 3; ch++) + ParallelMath::ConditionalSet(bestEndpoints[ep][ch], betterInt16, endPoints[ep][ch]); + + for (int px = 0; px < 16; px++) + ParallelMath::ConditionalSet(bestIndexes[px], betterInt16, indexes[px]); + + ParallelMath::ConditionalSet(bestRange, betterInt16, ParallelMath::MakeUInt15(static_cast<uint16_t>(range))); + } + } + + static void TestCounts(uint32_t flags, const int *counts, int nCounts, const MUInt15 &numElements, const MUInt15 pixels[16][4], const MFloat floatPixels[16][4], const MFloat preWeightedPixels[16][4], bool alphaTest, + const MFloat floatSortedInputs[16][4], const MFloat preWeightedFloatSortedInputs[16][4], const float *channelWeights, MFloat &bestError, MUInt15 bestEndpoints[2][3], MUInt15 bestIndexes[16], MUInt15 &bestRange, + const ParallelMath::RoundTowardNearestForScope* rtn) + { + UNREFERENCED_PARAMETER(alphaTest); + UNREFERENCED_PARAMETER(flags); + + EndpointRefiner<3> refiner; + + refiner.Init(nCounts, channelWeights); + + bool escape = false; + int e = 0; + for (int i = 0; i < nCounts; i++) + { + for (int n = 0; n < counts[i]; n++) + { + ParallelMath::Int16CompFlag valid = ParallelMath::Less(ParallelMath::MakeUInt15(static_cast<uint16_t>(n)), numElements); + if (!ParallelMath::AnySet(valid)) + { + escape = true; + break; + } + + if (ParallelMath::AllSet(valid)) + refiner.ContributeUnweightedPW(preWeightedFloatSortedInputs[e++], ParallelMath::MakeUInt15(static_cast<uint16_t>(i))); + else + { + MFloat weight = ParallelMath::Select(ParallelMath::Int16FlagToFloat(valid), ParallelMath::MakeFloat(1.0f), ParallelMath::MakeFloat(0.0f)); + refiner.ContributePW(preWeightedFloatSortedInputs[e++], ParallelMath::MakeUInt15(static_cast<uint16_t>(i)), weight); + } + } + + if (escape) + break; + } + + MUInt15 endPoints[2][3]; + refiner.GetRefinedEndpointsLDR(endPoints, rtn); + + TestEndpoints(flags, pixels, floatPixels, preWeightedPixels, endPoints, nCounts, channelWeights, bestError, bestEndpoints, bestIndexes, bestRange, NULL, rtn); + } + + static void PackExplicitAlpha(uint32_t flags, const PixelBlockU8* inputs, int inputChannel, uint8_t* packedBlocks, size_t packedBlockStride) + { + UNREFERENCED_PARAMETER(flags); + ParallelMath::RoundTowardNearestForScope rtn; + + float weights[1] = { 1.0f }; + + MUInt15 pixels[16]; + MFloat floatPixels[16]; + + for (int px = 0; px < 16; px++) + { + ParallelMath::ConvertLDRInputs(inputs, px, inputChannel, pixels[px]); + floatPixels[px] = ParallelMath::ToFloat(pixels[px]); + } + + MUInt15 ep[2][1] = { { ParallelMath::MakeUInt15(0) },{ ParallelMath::MakeUInt15(255) } }; + + IndexSelector<1> selector; + selector.Init<false>(weights, ep, 16); + + MUInt15 indexes[16]; + + for (int px = 0; px < 16; px++) + indexes[px] = selector.SelectIndexLDR(&floatPixels[px], &rtn); + + for (int block = 0; block < ParallelMath::ParallelSize; block++) + { + for (int px = 0; px < 16; px += 8) + { + int index0 = ParallelMath::Extract(indexes[px], block); + int index1 = ParallelMath::Extract(indexes[px], block); + + packedBlocks[px / 2] = static_cast<uint8_t>(index0 | (index1 << 4)); + } + + packedBlocks += packedBlockStride; + } + } + + static void PackInterpolatedAlpha(uint32_t flags, const PixelBlockU8* inputs, int inputChannel, uint8_t* packedBlocks, size_t packedBlockStride, bool isSigned, int maxTweakRounds, int numRefineRounds) + { + if (maxTweakRounds < 1) + maxTweakRounds = 1; + + if (numRefineRounds < 1) + numRefineRounds = 1; + + ParallelMath::RoundTowardNearestForScope rtn; + + float oneWeight[1] = { 1.0f }; + + MUInt15 pixels[16]; + MFloat floatPixels[16]; + + MUInt15 highTerminal = isSigned ? ParallelMath::MakeUInt15(254) : ParallelMath::MakeUInt15(255); + MUInt15 highTerminalMinusOne = highTerminal - ParallelMath::MakeUInt15(1); + + for (int px = 0; px < 16; px++) + { + ParallelMath::ConvertLDRInputs(inputs, px, inputChannel, pixels[px]); + + if (isSigned) + pixels[px] = ParallelMath::Min(pixels[px], highTerminal); + + floatPixels[px] = ParallelMath::ToFloat(pixels[px]); + } + + MUInt15 sortedPixels[16]; + for (int px = 0; px < 16; px++) + sortedPixels[px] = pixels[px]; + + for (int sortEnd = 15; sortEnd > 0; sortEnd--) + { + for (int sortOffset = 0; sortOffset < sortEnd; sortOffset++) + { + MUInt15 a = sortedPixels[sortOffset]; + MUInt15 b = sortedPixels[sortOffset + 1]; + + sortedPixels[sortOffset] = ParallelMath::Min(a, b); + sortedPixels[sortOffset + 1] = ParallelMath::Max(a, b); + } + } + + MUInt15 zero = ParallelMath::MakeUInt15(0); + MUInt15 one = ParallelMath::MakeUInt15(1); + + MUInt15 bestIsFullRange = zero; + MFloat bestError = ParallelMath::MakeFloat(FLT_MAX); + MUInt15 bestEP[2] = { zero, zero }; + MUInt15 bestIndexes[16] = { + zero, zero, zero, zero, + zero, zero, zero, zero, + zero, zero, zero, zero, + zero, zero, zero, zero + }; + + // Full-precision + { + MUInt15 minEP = sortedPixels[0]; + MUInt15 maxEP = sortedPixels[15]; + + MFloat base[1] = { ParallelMath::ToFloat(minEP) }; + MFloat offset[1] = { ParallelMath::ToFloat(maxEP - minEP) }; + + UnfinishedEndpoints<1> ufep = UnfinishedEndpoints<1>(base, offset); + + int numTweakRounds = BCCommon::TweakRoundsForRange(8); + if (numTweakRounds > maxTweakRounds) + numTweakRounds = maxTweakRounds; + + for (int tweak = 0; tweak < numTweakRounds; tweak++) + { + MUInt15 ep[2][1]; + + ufep.FinishLDR(tweak, 8, ep[0], ep[1]); + + for (int refinePass = 0; refinePass < numRefineRounds; refinePass++) + { + EndpointRefiner<1> refiner; + refiner.Init(8, oneWeight); + + if (isSigned) + for (int epi = 0; epi < 2; epi++) + ep[epi][0] = ParallelMath::Min(ep[epi][0], highTerminal); + + IndexSelector<1> indexSelector; + indexSelector.Init<false>(oneWeight, ep, 8); + + MUInt15 indexes[16]; + + AggregatedError<1> aggError; + for (int px = 0; px < 16; px++) + { + MUInt15 index = indexSelector.SelectIndexLDR(&floatPixels[px], &rtn); + + MUInt15 reconstructedPixel; + + indexSelector.ReconstructLDRPrecise(index, &reconstructedPixel); + BCCommon::ComputeErrorLDR<1>(flags, &reconstructedPixel, &pixels[px], aggError); + + if (refinePass != numRefineRounds - 1) + refiner.ContributeUnweightedPW(&floatPixels[px], index); + + indexes[px] = index; + } + MFloat error = aggError.Finalize(flags | Flags::Uniform, oneWeight); + + ParallelMath::FloatCompFlag errorBetter = ParallelMath::Less(error, bestError); + ParallelMath::Int16CompFlag errorBetter16 = ParallelMath::FloatFlagToInt16(errorBetter); + + if (ParallelMath::AnySet(errorBetter16)) + { + bestError = ParallelMath::Min(error, bestError); + ParallelMath::ConditionalSet(bestIsFullRange, errorBetter16, one); + for (int px = 0; px < 16; px++) + ParallelMath::ConditionalSet(bestIndexes[px], errorBetter16, indexes[px]); + + for (int epi = 0; epi < 2; epi++) + ParallelMath::ConditionalSet(bestEP[epi], errorBetter16, ep[epi][0]); + } + + if (refinePass != numRefineRounds - 1) + refiner.GetRefinedEndpointsLDR(ep, &rtn); + } + } + } + + // Reduced precision with special endpoints + { + MUInt15 bestHeuristicMin = sortedPixels[0]; + MUInt15 bestHeuristicMax = sortedPixels[15]; + + ParallelMath::Int16CompFlag canTryClipping; + + // In reduced precision, we want try putting endpoints at the reserved indexes at the ends. + // The heuristic we use is to assign indexes to the end as long as they aren't off by more than half of the index range. + // This will usually not find anything, but it's cheap to check. + + { + MUInt15 largestPossibleRange = bestHeuristicMax - bestHeuristicMin; // Max: 255 + MUInt15 lowestPossibleClearance = ParallelMath::Min(bestHeuristicMin, static_cast<MUInt15>(highTerminal - bestHeuristicMax)); + + MUInt15 lowestPossibleClearanceTimes10 = (lowestPossibleClearance << 2) + (lowestPossibleClearance << 4); + canTryClipping = ParallelMath::LessOrEqual(lowestPossibleClearanceTimes10, largestPossibleRange); + } + + if (ParallelMath::AnySet(canTryClipping)) + { + MUInt15 lowClearances[16]; + MUInt15 highClearances[16]; + MUInt15 bestSkipCount = ParallelMath::MakeUInt15(0); + + lowClearances[0] = highClearances[0] = ParallelMath::MakeUInt15(0); + + for (int px = 1; px < 16; px++) + { + lowClearances[px] = sortedPixels[px - 1]; + highClearances[px] = highTerminal - sortedPixels[16 - px]; + } + + for (uint16_t firstIndex = 0; firstIndex < 16; firstIndex++) + { + uint16_t numSkippedLow = firstIndex; + + MUInt15 lowClearance = lowClearances[firstIndex]; + + for (uint16_t lastIndex = firstIndex; lastIndex < 16; lastIndex++) + { + uint16_t numSkippedHigh = 15 - lastIndex; + uint16_t numSkipped = numSkippedLow + numSkippedHigh; + + MUInt15 numSkippedV = ParallelMath::MakeUInt15(numSkipped); + + ParallelMath::Int16CompFlag areMoreSkipped = ParallelMath::Less(bestSkipCount, numSkippedV); + + if (!ParallelMath::AnySet(areMoreSkipped)) + continue; + + MUInt15 clearance = ParallelMath::Max(highClearances[numSkippedHigh], lowClearance); + MUInt15 clearanceTimes10 = (clearance << 2) + (clearance << 4); + + MUInt15 range = sortedPixels[lastIndex] - sortedPixels[firstIndex]; + + ParallelMath::Int16CompFlag isBetter = (areMoreSkipped & ParallelMath::LessOrEqual(clearanceTimes10, range)); + ParallelMath::ConditionalSet(bestHeuristicMin, isBetter, sortedPixels[firstIndex]); + ParallelMath::ConditionalSet(bestHeuristicMax, isBetter, sortedPixels[lastIndex]); + } + } + } + + MUInt15 bestSimpleMin = one; + MUInt15 bestSimpleMax = highTerminalMinusOne; + + for (int px = 0; px < 16; px++) + { + ParallelMath::ConditionalSet(bestSimpleMin, ParallelMath::Less(zero, sortedPixels[15 - px]), sortedPixels[15 - px]); + ParallelMath::ConditionalSet(bestSimpleMax, ParallelMath::Less(sortedPixels[px], highTerminal), sortedPixels[px]); + } + + MUInt15 minEPs[2] = { bestSimpleMin, bestHeuristicMin }; + MUInt15 maxEPs[2] = { bestSimpleMax, bestHeuristicMax }; + + int minEPRange = 2; + if (ParallelMath::AllSet(ParallelMath::Equal(minEPs[0], minEPs[1]))) + minEPRange = 1; + + int maxEPRange = 2; + if (ParallelMath::AllSet(ParallelMath::Equal(maxEPs[0], maxEPs[1]))) + maxEPRange = 1; + + for (int minEPIndex = 0; minEPIndex < minEPRange; minEPIndex++) + { + for (int maxEPIndex = 0; maxEPIndex < maxEPRange; maxEPIndex++) + { + MFloat base[1] = { ParallelMath::ToFloat(minEPs[minEPIndex]) }; + MFloat offset[1] = { ParallelMath::ToFloat(maxEPs[maxEPIndex] - minEPs[minEPIndex]) }; + + UnfinishedEndpoints<1> ufep = UnfinishedEndpoints<1>(base, offset); + + int numTweakRounds = BCCommon::TweakRoundsForRange(6); + if (numTweakRounds > maxTweakRounds) + numTweakRounds = maxTweakRounds; + + for (int tweak = 0; tweak < numTweakRounds; tweak++) + { + MUInt15 ep[2][1]; + + ufep.FinishLDR(tweak, 8, ep[0], ep[1]); + + for (int refinePass = 0; refinePass < numRefineRounds; refinePass++) + { + EndpointRefiner<1> refiner; + refiner.Init(6, oneWeight); + + if (isSigned) + for (int epi = 0; epi < 2; epi++) + ep[epi][0] = ParallelMath::Min(ep[epi][0], highTerminal); + + IndexSelector<1> indexSelector; + indexSelector.Init<false>(oneWeight, ep, 6); + + MUInt15 indexes[16]; + MFloat error = ParallelMath::MakeFloatZero(); + + for (int px = 0; px < 16; px++) + { + MUInt15 selectedIndex = indexSelector.SelectIndexLDR(&floatPixels[px], &rtn); + + MUInt15 reconstructedPixel; + + indexSelector.ReconstructLDRPrecise(selectedIndex, &reconstructedPixel); + + MFloat zeroError = BCCommon::ComputeErrorLDRSimple<1>(flags | Flags::Uniform, &zero, &pixels[px], 1, oneWeight); + MFloat highTerminalError = BCCommon::ComputeErrorLDRSimple<1>(flags | Flags::Uniform, &highTerminal, &pixels[px], 1, oneWeight); + MFloat selectedIndexError = BCCommon::ComputeErrorLDRSimple<1>(flags | Flags::Uniform, &reconstructedPixel, &pixels[px], 1, oneWeight); + + MFloat bestPixelError = zeroError; + MUInt15 index = ParallelMath::MakeUInt15(6); + + ParallelMath::ConditionalSet(index, ParallelMath::FloatFlagToInt16(ParallelMath::Less(highTerminalError, bestPixelError)), ParallelMath::MakeUInt15(7)); + bestPixelError = ParallelMath::Min(bestPixelError, highTerminalError); + + ParallelMath::FloatCompFlag selectedIndexBetter = ParallelMath::Less(selectedIndexError, bestPixelError); + + if (ParallelMath::AllSet(selectedIndexBetter)) + { + if (refinePass != numRefineRounds - 1) + refiner.ContributeUnweightedPW(&floatPixels[px], selectedIndex); + } + else + { + MFloat refineWeight = ParallelMath::Select(selectedIndexBetter, ParallelMath::MakeFloat(1.0f), ParallelMath::MakeFloatZero()); + + if (refinePass != numRefineRounds - 1) + refiner.ContributePW(&floatPixels[px], selectedIndex, refineWeight); + } + + ParallelMath::ConditionalSet(index, ParallelMath::FloatFlagToInt16(selectedIndexBetter), selectedIndex); + bestPixelError = ParallelMath::Min(bestPixelError, selectedIndexError); + + error = error + bestPixelError; + + indexes[px] = index; + } + + ParallelMath::FloatCompFlag errorBetter = ParallelMath::Less(error, bestError); + ParallelMath::Int16CompFlag errorBetter16 = ParallelMath::FloatFlagToInt16(errorBetter); + + if (ParallelMath::AnySet(errorBetter16)) + { + bestError = ParallelMath::Min(error, bestError); + ParallelMath::ConditionalSet(bestIsFullRange, errorBetter16, zero); + for (int px = 0; px < 16; px++) + ParallelMath::ConditionalSet(bestIndexes[px], errorBetter16, indexes[px]); + + for (int epi = 0; epi < 2; epi++) + ParallelMath::ConditionalSet(bestEP[epi], errorBetter16, ep[epi][0]); + } + + if (refinePass != numRefineRounds - 1) + refiner.GetRefinedEndpointsLDR(ep, &rtn); + } + } + } + } + } + + for (int block = 0; block < ParallelMath::ParallelSize; block++) + { + int ep0 = ParallelMath::Extract(bestEP[0], block); + int ep1 = ParallelMath::Extract(bestEP[1], block); + int isFullRange = ParallelMath::Extract(bestIsFullRange, block); + + if (isSigned) + { + ep0 -= 127; + ep1 -= 127; + + assert(ep0 >= -127 && ep0 <= 127); + assert(ep1 >= -127 && ep1 <= 127); + } + + + bool swapEndpoints = (isFullRange != 0) != (ep0 > ep1); + + if (swapEndpoints) + std::swap(ep0, ep1); + + uint16_t dumpBits = 0; + int dumpBitsOffset = 0; + int dumpByteOffset = 2; + packedBlocks[0] = static_cast<uint8_t>(ep0 & 0xff); + packedBlocks[1] = static_cast<uint8_t>(ep1 & 0xff); + + int maxValue = (isFullRange != 0) ? 7 : 5; + + for (int px = 0; px < 16; px++) + { + int index = ParallelMath::Extract(bestIndexes[px], block); + + if (swapEndpoints && index <= maxValue) + index = maxValue - index; + + if (index != 0) + { + if (index == maxValue) + index = 1; + else if (index < maxValue) + index++; + } + + assert(index >= 0 && index < 8); + + dumpBits |= static_cast<uint16_t>(index << dumpBitsOffset); + dumpBitsOffset += 3; + + if (dumpBitsOffset >= 8) + { + assert(dumpByteOffset < 8); + packedBlocks[dumpByteOffset] = static_cast<uint8_t>(dumpBits & 0xff); + dumpBits >>= 8; + dumpBitsOffset -= 8; + dumpByteOffset++; + } + } + + assert(dumpBitsOffset == 0); + assert(dumpByteOffset == 8); + + packedBlocks += packedBlockStride; + } + } + + static void PackRGB(uint32_t flags, const PixelBlockU8* inputs, uint8_t* packedBlocks, size_t packedBlockStride, const float channelWeights[4], bool alphaTest, float alphaThreshold, bool exhaustive, int maxTweakRounds, int numRefineRounds) + { + ParallelMath::RoundTowardNearestForScope rtn; + + if (numRefineRounds < 1) + numRefineRounds = 1; + + if (maxTweakRounds < 1) + maxTweakRounds = 1; + + EndpointSelector<3, 8> endpointSelector; + + MUInt15 pixels[16][4]; + MFloat floatPixels[16][4]; + + MFloat preWeightedPixels[16][4]; + + for (int px = 0; px < 16; px++) + { + for (int ch = 0; ch < 4; ch++) + ParallelMath::ConvertLDRInputs(inputs, px, ch, pixels[px][ch]); + } + + for (int px = 0; px < 16; px++) + { + for (int ch = 0; ch < 4; ch++) + floatPixels[px][ch] = ParallelMath::ToFloat(pixels[px][ch]); + } + + if (alphaTest) + { + MUInt15 threshold = ParallelMath::MakeUInt15(static_cast<uint16_t>(floor(alphaThreshold * 255.0f + 0.5f))); + + for (int px = 0; px < 16; px++) + { + ParallelMath::Int16CompFlag belowThreshold = ParallelMath::Less(pixels[px][3], threshold); + pixels[px][3] = ParallelMath::Select(belowThreshold, ParallelMath::MakeUInt15(0), ParallelMath::MakeUInt15(255)); + } + } + + BCCommon::PreWeightPixelsLDR<4>(preWeightedPixels, pixels, channelWeights); + + MUInt15 minAlpha = ParallelMath::MakeUInt15(255); + + for (int px = 0; px < 16; px++) + minAlpha = ParallelMath::Min(minAlpha, pixels[px][3]); + + MFloat pixelWeights[16]; + for (int px = 0; px < 16; px++) + { + pixelWeights[px] = ParallelMath::MakeFloat(1.0f); + if (alphaTest) + { + ParallelMath::Int16CompFlag isTransparent = ParallelMath::Less(pixels[px][3], ParallelMath::MakeUInt15(255)); + + ParallelMath::ConditionalSet(pixelWeights[px], ParallelMath::Int16FlagToFloat(isTransparent), ParallelMath::MakeFloatZero()); + } + } + + for (int pass = 0; pass < NumEndpointSelectorPasses; pass++) + { + for (int px = 0; px < 16; px++) + endpointSelector.ContributePass(preWeightedPixels[px], pass, pixelWeights[px]); + + endpointSelector.FinishPass(pass); + } + + UnfinishedEndpoints<3> ufep = endpointSelector.GetEndpoints(channelWeights); + + MUInt15 bestEndpoints[2][3]; + MUInt15 bestIndexes[16]; + MUInt15 bestRange = ParallelMath::MakeUInt15(0); + MFloat bestError = ParallelMath::MakeFloat(FLT_MAX); + + for (int px = 0; px < 16; px++) + bestIndexes[px] = ParallelMath::MakeUInt15(0); + + for (int ep = 0; ep < 2; ep++) + for (int ch = 0; ch < 3; ch++) + bestEndpoints[ep][ch] = ParallelMath::MakeUInt15(0); + + if (exhaustive) + { + MSInt16 sortBins[16]; + + { + // Compute an 11-bit index, change it to signed, stuff it in the high bits of the sort bins, + // and pack the original indexes into the low bits. + + MUInt15 sortEP[2][3]; + ufep.FinishLDR(0, 11, sortEP[0], sortEP[1]); + + IndexSelector<3> sortSelector; + sortSelector.Init<false>(channelWeights, sortEP, 1 << 11); + + for (int16_t px = 0; px < 16; px++) + { + MSInt16 sortBin = ParallelMath::LosslessCast<MSInt16>::Cast(sortSelector.SelectIndexLDR(floatPixels[px], &rtn) << 4); + + if (alphaTest) + { + ParallelMath::Int16CompFlag isTransparent = ParallelMath::Less(pixels[px][3], ParallelMath::MakeUInt15(255)); + + ParallelMath::ConditionalSet(sortBin, isTransparent, ParallelMath::MakeSInt16(-16)); // 0xfff0 + } + + sortBin = sortBin + ParallelMath::MakeSInt16(px); + + sortBins[px] = sortBin; + } + } + + // Sort bins + for (int sortEnd = 1; sortEnd < 16; sortEnd++) + { + for (int sortLoc = sortEnd; sortLoc > 0; sortLoc--) + { + MSInt16 a = sortBins[sortLoc]; + MSInt16 b = sortBins[sortLoc - 1]; + + sortBins[sortLoc] = ParallelMath::Max(a, b); + sortBins[sortLoc - 1] = ParallelMath::Min(a, b); + } + } + + MUInt15 firstElement = ParallelMath::MakeUInt15(0); + for (uint16_t e = 0; e < 16; e++) + { + ParallelMath::Int16CompFlag isInvalid = ParallelMath::Less(sortBins[e], ParallelMath::MakeSInt16(0)); + ParallelMath::ConditionalSet(firstElement, isInvalid, ParallelMath::MakeUInt15(e + 1)); + if (!ParallelMath::AnySet(isInvalid)) + break; + } + + MUInt15 numElements = ParallelMath::MakeUInt15(16) - firstElement; + + MUInt15 sortedInputs[16][4]; + MFloat floatSortedInputs[16][4]; + MFloat pwFloatSortedInputs[16][4]; + + for (int e = 0; e < 16; e++) + { + for (int ch = 0; ch < 4; ch++) + sortedInputs[e][ch] = ParallelMath::MakeUInt15(0); + } + + for (int block = 0; block < ParallelMath::ParallelSize; block++) + { + for (int e = ParallelMath::Extract(firstElement, block); e < 16; e++) + { + ParallelMath::ScalarUInt16 sortBin = ParallelMath::Extract(sortBins[e], block); + int originalIndex = (sortBin & 15); + + for (int ch = 0; ch < 4; ch++) + ParallelMath::PutUInt15(sortedInputs[15 - e][ch], block, ParallelMath::Extract(pixels[originalIndex][ch], block)); + } + } + + for (int e = 0; e < 16; e++) + { + for (int ch = 0; ch < 4; ch++) + { + MFloat f = ParallelMath::ToFloat(sortedInputs[e][ch]); + floatSortedInputs[e][ch] = f; + pwFloatSortedInputs[e][ch] = f * channelWeights[ch]; + } + } + + for (int n0 = 0; n0 <= 15; n0++) + { + int remainingFor1 = 16 - n0; + if (remainingFor1 == 16) + remainingFor1 = 15; + + for (int n1 = 0; n1 <= remainingFor1; n1++) + { + int remainingFor2 = 16 - n1 - n0; + if (remainingFor2 == 16) + remainingFor2 = 15; + + for (int n2 = 0; n2 <= remainingFor2; n2++) + { + int n3 = 16 - n2 - n1 - n0; + + if (n3 == 16) + continue; + + int counts[4] = { n0, n1, n2, n3 }; + + TestCounts(flags, counts, 4, numElements, pixels, floatPixels, preWeightedPixels, alphaTest, floatSortedInputs, pwFloatSortedInputs, channelWeights, bestError, bestEndpoints, bestIndexes, bestRange, &rtn); + } + } + } + + TestSingleColor(flags, pixels, floatPixels, 4, channelWeights, bestError, bestEndpoints, bestIndexes, bestRange, &rtn); + + if (alphaTest) + { + for (int n0 = 0; n0 <= 15; n0++) + { + int remainingFor1 = 16 - n0; + if (remainingFor1 == 16) + remainingFor1 = 15; + + for (int n1 = 0; n1 <= remainingFor1; n1++) + { + int n2 = 16 - n1 - n0; + + if (n2 == 16) + continue; + + int counts[3] = { n0, n1, n2 }; + + TestCounts(flags, counts, 3, numElements, pixels, floatPixels, preWeightedPixels, alphaTest, floatSortedInputs, pwFloatSortedInputs, channelWeights, bestError, bestEndpoints, bestIndexes, bestRange, &rtn); + } + } + + TestSingleColor(flags, pixels, floatPixels, 3, channelWeights, bestError, bestEndpoints, bestIndexes, bestRange, &rtn); + } + } + else + { + int minRange = alphaTest ? 3 : 4; + + for (int range = minRange; range <= 4; range++) + { + int tweakRounds = BCCommon::TweakRoundsForRange(range); + if (tweakRounds > maxTweakRounds) + tweakRounds = maxTweakRounds; + + for (int tweak = 0; tweak < tweakRounds; tweak++) + { + MUInt15 endPoints[2][3]; + + ufep.FinishLDR(tweak, range, endPoints[0], endPoints[1]); + + for (int refine = 0; refine < numRefineRounds; refine++) + { + EndpointRefiner<3> refiner; + refiner.Init(range, channelWeights); + + TestEndpoints(flags, pixels, floatPixels, preWeightedPixels, endPoints, range, channelWeights, bestError, bestEndpoints, bestIndexes, bestRange, &refiner, &rtn); + + if (refine != numRefineRounds - 1) + refiner.GetRefinedEndpointsLDR(endPoints, &rtn); + } + } + } + } + + for (int block = 0; block < ParallelMath::ParallelSize; block++) + { + ParallelMath::ScalarUInt16 range = ParallelMath::Extract(bestRange, block); + assert(range == 3 || range == 4); + + ParallelMath::ScalarUInt16 compressedEP[2]; + for (int ep = 0; ep < 2; ep++) + { + ParallelMath::ScalarUInt16 endPoint[3]; + for (int ch = 0; ch < 3; ch++) + endPoint[ch] = ParallelMath::Extract(bestEndpoints[ep][ch], block); + + int compressed = (endPoint[0] & 0xf8) << 8; + compressed |= (endPoint[1] & 0xfc) << 3; + compressed |= (endPoint[2] & 0xf8) >> 3; + + compressedEP[ep] = static_cast<ParallelMath::ScalarUInt16>(compressed); + } + + int indexOrder[4]; + + if (range == 4) + { + if (compressedEP[0] == compressedEP[1]) + { + indexOrder[0] = 0; + indexOrder[1] = 0; + indexOrder[2] = 0; + indexOrder[3] = 0; + } + else if (compressedEP[0] < compressedEP[1]) + { + std::swap(compressedEP[0], compressedEP[1]); + indexOrder[0] = 1; + indexOrder[1] = 3; + indexOrder[2] = 2; + indexOrder[3] = 0; + } + else + { + indexOrder[0] = 0; + indexOrder[1] = 2; + indexOrder[2] = 3; + indexOrder[3] = 1; + } + } + else + { + assert(range == 3); + + if (compressedEP[0] > compressedEP[1]) + { + std::swap(compressedEP[0], compressedEP[1]); + indexOrder[0] = 1; + indexOrder[1] = 2; + indexOrder[2] = 0; + } + else + { + indexOrder[0] = 0; + indexOrder[1] = 2; + indexOrder[2] = 1; + } + indexOrder[3] = 3; + } + + packedBlocks[0] = static_cast<uint8_t>(compressedEP[0] & 0xff); + packedBlocks[1] = static_cast<uint8_t>((compressedEP[0] >> 8) & 0xff); + packedBlocks[2] = static_cast<uint8_t>(compressedEP[1] & 0xff); + packedBlocks[3] = static_cast<uint8_t>((compressedEP[1] >> 8) & 0xff); + + for (int i = 0; i < 16; i += 4) + { + int packedIndexes = 0; + for (int subi = 0; subi < 4; subi++) + { + ParallelMath::ScalarUInt16 index = ParallelMath::Extract(bestIndexes[i + subi], block); + packedIndexes |= (indexOrder[index] << (subi * 2)); + } + + packedBlocks[4 + i / 4] = static_cast<uint8_t>(packedIndexes); + } + + packedBlocks += packedBlockStride; + } + } + }; + + // Signed input blocks are converted into unsigned space, with the maximum value being 254 + void BiasSignedInput(PixelBlockU8 inputNormalized[ParallelMath::ParallelSize], const PixelBlockS8 inputSigned[ParallelMath::ParallelSize]) + { + for (size_t block = 0; block < ParallelMath::ParallelSize; block++) + { + const PixelBlockS8& inputSignedBlock = inputSigned[block]; + PixelBlockU8& inputNormalizedBlock = inputNormalized[block]; + + for (size_t px = 0; px < 16; px++) + { + for (size_t ch = 0; ch < 4; ch++) + inputNormalizedBlock.m_pixels[px][ch] = static_cast<uint8_t>(std::max<int>(inputSignedBlock.m_pixels[px][ch], -127) + 127); + } + } + } + + void FillWeights(const Options &options, float channelWeights[4]) + { + if (options.flags & Flags::Uniform) + channelWeights[0] = channelWeights[1] = channelWeights[2] = channelWeights[3] = 1.0f; + else + { + channelWeights[0] = options.redWeight; + channelWeights[1] = options.greenWeight; + channelWeights[2] = options.blueWeight; + channelWeights[3] = options.alphaWeight; + } + } + } + + namespace Kernels + { + void EncodeBC7(uint8_t *pBC, const PixelBlockU8 *pBlocks, const cvtt::Options &options) + { + assert(pBlocks); + assert(pBC); + + float channelWeights[4]; + Internal::FillWeights(options, channelWeights); + + for (size_t blockBase = 0; blockBase < cvtt::NumParallelBlocks; blockBase += ParallelMath::ParallelSize) + { + Internal::BC7Computer::Pack(options.flags, pBlocks + blockBase, pBC, channelWeights, options.seedPoints, options.refineRoundsBC7); + pBC += ParallelMath::ParallelSize * 16; + } + } + + void EncodeBC6HU(uint8_t *pBC, const PixelBlockF16 *pBlocks, const cvtt::Options &options) + { + assert(pBlocks); + assert(pBC); + + float channelWeights[4]; + Internal::FillWeights(options, channelWeights); + + for (size_t blockBase = 0; blockBase < cvtt::NumParallelBlocks; blockBase += ParallelMath::ParallelSize) + { + Internal::BC6HComputer::Pack(options.flags, pBlocks + blockBase, pBC, channelWeights, false, options.seedPoints, options.refineRoundsBC6H); + pBC += ParallelMath::ParallelSize * 16; + } + } + + void EncodeBC6HS(uint8_t *pBC, const PixelBlockF16 *pBlocks, const cvtt::Options &options) + { + assert(pBlocks); + assert(pBC); + + float channelWeights[4]; + Internal::FillWeights(options, channelWeights); + + for (size_t blockBase = 0; blockBase < cvtt::NumParallelBlocks; blockBase += ParallelMath::ParallelSize) + { + Internal::BC6HComputer::Pack(options.flags, pBlocks + blockBase, pBC, channelWeights, true, options.seedPoints, options.refineRoundsBC6H); + pBC += ParallelMath::ParallelSize * 16; + } + } + + void EncodeBC1(uint8_t *pBC, const PixelBlockU8 *pBlocks, const cvtt::Options &options) + { + assert(pBlocks); + assert(pBC); + + float channelWeights[4]; + Internal::FillWeights(options, channelWeights); + + for (size_t blockBase = 0; blockBase < cvtt::NumParallelBlocks; blockBase += ParallelMath::ParallelSize) + { + Internal::S3TCComputer::PackRGB(options.flags, pBlocks + blockBase, pBC, 8, channelWeights, true, options.threshold, (options.flags & Flags::S3TC_Exhaustive) != 0, options.seedPoints, options.refineRoundsS3TC); + pBC += ParallelMath::ParallelSize * 8; + } + } + + void EncodeBC2(uint8_t *pBC, const PixelBlockU8 *pBlocks, const Options &options) + { + assert(pBlocks); + assert(pBC); + + float channelWeights[4]; + Internal::FillWeights(options, channelWeights); + + for (size_t blockBase = 0; blockBase < NumParallelBlocks; blockBase += ParallelMath::ParallelSize) + { + Internal::S3TCComputer::PackRGB(options.flags, pBlocks + blockBase, pBC + 8, 16, channelWeights, false, 1.0f, (options.flags & Flags::S3TC_Exhaustive) != 0, options.seedPoints, options.refineRoundsS3TC); + Internal::S3TCComputer::PackExplicitAlpha(options.flags, pBlocks + blockBase, 3, pBC, 16); + pBC += ParallelMath::ParallelSize * 16; + } + } + + void EncodeBC3(uint8_t *pBC, const PixelBlockU8 *pBlocks, const Options &options) + { + assert(pBlocks); + assert(pBC); + + float channelWeights[4]; + Internal::FillWeights(options, channelWeights); + + for (size_t blockBase = 0; blockBase < NumParallelBlocks; blockBase += ParallelMath::ParallelSize) + { + Internal::S3TCComputer::PackRGB(options.flags, pBlocks + blockBase, pBC + 8, 16, channelWeights, false, 1.0f, (options.flags & Flags::S3TC_Exhaustive) != 0, options.seedPoints, options.refineRoundsS3TC); + Internal::S3TCComputer::PackInterpolatedAlpha(options.flags, pBlocks + blockBase, 3, pBC, 16, false, options.seedPoints, options.refineRoundsIIC); + pBC += ParallelMath::ParallelSize * 16; + } + } + + void EncodeBC4U(uint8_t *pBC, const PixelBlockU8 *pBlocks, const Options &options) + { + assert(pBlocks); + assert(pBC); + + float channelWeights[4]; + Internal::FillWeights(options, channelWeights); + + for (size_t blockBase = 0; blockBase < NumParallelBlocks; blockBase += ParallelMath::ParallelSize) + { + Internal::S3TCComputer::PackInterpolatedAlpha(options.flags, pBlocks + blockBase, 0, pBC, 8, false, options.seedPoints, options.refineRoundsIIC); + pBC += ParallelMath::ParallelSize * 8; + } + } + + void EncodeBC4S(uint8_t *pBC, const PixelBlockS8 *pBlocks, const Options &options) + { + assert(pBlocks); + assert(pBC); + + float channelWeights[4]; + Internal::FillWeights(options, channelWeights); + + for (size_t blockBase = 0; blockBase < NumParallelBlocks; blockBase += ParallelMath::ParallelSize) + { + PixelBlockU8 inputBlocks[ParallelMath::ParallelSize]; + Internal::BiasSignedInput(inputBlocks, pBlocks + blockBase); + + Internal::S3TCComputer::PackInterpolatedAlpha(options.flags, inputBlocks, 0, pBC, 8, true, options.seedPoints, options.refineRoundsIIC); + pBC += ParallelMath::ParallelSize * 8; + } + } + + void EncodeBC5U(uint8_t *pBC, const PixelBlockU8 *pBlocks, const Options &options) + { + assert(pBlocks); + assert(pBC); + + float channelWeights[4]; + Internal::FillWeights(options, channelWeights); + + for (size_t blockBase = 0; blockBase < NumParallelBlocks; blockBase += ParallelMath::ParallelSize) + { + Internal::S3TCComputer::PackInterpolatedAlpha(options.flags, pBlocks + blockBase, 0, pBC, 16, false, options.seedPoints, options.refineRoundsIIC); + Internal::S3TCComputer::PackInterpolatedAlpha(options.flags, pBlocks + blockBase, 1, pBC + 8, 16, false, options.seedPoints, options.refineRoundsIIC); + pBC += ParallelMath::ParallelSize * 16; + } + } + + void EncodeBC5S(uint8_t *pBC, const PixelBlockS8 *pBlocks, const Options &options) + { + assert(pBlocks); + assert(pBC); + + float channelWeights[4]; + Internal::FillWeights(options, channelWeights); + + for (size_t blockBase = 0; blockBase < NumParallelBlocks; blockBase += ParallelMath::ParallelSize) + { + PixelBlockU8 inputBlocks[ParallelMath::ParallelSize]; + Internal::BiasSignedInput(inputBlocks, pBlocks + blockBase); + + Internal::S3TCComputer::PackInterpolatedAlpha(options.flags, inputBlocks, 0, pBC, 16, true, options.seedPoints, options.refineRoundsIIC); + Internal::S3TCComputer::PackInterpolatedAlpha(options.flags, inputBlocks, 1, pBC + 8, 16, true, options.seedPoints, options.refineRoundsIIC); + pBC += ParallelMath::ParallelSize * 16; + } + } + + void DecodeBC7(PixelBlockU8 *pBlocks, const uint8_t *pBC) + { + assert(pBlocks); + assert(pBC); + + for (size_t blockBase = 0; blockBase < cvtt::NumParallelBlocks; blockBase++) + { + Internal::BC7Computer::UnpackOne(pBlocks[blockBase], pBC); + pBC += 16; + } + } + + void DecodeBC6HU(PixelBlockF16 *pBlocks, const uint8_t *pBC) + { + assert(pBlocks); + assert(pBC); + + for (size_t blockBase = 0; blockBase < cvtt::NumParallelBlocks; blockBase++) + { + Internal::BC6HComputer::UnpackOne(pBlocks[blockBase], pBC, false); + pBC += 16; + } + } + + void DecodeBC6HS(PixelBlockF16 *pBlocks, const uint8_t *pBC) + { + assert(pBlocks); + assert(pBC); + + for (size_t blockBase = 0; blockBase < cvtt::NumParallelBlocks; blockBase++) + { + Internal::BC6HComputer::UnpackOne(pBlocks[blockBase], pBC, true); + pBC += 16; + } + } + } +} diff --git a/thirdparty/cvtt/ConvectionKernels.h b/thirdparty/cvtt/ConvectionKernels.h new file mode 100644 index 0000000000..fb5ca130f9 --- /dev/null +++ b/thirdparty/cvtt/ConvectionKernels.h @@ -0,0 +1,145 @@ +/* +Convection Texture Tools +Copyright (c) 2018 Eric Lasota + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject +to the following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ +#pragma once +#ifndef __CVTT_CONVECTION_KERNELS__ +#define __CVTT_CONVECTION_KERNELS__ + +#include <stdint.h> + +namespace cvtt +{ + namespace Flags + { + // Enable partitioned modes in BC7 encoding (slower, better quality) + const uint32_t BC7_EnablePartitioning = 0x001; + + // Enable 3-partition modes in BC7 encoding (slower, better quality, requires BC7_EnablePartitioning) + const uint32_t BC7_Enable3Subsets = 0x002; + + // Enable dual-plane modes in BC7 encoding (slower, better quality) + const uint32_t BC7_EnableDualPlane = 0x004; + + // Use fast indexing in BC7 encoding (about 2x faster, slightly worse quality) + const uint32_t BC7_FastIndexing = 0x008; + + // Try precomputed single-color lookups where applicable (slightly slower, small quality increase on specific blocks) + const uint32_t BC7_TrySingleColor = 0x010; + + // Don't allow non-zero or non-max alpha values in blocks that only contain one or the other + const uint32_t BC7_RespectPunchThrough = 0x020; + + // Use fast indexing in HDR formats (faster, worse quality) + const uint32_t BC6H_FastIndexing = 0x040; + + // Exhaustive search RGB orderings when encoding BC1-BC3 (much slower, better quality) + const uint32_t S3TC_Exhaustive = 0x080; + + // Penalize distant endpoints, improving quality on inaccurate GPU decoders + const uint32_t S3TC_Paranoid = 0x100; + + // Uniform color channel importance + const uint32_t Uniform = 0x200; + + // Misc useful default flag combinations + const uint32_t Fastest = (BC6H_FastIndexing | S3TC_Paranoid); + const uint32_t Faster = (BC7_EnableDualPlane | BC6H_FastIndexing | S3TC_Paranoid); + const uint32_t Fast = (BC7_EnablePartitioning | BC7_EnableDualPlane | BC7_FastIndexing | S3TC_Paranoid); + const uint32_t Default = (BC7_EnablePartitioning | BC7_EnableDualPlane | BC7_Enable3Subsets | BC7_FastIndexing | S3TC_Paranoid); + const uint32_t Better = (BC7_EnablePartitioning | BC7_EnableDualPlane | BC7_Enable3Subsets | S3TC_Paranoid | S3TC_Exhaustive); + const uint32_t Ultra = (BC7_EnablePartitioning | BC7_EnableDualPlane | BC7_Enable3Subsets | BC7_TrySingleColor | S3TC_Paranoid | S3TC_Exhaustive); + } + + const unsigned int NumParallelBlocks = 8; + + struct Options + { + uint32_t flags; // Bitmask of cvtt::Flags values + float threshold; // Alpha test threshold for BC1 + float redWeight; // Red channel importance + float greenWeight; // Green channel importance + float blueWeight; // Blue channel importance + float alphaWeight; // Alpha channel importance + + int refineRoundsBC7; // Number of refine rounds for BC7 + int refineRoundsBC6H; // Number of refine rounds for BC6H (max 3) + int refineRoundsIIC; // Number of refine rounds for independent interpolated channels (BC3 alpha, BC4, BC5) + int refineRoundsS3TC; // Number of refine rounds for S3TC RGB + + int seedPoints; // Number of seed points (min 1, max 4) + + Options() + : flags(Flags::Default) + , threshold(0.5f) + , redWeight(0.2125f / 0.7154f) + , greenWeight(1.0f) + , blueWeight(0.0721f / 0.7154f) + , alphaWeight(1.0f) + , refineRoundsBC7(2) + , refineRoundsBC6H(3) + , refineRoundsIIC(8) + , refineRoundsS3TC(2) + , seedPoints(4) + { + } + }; + + // RGBA input block for unsigned 8-bit formats + struct PixelBlockU8 + { + uint8_t m_pixels[16][4]; + }; + + // RGBA input block for signed 8-bit formats + struct PixelBlockS8 + { + int8_t m_pixels[16][4]; + }; + + // RGBA input block for half-precision float formats (bit-cast to int16_t) + struct PixelBlockF16 + { + int16_t m_pixels[16][4]; + }; + + namespace Kernels + { + // NOTE: All functions accept and output NumParallelBlocks blocks at once + void EncodeBC1(uint8_t *pBC, const PixelBlockU8 *pBlocks, const Options &options); + void EncodeBC2(uint8_t *pBC, const PixelBlockU8 *pBlocks, const Options &options); + void EncodeBC3(uint8_t *pBC, const PixelBlockU8 *pBlocks, const Options &options); + void EncodeBC4U(uint8_t *pBC, const PixelBlockU8 *pBlocks, const Options &options); + void EncodeBC4S(uint8_t *pBC, const PixelBlockS8 *pBlocks, const Options &options); + void EncodeBC5U(uint8_t *pBC, const PixelBlockU8 *pBlocks, const Options &options); + void EncodeBC5S(uint8_t *pBC, const PixelBlockS8 *pBlocks, const Options &options); + void EncodeBC6HU(uint8_t *pBC, const PixelBlockF16 *pBlocks, const Options &options); + void EncodeBC6HS(uint8_t *pBC, const PixelBlockF16 *pBlocks, const Options &options); + void EncodeBC7(uint8_t *pBC, const PixelBlockU8 *pBlocks, const Options &options); + + void DecodeBC6HU(PixelBlockF16 *pBlocks, const uint8_t *pBC); + void DecodeBC6HS(PixelBlockF16 *pBlocks, const uint8_t *pBC); + void DecodeBC7(PixelBlockU8 *pBlocks, const uint8_t *pBC); + } +} + +#endif diff --git a/thirdparty/cvtt/ConvectionKernels_BC7_SingleColor.h b/thirdparty/cvtt/ConvectionKernels_BC7_SingleColor.h new file mode 100644 index 0000000000..b5564c0dab --- /dev/null +++ b/thirdparty/cvtt/ConvectionKernels_BC7_SingleColor.h @@ -0,0 +1,1940 @@ +#pragma once +#include <stdint.h> + +namespace cvtt { namespace Tables { namespace BC7SC { + +struct TableEntry +{ + uint8_t m_min; + uint8_t m_max; + uint8_t m_actualColor; +}; + +struct Table +{ + uint8_t m_index; + uint8_t m_pBits; + TableEntry m_entries[256]; +}; + +Table g_mode0_p00_i1= +{ + 1, + 0, + { + { 0, 0, 0 }, { 0, 0, 0 }, { 0, 16, 2 }, { 0, 16, 2 }, { 0, 33, 5 }, { 0, 33, 5 }, { 0, 33, 5 }, { 0, 49, 7 }, + { 0, 49, 7 }, { 0, 66, 9 }, { 0, 66, 9 }, { 0, 82, 12 }, { 0, 82, 12 }, { 0, 82, 12 }, { 0, 99, 14 }, { 0, 99, 14 }, + { 0, 115, 16 }, { 0, 115, 16 }, { 16, 33, 18 }, { 0, 132, 19 }, { 0, 132, 19 }, { 0, 148, 21 }, { 0, 148, 21 }, { 0, 165, 23 }, + { 0, 165, 23 }, { 0, 181, 25 }, { 0, 181, 25 }, { 0, 198, 28 }, { 0, 198, 28 }, { 0, 198, 28 }, { 0, 214, 30 }, { 33, 16, 31 }, + { 0, 231, 32 }, { 33, 33, 33 }, { 0, 247, 35 }, { 0, 247, 35 }, { 0, 247, 35 }, { 16, 165, 37 }, { 33, 66, 38 }, { 16, 181, 39 }, + { 33, 82, 40 }, { 16, 198, 42 }, { 16, 198, 42 }, { 16, 198, 42 }, { 16, 214, 44 }, { 33, 115, 45 }, { 16, 231, 46 }, { 33, 132, 47 }, + { 16, 247, 48 }, { 33, 148, 49 }, { 33, 148, 49 }, { 49, 66, 51 }, { 33, 165, 52 }, { 33, 165, 52 }, { 33, 181, 54 }, { 33, 181, 54 }, + { 33, 198, 56 }, { 66, 0, 57 }, { 33, 214, 58 }, { 66, 16, 59 }, { 33, 231, 61 }, { 33, 231, 61 }, { 33, 231, 61 }, { 33, 247, 63 }, + { 66, 49, 64 }, { 49, 165, 65 }, { 66, 66, 66 }, { 49, 181, 68 }, { 49, 181, 68 }, { 49, 181, 68 }, { 49, 198, 70 }, { 66, 99, 71 }, + { 49, 214, 72 }, { 66, 115, 73 }, { 49, 231, 75 }, { 49, 231, 75 }, { 49, 231, 75 }, { 49, 247, 77 }, { 66, 148, 78 }, { 66, 148, 78 }, + { 66, 165, 80 }, { 66, 165, 80 }, { 66, 181, 82 }, { 66, 181, 82 }, { 82, 99, 84 }, { 66, 198, 85 }, { 66, 198, 85 }, { 66, 214, 87 }, + { 66, 214, 87 }, { 66, 231, 89 }, { 99, 33, 90 }, { 66, 247, 91 }, { 99, 49, 92 }, { 82, 165, 94 }, { 82, 165, 94 }, { 82, 165, 94 }, + { 82, 181, 96 }, { 99, 82, 97 }, { 82, 198, 98 }, { 99, 99, 99 }, { 82, 214, 101 }, { 82, 214, 101 }, { 82, 214, 101 }, { 82, 231, 103 }, + { 99, 132, 104 }, { 82, 247, 105 }, { 99, 148, 106 }, { 99, 148, 106 }, { 99, 165, 108 }, { 99, 165, 108 }, { 115, 82, 110 }, { 99, 181, 111 }, + { 99, 181, 111 }, { 99, 198, 113 }, { 99, 198, 113 }, { 99, 214, 115 }, { 132, 16, 116 }, { 115, 132, 117 }, { 99, 231, 118 }, { 99, 231, 118 }, + { 99, 247, 120 }, { 99, 247, 120 }, { 115, 165, 122 }, { 132, 66, 123 }, { 115, 181, 124 }, { 132, 82, 125 }, { 115, 198, 127 }, { 115, 198, 127 }, + { 115, 198, 127 }, { 115, 214, 129 }, { 132, 115, 130 }, { 115, 231, 131 }, { 132, 132, 132 }, { 115, 247, 134 }, { 115, 247, 134 }, { 115, 247, 134 }, + { 148, 66, 136 }, { 132, 165, 137 }, { 132, 165, 137 }, { 132, 181, 139 }, { 132, 181, 139 }, { 132, 198, 141 }, { 165, 0, 142 }, { 148, 115, 143 }, + { 132, 214, 144 }, { 132, 214, 144 }, { 132, 231, 146 }, { 132, 231, 146 }, { 132, 247, 148 }, { 165, 49, 149 }, { 148, 165, 150 }, { 165, 66, 151 }, + { 148, 181, 153 }, { 148, 181, 153 }, { 148, 181, 153 }, { 148, 198, 155 }, { 165, 99, 156 }, { 148, 214, 157 }, { 165, 115, 158 }, { 148, 231, 160 }, + { 148, 231, 160 }, { 148, 231, 160 }, { 148, 247, 162 }, { 165, 148, 163 }, { 165, 148, 163 }, { 165, 165, 165 }, { 165, 165, 165 }, { 165, 181, 167 }, + { 165, 181, 167 }, { 181, 99, 169 }, { 165, 198, 170 }, { 165, 198, 170 }, { 165, 214, 172 }, { 165, 214, 172 }, { 165, 231, 174 }, { 198, 33, 175 }, + { 181, 148, 176 }, { 165, 247, 177 }, { 165, 247, 177 }, { 181, 165, 179 }, { 181, 165, 179 }, { 181, 181, 181 }, { 198, 82, 182 }, { 181, 198, 183 }, + { 198, 99, 184 }, { 181, 214, 186 }, { 181, 214, 186 }, { 181, 214, 186 }, { 181, 231, 188 }, { 198, 132, 189 }, { 181, 247, 190 }, { 198, 148, 191 }, + { 198, 148, 191 }, { 198, 165, 193 }, { 198, 165, 193 }, { 214, 82, 195 }, { 198, 181, 196 }, { 198, 181, 196 }, { 198, 198, 198 }, { 231, 0, 199 }, + { 198, 214, 200 }, { 231, 16, 201 }, { 214, 132, 202 }, { 198, 231, 203 }, { 198, 231, 203 }, { 198, 247, 205 }, { 198, 247, 205 }, { 214, 165, 207 }, + { 231, 66, 208 }, { 214, 181, 209 }, { 231, 82, 210 }, { 214, 198, 212 }, { 214, 198, 212 }, { 214, 198, 212 }, { 214, 214, 214 }, { 231, 115, 215 }, + { 214, 231, 216 }, { 231, 132, 217 }, { 214, 247, 219 }, { 214, 247, 219 }, { 214, 247, 219 }, { 231, 165, 222 }, { 231, 165, 222 }, { 231, 165, 222 }, + { 231, 181, 224 }, { 231, 181, 224 }, { 231, 198, 226 }, { 231, 198, 226 }, { 247, 115, 228 }, { 231, 214, 229 }, { 231, 214, 229 }, { 231, 231, 231 }, + { 231, 231, 231 }, { 231, 247, 233 }, { 231, 247, 233 }, { 247, 165, 235 }, { 247, 165, 235 }, { 247, 181, 238 }, { 247, 181, 238 }, { 247, 181, 238 }, + { 247, 198, 240 }, { 247, 198, 240 }, { 247, 214, 242 }, { 247, 214, 242 }, { 247, 231, 245 }, { 247, 231, 245 }, { 247, 231, 245 }, { 247, 247, 247 }, + { 247, 247, 247 }, { 247, 247, 247 }, { 247, 247, 247 }, { 247, 247, 247 }, { 247, 247, 247 }, { 247, 247, 247 }, { 247, 247, 247 }, { 247, 247, 247 }, + } +}; + +Table g_mode0_p00_i2= +{ + 2, + 0, + { + { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 16, 5 }, { 0, 16, 5 }, { 0, 16, 5 }, { 0, 16, 5 }, { 0, 16, 5 }, + { 0, 33, 9 }, { 0, 33, 9 }, { 0, 33, 9 }, { 16, 0, 12 }, { 16, 0, 12 }, { 0, 49, 14 }, { 0, 49, 14 }, { 0, 49, 14 }, + { 16, 16, 16 }, { 16, 16, 16 }, { 0, 66, 19 }, { 0, 66, 19 }, { 0, 66, 19 }, { 16, 33, 21 }, { 0, 82, 23 }, { 0, 82, 23 }, + { 33, 0, 24 }, { 16, 49, 25 }, { 16, 49, 25 }, { 0, 99, 28 }, { 0, 99, 28 }, { 0, 99, 28 }, { 16, 66, 30 }, { 0, 115, 32 }, + { 0, 115, 32 }, { 33, 33, 33 }, { 16, 82, 35 }, { 16, 82, 35 }, { 0, 132, 37 }, { 0, 132, 37 }, { 33, 49, 38 }, { 16, 99, 39 }, + { 49, 16, 40 }, { 0, 148, 42 }, { 0, 148, 42 }, { 0, 148, 42 }, { 16, 115, 44 }, { 49, 33, 45 }, { 0, 165, 46 }, { 33, 82, 47 }, + { 16, 132, 49 }, { 16, 132, 49 }, { 0, 181, 51 }, { 0, 181, 51 }, { 33, 99, 52 }, { 16, 148, 53 }, { 49, 66, 54 }, { 0, 198, 56 }, + { 0, 198, 56 }, { 66, 33, 57 }, { 16, 165, 58 }, { 82, 0, 59 }, { 0, 214, 60 }, { 33, 132, 61 }, { 16, 181, 62 }, { 49, 99, 63 }, + { 0, 231, 65 }, { 0, 231, 65 }, { 66, 66, 66 }, { 16, 198, 67 }, { 49, 115, 68 }, { 0, 247, 69 }, { 33, 165, 70 }, { 66, 82, 71 }, + { 16, 214, 72 }, { 82, 49, 73 }, { 33, 181, 75 }, { 33, 181, 75 }, { 16, 231, 76 }, { 49, 148, 77 }, { 82, 66, 78 }, { 33, 198, 79 }, + { 66, 115, 80 }, { 16, 247, 81 }, { 49, 165, 82 }, { 115, 0, 83 }, { 33, 214, 84 }, { 66, 132, 85 }, { 49, 181, 86 }, { 82, 99, 87 }, + { 33, 231, 89 }, { 33, 231, 89 }, { 99, 66, 90 }, { 49, 198, 91 }, { 115, 33, 92 }, { 33, 247, 93 }, { 66, 165, 94 }, { 49, 214, 95 }, + { 82, 132, 96 }, { 66, 181, 98 }, { 66, 181, 98 }, { 99, 99, 99 }, { 49, 231, 100 }, { 82, 148, 101 }, { 66, 198, 103 }, { 66, 198, 103 }, + { 99, 115, 104 }, { 49, 247, 105 }, { 115, 82, 106 }, { 66, 214, 108 }, { 66, 214, 108 }, { 132, 49, 109 }, { 82, 181, 110 }, { 115, 99, 111 }, + { 66, 231, 112 }, { 99, 148, 113 }, { 82, 198, 115 }, { 82, 198, 115 }, { 148, 33, 116 }, { 66, 247, 117 }, { 99, 165, 118 }, { 82, 214, 119 }, + { 115, 132, 120 }, { 99, 181, 122 }, { 99, 181, 122 }, { 132, 99, 123 }, { 82, 231, 124 }, { 148, 66, 125 }, { 99, 198, 127 }, { 99, 198, 127 }, + { 82, 247, 128 }, { 115, 165, 129 }, { 181, 0, 130 }, { 99, 214, 131 }, { 132, 132, 132 }, { 115, 181, 134 }, { 115, 181, 134 }, { 181, 16, 135 }, + { 99, 231, 136 }, { 132, 148, 137 }, { 115, 198, 138 }, { 148, 115, 139 }, { 99, 247, 141 }, { 99, 247, 141 }, { 165, 82, 142 }, { 115, 214, 143 }, + { 148, 132, 144 }, { 132, 181, 146 }, { 132, 181, 146 }, { 198, 16, 147 }, { 115, 231, 148 }, { 181, 66, 149 }, { 132, 198, 151 }, { 132, 198, 151 }, + { 115, 247, 152 }, { 148, 165, 153 }, { 214, 0, 154 }, { 132, 214, 155 }, { 165, 132, 156 }, { 148, 181, 157 }, { 181, 99, 158 }, { 132, 231, 160 }, + { 132, 231, 160 }, { 198, 66, 161 }, { 148, 198, 162 }, { 214, 33, 163 }, { 132, 247, 164 }, { 165, 165, 165 }, { 231, 0, 166 }, { 148, 214, 167 }, + { 214, 49, 168 }, { 165, 181, 170 }, { 165, 181, 170 }, { 148, 231, 171 }, { 181, 148, 172 }, { 165, 198, 174 }, { 165, 198, 174 }, { 198, 115, 175 }, + { 148, 247, 176 }, { 181, 165, 177 }, { 247, 0, 178 }, { 165, 214, 179 }, { 231, 49, 180 }, { 181, 181, 181 }, { 214, 99, 182 }, { 165, 231, 184 }, + { 165, 231, 184 }, { 231, 66, 185 }, { 181, 198, 186 }, { 247, 33, 187 }, { 165, 247, 188 }, { 198, 165, 189 }, { 181, 214, 190 }, { 214, 132, 191 }, + { 198, 181, 193 }, { 198, 181, 193 }, { 231, 99, 194 }, { 181, 231, 195 }, { 247, 66, 196 }, { 198, 198, 198 }, { 198, 198, 198 }, { 181, 247, 200 }, + { 181, 247, 200 }, { 247, 82, 201 }, { 198, 214, 203 }, { 198, 214, 203 }, { 198, 214, 203 }, { 214, 181, 205 }, { 198, 231, 207 }, { 198, 231, 207 }, + { 231, 148, 208 }, { 214, 198, 210 }, { 214, 198, 210 }, { 198, 247, 212 }, { 198, 247, 212 }, { 198, 247, 212 }, { 214, 214, 214 }, { 247, 132, 215 }, + { 231, 181, 217 }, { 231, 181, 217 }, { 214, 231, 219 }, { 214, 231, 219 }, { 214, 231, 219 }, { 231, 198, 222 }, { 231, 198, 222 }, { 214, 247, 223 }, + { 247, 165, 224 }, { 231, 214, 226 }, { 231, 214, 226 }, { 231, 214, 226 }, { 247, 181, 228 }, { 247, 181, 228 }, { 231, 231, 231 }, { 231, 231, 231 }, + { 231, 231, 231 }, { 247, 198, 233 }, { 247, 198, 233 }, { 231, 247, 236 }, { 231, 247, 236 }, { 231, 247, 236 }, { 247, 214, 238 }, { 247, 214, 238 }, + { 247, 214, 238 }, { 247, 231, 243 }, { 247, 231, 243 }, { 247, 231, 243 }, { 247, 231, 243 }, { 247, 231, 243 }, { 247, 247, 247 }, { 247, 247, 247 }, + { 247, 247, 247 }, { 247, 247, 247 }, { 247, 247, 247 }, { 247, 247, 247 }, { 247, 247, 247 }, { 247, 247, 247 }, { 247, 247, 247 }, { 247, 247, 247 }, + } +}; + +Table g_mode0_p00_i3= +{ + 3, + 0, + { + { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 16, 7 }, { 0, 16, 7 }, { 0, 16, 7 }, { 0, 16, 7 }, + { 0, 16, 7 }, { 16, 0, 9 }, { 16, 0, 9 }, { 16, 0, 9 }, { 0, 33, 14 }, { 0, 33, 14 }, { 0, 33, 14 }, { 0, 33, 14 }, + { 16, 16, 16 }, { 16, 16, 16 }, { 33, 0, 19 }, { 33, 0, 19 }, { 0, 49, 21 }, { 0, 49, 21 }, { 0, 49, 21 }, { 16, 33, 23 }, + { 16, 33, 23 }, { 33, 16, 26 }, { 33, 16, 26 }, { 0, 66, 28 }, { 0, 66, 28 }, { 0, 66, 28 }, { 16, 49, 30 }, { 16, 49, 30 }, + { 33, 33, 33 }, { 33, 33, 33 }, { 0, 82, 35 }, { 0, 82, 35 }, { 0, 82, 35 }, { 16, 66, 37 }, { 66, 0, 38 }, { 33, 49, 40 }, + { 33, 49, 40 }, { 0, 99, 42 }, { 0, 99, 42 }, { 0, 99, 42 }, { 16, 82, 44 }, { 66, 16, 45 }, { 33, 66, 47 }, { 33, 66, 47 }, + { 0, 115, 49 }, { 0, 115, 49 }, { 0, 115, 49 }, { 16, 99, 51 }, { 66, 33, 52 }, { 33, 82, 54 }, { 33, 82, 54 }, { 0, 132, 56 }, + { 0, 132, 56 }, { 99, 0, 57 }, { 16, 115, 58 }, { 66, 49, 59 }, { 33, 99, 61 }, { 33, 99, 61 }, { 0, 148, 62 }, { 49, 82, 63 }, + { 99, 16, 64 }, { 16, 132, 65 }, { 66, 66, 66 }, { 33, 115, 68 }, { 33, 115, 68 }, { 0, 165, 70 }, { 0, 165, 70 }, { 99, 33, 71 }, + { 16, 148, 72 }, { 66, 82, 73 }, { 33, 132, 75 }, { 33, 132, 75 }, { 0, 181, 76 }, { 49, 115, 77 }, { 99, 49, 78 }, { 16, 165, 79 }, + { 66, 99, 80 }, { 33, 148, 82 }, { 33, 148, 82 }, { 132, 16, 83 }, { 0, 198, 84 }, { 99, 66, 85 }, { 16, 181, 86 }, { 66, 115, 87 }, + { 33, 165, 89 }, { 33, 165, 89 }, { 0, 214, 90 }, { 49, 148, 91 }, { 99, 82, 92 }, { 16, 198, 93 }, { 66, 132, 94 }, { 33, 181, 95 }, + { 82, 115, 96 }, { 0, 231, 97 }, { 49, 165, 98 }, { 99, 99, 99 }, { 16, 214, 100 }, { 66, 148, 101 }, { 165, 16, 102 }, { 33, 198, 103 }, + { 0, 247, 104 }, { 49, 181, 105 }, { 99, 115, 106 }, { 16, 231, 107 }, { 66, 165, 108 }, { 33, 214, 109 }, { 82, 148, 110 }, { 132, 82, 111 }, + { 49, 198, 112 }, { 16, 247, 113 }, { 198, 0, 114 }, { 66, 181, 115 }, { 165, 49, 116 }, { 33, 231, 117 }, { 132, 99, 118 }, { 49, 214, 119 }, + { 99, 148, 120 }, { 198, 16, 121 }, { 66, 198, 122 }, { 33, 247, 123 }, { 82, 181, 124 }, { 132, 115, 125 }, { 49, 231, 126 }, { 99, 165, 127 }, + { 66, 214, 128 }, { 115, 148, 129 }, { 165, 82, 130 }, { 82, 198, 131 }, { 132, 132, 132 }, { 49, 247, 133 }, { 99, 181, 134 }, { 198, 49, 135 }, + { 66, 231, 136 }, { 165, 99, 137 }, { 82, 214, 138 }, { 132, 148, 139 }, { 231, 16, 140 }, { 99, 198, 141 }, { 66, 247, 142 }, { 115, 181, 143 }, + { 165, 115, 144 }, { 82, 231, 145 }, { 132, 165, 146 }, { 231, 33, 147 }, { 99, 214, 148 }, { 198, 82, 149 }, { 115, 198, 150 }, { 165, 132, 151 }, + { 82, 247, 152 }, { 132, 181, 153 }, { 231, 49, 154 }, { 99, 231, 155 }, { 198, 99, 156 }, { 115, 214, 157 }, { 165, 148, 158 }, { 132, 198, 160 }, + { 132, 198, 160 }, { 99, 247, 161 }, { 148, 181, 162 }, { 198, 115, 163 }, { 115, 231, 164 }, { 165, 165, 165 }, { 132, 214, 167 }, { 132, 214, 167 }, + { 231, 82, 168 }, { 148, 198, 169 }, { 198, 132, 170 }, { 115, 247, 171 }, { 165, 181, 172 }, { 132, 231, 174 }, { 132, 231, 174 }, { 231, 99, 175 }, + { 148, 214, 176 }, { 198, 148, 177 }, { 165, 198, 179 }, { 165, 198, 179 }, { 132, 247, 181 }, { 132, 247, 181 }, { 231, 115, 182 }, { 148, 231, 183 }, + { 198, 165, 184 }, { 247, 99, 185 }, { 165, 214, 186 }, { 165, 214, 186 }, { 181, 198, 188 }, { 231, 132, 189 }, { 148, 247, 190 }, { 198, 181, 191 }, + { 165, 231, 193 }, { 165, 231, 193 }, { 165, 231, 193 }, { 181, 214, 195 }, { 231, 148, 196 }, { 198, 198, 198 }, { 198, 198, 198 }, { 165, 247, 200 }, + { 165, 247, 200 }, { 165, 247, 200 }, { 181, 231, 202 }, { 231, 165, 203 }, { 198, 214, 205 }, { 198, 214, 205 }, { 198, 214, 205 }, { 214, 198, 207 }, + { 181, 247, 209 }, { 181, 247, 209 }, { 231, 181, 210 }, { 198, 231, 212 }, { 198, 231, 212 }, { 198, 231, 212 }, { 214, 214, 214 }, { 214, 214, 214 }, + { 231, 198, 217 }, { 231, 198, 217 }, { 198, 247, 219 }, { 198, 247, 219 }, { 198, 247, 219 }, { 214, 231, 221 }, { 214, 231, 221 }, { 231, 214, 224 }, + { 231, 214, 224 }, { 231, 214, 224 }, { 247, 198, 226 }, { 214, 247, 228 }, { 214, 247, 228 }, { 214, 247, 228 }, { 231, 231, 231 }, { 231, 231, 231 }, + { 231, 231, 231 }, { 247, 214, 233 }, { 247, 214, 233 }, { 247, 214, 233 }, { 231, 247, 238 }, { 231, 247, 238 }, { 231, 247, 238 }, { 231, 247, 238 }, + { 247, 231, 240 }, { 247, 231, 240 }, { 247, 231, 240 }, { 247, 231, 240 }, { 247, 247, 247 }, { 247, 247, 247 }, { 247, 247, 247 }, { 247, 247, 247 }, + { 247, 247, 247 }, { 247, 247, 247 }, { 247, 247, 247 }, { 247, 247, 247 }, { 247, 247, 247 }, { 247, 247, 247 }, { 247, 247, 247 }, { 247, 247, 247 }, + } +}; + +Table g_mode0_p01_i1= +{ + 1, + 2, + { + { 0, 8, 1 }, { 0, 8, 1 }, { 0, 8, 1 }, { 0, 24, 3 }, { 0, 24, 3 }, { 0, 41, 6 }, { 0, 41, 6 }, { 0, 41, 6 }, + { 0, 57, 8 }, { 0, 57, 8 }, { 0, 74, 10 }, { 0, 74, 10 }, { 0, 90, 13 }, { 0, 90, 13 }, { 0, 90, 13 }, { 0, 107, 15 }, + { 0, 107, 15 }, { 0, 123, 17 }, { 0, 123, 17 }, { 0, 140, 20 }, { 0, 140, 20 }, { 0, 140, 20 }, { 0, 156, 22 }, { 0, 156, 22 }, + { 0, 173, 24 }, { 0, 173, 24 }, { 16, 90, 26 }, { 0, 189, 27 }, { 0, 189, 27 }, { 0, 206, 29 }, { 0, 206, 29 }, { 0, 222, 31 }, + { 33, 24, 32 }, { 16, 140, 33 }, { 0, 239, 34 }, { 0, 239, 34 }, { 0, 255, 36 }, { 0, 255, 36 }, { 16, 173, 38 }, { 33, 74, 39 }, + { 16, 189, 40 }, { 33, 90, 41 }, { 16, 206, 43 }, { 16, 206, 43 }, { 16, 206, 43 }, { 16, 222, 45 }, { 33, 123, 46 }, { 16, 239, 47 }, + { 33, 140, 48 }, { 16, 255, 50 }, { 16, 255, 50 }, { 16, 255, 50 }, { 33, 173, 53 }, { 33, 173, 53 }, { 33, 173, 53 }, { 33, 189, 55 }, + { 33, 189, 55 }, { 33, 206, 57 }, { 66, 8, 58 }, { 49, 123, 59 }, { 33, 222, 60 }, { 33, 222, 60 }, { 33, 239, 62 }, { 33, 239, 62 }, + { 33, 255, 64 }, { 66, 57, 65 }, { 49, 173, 66 }, { 66, 74, 67 }, { 49, 189, 69 }, { 49, 189, 69 }, { 49, 189, 69 }, { 49, 206, 71 }, + { 66, 107, 72 }, { 49, 222, 73 }, { 66, 123, 74 }, { 49, 239, 76 }, { 49, 239, 76 }, { 49, 239, 76 }, { 49, 255, 78 }, { 66, 156, 79 }, + { 66, 156, 79 }, { 66, 173, 81 }, { 66, 173, 81 }, { 66, 189, 83 }, { 66, 189, 83 }, { 66, 206, 86 }, { 66, 206, 86 }, { 66, 206, 86 }, + { 66, 222, 88 }, { 66, 222, 88 }, { 66, 239, 90 }, { 99, 41, 91 }, { 82, 156, 92 }, { 66, 255, 93 }, { 66, 255, 93 }, { 82, 173, 95 }, + { 82, 173, 95 }, { 82, 189, 97 }, { 99, 90, 98 }, { 82, 206, 99 }, { 99, 107, 100 }, { 82, 222, 102 }, { 82, 222, 102 }, { 82, 222, 102 }, + { 82, 239, 104 }, { 99, 140, 105 }, { 82, 255, 106 }, { 99, 156, 107 }, { 99, 156, 107 }, { 99, 173, 109 }, { 99, 173, 109 }, { 115, 90, 111 }, + { 99, 189, 112 }, { 99, 189, 112 }, { 99, 206, 114 }, { 132, 8, 115 }, { 99, 222, 116 }, { 132, 24, 117 }, { 99, 239, 119 }, { 99, 239, 119 }, + { 99, 239, 119 }, { 99, 255, 121 }, { 99, 255, 121 }, { 115, 173, 123 }, { 132, 74, 124 }, { 115, 189, 125 }, { 132, 90, 126 }, { 115, 206, 128 }, + { 115, 206, 128 }, { 115, 206, 128 }, { 115, 222, 130 }, { 132, 123, 131 }, { 115, 239, 132 }, { 132, 140, 133 }, { 115, 255, 135 }, { 115, 255, 135 }, + { 115, 255, 135 }, { 132, 173, 138 }, { 132, 173, 138 }, { 132, 173, 138 }, { 132, 189, 140 }, { 132, 189, 140 }, { 132, 206, 142 }, { 165, 8, 143 }, + { 148, 123, 144 }, { 132, 222, 145 }, { 132, 222, 145 }, { 132, 239, 147 }, { 165, 41, 148 }, { 132, 255, 149 }, { 165, 57, 150 }, { 148, 173, 152 }, + { 148, 173, 152 }, { 148, 173, 152 }, { 148, 189, 154 }, { 148, 189, 154 }, { 148, 206, 156 }, { 165, 107, 157 }, { 148, 222, 158 }, { 165, 123, 159 }, + { 148, 239, 161 }, { 148, 239, 161 }, { 148, 239, 161 }, { 148, 255, 163 }, { 165, 156, 164 }, { 165, 156, 164 }, { 165, 173, 166 }, { 165, 173, 166 }, + { 165, 189, 168 }, { 165, 189, 168 }, { 165, 206, 171 }, { 165, 206, 171 }, { 165, 206, 171 }, { 165, 222, 173 }, { 198, 24, 174 }, { 165, 239, 175 }, + { 198, 41, 176 }, { 181, 156, 177 }, { 165, 255, 178 }, { 165, 255, 178 }, { 181, 173, 180 }, { 198, 74, 181 }, { 181, 189, 182 }, { 198, 90, 183 }, + { 181, 206, 185 }, { 181, 206, 185 }, { 181, 206, 185 }, { 181, 222, 187 }, { 181, 222, 187 }, { 181, 239, 189 }, { 198, 140, 190 }, { 181, 255, 191 }, + { 198, 156, 192 }, { 198, 156, 192 }, { 198, 173, 194 }, { 198, 173, 194 }, { 198, 189, 197 }, { 198, 189, 197 }, { 198, 189, 197 }, { 198, 206, 199 }, + { 231, 8, 200 }, { 198, 222, 201 }, { 231, 24, 202 }, { 198, 239, 204 }, { 198, 239, 204 }, { 198, 239, 204 }, { 198, 255, 206 }, { 231, 57, 207 }, + { 214, 173, 208 }, { 231, 74, 209 }, { 214, 189, 210 }, { 231, 90, 211 }, { 214, 206, 213 }, { 214, 206, 213 }, { 231, 107, 214 }, { 214, 222, 215 }, + { 231, 123, 216 }, { 214, 239, 218 }, { 214, 239, 218 }, { 214, 239, 218 }, { 214, 255, 220 }, { 214, 255, 220 }, { 231, 173, 223 }, { 231, 173, 223 }, + { 231, 173, 223 }, { 231, 189, 225 }, { 231, 189, 225 }, { 231, 206, 227 }, { 231, 206, 227 }, { 231, 222, 230 }, { 231, 222, 230 }, { 231, 222, 230 }, + { 231, 239, 232 }, { 231, 239, 232 }, { 231, 255, 234 }, { 231, 255, 234 }, { 247, 173, 237 }, { 247, 173, 237 }, { 247, 173, 237 }, { 247, 189, 239 }, + { 247, 189, 239 }, { 247, 206, 241 }, { 247, 206, 241 }, { 247, 222, 243 }, { 247, 222, 243 }, { 247, 239, 246 }, { 247, 239, 246 }, { 247, 239, 246 }, + { 247, 255, 248 }, { 247, 255, 248 }, { 247, 255, 248 }, { 247, 255, 248 }, { 247, 255, 248 }, { 247, 255, 248 }, { 247, 255, 248 }, { 247, 255, 248 }, + } +}; + +Table g_mode0_p01_i2= +{ + 2, + 2, + { + { 0, 8, 2 }, { 0, 8, 2 }, { 0, 8, 2 }, { 0, 8, 2 }, { 0, 8, 2 }, { 0, 24, 7 }, { 0, 24, 7 }, { 0, 24, 7 }, + { 0, 24, 7 }, { 0, 24, 7 }, { 0, 41, 12 }, { 0, 41, 12 }, { 0, 41, 12 }, { 0, 41, 12 }, { 16, 8, 14 }, { 0, 57, 16 }, + { 0, 57, 16 }, { 0, 57, 16 }, { 16, 24, 18 }, { 16, 24, 18 }, { 0, 74, 21 }, { 0, 74, 21 }, { 0, 74, 21 }, { 16, 41, 23 }, + { 0, 90, 25 }, { 0, 90, 25 }, { 33, 8, 26 }, { 16, 57, 28 }, { 16, 57, 28 }, { 0, 107, 30 }, { 0, 107, 30 }, { 0, 107, 30 }, + { 16, 74, 32 }, { 16, 74, 32 }, { 0, 123, 35 }, { 0, 123, 35 }, { 0, 123, 35 }, { 16, 90, 37 }, { 0, 140, 39 }, { 0, 140, 39 }, + { 33, 57, 40 }, { 16, 107, 42 }, { 16, 107, 42 }, { 0, 156, 44 }, { 0, 156, 44 }, { 33, 74, 45 }, { 16, 123, 46 }, { 49, 41, 47 }, + { 0, 173, 49 }, { 0, 173, 49 }, { 66, 8, 50 }, { 16, 140, 51 }, { 0, 189, 53 }, { 0, 189, 53 }, { 33, 107, 54 }, { 16, 156, 55 }, + { 49, 74, 56 }, { 0, 206, 58 }, { 0, 206, 58 }, { 66, 41, 59 }, { 16, 173, 60 }, { 49, 90, 61 }, { 0, 222, 62 }, { 33, 140, 63 }, + { 16, 189, 65 }, { 16, 189, 65 }, { 82, 24, 66 }, { 0, 239, 67 }, { 33, 156, 68 }, { 16, 206, 69 }, { 49, 123, 70 }, { 0, 255, 72 }, + { 0, 255, 72 }, { 66, 90, 73 }, { 16, 222, 74 }, { 49, 140, 75 }, { 33, 189, 77 }, { 33, 189, 77 }, { 66, 107, 78 }, { 16, 239, 79 }, + { 82, 74, 80 }, { 33, 206, 82 }, { 33, 206, 82 }, { 16, 255, 83 }, { 49, 173, 84 }, { 115, 8, 85 }, { 33, 222, 86 }, { 66, 140, 87 }, + { 49, 189, 88 }, { 82, 107, 89 }, { 33, 239, 91 }, { 33, 239, 91 }, { 99, 74, 92 }, { 49, 206, 93 }, { 82, 123, 94 }, { 33, 255, 95 }, + { 66, 173, 96 }, { 132, 8, 97 }, { 49, 222, 98 }, { 115, 57, 99 }, { 66, 189, 101 }, { 66, 189, 101 }, { 49, 239, 102 }, { 82, 156, 103 }, + { 66, 206, 105 }, { 66, 206, 105 }, { 99, 123, 106 }, { 49, 255, 107 }, { 82, 173, 108 }, { 148, 8, 109 }, { 66, 222, 110 }, { 99, 140, 111 }, + { 82, 189, 112 }, { 115, 107, 113 }, { 66, 239, 115 }, { 66, 239, 115 }, { 132, 74, 116 }, { 82, 206, 117 }, { 148, 41, 118 }, { 66, 255, 119 }, + { 99, 173, 120 }, { 82, 222, 121 }, { 115, 140, 122 }, { 99, 189, 124 }, { 99, 189, 124 }, { 132, 107, 125 }, { 82, 239, 126 }, { 115, 156, 127 }, + { 99, 206, 129 }, { 99, 206, 129 }, { 165, 41, 130 }, { 82, 255, 131 }, { 148, 90, 132 }, { 99, 222, 134 }, { 99, 222, 134 }, { 165, 57, 135 }, + { 115, 189, 136 }, { 181, 24, 137 }, { 99, 239, 138 }, { 132, 156, 139 }, { 115, 206, 141 }, { 115, 206, 141 }, { 181, 41, 142 }, { 99, 255, 143 }, + { 132, 173, 144 }, { 115, 222, 145 }, { 148, 140, 146 }, { 132, 189, 148 }, { 132, 189, 148 }, { 165, 107, 149 }, { 115, 239, 150 }, { 181, 74, 151 }, + { 132, 206, 153 }, { 132, 206, 153 }, { 115, 255, 154 }, { 148, 173, 155 }, { 214, 8, 156 }, { 132, 222, 157 }, { 165, 140, 158 }, { 148, 189, 160 }, + { 148, 189, 160 }, { 214, 24, 161 }, { 132, 239, 162 }, { 198, 74, 163 }, { 148, 206, 164 }, { 181, 123, 165 }, { 132, 255, 167 }, { 132, 255, 167 }, + { 198, 90, 168 }, { 148, 222, 169 }, { 214, 57, 170 }, { 165, 189, 172 }, { 165, 189, 172 }, { 231, 24, 173 }, { 148, 239, 174 }, { 214, 74, 175 }, + { 165, 206, 177 }, { 165, 206, 177 }, { 148, 255, 178 }, { 181, 173, 179 }, { 247, 8, 180 }, { 165, 222, 181 }, { 198, 140, 182 }, { 181, 189, 183 }, + { 214, 107, 184 }, { 165, 239, 186 }, { 165, 239, 186 }, { 231, 74, 187 }, { 181, 206, 188 }, { 247, 41, 189 }, { 165, 255, 190 }, { 198, 173, 191 }, + { 181, 222, 193 }, { 181, 222, 193 }, { 247, 57, 194 }, { 198, 189, 195 }, { 231, 107, 196 }, { 181, 239, 197 }, { 214, 156, 198 }, { 198, 206, 200 }, + { 198, 206, 200 }, { 231, 123, 201 }, { 181, 255, 202 }, { 247, 90, 203 }, { 198, 222, 205 }, { 198, 222, 205 }, { 198, 222, 205 }, { 214, 189, 207 }, + { 247, 107, 208 }, { 198, 239, 210 }, { 198, 239, 210 }, { 198, 239, 210 }, { 214, 206, 212 }, { 198, 255, 214 }, { 198, 255, 214 }, { 231, 173, 215 }, + { 214, 222, 216 }, { 247, 140, 217 }, { 231, 189, 219 }, { 231, 189, 219 }, { 214, 239, 221 }, { 214, 239, 221 }, { 214, 239, 221 }, { 231, 206, 224 }, + { 231, 206, 224 }, { 214, 255, 226 }, { 214, 255, 226 }, { 214, 255, 226 }, { 231, 222, 228 }, { 231, 222, 228 }, { 247, 189, 231 }, { 247, 189, 231 }, + { 231, 239, 233 }, { 231, 239, 233 }, { 231, 239, 233 }, { 247, 206, 235 }, { 247, 206, 235 }, { 231, 255, 238 }, { 231, 255, 238 }, { 231, 255, 238 }, + { 247, 222, 240 }, { 247, 222, 240 }, { 247, 222, 240 }, { 247, 239, 245 }, { 247, 239, 245 }, { 247, 239, 245 }, { 247, 239, 245 }, { 247, 239, 245 }, + { 247, 255, 249 }, { 247, 255, 249 }, { 247, 255, 249 }, { 247, 255, 249 }, { 247, 255, 249 }, { 247, 255, 249 }, { 247, 255, 249 }, { 247, 255, 249 }, + } +}; + +Table g_mode0_p01_i3= +{ + 3, + 2, + { + { 0, 8, 3 }, { 0, 8, 3 }, { 0, 8, 3 }, { 0, 8, 3 }, { 0, 8, 3 }, { 0, 8, 3 }, { 0, 8, 3 }, { 0, 24, 10 }, + { 0, 24, 10 }, { 0, 24, 10 }, { 0, 24, 10 }, { 0, 24, 10 }, { 16, 8, 13 }, { 16, 8, 13 }, { 16, 8, 13 }, { 0, 41, 17 }, + { 0, 41, 17 }, { 0, 41, 17 }, { 0, 41, 17 }, { 16, 24, 19 }, { 16, 24, 19 }, { 33, 8, 22 }, { 33, 8, 22 }, { 0, 57, 24 }, + { 0, 57, 24 }, { 0, 57, 24 }, { 16, 41, 27 }, { 16, 41, 27 }, { 16, 41, 27 }, { 33, 24, 29 }, { 0, 74, 31 }, { 0, 74, 31 }, + { 49, 8, 32 }, { 16, 57, 33 }, { 16, 57, 33 }, { 33, 41, 36 }, { 33, 41, 36 }, { 0, 90, 38 }, { 0, 90, 38 }, { 0, 90, 38 }, + { 16, 74, 40 }, { 16, 74, 40 }, { 66, 8, 42 }, { 33, 57, 43 }, { 0, 107, 45 }, { 0, 107, 45 }, { 49, 41, 46 }, { 16, 90, 47 }, + { 66, 24, 48 }, { 33, 74, 50 }, { 33, 74, 50 }, { 82, 8, 51 }, { 0, 123, 52 }, { 0, 123, 52 }, { 16, 107, 54 }, { 66, 41, 55 }, + { 33, 90, 57 }, { 33, 90, 57 }, { 82, 24, 58 }, { 0, 140, 59 }, { 49, 74, 60 }, { 16, 123, 61 }, { 66, 57, 62 }, { 33, 107, 64 }, + { 33, 107, 64 }, { 82, 41, 65 }, { 0, 156, 66 }, { 99, 24, 67 }, { 16, 140, 68 }, { 66, 74, 69 }, { 115, 8, 70 }, { 33, 123, 71 }, + { 0, 173, 73 }, { 0, 173, 73 }, { 0, 173, 73 }, { 16, 156, 75 }, { 66, 90, 76 }, { 115, 24, 77 }, { 33, 140, 78 }, { 82, 74, 79 }, + { 0, 189, 80 }, { 99, 57, 81 }, { 16, 173, 82 }, { 66, 107, 83 }, { 115, 41, 84 }, { 33, 156, 85 }, { 132, 24, 86 }, { 0, 206, 87 }, + { 99, 74, 88 }, { 16, 189, 89 }, { 66, 123, 90 }, { 115, 57, 91 }, { 33, 173, 92 }, { 82, 107, 93 }, { 0, 222, 94 }, { 99, 90, 95 }, + { 16, 206, 96 }, { 66, 140, 97 }, { 115, 74, 98 }, { 33, 189, 99 }, { 132, 57, 100 }, { 0, 239, 101 }, { 99, 107, 102 }, { 16, 222, 103 }, + { 66, 156, 104 }, { 33, 206, 106 }, { 33, 206, 106 }, { 0, 255, 108 }, { 0, 255, 108 }, { 99, 123, 109 }, { 16, 239, 110 }, { 66, 173, 111 }, + { 115, 107, 112 }, { 33, 222, 113 }, { 132, 90, 114 }, { 49, 206, 115 }, { 99, 140, 116 }, { 16, 255, 117 }, { 66, 189, 118 }, { 165, 57, 119 }, + { 33, 239, 120 }, { 132, 107, 121 }, { 49, 222, 122 }, { 99, 156, 123 }, { 148, 90, 124 }, { 66, 206, 125 }, { 115, 140, 126 }, { 33, 255, 127 }, + { 132, 123, 128 }, { 49, 239, 129 }, { 99, 173, 130 }, { 148, 107, 131 }, { 66, 222, 132 }, { 165, 90, 133 }, { 82, 206, 134 }, { 132, 140, 135 }, + { 49, 255, 136 }, { 99, 189, 137 }, { 66, 239, 139 }, { 66, 239, 139 }, { 66, 239, 139 }, { 82, 222, 141 }, { 132, 156, 142 }, { 181, 90, 143 }, + { 99, 206, 144 }, { 148, 140, 145 }, { 66, 255, 146 }, { 165, 123, 147 }, { 82, 239, 148 }, { 132, 173, 149 }, { 181, 107, 150 }, { 99, 222, 151 }, + { 198, 90, 152 }, { 115, 206, 153 }, { 165, 140, 154 }, { 82, 255, 155 }, { 132, 189, 156 }, { 181, 123, 157 }, { 99, 239, 158 }, { 148, 173, 159 }, + { 115, 222, 160 }, { 165, 156, 161 }, { 214, 90, 162 }, { 132, 206, 163 }, { 181, 140, 164 }, { 99, 255, 165 }, { 198, 123, 166 }, { 115, 239, 167 }, + { 165, 173, 168 }, { 214, 107, 169 }, { 132, 222, 170 }, { 132, 222, 170 }, { 148, 206, 172 }, { 115, 255, 174 }, { 115, 255, 174 }, { 165, 189, 175 }, + { 214, 123, 176 }, { 132, 239, 177 }, { 181, 173, 178 }, { 148, 222, 179 }, { 198, 156, 180 }, { 247, 90, 181 }, { 165, 206, 182 }, { 214, 140, 183 }, + { 132, 255, 184 }, { 231, 123, 185 }, { 148, 239, 186 }, { 198, 173, 187 }, { 247, 107, 188 }, { 165, 222, 189 }, { 214, 156, 190 }, { 181, 206, 192 }, + { 181, 206, 192 }, { 148, 255, 193 }, { 198, 189, 194 }, { 247, 123, 195 }, { 165, 239, 196 }, { 214, 173, 197 }, { 181, 222, 198 }, { 231, 156, 199 }, + { 198, 206, 201 }, { 198, 206, 201 }, { 247, 140, 202 }, { 165, 255, 203 }, { 165, 255, 203 }, { 181, 239, 205 }, { 181, 239, 205 }, { 231, 173, 207 }, + { 198, 222, 208 }, { 247, 156, 209 }, { 214, 206, 211 }, { 214, 206, 211 }, { 181, 255, 212 }, { 231, 189, 213 }, { 198, 239, 215 }, { 198, 239, 215 }, + { 247, 173, 216 }, { 214, 222, 217 }, { 214, 222, 217 }, { 231, 206, 220 }, { 231, 206, 220 }, { 198, 255, 222 }, { 198, 255, 222 }, { 247, 189, 223 }, + { 214, 239, 225 }, { 214, 239, 225 }, { 214, 239, 225 }, { 231, 222, 227 }, { 231, 222, 227 }, { 247, 206, 230 }, { 247, 206, 230 }, { 214, 255, 231 }, + { 214, 255, 231 }, { 231, 239, 234 }, { 231, 239, 234 }, { 231, 239, 234 }, { 247, 222, 236 }, { 247, 222, 236 }, { 247, 222, 236 }, { 231, 255, 241 }, + { 231, 255, 241 }, { 231, 255, 241 }, { 231, 255, 241 }, { 247, 239, 244 }, { 247, 239, 244 }, { 247, 239, 244 }, { 247, 239, 244 }, { 247, 239, 244 }, + { 247, 255, 250 }, { 247, 255, 250 }, { 247, 255, 250 }, { 247, 255, 250 }, { 247, 255, 250 }, { 247, 255, 250 }, { 247, 255, 250 }, { 247, 255, 250 }, + } +}; + +Table g_mode0_p10_i1= +{ + 1, + 1, + { + { 8, 0, 7 }, { 8, 0, 7 }, { 8, 0, 7 }, { 8, 0, 7 }, { 8, 0, 7 }, { 8, 0, 7 }, { 8, 0, 7 }, { 8, 0, 7 }, + { 8, 0, 7 }, { 8, 16, 9 }, { 8, 16, 9 }, { 8, 33, 12 }, { 8, 33, 12 }, { 8, 33, 12 }, { 8, 49, 14 }, { 8, 49, 14 }, + { 8, 66, 16 }, { 8, 66, 16 }, { 8, 82, 18 }, { 8, 82, 18 }, { 8, 99, 21 }, { 8, 99, 21 }, { 8, 99, 21 }, { 8, 115, 23 }, + { 8, 115, 23 }, { 8, 132, 25 }, { 8, 132, 25 }, { 8, 148, 28 }, { 8, 148, 28 }, { 8, 148, 28 }, { 8, 165, 30 }, { 8, 165, 30 }, + { 8, 181, 32 }, { 8, 181, 32 }, { 8, 198, 35 }, { 8, 198, 35 }, { 8, 198, 35 }, { 8, 214, 37 }, { 8, 214, 37 }, { 8, 231, 39 }, + { 41, 33, 40 }, { 24, 148, 41 }, { 8, 247, 42 }, { 8, 247, 42 }, { 24, 165, 44 }, { 41, 66, 45 }, { 24, 181, 46 }, { 41, 82, 47 }, + { 24, 198, 48 }, { 41, 99, 49 }, { 24, 214, 51 }, { 24, 214, 51 }, { 24, 214, 51 }, { 24, 231, 53 }, { 41, 132, 54 }, { 24, 247, 55 }, + { 41, 148, 56 }, { 41, 148, 56 }, { 41, 165, 58 }, { 41, 165, 58 }, { 41, 181, 61 }, { 41, 181, 61 }, { 41, 181, 61 }, { 41, 198, 63 }, + { 74, 0, 64 }, { 41, 214, 65 }, { 74, 16, 66 }, { 41, 231, 68 }, { 41, 231, 68 }, { 41, 231, 68 }, { 41, 247, 70 }, { 41, 247, 70 }, + { 57, 165, 72 }, { 74, 66, 73 }, { 57, 181, 74 }, { 74, 82, 75 }, { 57, 198, 77 }, { 57, 198, 77 }, { 74, 99, 78 }, { 57, 214, 79 }, + { 74, 115, 80 }, { 57, 231, 81 }, { 74, 132, 82 }, { 57, 247, 84 }, { 57, 247, 84 }, { 57, 247, 84 }, { 74, 165, 87 }, { 74, 165, 87 }, + { 74, 165, 87 }, { 74, 181, 89 }, { 74, 181, 89 }, { 74, 198, 91 }, { 107, 0, 92 }, { 74, 214, 94 }, { 74, 214, 94 }, { 74, 214, 94 }, + { 74, 231, 96 }, { 107, 33, 97 }, { 74, 247, 98 }, { 107, 49, 99 }, { 90, 165, 101 }, { 90, 165, 101 }, { 90, 165, 101 }, { 90, 181, 103 }, + { 90, 181, 103 }, { 90, 198, 105 }, { 107, 99, 106 }, { 90, 214, 107 }, { 107, 115, 108 }, { 90, 231, 110 }, { 90, 231, 110 }, { 107, 132, 111 }, + { 90, 247, 112 }, { 107, 148, 113 }, { 107, 148, 113 }, { 107, 165, 115 }, { 107, 165, 115 }, { 107, 181, 117 }, { 107, 181, 117 }, { 107, 198, 120 }, + { 107, 198, 120 }, { 107, 198, 120 }, { 107, 214, 122 }, { 140, 16, 123 }, { 107, 231, 124 }, { 140, 33, 125 }, { 107, 247, 127 }, { 107, 247, 127 }, + { 107, 247, 127 }, { 123, 165, 129 }, { 140, 66, 130 }, { 123, 181, 131 }, { 140, 82, 132 }, { 123, 198, 134 }, { 123, 198, 134 }, { 123, 198, 134 }, + { 123, 214, 136 }, { 123, 214, 136 }, { 123, 231, 138 }, { 140, 132, 139 }, { 123, 247, 140 }, { 140, 148, 141 }, { 140, 148, 141 }, { 156, 66, 143 }, + { 140, 165, 144 }, { 140, 165, 144 }, { 140, 181, 146 }, { 140, 181, 146 }, { 140, 198, 148 }, { 173, 0, 149 }, { 140, 214, 150 }, { 173, 16, 151 }, + { 140, 231, 153 }, { 140, 231, 153 }, { 140, 231, 153 }, { 140, 247, 155 }, { 173, 49, 156 }, { 156, 165, 157 }, { 173, 66, 158 }, { 156, 181, 160 }, + { 156, 181, 160 }, { 156, 181, 160 }, { 156, 198, 162 }, { 173, 99, 163 }, { 156, 214, 164 }, { 173, 115, 165 }, { 156, 231, 167 }, { 156, 231, 167 }, + { 156, 231, 167 }, { 156, 247, 169 }, { 156, 247, 169 }, { 173, 165, 172 }, { 173, 165, 172 }, { 173, 165, 172 }, { 173, 181, 174 }, { 173, 181, 174 }, + { 189, 99, 176 }, { 173, 198, 177 }, { 173, 198, 177 }, { 173, 214, 179 }, { 173, 214, 179 }, { 173, 231, 181 }, { 206, 33, 182 }, { 173, 247, 183 }, + { 206, 49, 184 }, { 189, 165, 186 }, { 189, 165, 186 }, { 189, 165, 186 }, { 189, 181, 188 }, { 206, 82, 189 }, { 189, 198, 190 }, { 206, 99, 191 }, + { 189, 214, 193 }, { 189, 214, 193 }, { 189, 214, 193 }, { 189, 231, 195 }, { 206, 132, 196 }, { 189, 247, 197 }, { 206, 148, 198 }, { 206, 148, 198 }, + { 206, 165, 200 }, { 206, 165, 200 }, { 206, 181, 202 }, { 206, 181, 202 }, { 206, 198, 205 }, { 206, 198, 205 }, { 206, 198, 205 }, { 206, 214, 207 }, + { 239, 16, 208 }, { 222, 132, 209 }, { 206, 231, 210 }, { 206, 231, 210 }, { 206, 247, 212 }, { 206, 247, 212 }, { 222, 165, 214 }, { 239, 66, 215 }, + { 222, 181, 216 }, { 239, 82, 217 }, { 222, 198, 219 }, { 222, 198, 219 }, { 222, 198, 219 }, { 222, 214, 221 }, { 239, 115, 222 }, { 222, 231, 223 }, + { 239, 132, 224 }, { 222, 247, 226 }, { 222, 247, 226 }, { 222, 247, 226 }, { 255, 66, 228 }, { 239, 165, 229 }, { 239, 165, 229 }, { 239, 181, 231 }, + { 239, 181, 231 }, { 239, 198, 233 }, { 239, 198, 233 }, { 239, 214, 235 }, { 239, 214, 235 }, { 239, 231, 238 }, { 239, 231, 238 }, { 239, 231, 238 }, + { 239, 247, 240 }, { 239, 247, 240 }, { 255, 165, 242 }, { 255, 165, 242 }, { 255, 181, 245 }, { 255, 181, 245 }, { 255, 181, 245 }, { 255, 198, 247 }, + { 255, 198, 247 }, { 255, 214, 249 }, { 255, 214, 249 }, { 255, 231, 252 }, { 255, 231, 252 }, { 255, 231, 252 }, { 255, 247, 254 }, { 255, 247, 254 }, + } +}; + +Table g_mode0_p10_i2= +{ + 2, + 1, + { + { 8, 0, 6 }, { 8, 0, 6 }, { 8, 0, 6 }, { 8, 0, 6 }, { 8, 0, 6 }, { 8, 0, 6 }, { 8, 0, 6 }, { 8, 0, 6 }, + { 8, 0, 6 }, { 8, 16, 10 }, { 8, 16, 10 }, { 8, 16, 10 }, { 8, 16, 10 }, { 8, 33, 15 }, { 8, 33, 15 }, { 8, 33, 15 }, + { 8, 33, 15 }, { 24, 0, 17 }, { 24, 0, 17 }, { 8, 49, 20 }, { 8, 49, 20 }, { 8, 49, 20 }, { 24, 16, 22 }, { 8, 66, 24 }, + { 8, 66, 24 }, { 8, 66, 24 }, { 24, 33, 27 }, { 24, 33, 27 }, { 8, 82, 29 }, { 8, 82, 29 }, { 8, 82, 29 }, { 24, 49, 31 }, + { 24, 49, 31 }, { 8, 99, 34 }, { 8, 99, 34 }, { 8, 99, 34 }, { 24, 66, 36 }, { 8, 115, 38 }, { 8, 115, 38 }, { 41, 33, 39 }, + { 24, 82, 40 }, { 57, 0, 41 }, { 8, 132, 43 }, { 8, 132, 43 }, { 8, 132, 43 }, { 24, 99, 45 }, { 8, 148, 47 }, { 8, 148, 47 }, + { 41, 66, 48 }, { 24, 115, 50 }, { 24, 115, 50 }, { 8, 165, 52 }, { 8, 165, 52 }, { 41, 82, 53 }, { 24, 132, 54 }, { 57, 49, 55 }, + { 8, 181, 57 }, { 8, 181, 57 }, { 74, 16, 58 }, { 24, 148, 59 }, { 57, 66, 60 }, { 8, 198, 61 }, { 41, 115, 62 }, { 24, 165, 64 }, + { 24, 165, 64 }, { 90, 0, 65 }, { 8, 214, 66 }, { 41, 132, 67 }, { 24, 181, 68 }, { 57, 99, 69 }, { 8, 231, 71 }, { 8, 231, 71 }, + { 74, 66, 72 }, { 24, 198, 73 }, { 90, 33, 74 }, { 8, 247, 75 }, { 41, 165, 76 }, { 24, 214, 77 }, { 57, 132, 78 }, { 41, 181, 80 }, + { 41, 181, 80 }, { 74, 99, 81 }, { 24, 231, 82 }, { 57, 148, 83 }, { 41, 198, 85 }, { 41, 198, 85 }, { 74, 115, 86 }, { 24, 247, 87 }, + { 90, 82, 88 }, { 41, 214, 90 }, { 41, 214, 90 }, { 107, 49, 91 }, { 57, 181, 92 }, { 90, 99, 93 }, { 41, 231, 94 }, { 74, 148, 95 }, + { 57, 198, 97 }, { 57, 198, 97 }, { 123, 33, 98 }, { 41, 247, 99 }, { 74, 165, 100 }, { 57, 214, 101 }, { 90, 132, 102 }, { 74, 181, 104 }, + { 74, 181, 104 }, { 107, 99, 105 }, { 57, 231, 106 }, { 123, 66, 107 }, { 74, 198, 109 }, { 74, 198, 109 }, { 57, 247, 110 }, { 90, 165, 111 }, + { 156, 0, 112 }, { 74, 214, 113 }, { 107, 132, 114 }, { 90, 181, 116 }, { 90, 181, 116 }, { 156, 16, 117 }, { 74, 231, 118 }, { 107, 148, 119 }, + { 90, 198, 120 }, { 123, 115, 121 }, { 74, 247, 123 }, { 74, 247, 123 }, { 140, 82, 124 }, { 90, 214, 125 }, { 123, 132, 126 }, { 107, 181, 128 }, + { 107, 181, 128 }, { 173, 16, 129 }, { 90, 231, 130 }, { 156, 66, 131 }, { 107, 198, 133 }, { 107, 198, 133 }, { 90, 247, 134 }, { 123, 165, 135 }, + { 189, 0, 136 }, { 107, 214, 137 }, { 140, 132, 138 }, { 123, 181, 139 }, { 156, 99, 140 }, { 107, 231, 142 }, { 107, 231, 142 }, { 173, 66, 143 }, + { 123, 198, 144 }, { 189, 33, 145 }, { 107, 247, 146 }, { 140, 165, 147 }, { 206, 0, 148 }, { 123, 214, 149 }, { 189, 49, 150 }, { 140, 181, 152 }, + { 140, 181, 152 }, { 123, 231, 153 }, { 156, 148, 154 }, { 140, 198, 156 }, { 140, 198, 156 }, { 173, 115, 157 }, { 123, 247, 158 }, { 156, 165, 159 }, + { 222, 0, 160 }, { 140, 214, 161 }, { 206, 49, 162 }, { 156, 181, 163 }, { 189, 99, 164 }, { 140, 231, 166 }, { 140, 231, 166 }, { 206, 66, 167 }, + { 156, 198, 168 }, { 222, 33, 169 }, { 140, 247, 170 }, { 173, 165, 171 }, { 156, 214, 172 }, { 189, 132, 173 }, { 173, 181, 175 }, { 173, 181, 175 }, + { 206, 99, 176 }, { 156, 231, 177 }, { 222, 66, 178 }, { 173, 198, 180 }, { 173, 198, 180 }, { 239, 33, 181 }, { 156, 247, 182 }, { 222, 82, 183 }, + { 173, 214, 185 }, { 173, 214, 185 }, { 239, 49, 186 }, { 189, 181, 187 }, { 255, 16, 188 }, { 173, 231, 189 }, { 206, 148, 190 }, { 189, 198, 192 }, + { 189, 198, 192 }, { 255, 33, 193 }, { 173, 247, 194 }, { 239, 82, 195 }, { 189, 214, 196 }, { 222, 132, 197 }, { 206, 181, 199 }, { 206, 181, 199 }, + { 239, 99, 200 }, { 189, 231, 201 }, { 255, 66, 202 }, { 206, 198, 204 }, { 206, 198, 204 }, { 189, 247, 205 }, { 222, 165, 206 }, { 206, 214, 208 }, + { 206, 214, 208 }, { 239, 132, 209 }, { 222, 181, 210 }, { 255, 99, 211 }, { 206, 231, 213 }, { 206, 231, 213 }, { 206, 231, 213 }, { 222, 198, 215 }, + { 255, 115, 216 }, { 206, 247, 218 }, { 206, 247, 218 }, { 206, 247, 218 }, { 222, 214, 220 }, { 222, 214, 220 }, { 239, 181, 223 }, { 239, 181, 223 }, + { 222, 231, 225 }, { 222, 231, 225 }, { 222, 231, 225 }, { 239, 198, 227 }, { 222, 247, 229 }, { 222, 247, 229 }, { 255, 165, 230 }, { 239, 214, 232 }, + { 239, 214, 232 }, { 239, 214, 232 }, { 255, 181, 234 }, { 255, 181, 234 }, { 239, 231, 237 }, { 239, 231, 237 }, { 239, 231, 237 }, { 255, 198, 239 }, + { 239, 247, 241 }, { 239, 247, 241 }, { 239, 247, 241 }, { 255, 214, 243 }, { 255, 214, 243 }, { 255, 214, 243 }, { 255, 231, 248 }, { 255, 231, 248 }, + { 255, 231, 248 }, { 255, 231, 248 }, { 255, 231, 248 }, { 255, 247, 253 }, { 255, 247, 253 }, { 255, 247, 253 }, { 255, 247, 253 }, { 255, 247, 253 }, + } +}; + +Table g_mode0_p10_i3= +{ + 3, + 3, + { + { 8, 8, 8 }, { 8, 8, 8 }, { 8, 8, 8 }, { 8, 8, 8 }, { 8, 8, 8 }, { 8, 8, 8 }, { 8, 8, 8 }, { 8, 8, 8 }, + { 8, 8, 8 }, { 8, 8, 8 }, { 8, 8, 8 }, { 8, 8, 8 }, { 8, 24, 15 }, { 8, 24, 15 }, { 8, 24, 15 }, { 8, 24, 15 }, + { 8, 24, 15 }, { 24, 8, 17 }, { 24, 8, 17 }, { 24, 8, 17 }, { 8, 41, 22 }, { 8, 41, 22 }, { 8, 41, 22 }, { 8, 41, 22 }, + { 24, 24, 24 }, { 24, 24, 24 }, { 41, 8, 27 }, { 41, 8, 27 }, { 8, 57, 29 }, { 8, 57, 29 }, { 8, 57, 29 }, { 24, 41, 31 }, + { 24, 41, 31 }, { 41, 24, 34 }, { 41, 24, 34 }, { 8, 74, 36 }, { 8, 74, 36 }, { 8, 74, 36 }, { 24, 57, 38 }, { 24, 57, 38 }, + { 41, 41, 41 }, { 41, 41, 41 }, { 8, 90, 43 }, { 8, 90, 43 }, { 8, 90, 43 }, { 24, 74, 45 }, { 74, 8, 46 }, { 41, 57, 48 }, + { 41, 57, 48 }, { 8, 107, 50 }, { 8, 107, 50 }, { 8, 107, 50 }, { 24, 90, 52 }, { 74, 24, 53 }, { 41, 74, 55 }, { 41, 74, 55 }, + { 8, 123, 57 }, { 8, 123, 57 }, { 8, 123, 57 }, { 24, 107, 59 }, { 74, 41, 60 }, { 41, 90, 62 }, { 41, 90, 62 }, { 8, 140, 64 }, + { 8, 140, 64 }, { 107, 8, 65 }, { 24, 123, 66 }, { 74, 57, 67 }, { 41, 107, 69 }, { 41, 107, 69 }, { 8, 156, 70 }, { 57, 90, 71 }, + { 107, 24, 72 }, { 24, 140, 73 }, { 74, 74, 74 }, { 41, 123, 76 }, { 41, 123, 76 }, { 8, 173, 78 }, { 8, 173, 78 }, { 107, 41, 79 }, + { 24, 156, 80 }, { 74, 90, 81 }, { 41, 140, 83 }, { 41, 140, 83 }, { 8, 189, 84 }, { 57, 123, 85 }, { 107, 57, 86 }, { 24, 173, 87 }, + { 74, 107, 88 }, { 41, 156, 90 }, { 41, 156, 90 }, { 140, 24, 91 }, { 8, 206, 92 }, { 107, 74, 93 }, { 24, 189, 94 }, { 74, 123, 95 }, + { 41, 173, 97 }, { 41, 173, 97 }, { 8, 222, 98 }, { 57, 156, 99 }, { 107, 90, 100 }, { 24, 206, 101 }, { 74, 140, 102 }, { 41, 189, 103 }, + { 90, 123, 104 }, { 8, 239, 105 }, { 57, 173, 106 }, { 107, 107, 107 }, { 24, 222, 108 }, { 74, 156, 109 }, { 173, 24, 110 }, { 41, 206, 111 }, + { 8, 255, 112 }, { 57, 189, 113 }, { 107, 123, 114 }, { 24, 239, 115 }, { 74, 173, 116 }, { 41, 222, 117 }, { 90, 156, 118 }, { 140, 90, 119 }, + { 57, 206, 120 }, { 24, 255, 121 }, { 206, 8, 122 }, { 74, 189, 123 }, { 173, 57, 124 }, { 41, 239, 125 }, { 140, 107, 126 }, { 57, 222, 127 }, + { 107, 156, 128 }, { 206, 24, 129 }, { 74, 206, 130 }, { 41, 255, 131 }, { 90, 189, 132 }, { 140, 123, 133 }, { 57, 239, 134 }, { 107, 173, 135 }, + { 74, 222, 136 }, { 123, 156, 137 }, { 173, 90, 138 }, { 90, 206, 139 }, { 140, 140, 140 }, { 57, 255, 141 }, { 107, 189, 142 }, { 206, 57, 143 }, + { 74, 239, 144 }, { 173, 107, 145 }, { 90, 222, 146 }, { 140, 156, 147 }, { 239, 24, 148 }, { 107, 206, 149 }, { 74, 255, 150 }, { 123, 189, 151 }, + { 173, 123, 152 }, { 90, 239, 153 }, { 140, 173, 154 }, { 239, 41, 155 }, { 107, 222, 156 }, { 206, 90, 157 }, { 123, 206, 158 }, { 173, 140, 159 }, + { 90, 255, 160 }, { 140, 189, 161 }, { 239, 57, 162 }, { 107, 239, 163 }, { 206, 107, 164 }, { 123, 222, 165 }, { 173, 156, 166 }, { 140, 206, 168 }, + { 140, 206, 168 }, { 107, 255, 169 }, { 156, 189, 170 }, { 206, 123, 171 }, { 123, 239, 172 }, { 173, 173, 173 }, { 140, 222, 175 }, { 140, 222, 175 }, + { 239, 90, 176 }, { 156, 206, 177 }, { 206, 140, 178 }, { 123, 255, 179 }, { 173, 189, 180 }, { 140, 239, 182 }, { 140, 239, 182 }, { 239, 107, 183 }, + { 156, 222, 184 }, { 206, 156, 185 }, { 173, 206, 187 }, { 173, 206, 187 }, { 140, 255, 189 }, { 140, 255, 189 }, { 239, 123, 190 }, { 156, 239, 191 }, + { 206, 173, 192 }, { 255, 107, 193 }, { 173, 222, 194 }, { 173, 222, 194 }, { 189, 206, 196 }, { 239, 140, 197 }, { 156, 255, 198 }, { 206, 189, 199 }, + { 173, 239, 201 }, { 173, 239, 201 }, { 173, 239, 201 }, { 189, 222, 203 }, { 239, 156, 204 }, { 206, 206, 206 }, { 206, 206, 206 }, { 173, 255, 208 }, + { 173, 255, 208 }, { 173, 255, 208 }, { 189, 239, 210 }, { 239, 173, 211 }, { 206, 222, 213 }, { 206, 222, 213 }, { 206, 222, 213 }, { 222, 206, 215 }, + { 189, 255, 217 }, { 189, 255, 217 }, { 239, 189, 218 }, { 206, 239, 220 }, { 206, 239, 220 }, { 206, 239, 220 }, { 222, 222, 222 }, { 222, 222, 222 }, + { 239, 206, 225 }, { 239, 206, 225 }, { 206, 255, 227 }, { 206, 255, 227 }, { 206, 255, 227 }, { 222, 239, 229 }, { 222, 239, 229 }, { 239, 222, 232 }, + { 239, 222, 232 }, { 239, 222, 232 }, { 255, 206, 234 }, { 222, 255, 236 }, { 222, 255, 236 }, { 222, 255, 236 }, { 239, 239, 239 }, { 239, 239, 239 }, + { 239, 239, 239 }, { 255, 222, 241 }, { 255, 222, 241 }, { 255, 222, 241 }, { 239, 255, 246 }, { 239, 255, 246 }, { 239, 255, 246 }, { 239, 255, 246 }, + { 255, 239, 248 }, { 255, 239, 248 }, { 255, 239, 248 }, { 255, 239, 248 }, { 255, 255, 255 }, { 255, 255, 255 }, { 255, 255, 255 }, { 255, 255, 255 }, + } +}; + +Table g_mode0_p11_i1= +{ + 1, + 3, + { + { 8, 8, 8 }, { 8, 8, 8 }, { 8, 8, 8 }, { 8, 8, 8 }, { 8, 8, 8 }, { 8, 8, 8 }, { 8, 8, 8 }, { 8, 8, 8 }, + { 8, 8, 8 }, { 8, 8, 8 }, { 8, 24, 10 }, { 8, 24, 10 }, { 8, 41, 13 }, { 8, 41, 13 }, { 8, 41, 13 }, { 8, 57, 15 }, + { 8, 57, 15 }, { 8, 74, 17 }, { 8, 74, 17 }, { 8, 90, 20 }, { 8, 90, 20 }, { 8, 90, 20 }, { 8, 107, 22 }, { 8, 107, 22 }, + { 8, 123, 24 }, { 8, 123, 24 }, { 24, 41, 26 }, { 8, 140, 27 }, { 8, 140, 27 }, { 8, 156, 29 }, { 8, 156, 29 }, { 8, 173, 31 }, + { 8, 173, 31 }, { 8, 189, 33 }, { 8, 189, 33 }, { 8, 206, 36 }, { 8, 206, 36 }, { 8, 206, 36 }, { 8, 222, 38 }, { 41, 24, 39 }, + { 8, 239, 40 }, { 41, 41, 41 }, { 8, 255, 43 }, { 8, 255, 43 }, { 8, 255, 43 }, { 24, 173, 45 }, { 41, 74, 46 }, { 24, 189, 47 }, + { 41, 90, 48 }, { 24, 206, 50 }, { 24, 206, 50 }, { 24, 206, 50 }, { 24, 222, 52 }, { 41, 123, 53 }, { 24, 239, 54 }, { 41, 140, 55 }, + { 24, 255, 56 }, { 41, 156, 57 }, { 41, 156, 57 }, { 57, 74, 59 }, { 41, 173, 60 }, { 41, 173, 60 }, { 41, 189, 62 }, { 41, 189, 62 }, + { 41, 206, 64 }, { 74, 8, 65 }, { 41, 222, 66 }, { 74, 24, 67 }, { 41, 239, 69 }, { 41, 239, 69 }, { 41, 239, 69 }, { 41, 255, 71 }, + { 74, 57, 72 }, { 57, 173, 73 }, { 74, 74, 74 }, { 57, 189, 76 }, { 57, 189, 76 }, { 57, 189, 76 }, { 57, 206, 78 }, { 74, 107, 79 }, + { 57, 222, 80 }, { 74, 123, 81 }, { 57, 239, 83 }, { 57, 239, 83 }, { 57, 239, 83 }, { 57, 255, 85 }, { 74, 156, 86 }, { 74, 156, 86 }, + { 74, 173, 88 }, { 74, 173, 88 }, { 74, 189, 90 }, { 74, 189, 90 }, { 90, 107, 92 }, { 74, 206, 93 }, { 74, 206, 93 }, { 74, 222, 95 }, + { 74, 222, 95 }, { 74, 239, 97 }, { 107, 41, 98 }, { 74, 255, 99 }, { 107, 57, 100 }, { 90, 173, 102 }, { 90, 173, 102 }, { 90, 173, 102 }, + { 90, 189, 104 }, { 107, 90, 105 }, { 90, 206, 106 }, { 107, 107, 107 }, { 90, 222, 109 }, { 90, 222, 109 }, { 90, 222, 109 }, { 90, 239, 111 }, + { 107, 140, 112 }, { 90, 255, 113 }, { 107, 156, 114 }, { 107, 156, 114 }, { 107, 173, 116 }, { 107, 173, 116 }, { 123, 90, 118 }, { 107, 189, 119 }, + { 107, 189, 119 }, { 107, 206, 121 }, { 107, 206, 121 }, { 107, 222, 123 }, { 140, 24, 124 }, { 123, 140, 125 }, { 107, 239, 126 }, { 107, 239, 126 }, + { 107, 255, 128 }, { 107, 255, 128 }, { 123, 173, 130 }, { 140, 74, 131 }, { 123, 189, 132 }, { 140, 90, 133 }, { 123, 206, 135 }, { 123, 206, 135 }, + { 123, 206, 135 }, { 123, 222, 137 }, { 140, 123, 138 }, { 123, 239, 139 }, { 140, 140, 140 }, { 123, 255, 142 }, { 123, 255, 142 }, { 123, 255, 142 }, + { 156, 74, 144 }, { 140, 173, 145 }, { 140, 173, 145 }, { 140, 189, 147 }, { 140, 189, 147 }, { 140, 206, 149 }, { 173, 8, 150 }, { 156, 123, 151 }, + { 140, 222, 152 }, { 140, 222, 152 }, { 140, 239, 154 }, { 140, 239, 154 }, { 140, 255, 156 }, { 173, 57, 157 }, { 156, 173, 158 }, { 173, 74, 159 }, + { 156, 189, 161 }, { 156, 189, 161 }, { 156, 189, 161 }, { 156, 206, 163 }, { 173, 107, 164 }, { 156, 222, 165 }, { 173, 123, 166 }, { 156, 239, 168 }, + { 156, 239, 168 }, { 156, 239, 168 }, { 156, 255, 170 }, { 173, 156, 171 }, { 173, 156, 171 }, { 173, 173, 173 }, { 173, 173, 173 }, { 173, 189, 175 }, + { 173, 189, 175 }, { 189, 107, 177 }, { 173, 206, 178 }, { 173, 206, 178 }, { 173, 222, 180 }, { 173, 222, 180 }, { 173, 239, 182 }, { 206, 41, 183 }, + { 189, 156, 184 }, { 173, 255, 185 }, { 173, 255, 185 }, { 189, 173, 187 }, { 189, 173, 187 }, { 189, 189, 189 }, { 206, 90, 190 }, { 189, 206, 191 }, + { 206, 107, 192 }, { 189, 222, 194 }, { 189, 222, 194 }, { 189, 222, 194 }, { 189, 239, 196 }, { 206, 140, 197 }, { 189, 255, 198 }, { 206, 156, 199 }, + { 206, 156, 199 }, { 206, 173, 201 }, { 206, 173, 201 }, { 222, 90, 203 }, { 206, 189, 204 }, { 206, 189, 204 }, { 206, 206, 206 }, { 239, 8, 207 }, + { 206, 222, 208 }, { 239, 24, 209 }, { 222, 140, 210 }, { 206, 239, 211 }, { 206, 239, 211 }, { 206, 255, 213 }, { 206, 255, 213 }, { 222, 173, 215 }, + { 239, 74, 216 }, { 222, 189, 217 }, { 239, 90, 218 }, { 222, 206, 220 }, { 222, 206, 220 }, { 222, 206, 220 }, { 222, 222, 222 }, { 239, 123, 223 }, + { 222, 239, 224 }, { 239, 140, 225 }, { 222, 255, 227 }, { 222, 255, 227 }, { 222, 255, 227 }, { 239, 173, 230 }, { 239, 173, 230 }, { 239, 173, 230 }, + { 239, 189, 232 }, { 239, 189, 232 }, { 239, 206, 234 }, { 239, 206, 234 }, { 255, 123, 236 }, { 239, 222, 237 }, { 239, 222, 237 }, { 239, 239, 239 }, + { 239, 239, 239 }, { 239, 255, 241 }, { 239, 255, 241 }, { 255, 173, 243 }, { 255, 173, 243 }, { 255, 189, 246 }, { 255, 189, 246 }, { 255, 189, 246 }, + { 255, 206, 248 }, { 255, 206, 248 }, { 255, 222, 250 }, { 255, 222, 250 }, { 255, 239, 253 }, { 255, 239, 253 }, { 255, 239, 253 }, { 255, 255, 255 }, + } +}; + +Table g_mode0_p11_i2= +{ + 2, + 3, + { + { 8, 8, 8 }, { 8, 8, 8 }, { 8, 8, 8 }, { 8, 8, 8 }, { 8, 8, 8 }, { 8, 8, 8 }, { 8, 8, 8 }, { 8, 8, 8 }, + { 8, 8, 8 }, { 8, 8, 8 }, { 8, 8, 8 }, { 8, 24, 13 }, { 8, 24, 13 }, { 8, 24, 13 }, { 8, 24, 13 }, { 8, 24, 13 }, + { 8, 41, 17 }, { 8, 41, 17 }, { 8, 41, 17 }, { 24, 8, 20 }, { 24, 8, 20 }, { 8, 57, 22 }, { 8, 57, 22 }, { 8, 57, 22 }, + { 24, 24, 24 }, { 24, 24, 24 }, { 8, 74, 27 }, { 8, 74, 27 }, { 8, 74, 27 }, { 24, 41, 29 }, { 8, 90, 31 }, { 8, 90, 31 }, + { 41, 8, 32 }, { 24, 57, 33 }, { 24, 57, 33 }, { 8, 107, 36 }, { 8, 107, 36 }, { 8, 107, 36 }, { 24, 74, 38 }, { 8, 123, 40 }, + { 8, 123, 40 }, { 41, 41, 41 }, { 24, 90, 43 }, { 24, 90, 43 }, { 8, 140, 45 }, { 8, 140, 45 }, { 41, 57, 46 }, { 24, 107, 47 }, + { 57, 24, 48 }, { 8, 156, 50 }, { 8, 156, 50 }, { 8, 156, 50 }, { 24, 123, 52 }, { 57, 41, 53 }, { 8, 173, 54 }, { 41, 90, 55 }, + { 24, 140, 57 }, { 24, 140, 57 }, { 8, 189, 59 }, { 8, 189, 59 }, { 41, 107, 60 }, { 24, 156, 61 }, { 57, 74, 62 }, { 8, 206, 64 }, + { 8, 206, 64 }, { 74, 41, 65 }, { 24, 173, 66 }, { 90, 8, 67 }, { 8, 222, 68 }, { 41, 140, 69 }, { 24, 189, 70 }, { 57, 107, 71 }, + { 8, 239, 73 }, { 8, 239, 73 }, { 74, 74, 74 }, { 24, 206, 75 }, { 57, 123, 76 }, { 8, 255, 77 }, { 41, 173, 78 }, { 74, 90, 79 }, + { 24, 222, 80 }, { 90, 57, 81 }, { 41, 189, 83 }, { 41, 189, 83 }, { 24, 239, 84 }, { 57, 156, 85 }, { 90, 74, 86 }, { 41, 206, 87 }, + { 74, 123, 88 }, { 24, 255, 89 }, { 57, 173, 90 }, { 123, 8, 91 }, { 41, 222, 92 }, { 74, 140, 93 }, { 57, 189, 94 }, { 90, 107, 95 }, + { 41, 239, 97 }, { 41, 239, 97 }, { 107, 74, 98 }, { 57, 206, 99 }, { 123, 41, 100 }, { 41, 255, 101 }, { 74, 173, 102 }, { 57, 222, 103 }, + { 90, 140, 104 }, { 74, 189, 106 }, { 74, 189, 106 }, { 107, 107, 107 }, { 57, 239, 108 }, { 90, 156, 109 }, { 74, 206, 111 }, { 74, 206, 111 }, + { 107, 123, 112 }, { 57, 255, 113 }, { 123, 90, 114 }, { 74, 222, 116 }, { 74, 222, 116 }, { 140, 57, 117 }, { 90, 189, 118 }, { 123, 107, 119 }, + { 74, 239, 120 }, { 107, 156, 121 }, { 90, 206, 123 }, { 90, 206, 123 }, { 156, 41, 124 }, { 74, 255, 125 }, { 107, 173, 126 }, { 90, 222, 127 }, + { 123, 140, 128 }, { 107, 189, 130 }, { 107, 189, 130 }, { 140, 107, 131 }, { 90, 239, 132 }, { 156, 74, 133 }, { 107, 206, 135 }, { 107, 206, 135 }, + { 90, 255, 136 }, { 123, 173, 137 }, { 189, 8, 138 }, { 107, 222, 139 }, { 140, 140, 140 }, { 123, 189, 142 }, { 123, 189, 142 }, { 189, 24, 143 }, + { 107, 239, 144 }, { 140, 156, 145 }, { 123, 206, 146 }, { 156, 123, 147 }, { 107, 255, 149 }, { 107, 255, 149 }, { 173, 90, 150 }, { 123, 222, 151 }, + { 156, 140, 152 }, { 140, 189, 154 }, { 140, 189, 154 }, { 206, 24, 155 }, { 123, 239, 156 }, { 189, 74, 157 }, { 140, 206, 159 }, { 140, 206, 159 }, + { 123, 255, 160 }, { 156, 173, 161 }, { 222, 8, 162 }, { 140, 222, 163 }, { 173, 140, 164 }, { 156, 189, 165 }, { 189, 107, 166 }, { 140, 239, 168 }, + { 140, 239, 168 }, { 206, 74, 169 }, { 156, 206, 170 }, { 222, 41, 171 }, { 140, 255, 172 }, { 173, 173, 173 }, { 239, 8, 174 }, { 156, 222, 175 }, + { 222, 57, 176 }, { 173, 189, 178 }, { 173, 189, 178 }, { 156, 239, 179 }, { 189, 156, 180 }, { 173, 206, 182 }, { 173, 206, 182 }, { 206, 123, 183 }, + { 156, 255, 184 }, { 189, 173, 185 }, { 255, 8, 186 }, { 173, 222, 187 }, { 239, 57, 188 }, { 189, 189, 189 }, { 222, 107, 190 }, { 173, 239, 192 }, + { 173, 239, 192 }, { 239, 74, 193 }, { 189, 206, 194 }, { 255, 41, 195 }, { 173, 255, 196 }, { 206, 173, 197 }, { 189, 222, 198 }, { 222, 140, 199 }, + { 206, 189, 201 }, { 206, 189, 201 }, { 239, 107, 202 }, { 189, 239, 203 }, { 255, 74, 204 }, { 206, 206, 206 }, { 206, 206, 206 }, { 189, 255, 208 }, + { 189, 255, 208 }, { 255, 90, 209 }, { 206, 222, 211 }, { 206, 222, 211 }, { 206, 222, 211 }, { 222, 189, 213 }, { 206, 239, 215 }, { 206, 239, 215 }, + { 239, 156, 216 }, { 222, 206, 218 }, { 222, 206, 218 }, { 206, 255, 220 }, { 206, 255, 220 }, { 206, 255, 220 }, { 222, 222, 222 }, { 255, 140, 223 }, + { 239, 189, 225 }, { 239, 189, 225 }, { 222, 239, 227 }, { 222, 239, 227 }, { 222, 239, 227 }, { 239, 206, 230 }, { 239, 206, 230 }, { 222, 255, 231 }, + { 255, 173, 232 }, { 239, 222, 234 }, { 239, 222, 234 }, { 239, 222, 234 }, { 255, 189, 236 }, { 255, 189, 236 }, { 239, 239, 239 }, { 239, 239, 239 }, + { 239, 239, 239 }, { 255, 206, 241 }, { 255, 206, 241 }, { 239, 255, 244 }, { 239, 255, 244 }, { 239, 255, 244 }, { 255, 222, 246 }, { 255, 222, 246 }, + { 255, 222, 246 }, { 255, 239, 251 }, { 255, 239, 251 }, { 255, 239, 251 }, { 255, 239, 251 }, { 255, 239, 251 }, { 255, 255, 255 }, { 255, 255, 255 }, + } +}; + +Table g_mode0_p11_i3= +{ + 3, + 3, + { + { 8, 8, 8 }, { 8, 8, 8 }, { 8, 8, 8 }, { 8, 8, 8 }, { 8, 8, 8 }, { 8, 8, 8 }, { 8, 8, 8 }, { 8, 8, 8 }, + { 8, 8, 8 }, { 8, 8, 8 }, { 8, 8, 8 }, { 8, 8, 8 }, { 8, 24, 15 }, { 8, 24, 15 }, { 8, 24, 15 }, { 8, 24, 15 }, + { 8, 24, 15 }, { 24, 8, 17 }, { 24, 8, 17 }, { 24, 8, 17 }, { 8, 41, 22 }, { 8, 41, 22 }, { 8, 41, 22 }, { 8, 41, 22 }, + { 24, 24, 24 }, { 24, 24, 24 }, { 41, 8, 27 }, { 41, 8, 27 }, { 8, 57, 29 }, { 8, 57, 29 }, { 8, 57, 29 }, { 24, 41, 31 }, + { 24, 41, 31 }, { 41, 24, 34 }, { 41, 24, 34 }, { 8, 74, 36 }, { 8, 74, 36 }, { 8, 74, 36 }, { 24, 57, 38 }, { 24, 57, 38 }, + { 41, 41, 41 }, { 41, 41, 41 }, { 8, 90, 43 }, { 8, 90, 43 }, { 8, 90, 43 }, { 24, 74, 45 }, { 74, 8, 46 }, { 41, 57, 48 }, + { 41, 57, 48 }, { 8, 107, 50 }, { 8, 107, 50 }, { 8, 107, 50 }, { 24, 90, 52 }, { 74, 24, 53 }, { 41, 74, 55 }, { 41, 74, 55 }, + { 8, 123, 57 }, { 8, 123, 57 }, { 8, 123, 57 }, { 24, 107, 59 }, { 74, 41, 60 }, { 41, 90, 62 }, { 41, 90, 62 }, { 8, 140, 64 }, + { 8, 140, 64 }, { 107, 8, 65 }, { 24, 123, 66 }, { 74, 57, 67 }, { 41, 107, 69 }, { 41, 107, 69 }, { 8, 156, 70 }, { 57, 90, 71 }, + { 107, 24, 72 }, { 24, 140, 73 }, { 74, 74, 74 }, { 41, 123, 76 }, { 41, 123, 76 }, { 8, 173, 78 }, { 8, 173, 78 }, { 107, 41, 79 }, + { 24, 156, 80 }, { 74, 90, 81 }, { 41, 140, 83 }, { 41, 140, 83 }, { 8, 189, 84 }, { 57, 123, 85 }, { 107, 57, 86 }, { 24, 173, 87 }, + { 74, 107, 88 }, { 41, 156, 90 }, { 41, 156, 90 }, { 140, 24, 91 }, { 8, 206, 92 }, { 107, 74, 93 }, { 24, 189, 94 }, { 74, 123, 95 }, + { 41, 173, 97 }, { 41, 173, 97 }, { 8, 222, 98 }, { 57, 156, 99 }, { 107, 90, 100 }, { 24, 206, 101 }, { 74, 140, 102 }, { 41, 189, 103 }, + { 90, 123, 104 }, { 8, 239, 105 }, { 57, 173, 106 }, { 107, 107, 107 }, { 24, 222, 108 }, { 74, 156, 109 }, { 173, 24, 110 }, { 41, 206, 111 }, + { 8, 255, 112 }, { 57, 189, 113 }, { 107, 123, 114 }, { 24, 239, 115 }, { 74, 173, 116 }, { 41, 222, 117 }, { 90, 156, 118 }, { 140, 90, 119 }, + { 57, 206, 120 }, { 24, 255, 121 }, { 206, 8, 122 }, { 74, 189, 123 }, { 173, 57, 124 }, { 41, 239, 125 }, { 140, 107, 126 }, { 57, 222, 127 }, + { 107, 156, 128 }, { 206, 24, 129 }, { 74, 206, 130 }, { 41, 255, 131 }, { 90, 189, 132 }, { 140, 123, 133 }, { 57, 239, 134 }, { 107, 173, 135 }, + { 74, 222, 136 }, { 123, 156, 137 }, { 173, 90, 138 }, { 90, 206, 139 }, { 140, 140, 140 }, { 57, 255, 141 }, { 107, 189, 142 }, { 206, 57, 143 }, + { 74, 239, 144 }, { 173, 107, 145 }, { 90, 222, 146 }, { 140, 156, 147 }, { 239, 24, 148 }, { 107, 206, 149 }, { 74, 255, 150 }, { 123, 189, 151 }, + { 173, 123, 152 }, { 90, 239, 153 }, { 140, 173, 154 }, { 239, 41, 155 }, { 107, 222, 156 }, { 206, 90, 157 }, { 123, 206, 158 }, { 173, 140, 159 }, + { 90, 255, 160 }, { 140, 189, 161 }, { 239, 57, 162 }, { 107, 239, 163 }, { 206, 107, 164 }, { 123, 222, 165 }, { 173, 156, 166 }, { 140, 206, 168 }, + { 140, 206, 168 }, { 107, 255, 169 }, { 156, 189, 170 }, { 206, 123, 171 }, { 123, 239, 172 }, { 173, 173, 173 }, { 140, 222, 175 }, { 140, 222, 175 }, + { 239, 90, 176 }, { 156, 206, 177 }, { 206, 140, 178 }, { 123, 255, 179 }, { 173, 189, 180 }, { 140, 239, 182 }, { 140, 239, 182 }, { 239, 107, 183 }, + { 156, 222, 184 }, { 206, 156, 185 }, { 173, 206, 187 }, { 173, 206, 187 }, { 140, 255, 189 }, { 140, 255, 189 }, { 239, 123, 190 }, { 156, 239, 191 }, + { 206, 173, 192 }, { 255, 107, 193 }, { 173, 222, 194 }, { 173, 222, 194 }, { 189, 206, 196 }, { 239, 140, 197 }, { 156, 255, 198 }, { 206, 189, 199 }, + { 173, 239, 201 }, { 173, 239, 201 }, { 173, 239, 201 }, { 189, 222, 203 }, { 239, 156, 204 }, { 206, 206, 206 }, { 206, 206, 206 }, { 173, 255, 208 }, + { 173, 255, 208 }, { 173, 255, 208 }, { 189, 239, 210 }, { 239, 173, 211 }, { 206, 222, 213 }, { 206, 222, 213 }, { 206, 222, 213 }, { 222, 206, 215 }, + { 189, 255, 217 }, { 189, 255, 217 }, { 239, 189, 218 }, { 206, 239, 220 }, { 206, 239, 220 }, { 206, 239, 220 }, { 222, 222, 222 }, { 222, 222, 222 }, + { 239, 206, 225 }, { 239, 206, 225 }, { 206, 255, 227 }, { 206, 255, 227 }, { 206, 255, 227 }, { 222, 239, 229 }, { 222, 239, 229 }, { 239, 222, 232 }, + { 239, 222, 232 }, { 239, 222, 232 }, { 255, 206, 234 }, { 222, 255, 236 }, { 222, 255, 236 }, { 222, 255, 236 }, { 239, 239, 239 }, { 239, 239, 239 }, + { 239, 239, 239 }, { 255, 222, 241 }, { 255, 222, 241 }, { 255, 222, 241 }, { 239, 255, 246 }, { 239, 255, 246 }, { 239, 255, 246 }, { 239, 255, 246 }, + { 255, 239, 248 }, { 255, 239, 248 }, { 255, 239, 248 }, { 255, 239, 248 }, { 255, 255, 255 }, { 255, 255, 255 }, { 255, 255, 255 }, { 255, 255, 255 }, + } +}; + +Table g_mode1_p0_i1= +{ + 1, + 0, + { + { 0, 0, 0 }, { 0, 4, 1 }, { 0, 12, 2 }, { 0, 20, 3 }, { 0, 28, 4 }, { 0, 32, 5 }, { 0, 40, 6 }, { 0, 48, 7 }, + { 0, 56, 8 }, { 0, 64, 9 }, { 0, 68, 10 }, { 0, 76, 11 }, { 0, 84, 12 }, { 0, 92, 13 }, { 0, 96, 14 }, { 0, 104, 15 }, + { 0, 112, 16 }, { 0, 120, 17 }, { 0, 129, 18 }, { 0, 133, 19 }, { 0, 141, 20 }, { 0, 149, 21 }, { 0, 153, 22 }, { 0, 161, 23 }, + { 0, 169, 24 }, { 0, 177, 25 }, { 0, 185, 26 }, { 0, 189, 27 }, { 0, 197, 28 }, { 0, 205, 29 }, { 0, 213, 30 }, { 0, 217, 31 }, + { 0, 225, 32 }, { 0, 233, 33 }, { 0, 241, 34 }, { 0, 249, 35 }, { 0, 253, 36 }, { 4, 237, 37 }, { 4, 245, 38 }, { 4, 253, 39 }, + { 8, 233, 40 }, { 8, 241, 41 }, { 8, 249, 42 }, { 12, 229, 43 }, { 12, 237, 44 }, { 12, 245, 45 }, { 12, 253, 46 }, { 16, 233, 47 }, + { 16, 241, 48 }, { 16, 249, 49 }, { 20, 233, 50 }, { 20, 237, 51 }, { 20, 245, 52 }, { 20, 253, 53 }, { 24, 237, 54 }, { 24, 241, 55 }, + { 24, 249, 56 }, { 28, 233, 57 }, { 28, 241, 58 }, { 28, 245, 59 }, { 28, 253, 60 }, { 32, 237, 61 }, { 32, 245, 62 }, { 32, 249, 63 }, + { 36, 233, 64 }, { 36, 241, 65 }, { 36, 249, 66 }, { 36, 253, 67 }, { 40, 237, 68 }, { 40, 245, 69 }, { 40, 253, 70 }, { 44, 233, 71 }, + { 44, 241, 72 }, { 44, 249, 73 }, { 48, 233, 74 }, { 48, 237, 75 }, { 48, 245, 76 }, { 48, 253, 77 }, { 52, 237, 78 }, { 52, 241, 79 }, + { 52, 249, 80 }, { 56, 233, 81 }, { 56, 241, 82 }, { 56, 245, 83 }, { 56, 253, 84 }, { 60, 237, 85 }, { 60, 245, 86 }, { 60, 249, 87 }, + { 64, 233, 88 }, { 64, 241, 89 }, { 64, 249, 90 }, { 64, 253, 91 }, { 68, 237, 92 }, { 68, 245, 93 }, { 68, 253, 94 }, { 72, 233, 95 }, + { 72, 241, 96 }, { 72, 249, 97 }, { 76, 229, 98 }, { 76, 237, 99 }, { 76, 245, 100 }, { 76, 253, 101 }, { 80, 233, 102 }, { 80, 241, 103 }, + { 80, 249, 104 }, { 84, 233, 105 }, { 84, 237, 106 }, { 84, 245, 107 }, { 84, 253, 108 }, { 88, 237, 109 }, { 88, 241, 110 }, { 88, 249, 111 }, + { 92, 233, 112 }, { 92, 241, 113 }, { 92, 245, 114 }, { 92, 253, 115 }, { 96, 237, 116 }, { 96, 245, 117 }, { 96, 249, 118 }, { 100, 233, 119 }, + { 100, 241, 120 }, { 100, 249, 121 }, { 100, 253, 122 }, { 104, 237, 123 }, { 104, 245, 124 }, { 104, 253, 125 }, { 108, 233, 126 }, { 108, 241, 127 }, + { 108, 249, 128 }, { 112, 233, 129 }, { 112, 237, 130 }, { 112, 245, 131 }, { 112, 253, 132 }, { 116, 237, 133 }, { 116, 241, 134 }, { 116, 249, 135 }, + { 120, 233, 136 }, { 120, 241, 137 }, { 120, 245, 138 }, { 120, 253, 139 }, { 124, 237, 140 }, { 124, 245, 141 }, { 124, 249, 142 }, { 129, 225, 143 }, + { 129, 233, 144 }, { 129, 241, 145 }, { 129, 249, 146 }, { 133, 229, 147 }, { 133, 237, 148 }, { 133, 245, 149 }, { 133, 253, 150 }, { 137, 233, 151 }, + { 137, 241, 152 }, { 137, 249, 153 }, { 141, 233, 154 }, { 141, 237, 155 }, { 141, 245, 156 }, { 141, 253, 157 }, { 145, 237, 158 }, { 145, 241, 159 }, + { 145, 249, 160 }, { 149, 233, 161 }, { 149, 241, 162 }, { 149, 245, 163 }, { 149, 253, 164 }, { 153, 237, 165 }, { 153, 245, 166 }, { 153, 249, 167 }, + { 157, 233, 168 }, { 157, 241, 169 }, { 157, 249, 170 }, { 157, 253, 171 }, { 161, 237, 172 }, { 161, 245, 173 }, { 161, 253, 174 }, { 165, 233, 175 }, + { 165, 241, 176 }, { 165, 249, 177 }, { 169, 233, 178 }, { 169, 237, 179 }, { 169, 245, 180 }, { 169, 253, 181 }, { 173, 237, 182 }, { 173, 241, 183 }, + { 173, 249, 184 }, { 177, 233, 185 }, { 177, 241, 186 }, { 177, 245, 187 }, { 177, 253, 188 }, { 181, 237, 189 }, { 181, 245, 190 }, { 181, 249, 191 }, + { 185, 233, 192 }, { 185, 241, 193 }, { 185, 249, 194 }, { 185, 253, 195 }, { 189, 237, 196 }, { 189, 245, 197 }, { 189, 253, 198 }, { 193, 233, 199 }, + { 193, 241, 200 }, { 193, 249, 201 }, { 197, 229, 202 }, { 197, 237, 203 }, { 197, 245, 204 }, { 197, 253, 205 }, { 201, 233, 206 }, { 201, 241, 207 }, + { 201, 249, 208 }, { 205, 233, 209 }, { 205, 237, 210 }, { 205, 245, 211 }, { 205, 253, 212 }, { 209, 237, 213 }, { 209, 241, 214 }, { 209, 249, 215 }, + { 213, 233, 216 }, { 213, 241, 217 }, { 213, 245, 218 }, { 213, 253, 219 }, { 217, 237, 220 }, { 217, 245, 221 }, { 217, 249, 222 }, { 221, 233, 223 }, + { 221, 241, 224 }, { 221, 249, 225 }, { 221, 253, 226 }, { 225, 237, 227 }, { 225, 245, 228 }, { 225, 253, 229 }, { 229, 233, 230 }, { 229, 241, 231 }, + { 229, 249, 232 }, { 233, 233, 233 }, { 233, 237, 234 }, { 233, 245, 235 }, { 233, 253, 236 }, { 237, 237, 237 }, { 237, 241, 238 }, { 237, 249, 239 }, + { 241, 233, 240 }, { 241, 241, 241 }, { 241, 245, 242 }, { 241, 253, 243 }, { 245, 237, 244 }, { 245, 245, 245 }, { 245, 249, 246 }, { 249, 233, 247 }, + { 249, 241, 248 }, { 249, 249, 249 }, { 249, 253, 250 }, { 253, 237, 251 }, { 253, 245, 252 }, { 253, 253, 253 }, { 253, 253, 253 }, { 253, 253, 253 }, + } +}; + +Table g_mode1_p0_i2= +{ + 2, + 0, + { + { 0, 0, 0 }, { 0, 4, 1 }, { 0, 8, 2 }, { 0, 12, 3 }, { 4, 4, 4 }, { 0, 16, 5 }, { 0, 20, 6 }, { 0, 24, 7 }, + { 0, 28, 8 }, { 0, 32, 9 }, { 0, 36, 10 }, { 0, 40, 11 }, { 0, 44, 12 }, { 4, 36, 13 }, { 0, 48, 14 }, { 0, 52, 15 }, + { 0, 56, 16 }, { 0, 60, 17 }, { 0, 64, 18 }, { 0, 68, 19 }, { 0, 72, 20 }, { 0, 76, 21 }, { 4, 68, 22 }, { 0, 80, 23 }, + { 0, 84, 24 }, { 0, 88, 25 }, { 0, 92, 26 }, { 0, 96, 27 }, { 0, 100, 28 }, { 0, 104, 29 }, { 0, 108, 30 }, { 4, 100, 31 }, + { 0, 112, 32 }, { 0, 116, 33 }, { 0, 120, 34 }, { 0, 124, 35 }, { 0, 129, 36 }, { 0, 133, 37 }, { 4, 124, 38 }, { 0, 137, 39 }, + { 0, 141, 40 }, { 0, 145, 41 }, { 0, 149, 42 }, { 0, 153, 43 }, { 0, 157, 44 }, { 0, 161, 45 }, { 0, 165, 46 }, { 4, 157, 47 }, + { 0, 169, 48 }, { 0, 173, 49 }, { 0, 177, 50 }, { 0, 181, 51 }, { 0, 185, 52 }, { 0, 189, 53 }, { 0, 193, 54 }, { 0, 197, 55 }, + { 4, 189, 56 }, { 0, 201, 57 }, { 0, 205, 58 }, { 0, 209, 59 }, { 0, 213, 60 }, { 0, 217, 61 }, { 0, 221, 62 }, { 0, 225, 63 }, + { 0, 229, 64 }, { 4, 221, 65 }, { 0, 233, 66 }, { 0, 237, 67 }, { 0, 241, 68 }, { 0, 245, 69 }, { 0, 249, 70 }, { 0, 253, 71 }, + { 4, 245, 72 }, { 4, 249, 73 }, { 4, 253, 74 }, { 8, 245, 75 }, { 8, 249, 76 }, { 8, 253, 77 }, { 12, 245, 78 }, { 12, 249, 79 }, + { 12, 253, 80 }, { 20, 237, 81 }, { 16, 249, 82 }, { 16, 253, 83 }, { 20, 249, 84 }, { 24, 241, 85 }, { 20, 253, 86 }, { 24, 249, 87 }, + { 24, 253, 88 }, { 28, 245, 89 }, { 28, 249, 90 }, { 28, 253, 91 }, { 32, 245, 92 }, { 32, 249, 93 }, { 32, 253, 94 }, { 36, 245, 95 }, + { 36, 249, 96 }, { 36, 253, 97 }, { 40, 245, 98 }, { 40, 249, 99 }, { 40, 253, 100 }, { 44, 245, 101 }, { 44, 249, 102 }, { 44, 253, 103 }, + { 52, 237, 104 }, { 48, 249, 105 }, { 48, 253, 106 }, { 52, 249, 107 }, { 56, 241, 108 }, { 52, 253, 109 }, { 56, 249, 110 }, { 56, 253, 111 }, + { 60, 245, 112 }, { 60, 249, 113 }, { 60, 253, 114 }, { 64, 245, 115 }, { 64, 249, 116 }, { 64, 253, 117 }, { 68, 245, 118 }, { 68, 249, 119 }, + { 68, 253, 120 }, { 72, 245, 121 }, { 72, 249, 122 }, { 72, 253, 123 }, { 76, 245, 124 }, { 76, 249, 125 }, { 76, 253, 126 }, { 84, 237, 127 }, + { 80, 249, 128 }, { 80, 253, 129 }, { 84, 249, 130 }, { 88, 241, 131 }, { 84, 253, 132 }, { 88, 249, 133 }, { 88, 253, 134 }, { 92, 245, 135 }, + { 92, 249, 136 }, { 92, 253, 137 }, { 96, 245, 138 }, { 96, 249, 139 }, { 96, 253, 140 }, { 100, 245, 141 }, { 100, 249, 142 }, { 100, 253, 143 }, + { 104, 245, 144 }, { 104, 249, 145 }, { 104, 253, 146 }, { 108, 245, 147 }, { 108, 249, 148 }, { 108, 253, 149 }, { 116, 237, 150 }, { 112, 249, 151 }, + { 112, 253, 152 }, { 116, 249, 153 }, { 120, 241, 154 }, { 116, 253, 155 }, { 120, 249, 156 }, { 120, 253, 157 }, { 124, 245, 158 }, { 124, 249, 159 }, + { 124, 253, 160 }, { 129, 241, 161 }, { 129, 245, 162 }, { 129, 249, 163 }, { 129, 253, 164 }, { 133, 245, 165 }, { 133, 249, 166 }, { 133, 253, 167 }, + { 141, 237, 168 }, { 137, 249, 169 }, { 137, 253, 170 }, { 141, 249, 171 }, { 145, 241, 172 }, { 141, 253, 173 }, { 145, 249, 174 }, { 145, 253, 175 }, + { 149, 245, 176 }, { 149, 249, 177 }, { 149, 253, 178 }, { 153, 245, 179 }, { 153, 249, 180 }, { 153, 253, 181 }, { 157, 245, 182 }, { 157, 249, 183 }, + { 157, 253, 184 }, { 161, 245, 185 }, { 161, 249, 186 }, { 161, 253, 187 }, { 165, 245, 188 }, { 165, 249, 189 }, { 165, 253, 190 }, { 173, 237, 191 }, + { 169, 249, 192 }, { 169, 253, 193 }, { 173, 249, 194 }, { 177, 241, 195 }, { 173, 253, 196 }, { 177, 249, 197 }, { 177, 253, 198 }, { 181, 245, 199 }, + { 181, 249, 200 }, { 181, 253, 201 }, { 185, 245, 202 }, { 185, 249, 203 }, { 185, 253, 204 }, { 189, 245, 205 }, { 189, 249, 206 }, { 189, 253, 207 }, + { 193, 245, 208 }, { 193, 249, 209 }, { 193, 253, 210 }, { 197, 245, 211 }, { 197, 249, 212 }, { 197, 253, 213 }, { 205, 237, 214 }, { 201, 249, 215 }, + { 201, 253, 216 }, { 205, 249, 217 }, { 209, 241, 218 }, { 205, 253, 219 }, { 209, 249, 220 }, { 209, 253, 221 }, { 213, 245, 222 }, { 213, 249, 223 }, + { 213, 253, 224 }, { 217, 245, 225 }, { 217, 249, 226 }, { 217, 253, 227 }, { 221, 245, 228 }, { 221, 249, 229 }, { 221, 253, 230 }, { 225, 245, 231 }, + { 225, 249, 232 }, { 225, 253, 233 }, { 229, 245, 234 }, { 229, 249, 235 }, { 229, 253, 236 }, { 237, 237, 237 }, { 233, 249, 238 }, { 233, 253, 239 }, + { 237, 249, 240 }, { 241, 241, 241 }, { 237, 253, 242 }, { 241, 249, 243 }, { 241, 253, 244 }, { 245, 245, 245 }, { 245, 249, 246 }, { 245, 253, 247 }, + { 249, 245, 248 }, { 249, 249, 249 }, { 249, 253, 250 }, { 253, 245, 251 }, { 253, 249, 252 }, { 253, 253, 253 }, { 253, 253, 253 }, { 253, 253, 253 }, + } +}; + +Table g_mode1_p0_i3= +{ + 3, + 0, + { + { 0, 0, 0 }, { 0, 0, 0 }, { 0, 4, 2 }, { 0, 8, 3 }, { 4, 4, 4 }, { 0, 12, 5 }, { 4, 8, 6 }, { 0, 16, 7 }, + { 0, 20, 8 }, { 4, 16, 9 }, { 0, 24, 10 }, { 4, 20, 11 }, { 0, 28, 12 }, { 8, 20, 13 }, { 0, 32, 14 }, { 0, 36, 15 }, + { 4, 32, 16 }, { 0, 40, 17 }, { 4, 36, 18 }, { 0, 44, 19 }, { 0, 48, 20 }, { 4, 44, 21 }, { 0, 52, 22 }, { 4, 48, 23 }, + { 0, 56, 24 }, { 0, 60, 25 }, { 4, 56, 26 }, { 0, 64, 27 }, { 4, 60, 28 }, { 0, 68, 29 }, { 0, 72, 30 }, { 4, 68, 31 }, + { 0, 76, 32 }, { 4, 72, 33 }, { 0, 80, 34 }, { 0, 84, 35 }, { 4, 80, 36 }, { 0, 88, 37 }, { 4, 84, 38 }, { 0, 92, 39 }, + { 8, 84, 40 }, { 0, 96, 41 }, { 0, 100, 42 }, { 4, 96, 43 }, { 0, 104, 44 }, { 4, 100, 45 }, { 0, 108, 46 }, { 0, 112, 47 }, + { 4, 108, 48 }, { 0, 116, 49 }, { 4, 112, 50 }, { 0, 120, 51 }, { 0, 124, 52 }, { 4, 120, 53 }, { 0, 129, 54 }, { 4, 124, 55 }, + { 0, 133, 56 }, { 4, 129, 57 }, { 0, 137, 58 }, { 0, 141, 59 }, { 4, 137, 60 }, { 0, 145, 61 }, { 4, 141, 62 }, { 0, 149, 63 }, + { 8, 141, 64 }, { 0, 153, 65 }, { 0, 157, 66 }, { 4, 153, 67 }, { 0, 161, 68 }, { 4, 157, 69 }, { 0, 165, 70 }, { 0, 169, 71 }, + { 4, 165, 72 }, { 0, 173, 73 }, { 4, 169, 74 }, { 0, 177, 75 }, { 0, 181, 76 }, { 4, 177, 77 }, { 0, 185, 78 }, { 4, 181, 79 }, + { 0, 189, 80 }, { 0, 193, 81 }, { 4, 189, 82 }, { 0, 197, 83 }, { 4, 193, 84 }, { 0, 201, 85 }, { 0, 205, 86 }, { 4, 201, 87 }, + { 0, 209, 88 }, { 4, 205, 89 }, { 0, 213, 90 }, { 8, 205, 91 }, { 0, 217, 92 }, { 0, 221, 93 }, { 4, 217, 94 }, { 0, 225, 95 }, + { 4, 221, 96 }, { 0, 229, 97 }, { 0, 233, 98 }, { 4, 229, 99 }, { 0, 237, 100 }, { 4, 233, 101 }, { 0, 241, 102 }, { 0, 245, 103 }, + { 4, 241, 104 }, { 0, 249, 105 }, { 4, 245, 106 }, { 0, 253, 107 }, { 8, 245, 108 }, { 4, 253, 109 }, { 8, 249, 110 }, { 8, 253, 111 }, + { 12, 249, 112 }, { 16, 245, 113 }, { 12, 253, 114 }, { 20, 245, 115 }, { 16, 253, 116 }, { 20, 249, 117 }, { 20, 253, 118 }, { 24, 249, 119 }, + { 28, 245, 120 }, { 24, 253, 121 }, { 32, 245, 122 }, { 28, 253, 123 }, { 32, 249, 124 }, { 32, 253, 125 }, { 36, 249, 126 }, { 44, 241, 127 }, + { 36, 253, 128 }, { 44, 245, 129 }, { 40, 253, 130 }, { 48, 245, 131 }, { 44, 253, 132 }, { 48, 249, 133 }, { 48, 253, 134 }, { 52, 249, 135 }, + { 56, 245, 136 }, { 52, 253, 137 }, { 60, 245, 138 }, { 56, 253, 139 }, { 60, 249, 140 }, { 60, 253, 141 }, { 64, 249, 142 }, { 68, 245, 143 }, + { 64, 253, 144 }, { 72, 245, 145 }, { 68, 253, 146 }, { 72, 249, 147 }, { 72, 253, 148 }, { 76, 249, 149 }, { 80, 245, 150 }, { 76, 253, 151 }, + { 84, 245, 152 }, { 80, 253, 153 }, { 84, 249, 154 }, { 84, 253, 155 }, { 88, 249, 156 }, { 92, 245, 157 }, { 88, 253, 158 }, { 96, 245, 159 }, + { 92, 253, 160 }, { 96, 249, 161 }, { 96, 253, 162 }, { 100, 249, 163 }, { 108, 241, 164 }, { 100, 253, 165 }, { 108, 245, 166 }, { 104, 253, 167 }, + { 112, 245, 168 }, { 108, 253, 169 }, { 112, 249, 170 }, { 112, 253, 171 }, { 116, 249, 172 }, { 120, 245, 173 }, { 116, 253, 174 }, { 124, 245, 175 }, + { 120, 253, 176 }, { 124, 249, 177 }, { 124, 253, 178 }, { 133, 241, 179 }, { 129, 249, 180 }, { 129, 253, 181 }, { 133, 249, 182 }, { 137, 245, 183 }, + { 133, 253, 184 }, { 141, 245, 185 }, { 137, 253, 186 }, { 141, 249, 187 }, { 141, 253, 188 }, { 145, 249, 189 }, { 149, 245, 190 }, { 145, 253, 191 }, + { 153, 245, 192 }, { 149, 253, 193 }, { 153, 249, 194 }, { 153, 253, 195 }, { 157, 249, 196 }, { 165, 241, 197 }, { 157, 253, 198 }, { 165, 245, 199 }, + { 161, 253, 200 }, { 169, 245, 201 }, { 165, 253, 202 }, { 169, 249, 203 }, { 169, 253, 204 }, { 173, 249, 205 }, { 177, 245, 206 }, { 173, 253, 207 }, + { 181, 245, 208 }, { 177, 253, 209 }, { 181, 249, 210 }, { 181, 253, 211 }, { 185, 249, 212 }, { 189, 245, 213 }, { 185, 253, 214 }, { 193, 245, 215 }, + { 189, 253, 216 }, { 193, 249, 217 }, { 193, 253, 218 }, { 197, 249, 219 }, { 201, 245, 220 }, { 197, 253, 221 }, { 205, 245, 222 }, { 201, 253, 223 }, + { 205, 249, 224 }, { 205, 253, 225 }, { 209, 249, 226 }, { 213, 245, 227 }, { 209, 253, 228 }, { 217, 245, 229 }, { 213, 253, 230 }, { 217, 249, 231 }, + { 217, 253, 232 }, { 221, 249, 233 }, { 229, 241, 234 }, { 221, 253, 235 }, { 229, 245, 236 }, { 225, 253, 237 }, { 233, 245, 238 }, { 229, 253, 239 }, + { 233, 249, 240 }, { 233, 253, 241 }, { 237, 249, 242 }, { 241, 245, 243 }, { 237, 253, 244 }, { 245, 245, 245 }, { 241, 253, 246 }, { 245, 249, 247 }, + { 245, 253, 248 }, { 249, 249, 249 }, { 253, 245, 250 }, { 249, 253, 251 }, { 249, 253, 251 }, { 253, 253, 253 }, { 253, 253, 253 }, { 253, 253, 253 }, + } +}; + +Table g_mode1_p1_i1= +{ + 1, + 1, + { + { 2, 2, 2 }, { 2, 2, 2 }, { 2, 2, 2 }, { 2, 6, 3 }, { 2, 14, 4 }, { 2, 22, 5 }, { 2, 30, 6 }, { 2, 34, 7 }, + { 2, 42, 8 }, { 2, 50, 9 }, { 2, 58, 10 }, { 2, 66, 11 }, { 2, 70, 12 }, { 2, 78, 13 }, { 2, 86, 14 }, { 2, 94, 15 }, + { 2, 98, 16 }, { 2, 106, 17 }, { 2, 114, 18 }, { 2, 122, 19 }, { 2, 131, 20 }, { 2, 135, 21 }, { 2, 143, 22 }, { 2, 151, 23 }, + { 2, 155, 24 }, { 2, 163, 25 }, { 2, 171, 26 }, { 2, 179, 27 }, { 2, 187, 28 }, { 2, 191, 29 }, { 2, 199, 30 }, { 2, 207, 31 }, + { 2, 215, 32 }, { 2, 219, 33 }, { 2, 227, 34 }, { 2, 235, 35 }, { 2, 243, 36 }, { 2, 251, 37 }, { 2, 255, 38 }, { 6, 239, 39 }, + { 6, 247, 40 }, { 6, 255, 41 }, { 10, 235, 42 }, { 10, 243, 43 }, { 10, 251, 44 }, { 14, 231, 45 }, { 14, 239, 46 }, { 14, 247, 47 }, + { 14, 255, 48 }, { 18, 235, 49 }, { 18, 243, 50 }, { 18, 251, 51 }, { 22, 235, 52 }, { 22, 239, 53 }, { 22, 247, 54 }, { 22, 255, 55 }, + { 26, 239, 56 }, { 26, 243, 57 }, { 26, 251, 58 }, { 30, 235, 59 }, { 30, 243, 60 }, { 30, 247, 61 }, { 30, 255, 62 }, { 34, 239, 63 }, + { 34, 247, 64 }, { 34, 251, 65 }, { 38, 235, 66 }, { 38, 243, 67 }, { 38, 251, 68 }, { 38, 255, 69 }, { 42, 239, 70 }, { 42, 247, 71 }, + { 42, 255, 72 }, { 46, 235, 73 }, { 46, 243, 74 }, { 46, 251, 75 }, { 50, 235, 76 }, { 50, 239, 77 }, { 50, 247, 78 }, { 50, 255, 79 }, + { 54, 239, 80 }, { 54, 243, 81 }, { 54, 251, 82 }, { 58, 235, 83 }, { 58, 243, 84 }, { 58, 247, 85 }, { 58, 255, 86 }, { 62, 239, 87 }, + { 62, 247, 88 }, { 62, 251, 89 }, { 66, 235, 90 }, { 66, 243, 91 }, { 66, 251, 92 }, { 66, 255, 93 }, { 70, 239, 94 }, { 70, 247, 95 }, + { 70, 255, 96 }, { 74, 235, 97 }, { 74, 243, 98 }, { 74, 251, 99 }, { 78, 231, 100 }, { 78, 239, 101 }, { 78, 247, 102 }, { 78, 255, 103 }, + { 82, 235, 104 }, { 82, 243, 105 }, { 82, 251, 106 }, { 86, 235, 107 }, { 86, 239, 108 }, { 86, 247, 109 }, { 86, 255, 110 }, { 90, 239, 111 }, + { 90, 243, 112 }, { 90, 251, 113 }, { 94, 235, 114 }, { 94, 243, 115 }, { 94, 247, 116 }, { 94, 255, 117 }, { 98, 239, 118 }, { 98, 247, 119 }, + { 98, 251, 120 }, { 102, 235, 121 }, { 102, 243, 122 }, { 102, 251, 123 }, { 102, 255, 124 }, { 106, 239, 125 }, { 106, 247, 126 }, { 106, 255, 127 }, + { 110, 235, 128 }, { 110, 243, 129 }, { 110, 251, 130 }, { 114, 235, 131 }, { 114, 239, 132 }, { 114, 247, 133 }, { 114, 255, 134 }, { 118, 239, 135 }, + { 118, 243, 136 }, { 118, 251, 137 }, { 122, 235, 138 }, { 122, 243, 139 }, { 122, 247, 140 }, { 122, 255, 141 }, { 126, 239, 142 }, { 126, 247, 143 }, + { 126, 251, 144 }, { 131, 227, 145 }, { 131, 235, 146 }, { 131, 243, 147 }, { 131, 251, 148 }, { 135, 231, 149 }, { 135, 239, 150 }, { 135, 247, 151 }, + { 135, 255, 152 }, { 139, 235, 153 }, { 139, 243, 154 }, { 139, 251, 155 }, { 143, 235, 156 }, { 143, 239, 157 }, { 143, 247, 158 }, { 143, 255, 159 }, + { 147, 239, 160 }, { 147, 243, 161 }, { 147, 251, 162 }, { 151, 235, 163 }, { 151, 243, 164 }, { 151, 247, 165 }, { 151, 255, 166 }, { 155, 239, 167 }, + { 155, 247, 168 }, { 155, 251, 169 }, { 159, 235, 170 }, { 159, 243, 171 }, { 159, 251, 172 }, { 159, 255, 173 }, { 163, 239, 174 }, { 163, 247, 175 }, + { 163, 255, 176 }, { 167, 235, 177 }, { 167, 243, 178 }, { 167, 251, 179 }, { 171, 235, 180 }, { 171, 239, 181 }, { 171, 247, 182 }, { 171, 255, 183 }, + { 175, 239, 184 }, { 175, 243, 185 }, { 175, 251, 186 }, { 179, 235, 187 }, { 179, 243, 188 }, { 179, 247, 189 }, { 179, 255, 190 }, { 183, 239, 191 }, + { 183, 247, 192 }, { 183, 251, 193 }, { 187, 235, 194 }, { 187, 243, 195 }, { 187, 251, 196 }, { 187, 255, 197 }, { 191, 239, 198 }, { 191, 247, 199 }, + { 191, 255, 200 }, { 195, 235, 201 }, { 195, 243, 202 }, { 195, 251, 203 }, { 199, 231, 204 }, { 199, 239, 205 }, { 199, 247, 206 }, { 199, 255, 207 }, + { 203, 235, 208 }, { 203, 243, 209 }, { 203, 251, 210 }, { 207, 235, 211 }, { 207, 239, 212 }, { 207, 247, 213 }, { 207, 255, 214 }, { 211, 239, 215 }, + { 211, 243, 216 }, { 211, 251, 217 }, { 215, 235, 218 }, { 215, 243, 219 }, { 215, 247, 220 }, { 215, 255, 221 }, { 219, 239, 222 }, { 219, 247, 223 }, + { 219, 251, 224 }, { 223, 235, 225 }, { 223, 243, 226 }, { 223, 251, 227 }, { 223, 255, 228 }, { 227, 239, 229 }, { 227, 247, 230 }, { 227, 255, 231 }, + { 231, 235, 232 }, { 231, 243, 233 }, { 231, 251, 234 }, { 235, 235, 235 }, { 235, 239, 236 }, { 235, 247, 237 }, { 235, 255, 238 }, { 239, 239, 239 }, + { 239, 243, 240 }, { 239, 251, 241 }, { 243, 235, 242 }, { 243, 243, 243 }, { 243, 247, 244 }, { 243, 255, 245 }, { 247, 239, 246 }, { 247, 247, 247 }, + { 247, 251, 248 }, { 251, 235, 249 }, { 251, 243, 250 }, { 251, 251, 251 }, { 251, 255, 252 }, { 255, 239, 253 }, { 255, 247, 254 }, { 255, 255, 255 }, + } +}; + +Table g_mode1_p1_i2= +{ + 2, + 1, + { + { 2, 2, 2 }, { 2, 2, 2 }, { 2, 2, 2 }, { 2, 6, 3 }, { 2, 10, 4 }, { 2, 14, 5 }, { 6, 6, 6 }, { 2, 18, 7 }, + { 2, 22, 8 }, { 2, 26, 9 }, { 2, 30, 10 }, { 2, 34, 11 }, { 2, 38, 12 }, { 2, 42, 13 }, { 2, 46, 14 }, { 6, 38, 15 }, + { 2, 50, 16 }, { 2, 54, 17 }, { 2, 58, 18 }, { 2, 62, 19 }, { 2, 66, 20 }, { 2, 70, 21 }, { 2, 74, 22 }, { 2, 78, 23 }, + { 6, 70, 24 }, { 2, 82, 25 }, { 2, 86, 26 }, { 2, 90, 27 }, { 2, 94, 28 }, { 2, 98, 29 }, { 2, 102, 30 }, { 2, 106, 31 }, + { 2, 110, 32 }, { 6, 102, 33 }, { 2, 114, 34 }, { 2, 118, 35 }, { 2, 122, 36 }, { 2, 126, 37 }, { 2, 131, 38 }, { 2, 135, 39 }, + { 6, 126, 40 }, { 2, 139, 41 }, { 2, 143, 42 }, { 2, 147, 43 }, { 2, 151, 44 }, { 2, 155, 45 }, { 2, 159, 46 }, { 2, 163, 47 }, + { 2, 167, 48 }, { 6, 159, 49 }, { 2, 171, 50 }, { 2, 175, 51 }, { 2, 179, 52 }, { 2, 183, 53 }, { 2, 187, 54 }, { 2, 191, 55 }, + { 2, 195, 56 }, { 2, 199, 57 }, { 6, 191, 58 }, { 2, 203, 59 }, { 2, 207, 60 }, { 2, 211, 61 }, { 2, 215, 62 }, { 2, 219, 63 }, + { 2, 223, 64 }, { 2, 227, 65 }, { 2, 231, 66 }, { 6, 223, 67 }, { 2, 235, 68 }, { 2, 239, 69 }, { 2, 243, 70 }, { 2, 247, 71 }, + { 2, 251, 72 }, { 2, 255, 73 }, { 6, 247, 74 }, { 6, 251, 75 }, { 6, 255, 76 }, { 10, 247, 77 }, { 10, 251, 78 }, { 10, 255, 79 }, + { 14, 247, 80 }, { 14, 251, 81 }, { 14, 255, 82 }, { 22, 239, 83 }, { 18, 251, 84 }, { 18, 255, 85 }, { 22, 251, 86 }, { 26, 243, 87 }, + { 22, 255, 88 }, { 26, 251, 89 }, { 26, 255, 90 }, { 30, 247, 91 }, { 30, 251, 92 }, { 30, 255, 93 }, { 34, 247, 94 }, { 34, 251, 95 }, + { 34, 255, 96 }, { 38, 247, 97 }, { 38, 251, 98 }, { 38, 255, 99 }, { 42, 247, 100 }, { 42, 251, 101 }, { 42, 255, 102 }, { 46, 247, 103 }, + { 46, 251, 104 }, { 46, 255, 105 }, { 54, 239, 106 }, { 50, 251, 107 }, { 50, 255, 108 }, { 54, 251, 109 }, { 58, 243, 110 }, { 54, 255, 111 }, + { 58, 251, 112 }, { 58, 255, 113 }, { 62, 247, 114 }, { 62, 251, 115 }, { 62, 255, 116 }, { 66, 247, 117 }, { 66, 251, 118 }, { 66, 255, 119 }, + { 70, 247, 120 }, { 70, 251, 121 }, { 70, 255, 122 }, { 74, 247, 123 }, { 74, 251, 124 }, { 74, 255, 125 }, { 78, 247, 126 }, { 78, 251, 127 }, + { 78, 255, 128 }, { 86, 239, 129 }, { 82, 251, 130 }, { 82, 255, 131 }, { 86, 251, 132 }, { 90, 243, 133 }, { 86, 255, 134 }, { 90, 251, 135 }, + { 90, 255, 136 }, { 94, 247, 137 }, { 94, 251, 138 }, { 94, 255, 139 }, { 98, 247, 140 }, { 98, 251, 141 }, { 98, 255, 142 }, { 102, 247, 143 }, + { 102, 251, 144 }, { 102, 255, 145 }, { 106, 247, 146 }, { 106, 251, 147 }, { 106, 255, 148 }, { 110, 247, 149 }, { 110, 251, 150 }, { 110, 255, 151 }, + { 118, 239, 152 }, { 114, 251, 153 }, { 114, 255, 154 }, { 118, 251, 155 }, { 122, 243, 156 }, { 118, 255, 157 }, { 122, 251, 158 }, { 122, 255, 159 }, + { 126, 247, 160 }, { 126, 251, 161 }, { 126, 255, 162 }, { 131, 243, 163 }, { 131, 247, 164 }, { 131, 251, 165 }, { 131, 255, 166 }, { 135, 247, 167 }, + { 135, 251, 168 }, { 135, 255, 169 }, { 143, 239, 170 }, { 139, 251, 171 }, { 139, 255, 172 }, { 143, 251, 173 }, { 147, 243, 174 }, { 143, 255, 175 }, + { 147, 251, 176 }, { 147, 255, 177 }, { 151, 247, 178 }, { 151, 251, 179 }, { 151, 255, 180 }, { 155, 247, 181 }, { 155, 251, 182 }, { 155, 255, 183 }, + { 159, 247, 184 }, { 159, 251, 185 }, { 159, 255, 186 }, { 163, 247, 187 }, { 163, 251, 188 }, { 163, 255, 189 }, { 167, 247, 190 }, { 167, 251, 191 }, + { 167, 255, 192 }, { 175, 239, 193 }, { 171, 251, 194 }, { 171, 255, 195 }, { 175, 251, 196 }, { 179, 243, 197 }, { 175, 255, 198 }, { 179, 251, 199 }, + { 179, 255, 200 }, { 183, 247, 201 }, { 183, 251, 202 }, { 183, 255, 203 }, { 187, 247, 204 }, { 187, 251, 205 }, { 187, 255, 206 }, { 191, 247, 207 }, + { 191, 251, 208 }, { 191, 255, 209 }, { 195, 247, 210 }, { 195, 251, 211 }, { 195, 255, 212 }, { 199, 247, 213 }, { 199, 251, 214 }, { 199, 255, 215 }, + { 207, 239, 216 }, { 203, 251, 217 }, { 203, 255, 218 }, { 207, 251, 219 }, { 211, 243, 220 }, { 207, 255, 221 }, { 211, 251, 222 }, { 211, 255, 223 }, + { 215, 247, 224 }, { 215, 251, 225 }, { 215, 255, 226 }, { 219, 247, 227 }, { 219, 251, 228 }, { 219, 255, 229 }, { 223, 247, 230 }, { 223, 251, 231 }, + { 223, 255, 232 }, { 227, 247, 233 }, { 227, 251, 234 }, { 227, 255, 235 }, { 231, 247, 236 }, { 231, 251, 237 }, { 231, 255, 238 }, { 239, 239, 239 }, + { 235, 251, 240 }, { 235, 255, 241 }, { 239, 251, 242 }, { 243, 243, 243 }, { 239, 255, 244 }, { 243, 251, 245 }, { 243, 255, 246 }, { 247, 247, 247 }, + { 247, 251, 248 }, { 247, 255, 249 }, { 251, 247, 250 }, { 251, 251, 251 }, { 251, 255, 252 }, { 255, 247, 253 }, { 255, 251, 254 }, { 255, 255, 255 }, + } +}; + +Table g_mode1_p1_i3= +{ + 3, + 1, + { + { 2, 2, 2 }, { 2, 2, 2 }, { 2, 2, 2 }, { 2, 2, 2 }, { 2, 6, 4 }, { 2, 10, 5 }, { 6, 6, 6 }, { 2, 14, 7 }, + { 6, 10, 8 }, { 2, 18, 9 }, { 2, 22, 10 }, { 6, 18, 11 }, { 2, 26, 12 }, { 6, 22, 13 }, { 2, 30, 14 }, { 10, 22, 15 }, + { 2, 34, 16 }, { 2, 38, 17 }, { 6, 34, 18 }, { 2, 42, 19 }, { 6, 38, 20 }, { 2, 46, 21 }, { 2, 50, 22 }, { 6, 46, 23 }, + { 2, 54, 24 }, { 6, 50, 25 }, { 2, 58, 26 }, { 2, 62, 27 }, { 6, 58, 28 }, { 2, 66, 29 }, { 6, 62, 30 }, { 2, 70, 31 }, + { 2, 74, 32 }, { 6, 70, 33 }, { 2, 78, 34 }, { 6, 74, 35 }, { 2, 82, 36 }, { 2, 86, 37 }, { 6, 82, 38 }, { 2, 90, 39 }, + { 6, 86, 40 }, { 2, 94, 41 }, { 10, 86, 42 }, { 2, 98, 43 }, { 2, 102, 44 }, { 6, 98, 45 }, { 2, 106, 46 }, { 6, 102, 47 }, + { 2, 110, 48 }, { 2, 114, 49 }, { 6, 110, 50 }, { 2, 118, 51 }, { 6, 114, 52 }, { 2, 122, 53 }, { 2, 126, 54 }, { 6, 122, 55 }, + { 2, 131, 56 }, { 6, 126, 57 }, { 2, 135, 58 }, { 6, 131, 59 }, { 2, 139, 60 }, { 2, 143, 61 }, { 6, 139, 62 }, { 2, 147, 63 }, + { 6, 143, 64 }, { 2, 151, 65 }, { 10, 143, 66 }, { 2, 155, 67 }, { 2, 159, 68 }, { 6, 155, 69 }, { 2, 163, 70 }, { 6, 159, 71 }, + { 2, 167, 72 }, { 2, 171, 73 }, { 6, 167, 74 }, { 2, 175, 75 }, { 6, 171, 76 }, { 2, 179, 77 }, { 2, 183, 78 }, { 6, 179, 79 }, + { 2, 187, 80 }, { 6, 183, 81 }, { 2, 191, 82 }, { 2, 195, 83 }, { 6, 191, 84 }, { 2, 199, 85 }, { 6, 195, 86 }, { 2, 203, 87 }, + { 2, 207, 88 }, { 6, 203, 89 }, { 2, 211, 90 }, { 6, 207, 91 }, { 2, 215, 92 }, { 10, 207, 93 }, { 2, 219, 94 }, { 2, 223, 95 }, + { 6, 219, 96 }, { 2, 227, 97 }, { 6, 223, 98 }, { 2, 231, 99 }, { 2, 235, 100 }, { 6, 231, 101 }, { 2, 239, 102 }, { 6, 235, 103 }, + { 2, 243, 104 }, { 2, 247, 105 }, { 6, 243, 106 }, { 2, 251, 107 }, { 6, 247, 108 }, { 2, 255, 109 }, { 10, 247, 110 }, { 6, 255, 111 }, + { 10, 251, 112 }, { 10, 255, 113 }, { 14, 251, 114 }, { 18, 247, 115 }, { 14, 255, 116 }, { 22, 247, 117 }, { 18, 255, 118 }, { 22, 251, 119 }, + { 22, 255, 120 }, { 26, 251, 121 }, { 30, 247, 122 }, { 26, 255, 123 }, { 34, 247, 124 }, { 30, 255, 125 }, { 34, 251, 126 }, { 34, 255, 127 }, + { 38, 251, 128 }, { 46, 243, 129 }, { 38, 255, 130 }, { 46, 247, 131 }, { 42, 255, 132 }, { 50, 247, 133 }, { 46, 255, 134 }, { 50, 251, 135 }, + { 50, 255, 136 }, { 54, 251, 137 }, { 58, 247, 138 }, { 54, 255, 139 }, { 62, 247, 140 }, { 58, 255, 141 }, { 62, 251, 142 }, { 62, 255, 143 }, + { 66, 251, 144 }, { 70, 247, 145 }, { 66, 255, 146 }, { 74, 247, 147 }, { 70, 255, 148 }, { 74, 251, 149 }, { 74, 255, 150 }, { 78, 251, 151 }, + { 82, 247, 152 }, { 78, 255, 153 }, { 86, 247, 154 }, { 82, 255, 155 }, { 86, 251, 156 }, { 86, 255, 157 }, { 90, 251, 158 }, { 94, 247, 159 }, + { 90, 255, 160 }, { 98, 247, 161 }, { 94, 255, 162 }, { 98, 251, 163 }, { 98, 255, 164 }, { 102, 251, 165 }, { 110, 243, 166 }, { 102, 255, 167 }, + { 110, 247, 168 }, { 106, 255, 169 }, { 114, 247, 170 }, { 110, 255, 171 }, { 114, 251, 172 }, { 114, 255, 173 }, { 118, 251, 174 }, { 122, 247, 175 }, + { 118, 255, 176 }, { 126, 247, 177 }, { 122, 255, 178 }, { 126, 251, 179 }, { 126, 255, 180 }, { 135, 243, 181 }, { 131, 251, 182 }, { 131, 255, 183 }, + { 135, 251, 184 }, { 139, 247, 185 }, { 135, 255, 186 }, { 143, 247, 187 }, { 139, 255, 188 }, { 143, 251, 189 }, { 143, 255, 190 }, { 147, 251, 191 }, + { 151, 247, 192 }, { 147, 255, 193 }, { 155, 247, 194 }, { 151, 255, 195 }, { 155, 251, 196 }, { 155, 255, 197 }, { 159, 251, 198 }, { 167, 243, 199 }, + { 159, 255, 200 }, { 167, 247, 201 }, { 163, 255, 202 }, { 171, 247, 203 }, { 167, 255, 204 }, { 171, 251, 205 }, { 171, 255, 206 }, { 175, 251, 207 }, + { 179, 247, 208 }, { 175, 255, 209 }, { 183, 247, 210 }, { 179, 255, 211 }, { 183, 251, 212 }, { 183, 255, 213 }, { 187, 251, 214 }, { 191, 247, 215 }, + { 187, 255, 216 }, { 195, 247, 217 }, { 191, 255, 218 }, { 195, 251, 219 }, { 195, 255, 220 }, { 199, 251, 221 }, { 203, 247, 222 }, { 199, 255, 223 }, + { 207, 247, 224 }, { 203, 255, 225 }, { 207, 251, 226 }, { 207, 255, 227 }, { 211, 251, 228 }, { 215, 247, 229 }, { 211, 255, 230 }, { 219, 247, 231 }, + { 215, 255, 232 }, { 219, 251, 233 }, { 219, 255, 234 }, { 223, 251, 235 }, { 231, 243, 236 }, { 223, 255, 237 }, { 231, 247, 238 }, { 227, 255, 239 }, + { 235, 247, 240 }, { 231, 255, 241 }, { 235, 251, 242 }, { 235, 255, 243 }, { 239, 251, 244 }, { 243, 247, 245 }, { 239, 255, 246 }, { 247, 247, 247 }, + { 243, 255, 248 }, { 247, 251, 249 }, { 247, 255, 250 }, { 251, 251, 251 }, { 255, 247, 252 }, { 251, 255, 253 }, { 251, 255, 253 }, { 255, 255, 255 }, + } +}; + +Table g_mode2= +{ + 1, + 0, + { + { 0, 0, 0 }, { 0, 0, 0 }, { 0, 8, 3 }, { 0, 8, 3 }, { 0, 8, 3 }, { 0, 16, 5 }, { 0, 16, 5 }, { 0, 24, 8 }, + { 0, 24, 8 }, { 0, 24, 8 }, { 0, 33, 11 }, { 0, 33, 11 }, { 0, 33, 11 }, { 0, 41, 13 }, { 0, 41, 13 }, { 0, 49, 16 }, + { 0, 49, 16 }, { 0, 49, 16 }, { 0, 57, 19 }, { 0, 57, 19 }, { 0, 57, 19 }, { 8, 49, 21 }, { 0, 66, 22 }, { 0, 66, 22 }, + { 0, 74, 24 }, { 33, 8, 25 }, { 0, 82, 27 }, { 0, 82, 27 }, { 41, 0, 28 }, { 16, 57, 29 }, { 0, 90, 30 }, { 0, 90, 30 }, + { 0, 99, 32 }, { 33, 33, 33 }, { 0, 107, 35 }, { 0, 107, 35 }, { 33, 41, 36 }, { 0, 115, 38 }, { 0, 115, 38 }, { 0, 115, 38 }, + { 0, 123, 40 }, { 33, 57, 41 }, { 0, 132, 43 }, { 0, 132, 43 }, { 33, 66, 44 }, { 0, 140, 46 }, { 0, 140, 46 }, { 66, 8, 47 }, + { 16, 115, 48 }, { 0, 148, 49 }, { 66, 16, 50 }, { 0, 156, 51 }, { 33, 90, 52 }, { 0, 165, 54 }, { 0, 165, 54 }, { 33, 99, 55 }, + { 24, 123, 56 }, { 0, 173, 57 }, { 66, 41, 58 }, { 0, 181, 59 }, { 8, 165, 60 }, { 74, 33, 61 }, { 0, 189, 62 }, { 33, 123, 63 }, + { 0, 198, 65 }, { 0, 198, 65 }, { 66, 66, 66 }, { 8, 189, 67 }, { 0, 206, 68 }, { 66, 74, 69 }, { 0, 214, 70 }, { 33, 148, 71 }, + { 99, 16, 72 }, { 0, 222, 73 }, { 66, 90, 74 }, { 107, 8, 75 }, { 0, 231, 76 }, { 66, 99, 77 }, { 0, 239, 78 }, { 33, 173, 79 }, + { 99, 41, 80 }, { 0, 247, 81 }, { 33, 181, 82 }, { 99, 49, 83 }, { 0, 255, 84 }, { 66, 123, 85 }, { 8, 247, 86 }, { 16, 231, 87 }, + { 66, 132, 88 }, { 8, 255, 89 }, { 33, 206, 90 }, { 99, 74, 91 }, { 16, 247, 92 }, { 41, 198, 93 }, { 16, 255, 94 }, { 24, 239, 95 }, + { 66, 156, 96 }, { 24, 247, 97 }, { 33, 231, 98 }, { 99, 99, 99 }, { 24, 255, 100 }, { 33, 239, 101 }, { 99, 107, 102 }, { 33, 247, 103 }, + { 66, 181, 104 }, { 132, 49, 105 }, { 33, 255, 106 }, { 99, 123, 107 }, { 140, 41, 108 }, { 41, 247, 109 }, { 99, 132, 110 }, { 41, 255, 111 }, + { 66, 206, 112 }, { 132, 74, 113 }, { 49, 247, 114 }, { 66, 214, 115 }, { 132, 82, 116 }, { 49, 255, 117 }, { 99, 156, 118 }, { 57, 247, 119 }, + { 66, 231, 120 }, { 99, 165, 121 }, { 57, 255, 122 }, { 66, 239, 123 }, { 132, 107, 124 }, { 66, 247, 125 }, { 74, 231, 126 }, { 140, 99, 127 }, + { 66, 255, 128 }, { 99, 189, 129 }, { 165, 57, 130 }, { 74, 247, 131 }, { 132, 132, 132 }, { 74, 255, 133 }, { 82, 239, 134 }, { 132, 140, 135 }, + { 82, 247, 136 }, { 99, 214, 137 }, { 165, 82, 138 }, { 82, 255, 139 }, { 132, 156, 140 }, { 173, 74, 141 }, { 90, 247, 142 }, { 132, 165, 143 }, + { 90, 255, 144 }, { 99, 239, 145 }, { 165, 107, 146 }, { 115, 214, 147 }, { 99, 247, 148 }, { 165, 115, 149 }, { 99, 255, 150 }, { 132, 189, 151 }, + { 198, 57, 152 }, { 107, 247, 153 }, { 132, 198, 154 }, { 123, 222, 155 }, { 107, 255, 156 }, { 165, 140, 157 }, { 115, 247, 158 }, { 132, 214, 159 }, + { 173, 132, 160 }, { 115, 255, 161 }, { 132, 222, 162 }, { 198, 90, 163 }, { 123, 247, 164 }, { 165, 165, 165 }, { 123, 255, 166 }, { 132, 239, 167 }, + { 165, 173, 168 }, { 231, 41, 169 }, { 132, 247, 170 }, { 198, 115, 171 }, { 132, 255, 172 }, { 165, 189, 173 }, { 206, 107, 174 }, { 140, 247, 175 }, + { 165, 198, 176 }, { 231, 66, 177 }, { 140, 255, 178 }, { 198, 140, 179 }, { 148, 247, 180 }, { 156, 231, 181 }, { 198, 148, 182 }, { 148, 255, 183 }, + { 165, 222, 184 }, { 231, 90, 185 }, { 156, 247, 186 }, { 165, 231, 187 }, { 156, 255, 188 }, { 165, 239, 189 }, { 198, 173, 190 }, { 165, 247, 192 }, + { 165, 247, 192 }, { 206, 165, 193 }, { 181, 222, 194 }, { 165, 255, 195 }, { 231, 123, 196 }, { 173, 247, 197 }, { 198, 198, 198 }, { 231, 132, 199 }, + { 173, 255, 200 }, { 198, 206, 201 }, { 181, 247, 203 }, { 181, 247, 203 }, { 231, 148, 204 }, { 181, 255, 205 }, { 198, 222, 206 }, { 239, 140, 207 }, + { 189, 247, 208 }, { 198, 231, 209 }, { 189, 255, 211 }, { 189, 255, 211 }, { 231, 173, 212 }, { 198, 247, 214 }, { 198, 247, 214 }, { 231, 181, 215 }, + { 198, 255, 217 }, { 198, 255, 217 }, { 198, 255, 217 }, { 206, 247, 219 }, { 214, 231, 220 }, { 206, 255, 222 }, { 206, 255, 222 }, { 231, 206, 223 }, + { 214, 247, 225 }, { 214, 247, 225 }, { 239, 198, 226 }, { 214, 255, 227 }, { 222, 239, 228 }, { 222, 239, 228 }, { 222, 247, 230 }, { 231, 231, 231 }, + { 222, 255, 233 }, { 222, 255, 233 }, { 231, 239, 234 }, { 231, 239, 234 }, { 231, 247, 236 }, { 231, 247, 236 }, { 231, 255, 239 }, { 231, 255, 239 }, + { 231, 255, 239 }, { 239, 247, 242 }, { 239, 247, 242 }, { 239, 247, 242 }, { 239, 255, 244 }, { 239, 255, 244 }, { 247, 247, 247 }, { 247, 247, 247 }, + { 247, 247, 247 }, { 247, 255, 250 }, { 247, 255, 250 }, { 247, 255, 250 }, { 255, 247, 252 }, { 255, 247, 252 }, { 255, 255, 255 }, { 255, 255, 255 }, + } +}; + +Table g_mode3_p0= +{ + 1, + 0, + { + { 0, 0, 0 }, { 0, 2, 1 }, { 0, 6, 2 }, { 0, 8, 3 }, { 0, 12, 4 }, { 0, 14, 5 }, { 0, 18, 6 }, { 0, 20, 7 }, + { 0, 24, 8 }, { 0, 26, 9 }, { 0, 30, 10 }, { 0, 32, 11 }, { 0, 36, 12 }, { 0, 40, 13 }, { 0, 42, 14 }, { 0, 46, 15 }, + { 0, 48, 16 }, { 0, 52, 17 }, { 0, 54, 18 }, { 0, 58, 19 }, { 0, 60, 20 }, { 0, 64, 21 }, { 0, 66, 22 }, { 0, 70, 23 }, + { 0, 72, 24 }, { 0, 76, 25 }, { 0, 78, 26 }, { 0, 82, 27 }, { 0, 84, 28 }, { 0, 88, 29 }, { 0, 90, 30 }, { 0, 94, 31 }, + { 0, 96, 32 }, { 0, 100, 33 }, { 0, 104, 34 }, { 0, 106, 35 }, { 0, 110, 36 }, { 0, 112, 37 }, { 0, 116, 38 }, { 0, 118, 39 }, + { 0, 122, 40 }, { 0, 124, 41 }, { 0, 128, 42 }, { 0, 130, 43 }, { 0, 134, 44 }, { 0, 136, 45 }, { 0, 140, 46 }, { 0, 142, 47 }, + { 0, 146, 48 }, { 0, 148, 49 }, { 0, 152, 50 }, { 0, 154, 51 }, { 0, 158, 52 }, { 0, 160, 53 }, { 0, 164, 54 }, { 0, 168, 55 }, + { 0, 170, 56 }, { 0, 174, 57 }, { 0, 176, 58 }, { 0, 180, 59 }, { 0, 182, 60 }, { 0, 186, 61 }, { 0, 188, 62 }, { 0, 192, 63 }, + { 0, 194, 64 }, { 0, 198, 65 }, { 0, 200, 66 }, { 0, 204, 67 }, { 0, 206, 68 }, { 0, 210, 69 }, { 0, 212, 70 }, { 0, 216, 71 }, + { 0, 218, 72 }, { 0, 222, 73 }, { 0, 224, 74 }, { 0, 228, 75 }, { 0, 232, 76 }, { 0, 234, 77 }, { 0, 238, 78 }, { 0, 240, 79 }, + { 0, 244, 80 }, { 0, 246, 81 }, { 0, 250, 82 }, { 0, 252, 83 }, { 2, 252, 84 }, { 2, 254, 85 }, { 4, 254, 86 }, { 6, 252, 87 }, + { 8, 252, 88 }, { 8, 254, 89 }, { 10, 254, 90 }, { 12, 252, 91 }, { 14, 252, 92 }, { 14, 254, 93 }, { 16, 254, 94 }, { 18, 252, 95 }, + { 20, 252, 96 }, { 20, 254, 97 }, { 22, 254, 98 }, { 24, 252, 99 }, { 26, 250, 100 }, { 26, 254, 101 }, { 28, 252, 102 }, { 30, 252, 103 }, + { 30, 254, 104 }, { 32, 254, 105 }, { 34, 252, 106 }, { 36, 252, 107 }, { 36, 254, 108 }, { 38, 254, 109 }, { 40, 252, 110 }, { 42, 252, 111 }, + { 42, 254, 112 }, { 44, 254, 113 }, { 46, 252, 114 }, { 48, 252, 115 }, { 48, 254, 116 }, { 50, 254, 117 }, { 52, 252, 118 }, { 54, 252, 119 }, + { 54, 254, 120 }, { 56, 254, 121 }, { 58, 252, 122 }, { 60, 252, 123 }, { 60, 254, 124 }, { 62, 254, 125 }, { 64, 252, 126 }, { 66, 252, 127 }, + { 66, 254, 128 }, { 68, 254, 129 }, { 70, 252, 130 }, { 72, 252, 131 }, { 72, 254, 132 }, { 74, 254, 133 }, { 76, 252, 134 }, { 78, 252, 135 }, + { 78, 254, 136 }, { 80, 254, 137 }, { 82, 252, 138 }, { 84, 252, 139 }, { 84, 254, 140 }, { 86, 254, 141 }, { 88, 252, 142 }, { 90, 250, 143 }, + { 90, 254, 144 }, { 92, 252, 145 }, { 94, 252, 146 }, { 94, 254, 147 }, { 96, 254, 148 }, { 98, 252, 149 }, { 100, 252, 150 }, { 100, 254, 151 }, + { 102, 254, 152 }, { 104, 252, 153 }, { 106, 252, 154 }, { 106, 254, 155 }, { 108, 254, 156 }, { 110, 252, 157 }, { 112, 252, 158 }, { 112, 254, 159 }, + { 114, 254, 160 }, { 116, 252, 161 }, { 118, 252, 162 }, { 118, 254, 163 }, { 120, 254, 164 }, { 122, 252, 165 }, { 124, 252, 166 }, { 124, 254, 167 }, + { 126, 254, 168 }, { 128, 252, 169 }, { 130, 252, 170 }, { 130, 254, 171 }, { 132, 254, 172 }, { 134, 252, 173 }, { 136, 252, 174 }, { 136, 254, 175 }, + { 138, 254, 176 }, { 140, 252, 177 }, { 142, 252, 178 }, { 142, 254, 179 }, { 144, 254, 180 }, { 146, 252, 181 }, { 148, 252, 182 }, { 148, 254, 183 }, + { 150, 254, 184 }, { 152, 252, 185 }, { 154, 250, 186 }, { 154, 254, 187 }, { 156, 252, 188 }, { 158, 252, 189 }, { 158, 254, 190 }, { 160, 254, 191 }, + { 162, 252, 192 }, { 164, 252, 193 }, { 164, 254, 194 }, { 166, 254, 195 }, { 168, 252, 196 }, { 170, 252, 197 }, { 170, 254, 198 }, { 172, 254, 199 }, + { 174, 252, 200 }, { 176, 252, 201 }, { 176, 254, 202 }, { 178, 254, 203 }, { 180, 252, 204 }, { 182, 252, 205 }, { 182, 254, 206 }, { 184, 254, 207 }, + { 186, 252, 208 }, { 188, 252, 209 }, { 188, 254, 210 }, { 190, 254, 211 }, { 192, 252, 212 }, { 194, 252, 213 }, { 194, 254, 214 }, { 196, 254, 215 }, + { 198, 252, 216 }, { 200, 252, 217 }, { 200, 254, 218 }, { 202, 254, 219 }, { 204, 252, 220 }, { 206, 252, 221 }, { 206, 254, 222 }, { 208, 254, 223 }, + { 210, 252, 224 }, { 212, 252, 225 }, { 212, 254, 226 }, { 214, 254, 227 }, { 216, 252, 228 }, { 218, 250, 229 }, { 218, 254, 230 }, { 220, 252, 231 }, + { 222, 252, 232 }, { 222, 254, 233 }, { 224, 254, 234 }, { 226, 252, 235 }, { 228, 252, 236 }, { 228, 254, 237 }, { 230, 254, 238 }, { 232, 252, 239 }, + { 234, 252, 240 }, { 234, 254, 241 }, { 236, 254, 242 }, { 238, 252, 243 }, { 240, 252, 244 }, { 240, 254, 245 }, { 242, 254, 246 }, { 244, 252, 247 }, + { 246, 252, 248 }, { 246, 254, 249 }, { 248, 254, 250 }, { 250, 252, 251 }, { 252, 252, 252 }, { 252, 254, 253 }, { 254, 254, 254 }, { 254, 254, 254 }, + } +}; + +Table g_mode3_p1= +{ + 1, + 1, + { + { 1, 1, 1 }, { 1, 1, 1 }, { 1, 3, 2 }, { 1, 7, 3 }, { 1, 9, 4 }, { 1, 13, 5 }, { 1, 15, 6 }, { 1, 19, 7 }, + { 1, 21, 8 }, { 1, 25, 9 }, { 1, 27, 10 }, { 1, 31, 11 }, { 1, 33, 12 }, { 1, 37, 13 }, { 1, 41, 14 }, { 1, 43, 15 }, + { 1, 47, 16 }, { 1, 49, 17 }, { 1, 53, 18 }, { 1, 55, 19 }, { 1, 59, 20 }, { 1, 61, 21 }, { 1, 65, 22 }, { 1, 67, 23 }, + { 1, 71, 24 }, { 1, 73, 25 }, { 1, 77, 26 }, { 1, 79, 27 }, { 1, 83, 28 }, { 1, 85, 29 }, { 1, 89, 30 }, { 1, 91, 31 }, + { 1, 95, 32 }, { 1, 97, 33 }, { 1, 101, 34 }, { 1, 105, 35 }, { 1, 107, 36 }, { 1, 111, 37 }, { 1, 113, 38 }, { 1, 117, 39 }, + { 1, 119, 40 }, { 1, 123, 41 }, { 1, 125, 42 }, { 1, 129, 43 }, { 1, 131, 44 }, { 1, 135, 45 }, { 1, 137, 46 }, { 1, 141, 47 }, + { 1, 143, 48 }, { 1, 147, 49 }, { 1, 149, 50 }, { 1, 153, 51 }, { 1, 155, 52 }, { 1, 159, 53 }, { 1, 161, 54 }, { 1, 165, 55 }, + { 1, 169, 56 }, { 1, 171, 57 }, { 1, 175, 58 }, { 1, 177, 59 }, { 1, 181, 60 }, { 1, 183, 61 }, { 1, 187, 62 }, { 1, 189, 63 }, + { 1, 193, 64 }, { 1, 195, 65 }, { 1, 199, 66 }, { 1, 201, 67 }, { 1, 205, 68 }, { 1, 207, 69 }, { 1, 211, 70 }, { 1, 213, 71 }, + { 1, 217, 72 }, { 1, 219, 73 }, { 1, 223, 74 }, { 1, 225, 75 }, { 1, 229, 76 }, { 1, 233, 77 }, { 1, 235, 78 }, { 1, 239, 79 }, + { 1, 241, 80 }, { 1, 245, 81 }, { 1, 247, 82 }, { 1, 251, 83 }, { 1, 253, 84 }, { 3, 253, 85 }, { 3, 255, 86 }, { 5, 255, 87 }, + { 7, 253, 88 }, { 9, 253, 89 }, { 9, 255, 90 }, { 11, 255, 91 }, { 13, 253, 92 }, { 15, 253, 93 }, { 15, 255, 94 }, { 17, 255, 95 }, + { 19, 253, 96 }, { 21, 253, 97 }, { 21, 255, 98 }, { 23, 255, 99 }, { 25, 253, 100 }, { 27, 251, 101 }, { 27, 255, 102 }, { 29, 253, 103 }, + { 31, 253, 104 }, { 31, 255, 105 }, { 33, 255, 106 }, { 35, 253, 107 }, { 37, 253, 108 }, { 37, 255, 109 }, { 39, 255, 110 }, { 41, 253, 111 }, + { 43, 253, 112 }, { 43, 255, 113 }, { 45, 255, 114 }, { 47, 253, 115 }, { 49, 253, 116 }, { 49, 255, 117 }, { 51, 255, 118 }, { 53, 253, 119 }, + { 55, 253, 120 }, { 55, 255, 121 }, { 57, 255, 122 }, { 59, 253, 123 }, { 61, 253, 124 }, { 61, 255, 125 }, { 63, 255, 126 }, { 65, 253, 127 }, + { 67, 253, 128 }, { 67, 255, 129 }, { 69, 255, 130 }, { 71, 253, 131 }, { 73, 253, 132 }, { 73, 255, 133 }, { 75, 255, 134 }, { 77, 253, 135 }, + { 79, 253, 136 }, { 79, 255, 137 }, { 81, 255, 138 }, { 83, 253, 139 }, { 85, 253, 140 }, { 85, 255, 141 }, { 87, 255, 142 }, { 89, 253, 143 }, + { 91, 251, 144 }, { 91, 255, 145 }, { 93, 253, 146 }, { 95, 253, 147 }, { 95, 255, 148 }, { 97, 255, 149 }, { 99, 253, 150 }, { 101, 253, 151 }, + { 101, 255, 152 }, { 103, 255, 153 }, { 105, 253, 154 }, { 107, 253, 155 }, { 107, 255, 156 }, { 109, 255, 157 }, { 111, 253, 158 }, { 113, 253, 159 }, + { 113, 255, 160 }, { 115, 255, 161 }, { 117, 253, 162 }, { 119, 253, 163 }, { 119, 255, 164 }, { 121, 255, 165 }, { 123, 253, 166 }, { 125, 253, 167 }, + { 125, 255, 168 }, { 127, 255, 169 }, { 129, 253, 170 }, { 131, 253, 171 }, { 131, 255, 172 }, { 133, 255, 173 }, { 135, 253, 174 }, { 137, 253, 175 }, + { 137, 255, 176 }, { 139, 255, 177 }, { 141, 253, 178 }, { 143, 253, 179 }, { 143, 255, 180 }, { 145, 255, 181 }, { 147, 253, 182 }, { 149, 253, 183 }, + { 149, 255, 184 }, { 151, 255, 185 }, { 153, 253, 186 }, { 155, 251, 187 }, { 155, 255, 188 }, { 157, 253, 189 }, { 159, 253, 190 }, { 159, 255, 191 }, + { 161, 255, 192 }, { 163, 253, 193 }, { 165, 253, 194 }, { 165, 255, 195 }, { 167, 255, 196 }, { 169, 253, 197 }, { 171, 253, 198 }, { 171, 255, 199 }, + { 173, 255, 200 }, { 175, 253, 201 }, { 177, 253, 202 }, { 177, 255, 203 }, { 179, 255, 204 }, { 181, 253, 205 }, { 183, 253, 206 }, { 183, 255, 207 }, + { 185, 255, 208 }, { 187, 253, 209 }, { 189, 253, 210 }, { 189, 255, 211 }, { 191, 255, 212 }, { 193, 253, 213 }, { 195, 253, 214 }, { 195, 255, 215 }, + { 197, 255, 216 }, { 199, 253, 217 }, { 201, 253, 218 }, { 201, 255, 219 }, { 203, 255, 220 }, { 205, 253, 221 }, { 207, 253, 222 }, { 207, 255, 223 }, + { 209, 255, 224 }, { 211, 253, 225 }, { 213, 253, 226 }, { 213, 255, 227 }, { 215, 255, 228 }, { 217, 253, 229 }, { 219, 251, 230 }, { 219, 255, 231 }, + { 221, 253, 232 }, { 223, 253, 233 }, { 223, 255, 234 }, { 225, 255, 235 }, { 227, 253, 236 }, { 229, 253, 237 }, { 229, 255, 238 }, { 231, 255, 239 }, + { 233, 253, 240 }, { 235, 253, 241 }, { 235, 255, 242 }, { 237, 255, 243 }, { 239, 253, 244 }, { 241, 253, 245 }, { 241, 255, 246 }, { 243, 255, 247 }, + { 245, 253, 248 }, { 247, 253, 249 }, { 247, 255, 250 }, { 249, 255, 251 }, { 251, 253, 252 }, { 253, 253, 253 }, { 253, 255, 254 }, { 255, 255, 255 }, + } +}; + +Table g_mode4_rgb_low= +{ + 1, + 0, + { + { 0, 0, 0 }, { 0, 0, 0 }, { 0, 8, 3 }, { 0, 8, 3 }, { 0, 8, 3 }, { 0, 16, 5 }, { 0, 16, 5 }, { 0, 24, 8 }, + { 0, 24, 8 }, { 0, 24, 8 }, { 0, 33, 11 }, { 0, 33, 11 }, { 0, 33, 11 }, { 0, 41, 13 }, { 0, 41, 13 }, { 0, 49, 16 }, + { 0, 49, 16 }, { 0, 49, 16 }, { 0, 57, 19 }, { 0, 57, 19 }, { 0, 57, 19 }, { 8, 49, 21 }, { 0, 66, 22 }, { 0, 66, 22 }, + { 0, 74, 24 }, { 33, 8, 25 }, { 0, 82, 27 }, { 0, 82, 27 }, { 41, 0, 28 }, { 16, 57, 29 }, { 0, 90, 30 }, { 0, 90, 30 }, + { 0, 99, 32 }, { 33, 33, 33 }, { 0, 107, 35 }, { 0, 107, 35 }, { 33, 41, 36 }, { 0, 115, 38 }, { 0, 115, 38 }, { 0, 115, 38 }, + { 0, 123, 40 }, { 33, 57, 41 }, { 0, 132, 43 }, { 0, 132, 43 }, { 33, 66, 44 }, { 0, 140, 46 }, { 0, 140, 46 }, { 66, 8, 47 }, + { 16, 115, 48 }, { 0, 148, 49 }, { 66, 16, 50 }, { 0, 156, 51 }, { 33, 90, 52 }, { 0, 165, 54 }, { 0, 165, 54 }, { 33, 99, 55 }, + { 24, 123, 56 }, { 0, 173, 57 }, { 66, 41, 58 }, { 0, 181, 59 }, { 8, 165, 60 }, { 74, 33, 61 }, { 0, 189, 62 }, { 33, 123, 63 }, + { 0, 198, 65 }, { 0, 198, 65 }, { 66, 66, 66 }, { 8, 189, 67 }, { 0, 206, 68 }, { 66, 74, 69 }, { 0, 214, 70 }, { 33, 148, 71 }, + { 99, 16, 72 }, { 0, 222, 73 }, { 66, 90, 74 }, { 107, 8, 75 }, { 0, 231, 76 }, { 66, 99, 77 }, { 0, 239, 78 }, { 33, 173, 79 }, + { 99, 41, 80 }, { 0, 247, 81 }, { 33, 181, 82 }, { 99, 49, 83 }, { 0, 255, 84 }, { 66, 123, 85 }, { 8, 247, 86 }, { 16, 231, 87 }, + { 66, 132, 88 }, { 8, 255, 89 }, { 33, 206, 90 }, { 99, 74, 91 }, { 16, 247, 92 }, { 41, 198, 93 }, { 16, 255, 94 }, { 24, 239, 95 }, + { 66, 156, 96 }, { 24, 247, 97 }, { 33, 231, 98 }, { 99, 99, 99 }, { 24, 255, 100 }, { 33, 239, 101 }, { 99, 107, 102 }, { 33, 247, 103 }, + { 66, 181, 104 }, { 132, 49, 105 }, { 33, 255, 106 }, { 99, 123, 107 }, { 140, 41, 108 }, { 41, 247, 109 }, { 99, 132, 110 }, { 41, 255, 111 }, + { 66, 206, 112 }, { 132, 74, 113 }, { 49, 247, 114 }, { 66, 214, 115 }, { 132, 82, 116 }, { 49, 255, 117 }, { 99, 156, 118 }, { 57, 247, 119 }, + { 66, 231, 120 }, { 99, 165, 121 }, { 57, 255, 122 }, { 66, 239, 123 }, { 132, 107, 124 }, { 66, 247, 125 }, { 74, 231, 126 }, { 140, 99, 127 }, + { 66, 255, 128 }, { 99, 189, 129 }, { 165, 57, 130 }, { 74, 247, 131 }, { 132, 132, 132 }, { 74, 255, 133 }, { 82, 239, 134 }, { 132, 140, 135 }, + { 82, 247, 136 }, { 99, 214, 137 }, { 165, 82, 138 }, { 82, 255, 139 }, { 132, 156, 140 }, { 173, 74, 141 }, { 90, 247, 142 }, { 132, 165, 143 }, + { 90, 255, 144 }, { 99, 239, 145 }, { 165, 107, 146 }, { 115, 214, 147 }, { 99, 247, 148 }, { 165, 115, 149 }, { 99, 255, 150 }, { 132, 189, 151 }, + { 198, 57, 152 }, { 107, 247, 153 }, { 132, 198, 154 }, { 123, 222, 155 }, { 107, 255, 156 }, { 165, 140, 157 }, { 115, 247, 158 }, { 132, 214, 159 }, + { 173, 132, 160 }, { 115, 255, 161 }, { 132, 222, 162 }, { 198, 90, 163 }, { 123, 247, 164 }, { 165, 165, 165 }, { 123, 255, 166 }, { 132, 239, 167 }, + { 165, 173, 168 }, { 231, 41, 169 }, { 132, 247, 170 }, { 198, 115, 171 }, { 132, 255, 172 }, { 165, 189, 173 }, { 206, 107, 174 }, { 140, 247, 175 }, + { 165, 198, 176 }, { 231, 66, 177 }, { 140, 255, 178 }, { 198, 140, 179 }, { 148, 247, 180 }, { 156, 231, 181 }, { 198, 148, 182 }, { 148, 255, 183 }, + { 165, 222, 184 }, { 231, 90, 185 }, { 156, 247, 186 }, { 165, 231, 187 }, { 156, 255, 188 }, { 165, 239, 189 }, { 198, 173, 190 }, { 165, 247, 192 }, + { 165, 247, 192 }, { 206, 165, 193 }, { 181, 222, 194 }, { 165, 255, 195 }, { 231, 123, 196 }, { 173, 247, 197 }, { 198, 198, 198 }, { 231, 132, 199 }, + { 173, 255, 200 }, { 198, 206, 201 }, { 181, 247, 203 }, { 181, 247, 203 }, { 231, 148, 204 }, { 181, 255, 205 }, { 198, 222, 206 }, { 239, 140, 207 }, + { 189, 247, 208 }, { 198, 231, 209 }, { 189, 255, 211 }, { 189, 255, 211 }, { 231, 173, 212 }, { 198, 247, 214 }, { 198, 247, 214 }, { 231, 181, 215 }, + { 198, 255, 217 }, { 198, 255, 217 }, { 198, 255, 217 }, { 206, 247, 219 }, { 214, 231, 220 }, { 206, 255, 222 }, { 206, 255, 222 }, { 231, 206, 223 }, + { 214, 247, 225 }, { 214, 247, 225 }, { 239, 198, 226 }, { 214, 255, 227 }, { 222, 239, 228 }, { 222, 239, 228 }, { 222, 247, 230 }, { 231, 231, 231 }, + { 222, 255, 233 }, { 222, 255, 233 }, { 231, 239, 234 }, { 231, 239, 234 }, { 231, 247, 236 }, { 231, 247, 236 }, { 231, 255, 239 }, { 231, 255, 239 }, + { 231, 255, 239 }, { 239, 247, 242 }, { 239, 247, 242 }, { 239, 247, 242 }, { 239, 255, 244 }, { 239, 255, 244 }, { 247, 247, 247 }, { 247, 247, 247 }, + { 247, 247, 247 }, { 247, 255, 250 }, { 247, 255, 250 }, { 247, 255, 250 }, { 255, 247, 252 }, { 255, 247, 252 }, { 255, 255, 255 }, { 255, 255, 255 }, + } +}; + +Table g_mode4_rgb_high_i1= +{ + 1, + 0, + { + { 0, 0, 0 }, { 0, 8, 1 }, { 0, 16, 2 }, { 0, 24, 3 }, { 0, 24, 3 }, { 0, 33, 5 }, { 0, 41, 6 }, { 0, 49, 7 }, + { 0, 57, 8 }, { 0, 66, 9 }, { 0, 74, 10 }, { 0, 74, 10 }, { 0, 82, 12 }, { 0, 90, 13 }, { 0, 99, 14 }, { 0, 107, 15 }, + { 0, 115, 16 }, { 0, 123, 17 }, { 8, 82, 18 }, { 0, 132, 19 }, { 0, 140, 20 }, { 0, 148, 21 }, { 0, 156, 22 }, { 0, 165, 23 }, + { 0, 173, 24 }, { 0, 181, 25 }, { 16, 90, 26 }, { 0, 189, 27 }, { 0, 198, 28 }, { 0, 206, 29 }, { 0, 214, 30 }, { 0, 222, 31 }, + { 0, 231, 32 }, { 8, 189, 33 }, { 0, 239, 34 }, { 0, 247, 35 }, { 0, 255, 36 }, { 8, 214, 37 }, { 8, 222, 38 }, { 8, 231, 39 }, + { 8, 239, 40 }, { 24, 148, 41 }, { 8, 247, 42 }, { 8, 255, 43 }, { 16, 214, 44 }, { 16, 222, 45 }, { 16, 231, 46 }, { 16, 239, 47 }, + { 16, 247, 48 }, { 33, 148, 49 }, { 16, 255, 50 }, { 24, 214, 51 }, { 24, 222, 52 }, { 24, 231, 53 }, { 24, 239, 54 }, { 24, 247, 55 }, + { 24, 255, 56 }, { 33, 206, 57 }, { 33, 214, 58 }, { 49, 123, 59 }, { 33, 222, 60 }, { 33, 231, 61 }, { 33, 239, 62 }, { 33, 247, 63 }, + { 33, 255, 64 }, { 41, 214, 65 }, { 41, 222, 66 }, { 66, 74, 67 }, { 41, 231, 68 }, { 41, 239, 69 }, { 41, 247, 70 }, { 41, 255, 71 }, + { 49, 214, 72 }, { 49, 222, 73 }, { 57, 181, 74 }, { 49, 231, 75 }, { 49, 239, 76 }, { 49, 247, 77 }, { 49, 255, 78 }, { 57, 214, 79 }, + { 57, 222, 80 }, { 57, 231, 81 }, { 66, 181, 82 }, { 57, 239, 83 }, { 57, 247, 84 }, { 57, 255, 85 }, { 66, 206, 86 }, { 66, 214, 87 }, + { 66, 222, 88 }, { 66, 231, 89 }, { 66, 239, 90 }, { 66, 247, 91 }, { 82, 156, 92 }, { 66, 255, 93 }, { 74, 214, 94 }, { 74, 222, 95 }, + { 74, 231, 96 }, { 74, 239, 97 }, { 74, 247, 98 }, { 74, 255, 99 }, { 99, 107, 100 }, { 82, 214, 101 }, { 82, 222, 102 }, { 82, 231, 103 }, + { 82, 239, 104 }, { 82, 247, 105 }, { 82, 255, 106 }, { 90, 214, 107 }, { 99, 165, 108 }, { 90, 222, 109 }, { 90, 231, 110 }, { 90, 239, 111 }, + { 90, 247, 112 }, { 90, 255, 113 }, { 99, 206, 114 }, { 99, 214, 115 }, { 99, 222, 116 }, { 107, 181, 117 }, { 99, 231, 118 }, { 99, 239, 119 }, + { 99, 247, 120 }, { 99, 255, 121 }, { 107, 214, 122 }, { 107, 222, 123 }, { 107, 231, 124 }, { 115, 189, 125 }, { 107, 239, 126 }, { 107, 247, 127 }, + { 107, 255, 128 }, { 115, 214, 129 }, { 115, 222, 130 }, { 115, 231, 131 }, { 115, 239, 132 }, { 132, 140, 133 }, { 115, 247, 134 }, { 115, 255, 135 }, + { 123, 214, 136 }, { 123, 222, 137 }, { 123, 231, 138 }, { 123, 239, 139 }, { 123, 247, 140 }, { 132, 198, 141 }, { 123, 255, 142 }, { 148, 115, 143 }, + { 132, 214, 144 }, { 132, 222, 145 }, { 132, 231, 146 }, { 132, 239, 147 }, { 132, 247, 148 }, { 132, 255, 149 }, { 140, 214, 150 }, { 156, 123, 151 }, + { 140, 222, 152 }, { 140, 231, 153 }, { 140, 239, 154 }, { 140, 247, 155 }, { 140, 255, 156 }, { 148, 214, 157 }, { 148, 222, 158 }, { 165, 123, 159 }, + { 148, 231, 160 }, { 148, 239, 161 }, { 148, 247, 162 }, { 148, 255, 163 }, { 156, 214, 164 }, { 156, 222, 165 }, { 165, 173, 166 }, { 156, 231, 167 }, + { 156, 239, 168 }, { 156, 247, 169 }, { 156, 255, 170 }, { 165, 206, 171 }, { 165, 214, 172 }, { 165, 222, 173 }, { 165, 231, 174 }, { 165, 239, 175 }, + { 181, 148, 176 }, { 165, 247, 177 }, { 165, 255, 178 }, { 173, 214, 179 }, { 173, 222, 180 }, { 173, 231, 181 }, { 173, 239, 182 }, { 173, 247, 183 }, + { 189, 156, 184 }, { 173, 255, 185 }, { 181, 214, 186 }, { 181, 222, 187 }, { 181, 231, 188 }, { 181, 239, 189 }, { 181, 247, 190 }, { 181, 255, 191 }, + { 198, 156, 192 }, { 189, 214, 193 }, { 189, 222, 194 }, { 189, 231, 195 }, { 189, 239, 196 }, { 189, 247, 197 }, { 189, 255, 198 }, { 198, 206, 199 }, + { 198, 214, 200 }, { 198, 222, 201 }, { 206, 181, 202 }, { 198, 231, 203 }, { 198, 239, 204 }, { 198, 247, 205 }, { 198, 255, 206 }, { 206, 214, 207 }, + { 206, 222, 208 }, { 214, 181, 209 }, { 206, 231, 210 }, { 206, 239, 211 }, { 206, 247, 212 }, { 206, 255, 213 }, { 214, 214, 214 }, { 214, 222, 215 }, + { 214, 231, 216 }, { 222, 189, 217 }, { 214, 239, 218 }, { 214, 247, 219 }, { 214, 255, 220 }, { 222, 214, 221 }, { 222, 222, 222 }, { 222, 231, 223 }, + { 222, 239, 224 }, { 231, 189, 225 }, { 222, 247, 226 }, { 222, 255, 227 }, { 247, 115, 228 }, { 231, 214, 229 }, { 231, 222, 230 }, { 231, 231, 231 }, + { 231, 239, 232 }, { 231, 247, 233 }, { 231, 255, 234 }, { 239, 214, 235 }, { 255, 123, 236 }, { 239, 222, 237 }, { 239, 231, 238 }, { 239, 239, 239 }, + { 239, 247, 240 }, { 239, 255, 241 }, { 247, 214, 242 }, { 247, 222, 243 }, { 247, 222, 243 }, { 247, 231, 245 }, { 247, 239, 246 }, { 247, 247, 247 }, + { 247, 255, 248 }, { 255, 214, 249 }, { 255, 222, 250 }, { 255, 222, 250 }, { 255, 231, 252 }, { 255, 239, 253 }, { 255, 247, 254 }, { 255, 255, 255 }, + } +}; + +Table g_mode4_rgb_high_i2= +{ + 2, + 0, + { + { 0, 0, 0 }, { 0, 0, 0 }, { 0, 8, 2 }, { 0, 8, 2 }, { 0, 16, 5 }, { 0, 16, 5 }, { 8, 0, 6 }, { 0, 24, 7 }, + { 8, 8, 8 }, { 0, 33, 9 }, { 8, 16, 10 }, { 0, 41, 12 }, { 0, 41, 12 }, { 8, 24, 13 }, { 0, 49, 14 }, { 8, 33, 15 }, + { 0, 57, 16 }, { 8, 41, 17 }, { 16, 24, 18 }, { 0, 66, 19 }, { 8, 49, 20 }, { 0, 74, 21 }, { 8, 57, 22 }, { 0, 82, 23 }, + { 8, 66, 24 }, { 0, 90, 25 }, { 33, 8, 26 }, { 8, 74, 27 }, { 0, 99, 28 }, { 8, 82, 29 }, { 0, 107, 30 }, { 8, 90, 31 }, + { 0, 115, 32 }, { 24, 57, 33 }, { 8, 99, 34 }, { 0, 123, 35 }, { 8, 107, 36 }, { 0, 132, 37 }, { 8, 115, 38 }, { 0, 140, 39 }, + { 8, 123, 40 }, { 41, 41, 41 }, { 0, 148, 42 }, { 8, 132, 43 }, { 0, 156, 44 }, { 8, 140, 45 }, { 0, 165, 46 }, { 8, 148, 47 }, + { 41, 66, 48 }, { 0, 173, 49 }, { 8, 156, 50 }, { 0, 181, 51 }, { 8, 165, 52 }, { 0, 189, 53 }, { 8, 173, 54 }, { 16, 156, 55 }, + { 0, 198, 56 }, { 8, 181, 57 }, { 0, 206, 58 }, { 8, 189, 59 }, { 0, 214, 60 }, { 8, 198, 61 }, { 0, 222, 62 }, { 33, 140, 63 }, + { 8, 206, 64 }, { 0, 231, 65 }, { 8, 214, 66 }, { 0, 239, 67 }, { 8, 222, 68 }, { 0, 247, 69 }, { 24, 189, 70 }, { 8, 231, 71 }, + { 0, 255, 72 }, { 8, 239, 73 }, { 16, 222, 74 }, { 8, 247, 75 }, { 16, 231, 76 }, { 8, 255, 77 }, { 41, 173, 78 }, { 16, 239, 79 }, + { 24, 222, 80 }, { 16, 247, 81 }, { 24, 231, 82 }, { 16, 255, 83 }, { 24, 239, 84 }, { 41, 198, 85 }, { 33, 222, 86 }, { 24, 247, 87 }, + { 49, 189, 88 }, { 24, 255, 89 }, { 41, 214, 90 }, { 33, 239, 91 }, { 41, 222, 92 }, { 33, 247, 93 }, { 41, 231, 94 }, { 33, 255, 95 }, + { 66, 173, 96 }, { 41, 239, 97 }, { 49, 222, 98 }, { 41, 247, 99 }, { 49, 231, 100 }, { 41, 255, 101 }, { 49, 239, 102 }, { 57, 222, 103 }, + { 74, 181, 104 }, { 49, 247, 105 }, { 57, 231, 106 }, { 49, 255, 107 }, { 57, 239, 108 }, { 74, 198, 109 }, { 57, 247, 110 }, { 74, 206, 111 }, + { 66, 231, 112 }, { 57, 255, 113 }, { 107, 132, 114 }, { 66, 239, 115 }, { 74, 222, 116 }, { 66, 247, 117 }, { 74, 231, 118 }, { 66, 255, 119 }, + { 74, 239, 120 }, { 82, 222, 121 }, { 99, 181, 122 }, { 74, 247, 123 }, { 82, 231, 124 }, { 74, 255, 125 }, { 82, 239, 126 }, { 90, 222, 127 }, + { 82, 247, 128 }, { 99, 206, 129 }, { 90, 231, 130 }, { 82, 255, 131 }, { 90, 239, 132 }, { 107, 198, 133 }, { 90, 247, 134 }, { 107, 206, 135 }, + { 90, 255, 136 }, { 107, 214, 137 }, { 99, 239, 138 }, { 107, 222, 139 }, { 140, 140, 140 }, { 99, 247, 141 }, { 107, 231, 142 }, { 99, 255, 143 }, + { 107, 239, 144 }, { 115, 222, 145 }, { 107, 247, 146 }, { 140, 165, 147 }, { 115, 231, 148 }, { 107, 255, 149 }, { 115, 239, 150 }, { 123, 222, 151 }, + { 115, 247, 152 }, { 123, 231, 153 }, { 115, 255, 154 }, { 132, 214, 155 }, { 123, 239, 156 }, { 132, 222, 157 }, { 123, 247, 158 }, { 140, 206, 159 }, + { 123, 255, 160 }, { 140, 214, 161 }, { 132, 239, 162 }, { 140, 222, 163 }, { 132, 247, 164 }, { 156, 189, 165 }, { 140, 231, 166 }, { 132, 255, 167 }, + { 140, 239, 168 }, { 148, 222, 169 }, { 140, 247, 170 }, { 148, 231, 171 }, { 140, 255, 172 }, { 173, 173, 173 }, { 148, 239, 174 }, { 156, 222, 175 }, + { 148, 247, 176 }, { 156, 231, 177 }, { 148, 255, 178 }, { 156, 239, 179 }, { 173, 198, 180 }, { 165, 222, 181 }, { 156, 247, 182 }, { 181, 189, 183 }, + { 156, 255, 184 }, { 173, 214, 185 }, { 165, 239, 186 }, { 173, 222, 187 }, { 165, 247, 188 }, { 173, 231, 189 }, { 165, 255, 190 }, { 198, 173, 191 }, + { 173, 239, 192 }, { 181, 222, 193 }, { 173, 247, 194 }, { 181, 231, 195 }, { 173, 255, 196 }, { 181, 239, 197 }, { 189, 222, 198 }, { 206, 181, 199 }, + { 181, 247, 200 }, { 189, 231, 201 }, { 181, 255, 202 }, { 189, 239, 203 }, { 206, 198, 204 }, { 189, 247, 205 }, { 206, 206, 206 }, { 198, 231, 207 }, + { 189, 255, 208 }, { 239, 132, 209 }, { 198, 239, 210 }, { 206, 222, 211 }, { 198, 247, 212 }, { 206, 231, 213 }, { 198, 255, 214 }, { 206, 239, 215 }, + { 214, 222, 216 }, { 231, 181, 217 }, { 206, 247, 218 }, { 214, 231, 219 }, { 206, 255, 220 }, { 214, 239, 221 }, { 222, 222, 222 }, { 214, 247, 223 }, + { 231, 206, 224 }, { 222, 231, 225 }, { 214, 255, 226 }, { 222, 239, 227 }, { 231, 222, 228 }, { 222, 247, 229 }, { 239, 206, 230 }, { 222, 255, 231 }, + { 239, 214, 232 }, { 231, 239, 233 }, { 239, 222, 234 }, { 247, 206, 235 }, { 231, 247, 236 }, { 239, 231, 237 }, { 231, 255, 238 }, { 239, 239, 239 }, + { 247, 222, 240 }, { 239, 247, 241 }, { 239, 247, 241 }, { 247, 231, 243 }, { 239, 255, 244 }, { 247, 239, 245 }, { 255, 222, 246 }, { 247, 247, 247 }, + { 255, 231, 248 }, { 247, 255, 249 }, { 247, 255, 249 }, { 255, 239, 251 }, { 255, 239, 251 }, { 255, 247, 253 }, { 255, 247, 253 }, { 255, 255, 255 }, + } +}; + +Table g_mode4_rgb_high_i3= +{ + 3, + 0, + { + { 0, 0, 0 }, { 0, 0, 0 }, { 0, 8, 3 }, { 0, 8, 3 }, { 0, 8, 3 }, { 8, 0, 5 }, { 0, 16, 7 }, { 0, 16, 7 }, + { 8, 8, 8 }, { 16, 0, 9 }, { 0, 24, 10 }, { 8, 16, 11 }, { 8, 16, 11 }, { 16, 8, 13 }, { 0, 33, 14 }, { 8, 24, 15 }, + { 16, 16, 16 }, { 0, 41, 17 }, { 0, 41, 17 }, { 8, 33, 19 }, { 0, 49, 21 }, { 0, 49, 21 }, { 8, 41, 22 }, { 16, 33, 23 }, + { 0, 57, 24 }, { 8, 49, 25 }, { 33, 16, 26 }, { 16, 41, 27 }, { 0, 66, 28 }, { 8, 57, 29 }, { 16, 49, 30 }, { 0, 74, 31 }, + { 8, 66, 32 }, { 16, 57, 33 }, { 41, 24, 34 }, { 0, 82, 35 }, { 8, 74, 36 }, { 16, 66, 37 }, { 0, 90, 38 }, { 8, 82, 39 }, + { 16, 74, 40 }, { 41, 41, 41 }, { 0, 99, 42 }, { 8, 90, 43 }, { 16, 82, 44 }, { 0, 107, 45 }, { 8, 99, 46 }, { 16, 90, 47 }, + { 24, 82, 48 }, { 0, 115, 49 }, { 8, 107, 50 }, { 16, 99, 51 }, { 0, 123, 52 }, { 8, 115, 53 }, { 16, 107, 54 }, { 41, 74, 55 }, + { 0, 132, 56 }, { 8, 123, 57 }, { 16, 115, 58 }, { 0, 140, 59 }, { 8, 132, 60 }, { 16, 123, 61 }, { 0, 148, 62 }, { 49, 82, 63 }, + { 8, 140, 64 }, { 16, 132, 65 }, { 0, 156, 66 }, { 8, 148, 67 }, { 16, 140, 68 }, { 41, 107, 69 }, { 0, 165, 70 }, { 33, 123, 71 }, + { 16, 148, 72 }, { 0, 173, 73 }, { 8, 165, 74 }, { 16, 156, 75 }, { 0, 181, 76 }, { 49, 115, 77 }, { 8, 173, 78 }, { 16, 165, 79 }, + { 0, 189, 80 }, { 8, 181, 81 }, { 16, 173, 82 }, { 24, 165, 83 }, { 0, 198, 84 }, { 33, 156, 85 }, { 16, 181, 86 }, { 0, 206, 87 }, + { 8, 198, 88 }, { 16, 189, 89 }, { 0, 214, 90 }, { 49, 148, 91 }, { 8, 206, 92 }, { 16, 198, 93 }, { 0, 222, 94 }, { 8, 214, 95 }, + { 16, 206, 96 }, { 0, 231, 97 }, { 8, 222, 98 }, { 33, 189, 99 }, { 16, 214, 100 }, { 0, 239, 101 }, { 8, 231, 102 }, { 16, 222, 103 }, + { 0, 247, 104 }, { 8, 239, 105 }, { 33, 206, 106 }, { 16, 231, 107 }, { 0, 255, 108 }, { 8, 247, 109 }, { 16, 239, 110 }, { 24, 231, 111 }, + { 8, 255, 112 }, { 16, 247, 113 }, { 41, 214, 114 }, { 24, 239, 115 }, { 57, 198, 116 }, { 16, 255, 117 }, { 24, 247, 118 }, { 49, 214, 119 }, + { 33, 239, 120 }, { 24, 255, 121 }, { 49, 222, 122 }, { 33, 247, 123 }, { 82, 181, 124 }, { 41, 239, 125 }, { 49, 231, 126 }, { 33, 255, 127 }, + { 41, 247, 128 }, { 49, 239, 129 }, { 57, 231, 130 }, { 41, 255, 131 }, { 66, 222, 132 }, { 49, 247, 133 }, { 57, 239, 134 }, { 107, 173, 135 }, + { 49, 255, 136 }, { 57, 247, 137 }, { 82, 214, 138 }, { 66, 239, 139 }, { 74, 231, 140 }, { 57, 255, 141 }, { 66, 247, 142 }, { 115, 181, 143 }, + { 74, 239, 144 }, { 82, 231, 145 }, { 66, 255, 146 }, { 74, 247, 147 }, { 82, 239, 148 }, { 90, 231, 149 }, { 74, 255, 150 }, { 99, 222, 151 }, + { 82, 247, 152 }, { 90, 239, 153 }, { 140, 173, 154 }, { 82, 255, 155 }, { 90, 247, 156 }, { 115, 214, 157 }, { 99, 239, 158 }, { 107, 231, 159 }, + { 90, 255, 160 }, { 99, 247, 161 }, { 148, 181, 162 }, { 107, 239, 163 }, { 115, 231, 164 }, { 99, 255, 165 }, { 107, 247, 166 }, { 115, 239, 167 }, + { 140, 206, 168 }, { 107, 255, 169 }, { 132, 222, 170 }, { 115, 247, 171 }, { 123, 239, 172 }, { 173, 173, 173 }, { 115, 255, 174 }, { 123, 247, 175 }, + { 148, 214, 176 }, { 132, 239, 177 }, { 140, 231, 178 }, { 123, 255, 179 }, { 156, 214, 180 }, { 132, 247, 181 }, { 140, 239, 182 }, { 148, 231, 183 }, + { 132, 255, 184 }, { 140, 247, 185 }, { 148, 239, 186 }, { 173, 206, 187 }, { 156, 231, 188 }, { 140, 255, 189 }, { 148, 247, 190 }, { 156, 239, 191 }, + { 181, 206, 192 }, { 148, 255, 193 }, { 156, 247, 194 }, { 181, 214, 195 }, { 165, 239, 196 }, { 173, 231, 197 }, { 156, 255, 198 }, { 206, 189, 199 }, + { 165, 247, 200 }, { 173, 239, 201 }, { 181, 231, 202 }, { 165, 255, 203 }, { 173, 247, 204 }, { 181, 239, 205 }, { 206, 206, 206 }, { 189, 231, 207 }, + { 173, 255, 208 }, { 181, 247, 209 }, { 189, 239, 210 }, { 214, 206, 211 }, { 181, 255, 212 }, { 189, 247, 213 }, { 214, 214, 214 }, { 198, 239, 215 }, + { 247, 173, 216 }, { 189, 255, 217 }, { 239, 189, 218 }, { 198, 247, 219 }, { 206, 239, 220 }, { 214, 231, 221 }, { 198, 255, 222 }, { 206, 247, 223 }, + { 231, 214, 224 }, { 214, 239, 225 }, { 222, 231, 226 }, { 206, 255, 227 }, { 214, 247, 228 }, { 222, 239, 229 }, { 247, 206, 230 }, { 214, 255, 231 }, + { 239, 222, 232 }, { 222, 247, 233 }, { 231, 239, 234 }, { 222, 255, 236 }, { 222, 255, 236 }, { 222, 255, 236 }, { 231, 247, 238 }, { 239, 239, 239 }, + { 247, 231, 240 }, { 231, 255, 241 }, { 239, 247, 242 }, { 239, 247, 242 }, { 247, 239, 244 }, { 255, 231, 245 }, { 239, 255, 246 }, { 247, 247, 247 }, + { 255, 239, 248 }, { 247, 255, 250 }, { 247, 255, 250 }, { 247, 255, 250 }, { 255, 247, 252 }, { 255, 247, 252 }, { 255, 255, 255 }, { 255, 255, 255 }, + } +}; + +Table g_mode4_a_low= +{ + 1, + 0, + { + { 0, 0, 0 }, { 0, 4, 1 }, { 0, 4, 1 }, { 0, 8, 3 }, { 0, 12, 4 }, { 0, 16, 5 }, { 0, 16, 5 }, { 0, 20, 7 }, + { 0, 24, 8 }, { 0, 28, 9 }, { 0, 28, 9 }, { 0, 32, 11 }, { 0, 36, 12 }, { 0, 40, 13 }, { 0, 44, 14 }, { 4, 36, 15 }, + { 0, 48, 16 }, { 0, 52, 17 }, { 0, 56, 18 }, { 8, 40, 19 }, { 0, 60, 20 }, { 0, 65, 21 }, { 4, 60, 22 }, { 0, 69, 23 }, + { 0, 73, 24 }, { 0, 77, 25 }, { 12, 56, 26 }, { 0, 81, 27 }, { 0, 85, 28 }, { 0, 89, 29 }, { 16, 60, 30 }, { 0, 93, 31 }, + { 0, 97, 32 }, { 0, 101, 33 }, { 0, 105, 34 }, { 4, 97, 35 }, { 0, 109, 36 }, { 0, 113, 37 }, { 0, 117, 38 }, { 8, 101, 39 }, + { 0, 121, 40 }, { 0, 125, 41 }, { 4, 121, 42 }, { 0, 130, 43 }, { 0, 134, 44 }, { 0, 138, 45 }, { 8, 125, 46 }, { 0, 142, 47 }, + { 0, 146, 48 }, { 0, 150, 49 }, { 16, 121, 50 }, { 0, 154, 51 }, { 0, 158, 52 }, { 0, 162, 53 }, { 0, 166, 54 }, { 4, 158, 55 }, + { 0, 170, 56 }, { 0, 174, 57 }, { 0, 178, 58 }, { 8, 162, 59 }, { 0, 182, 60 }, { 0, 186, 61 }, { 0, 190, 62 }, { 12, 166, 63 }, + { 0, 195, 64 }, { 0, 199, 65 }, { 8, 186, 66 }, { 0, 203, 67 }, { 0, 207, 68 }, { 0, 211, 69 }, { 12, 190, 70 }, { 0, 215, 71 }, + { 0, 219, 72 }, { 0, 223, 73 }, { 0, 227, 74 }, { 4, 219, 75 }, { 0, 231, 76 }, { 0, 235, 77 }, { 0, 239, 78 }, { 8, 223, 79 }, + { 0, 243, 80 }, { 0, 247, 81 }, { 0, 251, 82 }, { 12, 227, 83 }, { 0, 255, 84 }, { 4, 251, 85 }, { 4, 255, 86 }, { 16, 231, 87 }, + { 8, 251, 88 }, { 8, 255, 89 }, { 12, 251, 90 }, { 20, 235, 91 }, { 12, 255, 92 }, { 16, 251, 93 }, { 16, 255, 94 }, { 24, 239, 95 }, + { 20, 251, 96 }, { 20, 255, 97 }, { 24, 251, 98 }, { 28, 243, 99 }, { 24, 255, 100 }, { 28, 251, 101 }, { 28, 255, 102 }, { 32, 247, 103 }, + { 32, 251, 104 }, { 32, 255, 105 }, { 56, 207, 106 }, { 36, 251, 107 }, { 36, 255, 108 }, { 40, 251, 109 }, { 60, 211, 110 }, { 40, 255, 111 }, + { 44, 251, 112 }, { 44, 255, 113 }, { 65, 215, 114 }, { 48, 251, 115 }, { 48, 255, 116 }, { 52, 251, 117 }, { 65, 227, 118 }, { 52, 255, 119 }, + { 56, 251, 120 }, { 56, 255, 121 }, { 65, 239, 122 }, { 60, 251, 123 }, { 60, 255, 124 }, { 65, 247, 125 }, { 65, 251, 126 }, { 65, 255, 127 }, + { 77, 231, 128 }, { 69, 251, 129 }, { 69, 255, 130 }, { 73, 251, 131 }, { 81, 235, 132 }, { 73, 255, 133 }, { 77, 251, 134 }, { 77, 255, 135 }, + { 85, 239, 136 }, { 81, 251, 137 }, { 81, 255, 138 }, { 85, 251, 139 }, { 89, 243, 140 }, { 85, 255, 141 }, { 89, 251, 142 }, { 89, 255, 143 }, + { 93, 247, 144 }, { 93, 251, 145 }, { 93, 255, 146 }, { 117, 207, 147 }, { 97, 251, 148 }, { 97, 255, 149 }, { 101, 251, 150 }, { 121, 211, 151 }, + { 101, 255, 152 }, { 105, 251, 153 }, { 105, 255, 154 }, { 125, 215, 155 }, { 109, 251, 156 }, { 109, 255, 157 }, { 113, 251, 158 }, { 130, 219, 159 }, + { 113, 255, 160 }, { 117, 251, 161 }, { 117, 255, 162 }, { 130, 231, 163 }, { 121, 251, 164 }, { 121, 255, 165 }, { 125, 251, 166 }, { 130, 243, 167 }, + { 125, 255, 168 }, { 138, 231, 169 }, { 130, 251, 170 }, { 130, 255, 171 }, { 134, 251, 172 }, { 142, 235, 173 }, { 134, 255, 174 }, { 138, 251, 175 }, + { 138, 255, 176 }, { 146, 239, 177 }, { 142, 251, 178 }, { 142, 255, 179 }, { 146, 251, 180 }, { 150, 243, 181 }, { 146, 255, 182 }, { 150, 251, 183 }, + { 150, 255, 184 }, { 154, 247, 185 }, { 154, 251, 186 }, { 154, 255, 187 }, { 178, 207, 188 }, { 158, 251, 189 }, { 158, 255, 190 }, { 162, 251, 191 }, + { 182, 211, 192 }, { 162, 255, 193 }, { 166, 251, 194 }, { 166, 255, 195 }, { 186, 215, 196 }, { 170, 251, 197 }, { 170, 255, 198 }, { 174, 251, 199 }, + { 190, 219, 200 }, { 174, 255, 201 }, { 178, 251, 202 }, { 178, 255, 203 }, { 195, 223, 204 }, { 182, 251, 205 }, { 182, 255, 206 }, { 186, 251, 207 }, + { 195, 235, 208 }, { 186, 255, 209 }, { 190, 251, 210 }, { 190, 255, 211 }, { 195, 247, 212 }, { 195, 251, 213 }, { 203, 235, 214 }, { 195, 255, 215 }, + { 199, 251, 216 }, { 199, 255, 217 }, { 207, 239, 218 }, { 203, 251, 219 }, { 203, 255, 220 }, { 207, 251, 221 }, { 211, 243, 222 }, { 207, 255, 223 }, + { 211, 251, 224 }, { 211, 255, 225 }, { 215, 247, 226 }, { 215, 251, 227 }, { 215, 255, 228 }, { 239, 207, 229 }, { 219, 251, 230 }, { 219, 255, 231 }, + { 223, 251, 232 }, { 243, 211, 233 }, { 223, 255, 234 }, { 227, 251, 235 }, { 227, 255, 236 }, { 247, 215, 237 }, { 231, 251, 238 }, { 231, 255, 239 }, + { 235, 251, 240 }, { 251, 219, 241 }, { 235, 255, 242 }, { 239, 251, 243 }, { 239, 255, 244 }, { 255, 223, 245 }, { 243, 251, 246 }, { 243, 255, 247 }, + { 247, 251, 248 }, { 247, 251, 248 }, { 247, 255, 250 }, { 251, 251, 251 }, { 251, 255, 252 }, { 251, 255, 252 }, { 255, 251, 254 }, { 255, 255, 255 }, + } +}; + +Table g_mode4_a_high_i1= +{ + 1, + 0, + { + { 0, 0, 0 }, { 0, 4, 1 }, { 0, 12, 2 }, { 0, 20, 3 }, { 0, 28, 4 }, { 0, 32, 5 }, { 0, 40, 6 }, { 0, 48, 7 }, + { 0, 56, 8 }, { 0, 65, 9 }, { 0, 69, 10 }, { 0, 77, 11 }, { 0, 85, 12 }, { 0, 89, 13 }, { 0, 97, 14 }, { 0, 105, 15 }, + { 0, 113, 16 }, { 0, 121, 17 }, { 0, 125, 18 }, { 0, 134, 19 }, { 0, 142, 20 }, { 0, 146, 21 }, { 0, 154, 22 }, { 0, 162, 23 }, + { 0, 170, 24 }, { 0, 178, 25 }, { 0, 182, 26 }, { 0, 190, 27 }, { 0, 199, 28 }, { 0, 203, 29 }, { 0, 211, 30 }, { 0, 219, 31 }, + { 0, 227, 32 }, { 0, 235, 33 }, { 0, 239, 34 }, { 0, 247, 35 }, { 0, 255, 36 }, { 4, 239, 37 }, { 4, 243, 38 }, { 4, 251, 39 }, + { 8, 235, 40 }, { 8, 243, 41 }, { 8, 247, 42 }, { 8, 255, 43 }, { 12, 239, 44 }, { 12, 247, 45 }, { 12, 251, 46 }, { 16, 235, 47 }, + { 16, 243, 48 }, { 16, 251, 49 }, { 16, 255, 50 }, { 20, 239, 51 }, { 20, 247, 52 }, { 20, 255, 53 }, { 24, 235, 54 }, { 24, 243, 55 }, + { 24, 251, 56 }, { 28, 231, 57 }, { 28, 239, 58 }, { 28, 247, 59 }, { 28, 255, 60 }, { 32, 235, 61 }, { 32, 243, 62 }, { 32, 251, 63 }, + { 36, 235, 64 }, { 36, 239, 65 }, { 36, 247, 66 }, { 36, 255, 67 }, { 40, 239, 68 }, { 40, 243, 69 }, { 40, 251, 70 }, { 44, 235, 71 }, + { 44, 243, 72 }, { 44, 247, 73 }, { 44, 255, 74 }, { 48, 239, 75 }, { 48, 247, 76 }, { 48, 251, 77 }, { 52, 235, 78 }, { 52, 243, 79 }, + { 52, 251, 80 }, { 52, 255, 81 }, { 56, 239, 82 }, { 56, 247, 83 }, { 56, 255, 84 }, { 60, 235, 85 }, { 60, 243, 86 }, { 60, 251, 87 }, + { 65, 227, 88 }, { 65, 235, 89 }, { 65, 243, 90 }, { 65, 247, 91 }, { 65, 255, 92 }, { 69, 239, 93 }, { 69, 247, 94 }, { 69, 251, 95 }, + { 73, 235, 96 }, { 73, 243, 97 }, { 73, 251, 98 }, { 73, 255, 99 }, { 77, 239, 100 }, { 77, 247, 101 }, { 77, 255, 102 }, { 81, 235, 103 }, + { 81, 243, 104 }, { 81, 251, 105 }, { 85, 231, 106 }, { 85, 239, 107 }, { 85, 247, 108 }, { 85, 255, 109 }, { 89, 235, 110 }, { 89, 243, 111 }, + { 89, 251, 112 }, { 93, 235, 113 }, { 93, 239, 114 }, { 93, 247, 115 }, { 93, 255, 116 }, { 97, 239, 117 }, { 97, 243, 118 }, { 97, 251, 119 }, + { 101, 235, 120 }, { 101, 243, 121 }, { 101, 247, 122 }, { 101, 255, 123 }, { 105, 239, 124 }, { 105, 247, 125 }, { 105, 251, 126 }, { 109, 235, 127 }, + { 109, 243, 128 }, { 109, 251, 129 }, { 109, 255, 130 }, { 113, 239, 131 }, { 113, 247, 132 }, { 113, 255, 133 }, { 117, 235, 134 }, { 117, 243, 135 }, + { 117, 251, 136 }, { 121, 235, 137 }, { 121, 239, 138 }, { 121, 247, 139 }, { 121, 255, 140 }, { 125, 239, 141 }, { 125, 243, 142 }, { 125, 251, 143 }, + { 130, 227, 144 }, { 130, 235, 145 }, { 130, 243, 146 }, { 130, 251, 147 }, { 130, 255, 148 }, { 134, 239, 149 }, { 134, 247, 150 }, { 134, 255, 151 }, + { 138, 235, 152 }, { 138, 243, 153 }, { 138, 251, 154 }, { 142, 231, 155 }, { 142, 239, 156 }, { 142, 247, 157 }, { 142, 255, 158 }, { 146, 235, 159 }, + { 146, 243, 160 }, { 146, 251, 161 }, { 150, 235, 162 }, { 150, 239, 163 }, { 150, 247, 164 }, { 150, 255, 165 }, { 154, 239, 166 }, { 154, 243, 167 }, + { 154, 251, 168 }, { 158, 235, 169 }, { 158, 243, 170 }, { 158, 247, 171 }, { 158, 255, 172 }, { 162, 239, 173 }, { 162, 247, 174 }, { 162, 251, 175 }, + { 166, 235, 176 }, { 166, 243, 177 }, { 166, 251, 178 }, { 166, 255, 179 }, { 170, 239, 180 }, { 170, 247, 181 }, { 170, 255, 182 }, { 174, 235, 183 }, + { 174, 243, 184 }, { 174, 251, 185 }, { 178, 235, 186 }, { 178, 239, 187 }, { 178, 247, 188 }, { 178, 255, 189 }, { 182, 239, 190 }, { 182, 243, 191 }, + { 182, 251, 192 }, { 186, 235, 193 }, { 186, 243, 194 }, { 186, 247, 195 }, { 186, 255, 196 }, { 190, 239, 197 }, { 190, 247, 198 }, { 190, 251, 199 }, + { 195, 227, 200 }, { 195, 235, 201 }, { 195, 243, 202 }, { 195, 251, 203 }, { 199, 231, 204 }, { 199, 239, 205 }, { 199, 247, 206 }, { 199, 255, 207 }, + { 203, 235, 208 }, { 203, 243, 209 }, { 203, 251, 210 }, { 207, 235, 211 }, { 207, 239, 212 }, { 207, 247, 213 }, { 207, 255, 214 }, { 211, 239, 215 }, + { 211, 243, 216 }, { 211, 251, 217 }, { 215, 235, 218 }, { 215, 243, 219 }, { 215, 247, 220 }, { 215, 255, 221 }, { 219, 239, 222 }, { 219, 247, 223 }, + { 219, 251, 224 }, { 223, 235, 225 }, { 223, 243, 226 }, { 223, 251, 227 }, { 223, 255, 228 }, { 227, 239, 229 }, { 227, 247, 230 }, { 227, 255, 231 }, + { 231, 235, 232 }, { 231, 243, 233 }, { 231, 251, 234 }, { 235, 235, 235 }, { 235, 239, 236 }, { 235, 247, 237 }, { 235, 255, 238 }, { 239, 239, 239 }, + { 239, 243, 240 }, { 239, 251, 241 }, { 243, 235, 242 }, { 243, 243, 243 }, { 243, 247, 244 }, { 243, 255, 245 }, { 247, 239, 246 }, { 247, 247, 247 }, + { 247, 251, 248 }, { 251, 235, 249 }, { 251, 243, 250 }, { 251, 251, 251 }, { 251, 255, 252 }, { 255, 239, 253 }, { 255, 247, 254 }, { 255, 255, 255 }, + } +}; + +Table g_mode4_a_high_i2= +{ + 2, + 0, + { + { 0, 0, 0 }, { 0, 4, 1 }, { 0, 8, 2 }, { 0, 12, 3 }, { 4, 4, 4 }, { 0, 16, 5 }, { 0, 20, 6 }, { 0, 24, 7 }, + { 0, 28, 8 }, { 0, 32, 9 }, { 0, 36, 10 }, { 0, 40, 11 }, { 0, 44, 12 }, { 4, 36, 13 }, { 0, 48, 14 }, { 0, 52, 15 }, + { 0, 56, 16 }, { 0, 60, 17 }, { 0, 65, 18 }, { 0, 69, 19 }, { 4, 60, 20 }, { 0, 73, 21 }, { 0, 77, 22 }, { 0, 81, 23 }, + { 0, 85, 24 }, { 0, 89, 25 }, { 0, 93, 26 }, { 0, 97, 27 }, { 0, 101, 28 }, { 4, 93, 29 }, { 0, 105, 30 }, { 0, 109, 31 }, + { 0, 113, 32 }, { 0, 117, 33 }, { 0, 121, 34 }, { 0, 125, 35 }, { 4, 117, 36 }, { 0, 130, 37 }, { 0, 134, 38 }, { 0, 138, 39 }, + { 0, 142, 40 }, { 0, 146, 41 }, { 0, 150, 42 }, { 0, 154, 43 }, { 0, 158, 44 }, { 4, 150, 45 }, { 0, 162, 46 }, { 0, 166, 47 }, + { 0, 170, 48 }, { 0, 174, 49 }, { 0, 178, 50 }, { 0, 182, 51 }, { 0, 186, 52 }, { 0, 190, 53 }, { 4, 182, 54 }, { 0, 195, 55 }, + { 0, 199, 56 }, { 0, 203, 57 }, { 0, 207, 58 }, { 0, 211, 59 }, { 0, 215, 60 }, { 4, 207, 61 }, { 0, 219, 62 }, { 0, 223, 63 }, + { 0, 227, 64 }, { 0, 231, 65 }, { 0, 235, 66 }, { 0, 239, 67 }, { 0, 243, 68 }, { 0, 247, 69 }, { 4, 239, 70 }, { 0, 251, 71 }, + { 0, 255, 72 }, { 4, 251, 73 }, { 8, 243, 74 }, { 4, 255, 75 }, { 8, 251, 76 }, { 8, 255, 77 }, { 12, 247, 78 }, { 12, 251, 79 }, + { 12, 255, 80 }, { 16, 247, 81 }, { 16, 251, 82 }, { 16, 255, 83 }, { 20, 247, 84 }, { 20, 251, 85 }, { 20, 255, 86 }, { 24, 247, 87 }, + { 24, 251, 88 }, { 24, 255, 89 }, { 28, 247, 90 }, { 28, 251, 91 }, { 28, 255, 92 }, { 36, 239, 93 }, { 32, 251, 94 }, { 32, 255, 95 }, + { 36, 251, 96 }, { 40, 243, 97 }, { 36, 255, 98 }, { 40, 251, 99 }, { 40, 255, 100 }, { 44, 247, 101 }, { 44, 251, 102 }, { 44, 255, 103 }, + { 48, 247, 104 }, { 48, 251, 105 }, { 48, 255, 106 }, { 52, 247, 107 }, { 52, 251, 108 }, { 52, 255, 109 }, { 56, 247, 110 }, { 56, 251, 111 }, + { 56, 255, 112 }, { 60, 247, 113 }, { 60, 251, 114 }, { 60, 255, 115 }, { 65, 247, 116 }, { 65, 251, 117 }, { 65, 255, 118 }, { 69, 247, 119 }, + { 69, 251, 120 }, { 69, 255, 121 }, { 73, 247, 122 }, { 73, 251, 123 }, { 73, 255, 124 }, { 77, 247, 125 }, { 77, 251, 126 }, { 77, 255, 127 }, + { 81, 247, 128 }, { 81, 251, 129 }, { 81, 255, 130 }, { 85, 247, 131 }, { 85, 251, 132 }, { 85, 255, 133 }, { 93, 239, 134 }, { 89, 251, 135 }, + { 89, 255, 136 }, { 93, 251, 137 }, { 97, 243, 138 }, { 93, 255, 139 }, { 97, 251, 140 }, { 97, 255, 141 }, { 101, 247, 142 }, { 101, 251, 143 }, + { 101, 255, 144 }, { 105, 247, 145 }, { 105, 251, 146 }, { 105, 255, 147 }, { 109, 247, 148 }, { 109, 251, 149 }, { 109, 255, 150 }, { 113, 247, 151 }, + { 113, 251, 152 }, { 113, 255, 153 }, { 117, 247, 154 }, { 117, 251, 155 }, { 117, 255, 156 }, { 125, 239, 157 }, { 121, 251, 158 }, { 121, 255, 159 }, + { 125, 251, 160 }, { 130, 239, 161 }, { 125, 255, 162 }, { 130, 247, 163 }, { 130, 251, 164 }, { 130, 255, 165 }, { 134, 247, 166 }, { 134, 251, 167 }, + { 134, 255, 168 }, { 138, 247, 169 }, { 138, 251, 170 }, { 138, 255, 171 }, { 142, 247, 172 }, { 142, 251, 173 }, { 142, 255, 174 }, { 150, 239, 175 }, + { 146, 251, 176 }, { 146, 255, 177 }, { 150, 251, 178 }, { 154, 243, 179 }, { 150, 255, 180 }, { 154, 251, 181 }, { 154, 255, 182 }, { 158, 247, 183 }, + { 158, 251, 184 }, { 158, 255, 185 }, { 162, 247, 186 }, { 162, 251, 187 }, { 162, 255, 188 }, { 166, 247, 189 }, { 166, 251, 190 }, { 166, 255, 191 }, + { 170, 247, 192 }, { 170, 251, 193 }, { 170, 255, 194 }, { 174, 247, 195 }, { 174, 251, 196 }, { 174, 255, 197 }, { 182, 239, 198 }, { 178, 251, 199 }, + { 178, 255, 200 }, { 182, 251, 201 }, { 186, 243, 202 }, { 182, 255, 203 }, { 186, 251, 204 }, { 186, 255, 205 }, { 190, 247, 206 }, { 190, 251, 207 }, + { 190, 255, 208 }, { 195, 243, 209 }, { 195, 247, 210 }, { 195, 251, 211 }, { 195, 255, 212 }, { 199, 247, 213 }, { 199, 251, 214 }, { 199, 255, 215 }, + { 207, 239, 216 }, { 203, 251, 217 }, { 203, 255, 218 }, { 207, 251, 219 }, { 211, 243, 220 }, { 207, 255, 221 }, { 211, 251, 222 }, { 211, 255, 223 }, + { 215, 247, 224 }, { 215, 251, 225 }, { 215, 255, 226 }, { 219, 247, 227 }, { 219, 251, 228 }, { 219, 255, 229 }, { 223, 247, 230 }, { 223, 251, 231 }, + { 223, 255, 232 }, { 227, 247, 233 }, { 227, 251, 234 }, { 227, 255, 235 }, { 231, 247, 236 }, { 231, 251, 237 }, { 231, 255, 238 }, { 239, 239, 239 }, + { 235, 251, 240 }, { 235, 255, 241 }, { 239, 251, 242 }, { 243, 243, 243 }, { 239, 255, 244 }, { 243, 251, 245 }, { 243, 255, 246 }, { 247, 247, 247 }, + { 247, 251, 248 }, { 247, 255, 249 }, { 251, 247, 250 }, { 251, 251, 251 }, { 251, 255, 252 }, { 255, 247, 253 }, { 255, 251, 254 }, { 255, 255, 255 }, + } +}; + +Table g_mode4_a_high_i3= +{ + 3, + 0, + { + { 0, 0, 0 }, { 0, 0, 0 }, { 0, 4, 2 }, { 0, 8, 3 }, { 4, 4, 4 }, { 0, 12, 5 }, { 4, 8, 6 }, { 0, 16, 7 }, + { 0, 20, 8 }, { 4, 16, 9 }, { 0, 24, 10 }, { 4, 20, 11 }, { 0, 28, 12 }, { 8, 20, 13 }, { 0, 32, 14 }, { 0, 36, 15 }, + { 4, 32, 16 }, { 0, 40, 17 }, { 4, 36, 18 }, { 0, 44, 19 }, { 0, 48, 20 }, { 4, 44, 21 }, { 0, 52, 22 }, { 4, 48, 23 }, + { 0, 56, 24 }, { 0, 60, 25 }, { 4, 56, 26 }, { 0, 65, 27 }, { 4, 60, 28 }, { 0, 69, 29 }, { 4, 65, 30 }, { 0, 73, 31 }, + { 0, 77, 32 }, { 4, 73, 33 }, { 0, 81, 34 }, { 4, 77, 35 }, { 0, 85, 36 }, { 8, 77, 37 }, { 0, 89, 38 }, { 0, 93, 39 }, + { 4, 89, 40 }, { 0, 97, 41 }, { 4, 93, 42 }, { 0, 101, 43 }, { 0, 105, 44 }, { 4, 101, 45 }, { 0, 109, 46 }, { 4, 105, 47 }, + { 0, 113, 48 }, { 0, 117, 49 }, { 4, 113, 50 }, { 0, 121, 51 }, { 4, 117, 52 }, { 0, 125, 53 }, { 8, 117, 54 }, { 0, 130, 55 }, + { 8, 121, 56 }, { 0, 134, 57 }, { 0, 138, 58 }, { 4, 134, 59 }, { 0, 142, 60 }, { 4, 138, 61 }, { 0, 146, 62 }, { 0, 150, 63 }, + { 4, 146, 64 }, { 0, 154, 65 }, { 4, 150, 66 }, { 0, 158, 67 }, { 0, 162, 68 }, { 4, 158, 69 }, { 0, 166, 70 }, { 4, 162, 71 }, + { 0, 170, 72 }, { 0, 174, 73 }, { 4, 170, 74 }, { 0, 178, 75 }, { 4, 174, 76 }, { 0, 182, 77 }, { 0, 186, 78 }, { 4, 182, 79 }, + { 0, 190, 80 }, { 4, 186, 81 }, { 0, 195, 82 }, { 8, 186, 83 }, { 0, 199, 84 }, { 4, 195, 85 }, { 0, 203, 86 }, { 0, 207, 87 }, + { 4, 203, 88 }, { 0, 211, 89 }, { 4, 207, 90 }, { 0, 215, 91 }, { 0, 219, 92 }, { 4, 215, 93 }, { 0, 223, 94 }, { 4, 219, 95 }, + { 0, 227, 96 }, { 0, 231, 97 }, { 4, 227, 98 }, { 0, 235, 99 }, { 4, 231, 100 }, { 0, 239, 101 }, { 8, 231, 102 }, { 0, 243, 103 }, + { 0, 247, 104 }, { 4, 243, 105 }, { 0, 251, 106 }, { 4, 247, 107 }, { 0, 255, 108 }, { 8, 247, 109 }, { 4, 255, 110 }, { 8, 251, 111 }, + { 8, 255, 112 }, { 12, 251, 113 }, { 20, 243, 114 }, { 12, 255, 115 }, { 20, 247, 116 }, { 16, 255, 117 }, { 24, 247, 118 }, { 20, 255, 119 }, + { 24, 251, 120 }, { 24, 255, 121 }, { 28, 251, 122 }, { 32, 247, 123 }, { 28, 255, 124 }, { 36, 247, 125 }, { 32, 255, 126 }, { 36, 251, 127 }, + { 36, 255, 128 }, { 40, 251, 129 }, { 44, 247, 130 }, { 40, 255, 131 }, { 48, 247, 132 }, { 44, 255, 133 }, { 48, 251, 134 }, { 48, 255, 135 }, + { 52, 251, 136 }, { 56, 247, 137 }, { 52, 255, 138 }, { 60, 247, 139 }, { 56, 255, 140 }, { 60, 251, 141 }, { 60, 255, 142 }, { 65, 251, 143 }, + { 69, 247, 144 }, { 65, 255, 145 }, { 69, 251, 146 }, { 69, 255, 147 }, { 73, 251, 148 }, { 77, 247, 149 }, { 73, 255, 150 }, { 81, 247, 151 }, + { 77, 255, 152 }, { 81, 251, 153 }, { 81, 255, 154 }, { 85, 251, 155 }, { 89, 247, 156 }, { 85, 255, 157 }, { 93, 247, 158 }, { 89, 255, 159 }, + { 93, 251, 160 }, { 93, 255, 161 }, { 97, 251, 162 }, { 101, 247, 163 }, { 97, 255, 164 }, { 105, 247, 165 }, { 101, 255, 166 }, { 105, 251, 167 }, + { 105, 255, 168 }, { 109, 251, 169 }, { 113, 247, 170 }, { 109, 255, 171 }, { 117, 247, 172 }, { 113, 255, 173 }, { 117, 251, 174 }, { 117, 255, 175 }, + { 121, 251, 176 }, { 134, 235, 177 }, { 121, 255, 178 }, { 130, 247, 179 }, { 125, 255, 180 }, { 130, 251, 181 }, { 134, 247, 182 }, { 130, 255, 183 }, + { 138, 247, 184 }, { 134, 255, 185 }, { 138, 251, 186 }, { 138, 255, 187 }, { 142, 251, 188 }, { 146, 247, 189 }, { 142, 255, 190 }, { 150, 247, 191 }, + { 146, 255, 192 }, { 150, 251, 193 }, { 150, 255, 194 }, { 154, 251, 195 }, { 158, 247, 196 }, { 154, 255, 197 }, { 162, 247, 198 }, { 158, 255, 199 }, + { 162, 251, 200 }, { 162, 255, 201 }, { 166, 251, 202 }, { 174, 243, 203 }, { 166, 255, 204 }, { 174, 247, 205 }, { 170, 255, 206 }, { 178, 247, 207 }, + { 174, 255, 208 }, { 178, 251, 209 }, { 178, 255, 210 }, { 182, 251, 211 }, { 186, 247, 212 }, { 182, 255, 213 }, { 190, 247, 214 }, { 186, 255, 215 }, + { 190, 251, 216 }, { 190, 255, 217 }, { 199, 243, 218 }, { 195, 251, 219 }, { 195, 255, 220 }, { 199, 251, 221 }, { 203, 247, 222 }, { 199, 255, 223 }, + { 207, 247, 224 }, { 203, 255, 225 }, { 207, 251, 226 }, { 207, 255, 227 }, { 211, 251, 228 }, { 215, 247, 229 }, { 211, 255, 230 }, { 219, 247, 231 }, + { 215, 255, 232 }, { 219, 251, 233 }, { 219, 255, 234 }, { 223, 251, 235 }, { 231, 243, 236 }, { 223, 255, 237 }, { 231, 247, 238 }, { 227, 255, 239 }, + { 235, 247, 240 }, { 231, 255, 241 }, { 235, 251, 242 }, { 235, 255, 243 }, { 239, 251, 244 }, { 243, 247, 245 }, { 239, 255, 246 }, { 247, 247, 247 }, + { 243, 255, 248 }, { 247, 251, 249 }, { 247, 255, 250 }, { 251, 251, 251 }, { 255, 247, 252 }, { 251, 255, 253 }, { 251, 255, 253 }, { 255, 255, 255 }, + } +}; + +Table g_mode5_rgb_low= +{ + 1, + 0, + { + { 0, 0, 0 }, { 0, 2, 1 }, { 0, 6, 2 }, { 0, 8, 3 }, { 0, 12, 4 }, { 0, 14, 5 }, { 0, 18, 6 }, { 0, 20, 7 }, + { 0, 24, 8 }, { 0, 26, 9 }, { 0, 30, 10 }, { 0, 32, 11 }, { 0, 36, 12 }, { 0, 40, 13 }, { 0, 42, 14 }, { 0, 46, 15 }, + { 0, 48, 16 }, { 0, 52, 17 }, { 0, 54, 18 }, { 0, 58, 19 }, { 0, 60, 20 }, { 0, 64, 21 }, { 0, 66, 22 }, { 0, 70, 23 }, + { 0, 72, 24 }, { 0, 76, 25 }, { 0, 78, 26 }, { 0, 82, 27 }, { 0, 84, 28 }, { 0, 88, 29 }, { 0, 90, 30 }, { 0, 94, 31 }, + { 0, 96, 32 }, { 0, 100, 33 }, { 0, 104, 34 }, { 0, 106, 35 }, { 0, 110, 36 }, { 0, 112, 37 }, { 0, 116, 38 }, { 0, 118, 39 }, + { 0, 122, 40 }, { 0, 124, 41 }, { 0, 129, 42 }, { 0, 131, 43 }, { 0, 133, 44 }, { 0, 137, 45 }, { 0, 139, 46 }, { 0, 143, 47 }, + { 0, 145, 48 }, { 0, 149, 49 }, { 0, 151, 50 }, { 0, 155, 51 }, { 0, 157, 52 }, { 0, 161, 53 }, { 0, 165, 54 }, { 0, 167, 55 }, + { 0, 171, 56 }, { 0, 173, 57 }, { 0, 177, 58 }, { 0, 179, 59 }, { 0, 183, 60 }, { 0, 185, 61 }, { 0, 189, 62 }, { 0, 191, 63 }, + { 0, 195, 64 }, { 0, 197, 65 }, { 0, 201, 66 }, { 0, 203, 67 }, { 0, 207, 68 }, { 0, 209, 69 }, { 0, 213, 70 }, { 0, 215, 71 }, + { 0, 219, 72 }, { 0, 221, 73 }, { 0, 225, 74 }, { 0, 229, 75 }, { 0, 231, 76 }, { 0, 235, 77 }, { 0, 237, 78 }, { 0, 241, 79 }, + { 0, 243, 80 }, { 0, 247, 81 }, { 0, 249, 82 }, { 0, 253, 83 }, { 0, 255, 84 }, { 2, 255, 85 }, { 4, 253, 86 }, { 6, 253, 87 }, + { 6, 255, 88 }, { 8, 255, 89 }, { 10, 253, 90 }, { 12, 253, 91 }, { 12, 255, 92 }, { 14, 255, 93 }, { 16, 253, 94 }, { 18, 253, 95 }, + { 18, 255, 96 }, { 20, 255, 97 }, { 22, 253, 98 }, { 24, 253, 99 }, { 24, 255, 100 }, { 26, 255, 101 }, { 28, 253, 102 }, { 30, 251, 103 }, + { 30, 255, 104 }, { 32, 253, 105 }, { 34, 253, 106 }, { 34, 255, 107 }, { 36, 255, 108 }, { 38, 253, 109 }, { 40, 253, 110 }, { 40, 255, 111 }, + { 42, 255, 112 }, { 44, 253, 113 }, { 46, 253, 114 }, { 46, 255, 115 }, { 48, 255, 116 }, { 50, 253, 117 }, { 52, 253, 118 }, { 52, 255, 119 }, + { 54, 255, 120 }, { 56, 253, 121 }, { 58, 253, 122 }, { 58, 255, 123 }, { 60, 255, 124 }, { 62, 253, 125 }, { 64, 253, 126 }, { 64, 255, 127 }, + { 66, 255, 128 }, { 68, 253, 129 }, { 70, 253, 130 }, { 70, 255, 131 }, { 72, 255, 132 }, { 74, 253, 133 }, { 76, 253, 134 }, { 76, 255, 135 }, + { 78, 255, 136 }, { 80, 253, 137 }, { 82, 253, 138 }, { 82, 255, 139 }, { 84, 255, 140 }, { 86, 253, 141 }, { 88, 253, 142 }, { 88, 255, 143 }, + { 90, 255, 144 }, { 92, 253, 145 }, { 94, 251, 146 }, { 94, 255, 147 }, { 96, 253, 148 }, { 98, 253, 149 }, { 98, 255, 150 }, { 100, 255, 151 }, + { 102, 253, 152 }, { 104, 253, 153 }, { 104, 255, 154 }, { 106, 255, 155 }, { 108, 253, 156 }, { 110, 253, 157 }, { 110, 255, 158 }, { 112, 255, 159 }, + { 114, 253, 160 }, { 116, 253, 161 }, { 116, 255, 162 }, { 118, 255, 163 }, { 120, 253, 164 }, { 122, 253, 165 }, { 122, 255, 166 }, { 124, 255, 167 }, + { 126, 253, 168 }, { 129, 251, 169 }, { 129, 253, 170 }, { 131, 253, 171 }, { 131, 255, 172 }, { 133, 255, 173 }, { 135, 253, 174 }, { 137, 253, 175 }, + { 137, 255, 176 }, { 139, 255, 177 }, { 141, 253, 178 }, { 143, 253, 179 }, { 143, 255, 180 }, { 145, 255, 181 }, { 147, 253, 182 }, { 149, 253, 183 }, + { 149, 255, 184 }, { 151, 255, 185 }, { 153, 253, 186 }, { 155, 251, 187 }, { 155, 255, 188 }, { 157, 253, 189 }, { 159, 253, 190 }, { 159, 255, 191 }, + { 161, 255, 192 }, { 163, 253, 193 }, { 165, 253, 194 }, { 165, 255, 195 }, { 167, 255, 196 }, { 169, 253, 197 }, { 171, 253, 198 }, { 171, 255, 199 }, + { 173, 255, 200 }, { 175, 253, 201 }, { 177, 253, 202 }, { 177, 255, 203 }, { 179, 255, 204 }, { 181, 253, 205 }, { 183, 253, 206 }, { 183, 255, 207 }, + { 185, 255, 208 }, { 187, 253, 209 }, { 189, 253, 210 }, { 189, 255, 211 }, { 191, 255, 212 }, { 193, 253, 213 }, { 195, 253, 214 }, { 195, 255, 215 }, + { 197, 255, 216 }, { 199, 253, 217 }, { 201, 253, 218 }, { 201, 255, 219 }, { 203, 255, 220 }, { 205, 253, 221 }, { 207, 253, 222 }, { 207, 255, 223 }, + { 209, 255, 224 }, { 211, 253, 225 }, { 213, 253, 226 }, { 213, 255, 227 }, { 215, 255, 228 }, { 217, 253, 229 }, { 219, 251, 230 }, { 219, 255, 231 }, + { 221, 253, 232 }, { 223, 253, 233 }, { 223, 255, 234 }, { 225, 255, 235 }, { 227, 253, 236 }, { 229, 253, 237 }, { 229, 255, 238 }, { 231, 255, 239 }, + { 233, 253, 240 }, { 235, 253, 241 }, { 235, 255, 242 }, { 237, 255, 243 }, { 239, 253, 244 }, { 241, 253, 245 }, { 241, 255, 246 }, { 243, 255, 247 }, + { 245, 253, 248 }, { 247, 253, 249 }, { 247, 255, 250 }, { 249, 255, 251 }, { 251, 253, 252 }, { 253, 253, 253 }, { 253, 255, 254 }, { 255, 255, 255 }, + } +}; + +Table g_mode6_p0_i1= +{ + 1, + 0, + { + { 0, 0, 0 }, { 0, 8, 1 }, { 0, 24, 2 }, { 0, 40, 3 }, { 0, 56, 4 }, { 0, 72, 5 }, { 0, 88, 6 }, { 0, 104, 7 }, + { 0, 120, 8 }, { 0, 136, 9 }, { 0, 152, 10 }, { 0, 168, 11 }, { 0, 184, 12 }, { 0, 200, 13 }, { 0, 216, 14 }, { 0, 232, 15 }, + { 0, 248, 16 }, { 2, 234, 17 }, { 2, 250, 18 }, { 4, 236, 19 }, { 4, 252, 20 }, { 6, 238, 21 }, { 6, 254, 22 }, { 8, 240, 23 }, + { 10, 226, 24 }, { 10, 242, 25 }, { 12, 228, 26 }, { 12, 244, 27 }, { 14, 230, 28 }, { 14, 246, 29 }, { 16, 232, 30 }, { 16, 248, 31 }, + { 18, 234, 32 }, { 18, 250, 33 }, { 20, 236, 34 }, { 20, 252, 35 }, { 22, 238, 36 }, { 22, 254, 37 }, { 24, 240, 38 }, { 26, 226, 39 }, + { 26, 242, 40 }, { 28, 228, 41 }, { 28, 244, 42 }, { 30, 230, 43 }, { 30, 246, 44 }, { 32, 232, 45 }, { 32, 248, 46 }, { 34, 234, 47 }, + { 34, 250, 48 }, { 36, 236, 49 }, { 36, 252, 50 }, { 38, 238, 51 }, { 38, 254, 52 }, { 40, 240, 53 }, { 42, 226, 54 }, { 42, 242, 55 }, + { 44, 228, 56 }, { 44, 244, 57 }, { 46, 230, 58 }, { 46, 246, 59 }, { 48, 232, 60 }, { 48, 248, 61 }, { 50, 234, 62 }, { 50, 250, 63 }, + { 52, 236, 64 }, { 52, 252, 65 }, { 54, 238, 66 }, { 54, 254, 67 }, { 56, 240, 68 }, { 58, 226, 69 }, { 58, 242, 70 }, { 60, 228, 71 }, + { 60, 244, 72 }, { 62, 230, 73 }, { 62, 246, 74 }, { 64, 232, 75 }, { 64, 248, 76 }, { 66, 234, 77 }, { 66, 250, 78 }, { 68, 236, 79 }, + { 68, 252, 80 }, { 70, 238, 81 }, { 70, 254, 82 }, { 72, 240, 83 }, { 74, 226, 84 }, { 74, 242, 85 }, { 76, 228, 86 }, { 76, 244, 87 }, + { 78, 230, 88 }, { 78, 246, 89 }, { 80, 232, 90 }, { 80, 248, 91 }, { 82, 234, 92 }, { 82, 250, 93 }, { 84, 236, 94 }, { 84, 252, 95 }, + { 86, 238, 96 }, { 86, 254, 97 }, { 88, 240, 98 }, { 90, 226, 99 }, { 90, 242, 100 }, { 92, 228, 101 }, { 92, 244, 102 }, { 94, 230, 103 }, + { 94, 246, 104 }, { 96, 232, 105 }, { 96, 248, 106 }, { 98, 234, 107 }, { 98, 250, 108 }, { 100, 236, 109 }, { 100, 252, 110 }, { 102, 238, 111 }, + { 102, 254, 112 }, { 104, 240, 113 }, { 106, 226, 114 }, { 106, 242, 115 }, { 108, 228, 116 }, { 108, 244, 117 }, { 110, 230, 118 }, { 110, 246, 119 }, + { 112, 232, 120 }, { 112, 248, 121 }, { 114, 234, 122 }, { 114, 250, 123 }, { 116, 236, 124 }, { 116, 252, 125 }, { 118, 238, 126 }, { 118, 254, 127 }, + { 120, 240, 128 }, { 122, 226, 129 }, { 122, 242, 130 }, { 124, 228, 131 }, { 124, 244, 132 }, { 126, 230, 133 }, { 126, 246, 134 }, { 128, 232, 135 }, + { 128, 248, 136 }, { 130, 234, 137 }, { 130, 250, 138 }, { 132, 236, 139 }, { 132, 252, 140 }, { 134, 238, 141 }, { 134, 254, 142 }, { 136, 240, 143 }, + { 138, 226, 144 }, { 138, 242, 145 }, { 140, 228, 146 }, { 140, 244, 147 }, { 142, 230, 148 }, { 142, 246, 149 }, { 144, 232, 150 }, { 144, 248, 151 }, + { 146, 234, 152 }, { 146, 250, 153 }, { 148, 236, 154 }, { 148, 252, 155 }, { 150, 238, 156 }, { 150, 254, 157 }, { 152, 240, 158 }, { 154, 226, 159 }, + { 154, 242, 160 }, { 156, 228, 161 }, { 156, 244, 162 }, { 158, 230, 163 }, { 158, 246, 164 }, { 160, 232, 165 }, { 160, 248, 166 }, { 162, 234, 167 }, + { 162, 250, 168 }, { 164, 236, 169 }, { 164, 252, 170 }, { 166, 238, 171 }, { 166, 254, 172 }, { 168, 240, 173 }, { 170, 226, 174 }, { 170, 242, 175 }, + { 172, 228, 176 }, { 172, 244, 177 }, { 174, 230, 178 }, { 174, 246, 179 }, { 176, 232, 180 }, { 176, 248, 181 }, { 178, 234, 182 }, { 178, 250, 183 }, + { 180, 236, 184 }, { 180, 252, 185 }, { 182, 238, 186 }, { 182, 254, 187 }, { 184, 240, 188 }, { 186, 226, 189 }, { 186, 242, 190 }, { 188, 228, 191 }, + { 188, 244, 192 }, { 190, 230, 193 }, { 190, 246, 194 }, { 192, 232, 195 }, { 192, 248, 196 }, { 194, 234, 197 }, { 194, 250, 198 }, { 196, 236, 199 }, + { 196, 252, 200 }, { 198, 238, 201 }, { 198, 254, 202 }, { 200, 240, 203 }, { 202, 226, 204 }, { 202, 242, 205 }, { 204, 228, 206 }, { 204, 244, 207 }, + { 206, 230, 208 }, { 206, 246, 209 }, { 208, 232, 210 }, { 208, 248, 211 }, { 210, 234, 212 }, { 210, 250, 213 }, { 212, 236, 214 }, { 212, 252, 215 }, + { 214, 238, 216 }, { 214, 254, 217 }, { 216, 240, 218 }, { 218, 226, 219 }, { 218, 242, 220 }, { 220, 228, 221 }, { 220, 244, 222 }, { 222, 230, 223 }, + { 222, 246, 224 }, { 224, 232, 225 }, { 224, 248, 226 }, { 226, 234, 227 }, { 226, 250, 228 }, { 228, 236, 229 }, { 228, 252, 230 }, { 230, 238, 231 }, + { 230, 254, 232 }, { 232, 240, 233 }, { 234, 226, 234 }, { 234, 242, 235 }, { 236, 228, 236 }, { 236, 244, 237 }, { 238, 230, 238 }, { 238, 246, 239 }, + { 240, 232, 240 }, { 240, 248, 241 }, { 242, 234, 242 }, { 242, 250, 243 }, { 244, 236, 244 }, { 244, 252, 245 }, { 246, 238, 246 }, { 246, 254, 247 }, + { 248, 240, 248 }, { 250, 226, 249 }, { 250, 242, 250 }, { 252, 228, 251 }, { 252, 244, 252 }, { 254, 230, 253 }, { 254, 246, 254 }, { 254, 246, 254 }, + } +}; + +Table g_mode6_p0_i2= +{ + 2, + 0, + { + { 0, 0, 0 }, { 0, 4, 1 }, { 0, 12, 2 }, { 0, 18, 3 }, { 0, 26, 4 }, { 0, 32, 5 }, { 0, 40, 6 }, { 0, 48, 7 }, + { 0, 54, 8 }, { 0, 62, 9 }, { 0, 68, 10 }, { 0, 76, 11 }, { 0, 82, 12 }, { 0, 90, 13 }, { 0, 96, 14 }, { 0, 104, 15 }, + { 0, 112, 16 }, { 0, 118, 17 }, { 0, 126, 18 }, { 0, 132, 19 }, { 0, 140, 20 }, { 0, 146, 21 }, { 0, 154, 22 }, { 0, 160, 23 }, + { 0, 168, 24 }, { 0, 176, 25 }, { 0, 182, 26 }, { 0, 190, 27 }, { 0, 196, 28 }, { 0, 204, 29 }, { 0, 210, 30 }, { 0, 218, 31 }, + { 0, 224, 32 }, { 0, 232, 33 }, { 0, 240, 34 }, { 0, 246, 35 }, { 0, 254, 36 }, { 2, 248, 37 }, { 4, 244, 38 }, { 4, 250, 39 }, + { 6, 246, 40 }, { 6, 252, 41 }, { 8, 248, 42 }, { 8, 254, 43 }, { 10, 250, 44 }, { 12, 244, 45 }, { 12, 252, 46 }, { 14, 246, 47 }, + { 14, 254, 48 }, { 16, 248, 49 }, { 18, 242, 50 }, { 18, 250, 51 }, { 20, 244, 52 }, { 20, 252, 53 }, { 22, 246, 54 }, { 22, 254, 55 }, + { 24, 248, 56 }, { 26, 244, 57 }, { 26, 250, 58 }, { 28, 246, 59 }, { 28, 252, 60 }, { 30, 248, 61 }, { 30, 254, 62 }, { 32, 250, 63 }, + { 34, 244, 64 }, { 34, 252, 65 }, { 36, 246, 66 }, { 36, 254, 67 }, { 38, 248, 68 }, { 40, 244, 69 }, { 40, 250, 70 }, { 42, 246, 71 }, + { 42, 252, 72 }, { 44, 248, 73 }, { 44, 254, 74 }, { 46, 250, 75 }, { 48, 244, 76 }, { 48, 252, 77 }, { 50, 246, 78 }, { 50, 254, 79 }, + { 52, 248, 80 }, { 54, 244, 81 }, { 54, 250, 82 }, { 56, 246, 83 }, { 56, 252, 84 }, { 58, 248, 85 }, { 58, 254, 86 }, { 60, 250, 87 }, + { 62, 244, 88 }, { 62, 252, 89 }, { 64, 246, 90 }, { 64, 254, 91 }, { 66, 248, 92 }, { 68, 244, 93 }, { 68, 250, 94 }, { 70, 246, 95 }, + { 70, 252, 96 }, { 72, 248, 97 }, { 72, 254, 98 }, { 74, 250, 99 }, { 76, 244, 100 }, { 76, 252, 101 }, { 78, 246, 102 }, { 78, 254, 103 }, + { 80, 248, 104 }, { 82, 242, 105 }, { 82, 250, 106 }, { 84, 244, 107 }, { 84, 252, 108 }, { 86, 246, 109 }, { 86, 254, 110 }, { 88, 248, 111 }, + { 90, 244, 112 }, { 90, 250, 113 }, { 92, 246, 114 }, { 92, 252, 115 }, { 94, 248, 116 }, { 94, 254, 117 }, { 96, 250, 118 }, { 98, 244, 119 }, + { 98, 252, 120 }, { 100, 246, 121 }, { 100, 254, 122 }, { 102, 248, 123 }, { 104, 244, 124 }, { 104, 250, 125 }, { 106, 246, 126 }, { 106, 252, 127 }, + { 108, 248, 128 }, { 108, 254, 129 }, { 110, 250, 130 }, { 112, 244, 131 }, { 112, 252, 132 }, { 114, 246, 133 }, { 114, 254, 134 }, { 116, 248, 135 }, + { 118, 244, 136 }, { 118, 250, 137 }, { 120, 246, 138 }, { 120, 252, 139 }, { 122, 248, 140 }, { 122, 254, 141 }, { 124, 250, 142 }, { 126, 244, 143 }, + { 126, 252, 144 }, { 128, 246, 145 }, { 128, 254, 146 }, { 130, 248, 147 }, { 132, 244, 148 }, { 132, 250, 149 }, { 134, 246, 150 }, { 134, 252, 151 }, + { 136, 248, 152 }, { 136, 254, 153 }, { 138, 250, 154 }, { 140, 244, 155 }, { 140, 252, 156 }, { 142, 246, 157 }, { 142, 254, 158 }, { 144, 248, 159 }, + { 146, 242, 160 }, { 146, 250, 161 }, { 148, 244, 162 }, { 148, 252, 163 }, { 150, 246, 164 }, { 150, 254, 165 }, { 152, 248, 166 }, { 154, 244, 167 }, + { 154, 250, 168 }, { 156, 246, 169 }, { 156, 252, 170 }, { 158, 248, 171 }, { 158, 254, 172 }, { 160, 250, 173 }, { 162, 244, 174 }, { 162, 252, 175 }, + { 164, 246, 176 }, { 164, 254, 177 }, { 166, 248, 178 }, { 168, 244, 179 }, { 168, 250, 180 }, { 170, 246, 181 }, { 170, 252, 182 }, { 172, 248, 183 }, + { 172, 254, 184 }, { 174, 250, 185 }, { 176, 244, 186 }, { 176, 252, 187 }, { 178, 246, 188 }, { 178, 254, 189 }, { 180, 248, 190 }, { 182, 244, 191 }, + { 182, 250, 192 }, { 184, 246, 193 }, { 184, 252, 194 }, { 186, 248, 195 }, { 186, 254, 196 }, { 188, 250, 197 }, { 190, 244, 198 }, { 190, 252, 199 }, + { 192, 246, 200 }, { 192, 254, 201 }, { 194, 248, 202 }, { 196, 244, 203 }, { 196, 250, 204 }, { 198, 246, 205 }, { 198, 252, 206 }, { 200, 248, 207 }, + { 200, 254, 208 }, { 202, 250, 209 }, { 204, 244, 210 }, { 204, 252, 211 }, { 206, 246, 212 }, { 206, 254, 213 }, { 208, 248, 214 }, { 210, 242, 215 }, + { 210, 250, 216 }, { 212, 244, 217 }, { 212, 252, 218 }, { 214, 246, 219 }, { 214, 254, 220 }, { 216, 248, 221 }, { 218, 244, 222 }, { 218, 250, 223 }, + { 220, 246, 224 }, { 220, 252, 225 }, { 222, 248, 226 }, { 222, 254, 227 }, { 224, 250, 228 }, { 226, 244, 229 }, { 226, 252, 230 }, { 228, 246, 231 }, + { 228, 254, 232 }, { 230, 248, 233 }, { 232, 244, 234 }, { 232, 250, 235 }, { 234, 246, 236 }, { 234, 252, 237 }, { 236, 248, 238 }, { 236, 254, 239 }, + { 238, 250, 240 }, { 240, 244, 241 }, { 240, 252, 242 }, { 242, 246, 243 }, { 242, 254, 244 }, { 244, 248, 245 }, { 246, 244, 246 }, { 246, 250, 247 }, + { 248, 246, 248 }, { 248, 252, 249 }, { 250, 248, 250 }, { 250, 254, 251 }, { 252, 250, 252 }, { 254, 244, 253 }, { 254, 252, 254 }, { 254, 252, 254 }, + } +}; + +Table g_mode6_p0_i3= +{ + 3, + 0, + { + { 0, 0, 0 }, { 0, 4, 1 }, { 0, 8, 2 }, { 0, 14, 3 }, { 0, 18, 4 }, { 0, 24, 5 }, { 0, 28, 6 }, { 0, 32, 7 }, + { 0, 38, 8 }, { 0, 42, 9 }, { 0, 48, 10 }, { 0, 52, 11 }, { 0, 58, 12 }, { 0, 62, 13 }, { 0, 68, 14 }, { 0, 72, 15 }, + { 0, 78, 16 }, { 0, 82, 17 }, { 0, 88, 18 }, { 0, 92, 19 }, { 0, 96, 20 }, { 0, 102, 21 }, { 0, 106, 22 }, { 0, 112, 23 }, + { 0, 116, 24 }, { 0, 122, 25 }, { 0, 126, 26 }, { 0, 132, 27 }, { 0, 136, 28 }, { 0, 142, 29 }, { 0, 146, 30 }, { 0, 152, 31 }, + { 0, 156, 32 }, { 0, 160, 33 }, { 0, 166, 34 }, { 0, 170, 35 }, { 0, 176, 36 }, { 0, 180, 37 }, { 0, 186, 38 }, { 0, 190, 39 }, + { 0, 196, 40 }, { 0, 200, 41 }, { 0, 206, 42 }, { 0, 210, 43 }, { 0, 216, 44 }, { 0, 220, 45 }, { 0, 224, 46 }, { 0, 230, 47 }, + { 0, 234, 48 }, { 0, 240, 49 }, { 0, 244, 50 }, { 0, 250, 51 }, { 0, 254, 52 }, { 2, 252, 53 }, { 4, 248, 54 }, { 4, 254, 55 }, + { 6, 250, 56 }, { 8, 248, 57 }, { 8, 252, 58 }, { 10, 250, 59 }, { 10, 254, 60 }, { 12, 252, 61 }, { 14, 248, 62 }, { 14, 254, 63 }, + { 16, 250, 64 }, { 18, 248, 65 }, { 18, 252, 66 }, { 20, 250, 67 }, { 20, 254, 68 }, { 22, 252, 69 }, { 24, 248, 70 }, { 24, 254, 71 }, + { 26, 250, 72 }, { 28, 248, 73 }, { 28, 252, 74 }, { 30, 250, 75 }, { 30, 254, 76 }, { 32, 252, 77 }, { 34, 250, 78 }, { 34, 254, 79 }, + { 36, 252, 80 }, { 38, 248, 81 }, { 38, 254, 82 }, { 40, 250, 83 }, { 42, 248, 84 }, { 42, 252, 85 }, { 44, 250, 86 }, { 44, 254, 87 }, + { 46, 252, 88 }, { 48, 248, 89 }, { 48, 254, 90 }, { 50, 250, 91 }, { 52, 248, 92 }, { 52, 252, 93 }, { 54, 250, 94 }, { 54, 254, 95 }, + { 56, 252, 96 }, { 58, 248, 97 }, { 58, 254, 98 }, { 60, 250, 99 }, { 62, 248, 100 }, { 62, 252, 101 }, { 64, 250, 102 }, { 64, 254, 103 }, + { 66, 252, 104 }, { 68, 248, 105 }, { 68, 254, 106 }, { 70, 250, 107 }, { 72, 248, 108 }, { 72, 252, 109 }, { 74, 250, 110 }, { 74, 254, 111 }, + { 76, 252, 112 }, { 78, 248, 113 }, { 78, 254, 114 }, { 80, 250, 115 }, { 82, 248, 116 }, { 82, 252, 117 }, { 84, 250, 118 }, { 84, 254, 119 }, + { 86, 252, 120 }, { 88, 248, 121 }, { 88, 254, 122 }, { 90, 250, 123 }, { 92, 248, 124 }, { 92, 252, 125 }, { 94, 250, 126 }, { 94, 254, 127 }, + { 96, 252, 128 }, { 98, 250, 129 }, { 98, 254, 130 }, { 100, 252, 131 }, { 102, 248, 132 }, { 102, 254, 133 }, { 104, 250, 134 }, { 106, 248, 135 }, + { 106, 252, 136 }, { 108, 250, 137 }, { 108, 254, 138 }, { 110, 252, 139 }, { 112, 248, 140 }, { 112, 254, 141 }, { 114, 250, 142 }, { 116, 248, 143 }, + { 116, 252, 144 }, { 118, 250, 145 }, { 118, 254, 146 }, { 120, 252, 147 }, { 122, 248, 148 }, { 122, 254, 149 }, { 124, 250, 150 }, { 126, 248, 151 }, + { 126, 252, 152 }, { 128, 250, 153 }, { 128, 254, 154 }, { 130, 252, 155 }, { 132, 248, 156 }, { 132, 254, 157 }, { 134, 250, 158 }, { 136, 248, 159 }, + { 136, 252, 160 }, { 138, 250, 161 }, { 138, 254, 162 }, { 140, 252, 163 }, { 142, 248, 164 }, { 142, 254, 165 }, { 144, 250, 166 }, { 146, 248, 167 }, + { 146, 252, 168 }, { 148, 250, 169 }, { 148, 254, 170 }, { 150, 252, 171 }, { 152, 248, 172 }, { 152, 254, 173 }, { 154, 250, 174 }, { 156, 248, 175 }, + { 156, 252, 176 }, { 158, 250, 177 }, { 158, 254, 178 }, { 160, 252, 179 }, { 162, 250, 180 }, { 162, 254, 181 }, { 164, 252, 182 }, { 166, 248, 183 }, + { 166, 254, 184 }, { 168, 250, 185 }, { 170, 248, 186 }, { 170, 252, 187 }, { 172, 250, 188 }, { 172, 254, 189 }, { 174, 252, 190 }, { 176, 248, 191 }, + { 176, 254, 192 }, { 178, 250, 193 }, { 180, 248, 194 }, { 180, 252, 195 }, { 182, 250, 196 }, { 182, 254, 197 }, { 184, 252, 198 }, { 186, 248, 199 }, + { 186, 254, 200 }, { 188, 250, 201 }, { 190, 248, 202 }, { 190, 252, 203 }, { 192, 250, 204 }, { 192, 254, 205 }, { 194, 252, 206 }, { 196, 248, 207 }, + { 196, 254, 208 }, { 198, 250, 209 }, { 200, 248, 210 }, { 200, 252, 211 }, { 202, 250, 212 }, { 202, 254, 213 }, { 204, 252, 214 }, { 206, 248, 215 }, + { 206, 254, 216 }, { 208, 250, 217 }, { 210, 248, 218 }, { 210, 252, 219 }, { 212, 250, 220 }, { 212, 254, 221 }, { 214, 252, 222 }, { 216, 248, 223 }, + { 216, 254, 224 }, { 218, 250, 225 }, { 220, 248, 226 }, { 220, 252, 227 }, { 222, 250, 228 }, { 222, 254, 229 }, { 224, 252, 230 }, { 226, 250, 231 }, + { 226, 254, 232 }, { 228, 252, 233 }, { 230, 248, 234 }, { 230, 254, 235 }, { 232, 250, 236 }, { 234, 248, 237 }, { 234, 252, 238 }, { 236, 250, 239 }, + { 236, 254, 240 }, { 238, 252, 241 }, { 240, 248, 242 }, { 240, 254, 243 }, { 242, 250, 244 }, { 244, 248, 245 }, { 244, 252, 246 }, { 246, 250, 247 }, + { 246, 254, 248 }, { 248, 252, 249 }, { 250, 248, 250 }, { 250, 254, 251 }, { 252, 250, 252 }, { 254, 248, 253 }, { 254, 252, 254 }, { 254, 252, 254 }, + } +}; + +Table g_mode6_p0_i4= +{ + 4, + 0, + { + { 0, 0, 0 }, { 0, 2, 1 }, { 0, 6, 2 }, { 0, 10, 3 }, { 0, 14, 4 }, { 0, 18, 5 }, { 0, 22, 6 }, { 0, 26, 7 }, + { 0, 30, 8 }, { 0, 32, 9 }, { 0, 36, 10 }, { 0, 40, 11 }, { 0, 44, 12 }, { 0, 48, 13 }, { 0, 52, 14 }, { 0, 56, 15 }, + { 0, 60, 16 }, { 0, 64, 17 }, { 0, 66, 18 }, { 0, 70, 19 }, { 0, 74, 20 }, { 0, 78, 21 }, { 0, 82, 22 }, { 0, 86, 23 }, + { 0, 90, 24 }, { 0, 94, 25 }, { 0, 96, 26 }, { 0, 100, 27 }, { 0, 104, 28 }, { 0, 108, 29 }, { 0, 112, 30 }, { 0, 116, 31 }, + { 0, 120, 32 }, { 0, 124, 33 }, { 0, 128, 34 }, { 0, 130, 35 }, { 0, 134, 36 }, { 0, 138, 37 }, { 0, 142, 38 }, { 0, 146, 39 }, + { 0, 150, 40 }, { 0, 154, 41 }, { 0, 158, 42 }, { 0, 160, 43 }, { 0, 164, 44 }, { 0, 168, 45 }, { 0, 172, 46 }, { 0, 176, 47 }, + { 0, 180, 48 }, { 0, 184, 49 }, { 0, 188, 50 }, { 0, 192, 51 }, { 0, 194, 52 }, { 0, 198, 53 }, { 0, 202, 54 }, { 0, 206, 55 }, + { 0, 210, 56 }, { 0, 214, 57 }, { 0, 218, 58 }, { 0, 222, 59 }, { 0, 224, 60 }, { 0, 228, 61 }, { 0, 232, 62 }, { 0, 236, 63 }, + { 0, 240, 64 }, { 0, 244, 65 }, { 0, 248, 66 }, { 0, 252, 67 }, { 2, 250, 68 }, { 2, 254, 69 }, { 4, 252, 70 }, { 6, 250, 71 }, + { 6, 254, 72 }, { 8, 252, 73 }, { 10, 250, 74 }, { 10, 254, 75 }, { 12, 252, 76 }, { 14, 250, 77 }, { 14, 254, 78 }, { 16, 252, 79 }, + { 18, 250, 80 }, { 18, 254, 81 }, { 20, 252, 82 }, { 22, 250, 83 }, { 22, 254, 84 }, { 24, 252, 85 }, { 26, 250, 86 }, { 26, 254, 87 }, + { 28, 252, 88 }, { 30, 252, 89 }, { 30, 254, 90 }, { 32, 254, 91 }, { 34, 252, 92 }, { 36, 250, 93 }, { 36, 254, 94 }, { 38, 252, 95 }, + { 40, 250, 96 }, { 40, 254, 97 }, { 42, 252, 98 }, { 44, 250, 99 }, { 44, 254, 100 }, { 46, 252, 101 }, { 48, 250, 102 }, { 48, 254, 103 }, + { 50, 252, 104 }, { 52, 250, 105 }, { 52, 254, 106 }, { 54, 252, 107 }, { 56, 250, 108 }, { 56, 254, 109 }, { 58, 252, 110 }, { 60, 252, 111 }, + { 60, 254, 112 }, { 62, 254, 113 }, { 64, 252, 114 }, { 66, 250, 115 }, { 66, 254, 116 }, { 68, 252, 117 }, { 70, 250, 118 }, { 70, 254, 119 }, + { 72, 252, 120 }, { 74, 250, 121 }, { 74, 254, 122 }, { 76, 252, 123 }, { 78, 250, 124 }, { 78, 254, 125 }, { 80, 252, 126 }, { 82, 250, 127 }, + { 82, 254, 128 }, { 84, 252, 129 }, { 86, 250, 130 }, { 86, 254, 131 }, { 88, 252, 132 }, { 90, 250, 133 }, { 90, 254, 134 }, { 92, 252, 135 }, + { 94, 252, 136 }, { 94, 254, 137 }, { 96, 254, 138 }, { 98, 252, 139 }, { 100, 250, 140 }, { 100, 254, 141 }, { 102, 252, 142 }, { 104, 250, 143 }, + { 104, 254, 144 }, { 106, 252, 145 }, { 108, 250, 146 }, { 108, 254, 147 }, { 110, 252, 148 }, { 112, 250, 149 }, { 112, 254, 150 }, { 114, 252, 151 }, + { 116, 250, 152 }, { 116, 254, 153 }, { 118, 252, 154 }, { 120, 250, 155 }, { 120, 254, 156 }, { 122, 252, 157 }, { 124, 252, 158 }, { 124, 254, 159 }, + { 126, 254, 160 }, { 128, 252, 161 }, { 130, 250, 162 }, { 130, 254, 163 }, { 132, 252, 164 }, { 134, 250, 165 }, { 134, 254, 166 }, { 136, 252, 167 }, + { 138, 250, 168 }, { 138, 254, 169 }, { 140, 252, 170 }, { 142, 250, 171 }, { 142, 254, 172 }, { 144, 252, 173 }, { 146, 250, 174 }, { 146, 254, 175 }, + { 148, 252, 176 }, { 150, 250, 177 }, { 150, 254, 178 }, { 152, 252, 179 }, { 154, 250, 180 }, { 154, 254, 181 }, { 156, 252, 182 }, { 158, 252, 183 }, + { 158, 254, 184 }, { 160, 254, 185 }, { 162, 252, 186 }, { 164, 250, 187 }, { 164, 254, 188 }, { 166, 252, 189 }, { 168, 250, 190 }, { 168, 254, 191 }, + { 170, 252, 192 }, { 172, 250, 193 }, { 172, 254, 194 }, { 174, 252, 195 }, { 176, 250, 196 }, { 176, 254, 197 }, { 178, 252, 198 }, { 180, 250, 199 }, + { 180, 254, 200 }, { 182, 252, 201 }, { 184, 250, 202 }, { 184, 254, 203 }, { 186, 252, 204 }, { 188, 252, 205 }, { 188, 254, 206 }, { 190, 254, 207 }, + { 192, 252, 208 }, { 194, 250, 209 }, { 194, 254, 210 }, { 196, 252, 211 }, { 198, 250, 212 }, { 198, 254, 213 }, { 200, 252, 214 }, { 202, 250, 215 }, + { 202, 254, 216 }, { 204, 252, 217 }, { 206, 250, 218 }, { 206, 254, 219 }, { 208, 252, 220 }, { 210, 250, 221 }, { 210, 254, 222 }, { 212, 252, 223 }, + { 214, 250, 224 }, { 214, 254, 225 }, { 216, 252, 226 }, { 218, 250, 227 }, { 218, 254, 228 }, { 220, 252, 229 }, { 222, 252, 230 }, { 222, 254, 231 }, + { 224, 254, 232 }, { 226, 252, 233 }, { 228, 250, 234 }, { 228, 254, 235 }, { 230, 252, 236 }, { 232, 250, 237 }, { 232, 254, 238 }, { 234, 252, 239 }, + { 236, 250, 240 }, { 236, 254, 241 }, { 238, 252, 242 }, { 240, 250, 243 }, { 240, 254, 244 }, { 242, 252, 245 }, { 244, 250, 246 }, { 244, 254, 247 }, + { 246, 252, 248 }, { 248, 250, 249 }, { 248, 254, 250 }, { 250, 252, 251 }, { 252, 252, 252 }, { 252, 254, 253 }, { 254, 254, 254 }, { 254, 254, 254 }, + } +}; + +Table g_mode6_p0_i5= +{ + 5, + 0, + { + { 0, 0, 0 }, { 0, 2, 1 }, { 0, 6, 2 }, { 0, 8, 3 }, { 0, 12, 4 }, { 0, 14, 5 }, { 0, 18, 6 }, { 0, 20, 7 }, + { 0, 24, 8 }, { 0, 26, 9 }, { 0, 30, 10 }, { 0, 32, 11 }, { 0, 36, 12 }, { 0, 40, 13 }, { 0, 42, 14 }, { 0, 46, 15 }, + { 0, 48, 16 }, { 0, 52, 17 }, { 0, 54, 18 }, { 0, 58, 19 }, { 0, 60, 20 }, { 0, 64, 21 }, { 0, 66, 22 }, { 0, 70, 23 }, + { 0, 72, 24 }, { 0, 76, 25 }, { 0, 78, 26 }, { 0, 82, 27 }, { 0, 84, 28 }, { 0, 88, 29 }, { 0, 90, 30 }, { 0, 94, 31 }, + { 0, 96, 32 }, { 0, 100, 33 }, { 0, 104, 34 }, { 0, 106, 35 }, { 0, 110, 36 }, { 0, 112, 37 }, { 0, 116, 38 }, { 0, 118, 39 }, + { 0, 122, 40 }, { 0, 124, 41 }, { 0, 128, 42 }, { 0, 130, 43 }, { 0, 134, 44 }, { 0, 136, 45 }, { 0, 140, 46 }, { 0, 142, 47 }, + { 0, 146, 48 }, { 0, 148, 49 }, { 0, 152, 50 }, { 0, 154, 51 }, { 0, 158, 52 }, { 0, 160, 53 }, { 0, 164, 54 }, { 0, 168, 55 }, + { 0, 170, 56 }, { 0, 174, 57 }, { 0, 176, 58 }, { 0, 180, 59 }, { 0, 182, 60 }, { 0, 186, 61 }, { 0, 188, 62 }, { 0, 192, 63 }, + { 0, 194, 64 }, { 0, 198, 65 }, { 0, 200, 66 }, { 0, 204, 67 }, { 0, 206, 68 }, { 0, 210, 69 }, { 0, 212, 70 }, { 0, 216, 71 }, + { 0, 218, 72 }, { 0, 222, 73 }, { 0, 224, 74 }, { 0, 228, 75 }, { 0, 232, 76 }, { 0, 234, 77 }, { 0, 238, 78 }, { 0, 240, 79 }, + { 0, 244, 80 }, { 0, 246, 81 }, { 0, 250, 82 }, { 0, 252, 83 }, { 2, 252, 84 }, { 2, 254, 85 }, { 4, 254, 86 }, { 6, 252, 87 }, + { 8, 252, 88 }, { 8, 254, 89 }, { 10, 254, 90 }, { 12, 252, 91 }, { 14, 252, 92 }, { 14, 254, 93 }, { 16, 254, 94 }, { 18, 252, 95 }, + { 20, 252, 96 }, { 20, 254, 97 }, { 22, 254, 98 }, { 24, 252, 99 }, { 26, 250, 100 }, { 26, 254, 101 }, { 28, 252, 102 }, { 30, 252, 103 }, + { 30, 254, 104 }, { 32, 254, 105 }, { 34, 252, 106 }, { 36, 252, 107 }, { 36, 254, 108 }, { 38, 254, 109 }, { 40, 252, 110 }, { 42, 252, 111 }, + { 42, 254, 112 }, { 44, 254, 113 }, { 46, 252, 114 }, { 48, 252, 115 }, { 48, 254, 116 }, { 50, 254, 117 }, { 52, 252, 118 }, { 54, 252, 119 }, + { 54, 254, 120 }, { 56, 254, 121 }, { 58, 252, 122 }, { 60, 252, 123 }, { 60, 254, 124 }, { 62, 254, 125 }, { 64, 252, 126 }, { 66, 252, 127 }, + { 66, 254, 128 }, { 68, 254, 129 }, { 70, 252, 130 }, { 72, 252, 131 }, { 72, 254, 132 }, { 74, 254, 133 }, { 76, 252, 134 }, { 78, 252, 135 }, + { 78, 254, 136 }, { 80, 254, 137 }, { 82, 252, 138 }, { 84, 252, 139 }, { 84, 254, 140 }, { 86, 254, 141 }, { 88, 252, 142 }, { 90, 250, 143 }, + { 90, 254, 144 }, { 92, 252, 145 }, { 94, 252, 146 }, { 94, 254, 147 }, { 96, 254, 148 }, { 98, 252, 149 }, { 100, 252, 150 }, { 100, 254, 151 }, + { 102, 254, 152 }, { 104, 252, 153 }, { 106, 252, 154 }, { 106, 254, 155 }, { 108, 254, 156 }, { 110, 252, 157 }, { 112, 252, 158 }, { 112, 254, 159 }, + { 114, 254, 160 }, { 116, 252, 161 }, { 118, 252, 162 }, { 118, 254, 163 }, { 120, 254, 164 }, { 122, 252, 165 }, { 124, 252, 166 }, { 124, 254, 167 }, + { 126, 254, 168 }, { 128, 252, 169 }, { 130, 252, 170 }, { 130, 254, 171 }, { 132, 254, 172 }, { 134, 252, 173 }, { 136, 252, 174 }, { 136, 254, 175 }, + { 138, 254, 176 }, { 140, 252, 177 }, { 142, 252, 178 }, { 142, 254, 179 }, { 144, 254, 180 }, { 146, 252, 181 }, { 148, 252, 182 }, { 148, 254, 183 }, + { 150, 254, 184 }, { 152, 252, 185 }, { 154, 250, 186 }, { 154, 254, 187 }, { 156, 252, 188 }, { 158, 252, 189 }, { 158, 254, 190 }, { 160, 254, 191 }, + { 162, 252, 192 }, { 164, 252, 193 }, { 164, 254, 194 }, { 166, 254, 195 }, { 168, 252, 196 }, { 170, 252, 197 }, { 170, 254, 198 }, { 172, 254, 199 }, + { 174, 252, 200 }, { 176, 252, 201 }, { 176, 254, 202 }, { 178, 254, 203 }, { 180, 252, 204 }, { 182, 252, 205 }, { 182, 254, 206 }, { 184, 254, 207 }, + { 186, 252, 208 }, { 188, 252, 209 }, { 188, 254, 210 }, { 190, 254, 211 }, { 192, 252, 212 }, { 194, 252, 213 }, { 194, 254, 214 }, { 196, 254, 215 }, + { 198, 252, 216 }, { 200, 252, 217 }, { 200, 254, 218 }, { 202, 254, 219 }, { 204, 252, 220 }, { 206, 252, 221 }, { 206, 254, 222 }, { 208, 254, 223 }, + { 210, 252, 224 }, { 212, 252, 225 }, { 212, 254, 226 }, { 214, 254, 227 }, { 216, 252, 228 }, { 218, 250, 229 }, { 218, 254, 230 }, { 220, 252, 231 }, + { 222, 252, 232 }, { 222, 254, 233 }, { 224, 254, 234 }, { 226, 252, 235 }, { 228, 252, 236 }, { 228, 254, 237 }, { 230, 254, 238 }, { 232, 252, 239 }, + { 234, 252, 240 }, { 234, 254, 241 }, { 236, 254, 242 }, { 238, 252, 243 }, { 240, 252, 244 }, { 240, 254, 245 }, { 242, 254, 246 }, { 244, 252, 247 }, + { 246, 252, 248 }, { 246, 254, 249 }, { 248, 254, 250 }, { 250, 252, 251 }, { 252, 252, 252 }, { 252, 254, 253 }, { 254, 254, 254 }, { 254, 254, 254 }, + } +}; + +Table g_mode6_p0_i6= +{ + 6, + 0, + { + { 0, 0, 0 }, { 0, 2, 1 }, { 0, 4, 2 }, { 0, 8, 3 }, { 0, 10, 4 }, { 0, 12, 5 }, { 0, 14, 6 }, { 0, 16, 7 }, + { 0, 20, 8 }, { 0, 22, 9 }, { 0, 24, 10 }, { 0, 26, 11 }, { 0, 30, 12 }, { 0, 32, 13 }, { 0, 34, 14 }, { 0, 36, 15 }, + { 0, 40, 16 }, { 0, 42, 17 }, { 0, 44, 18 }, { 0, 46, 19 }, { 0, 48, 20 }, { 0, 52, 21 }, { 0, 54, 22 }, { 0, 56, 23 }, + { 0, 58, 24 }, { 0, 62, 25 }, { 0, 64, 26 }, { 0, 66, 27 }, { 0, 68, 28 }, { 0, 72, 29 }, { 0, 74, 30 }, { 0, 76, 31 }, + { 0, 78, 32 }, { 0, 80, 33 }, { 0, 84, 34 }, { 0, 86, 35 }, { 0, 88, 36 }, { 0, 90, 37 }, { 0, 94, 38 }, { 0, 96, 39 }, + { 0, 98, 40 }, { 0, 100, 41 }, { 0, 104, 42 }, { 0, 106, 43 }, { 0, 108, 44 }, { 0, 110, 45 }, { 0, 112, 46 }, { 0, 116, 47 }, + { 0, 118, 48 }, { 0, 120, 49 }, { 0, 122, 50 }, { 0, 126, 51 }, { 0, 128, 52 }, { 0, 130, 53 }, { 0, 132, 54 }, { 0, 136, 55 }, + { 0, 138, 56 }, { 0, 140, 57 }, { 0, 142, 58 }, { 0, 144, 59 }, { 0, 148, 60 }, { 0, 150, 61 }, { 0, 152, 62 }, { 0, 154, 63 }, + { 0, 158, 64 }, { 0, 160, 65 }, { 0, 162, 66 }, { 0, 164, 67 }, { 0, 168, 68 }, { 0, 170, 69 }, { 0, 172, 70 }, { 0, 174, 71 }, + { 0, 176, 72 }, { 0, 180, 73 }, { 0, 182, 74 }, { 0, 184, 75 }, { 0, 186, 76 }, { 0, 190, 77 }, { 0, 192, 78 }, { 0, 194, 79 }, + { 0, 196, 80 }, { 0, 200, 81 }, { 0, 202, 82 }, { 0, 204, 83 }, { 0, 206, 84 }, { 0, 208, 85 }, { 0, 212, 86 }, { 0, 214, 87 }, + { 0, 216, 88 }, { 0, 218, 89 }, { 0, 222, 90 }, { 0, 224, 91 }, { 0, 226, 92 }, { 0, 228, 93 }, { 0, 232, 94 }, { 0, 234, 95 }, + { 0, 236, 96 }, { 0, 238, 97 }, { 0, 240, 98 }, { 0, 244, 99 }, { 0, 246, 100 }, { 0, 248, 101 }, { 0, 250, 102 }, { 0, 254, 103 }, + { 2, 252, 104 }, { 4, 252, 105 }, { 4, 254, 106 }, { 6, 254, 107 }, { 8, 254, 108 }, { 10, 254, 109 }, { 12, 252, 110 }, { 14, 252, 111 }, + { 14, 254, 112 }, { 16, 254, 113 }, { 18, 254, 114 }, { 20, 254, 115 }, { 22, 254, 116 }, { 24, 252, 117 }, { 26, 252, 118 }, { 26, 254, 119 }, + { 28, 254, 120 }, { 30, 254, 121 }, { 32, 254, 122 }, { 34, 252, 123 }, { 36, 252, 124 }, { 36, 254, 125 }, { 38, 254, 126 }, { 40, 254, 127 }, + { 42, 254, 128 }, { 44, 252, 129 }, { 46, 252, 130 }, { 46, 254, 131 }, { 48, 254, 132 }, { 50, 254, 133 }, { 52, 254, 134 }, { 54, 254, 135 }, + { 56, 252, 136 }, { 58, 252, 137 }, { 58, 254, 138 }, { 60, 254, 139 }, { 62, 254, 140 }, { 64, 254, 141 }, { 66, 252, 142 }, { 68, 252, 143 }, + { 68, 254, 144 }, { 70, 254, 145 }, { 72, 254, 146 }, { 74, 254, 147 }, { 76, 252, 148 }, { 78, 252, 149 }, { 78, 254, 150 }, { 80, 254, 151 }, + { 82, 254, 152 }, { 84, 254, 153 }, { 86, 254, 154 }, { 88, 252, 155 }, { 90, 252, 156 }, { 90, 254, 157 }, { 92, 254, 158 }, { 94, 254, 159 }, + { 96, 254, 160 }, { 98, 252, 161 }, { 100, 252, 162 }, { 100, 254, 163 }, { 102, 254, 164 }, { 104, 254, 165 }, { 106, 254, 166 }, { 108, 252, 167 }, + { 110, 252, 168 }, { 110, 254, 169 }, { 112, 254, 170 }, { 114, 254, 171 }, { 116, 254, 172 }, { 118, 254, 173 }, { 120, 252, 174 }, { 122, 252, 175 }, + { 122, 254, 176 }, { 124, 254, 177 }, { 126, 254, 178 }, { 128, 254, 179 }, { 130, 252, 180 }, { 132, 252, 181 }, { 132, 254, 182 }, { 134, 254, 183 }, + { 136, 254, 184 }, { 138, 254, 185 }, { 140, 252, 186 }, { 142, 252, 187 }, { 142, 254, 188 }, { 144, 254, 189 }, { 146, 254, 190 }, { 148, 254, 191 }, + { 150, 254, 192 }, { 152, 252, 193 }, { 154, 252, 194 }, { 154, 254, 195 }, { 156, 254, 196 }, { 158, 254, 197 }, { 160, 254, 198 }, { 162, 252, 199 }, + { 164, 252, 200 }, { 164, 254, 201 }, { 166, 254, 202 }, { 168, 254, 203 }, { 170, 254, 204 }, { 172, 252, 205 }, { 174, 252, 206 }, { 174, 254, 207 }, + { 176, 254, 208 }, { 178, 254, 209 }, { 180, 254, 210 }, { 182, 254, 211 }, { 184, 252, 212 }, { 186, 252, 213 }, { 186, 254, 214 }, { 188, 254, 215 }, + { 190, 254, 216 }, { 192, 254, 217 }, { 194, 252, 218 }, { 196, 252, 219 }, { 196, 254, 220 }, { 198, 254, 221 }, { 200, 254, 222 }, { 202, 254, 223 }, + { 204, 252, 224 }, { 206, 252, 225 }, { 206, 254, 226 }, { 208, 254, 227 }, { 210, 254, 228 }, { 212, 254, 229 }, { 214, 254, 230 }, { 216, 252, 231 }, + { 218, 252, 232 }, { 218, 254, 233 }, { 220, 254, 234 }, { 222, 254, 235 }, { 224, 254, 236 }, { 226, 252, 237 }, { 228, 252, 238 }, { 228, 254, 239 }, + { 230, 254, 240 }, { 232, 254, 241 }, { 234, 254, 242 }, { 236, 252, 243 }, { 238, 252, 244 }, { 238, 254, 245 }, { 240, 254, 246 }, { 242, 254, 247 }, + { 244, 254, 248 }, { 246, 254, 249 }, { 248, 252, 250 }, { 250, 252, 251 }, { 250, 254, 252 }, { 252, 254, 253 }, { 254, 254, 254 }, { 254, 254, 254 }, + } +}; + +Table g_mode6_p0_i7= +{ + 7, + 0, + { + { 0, 0, 0 }, { 0, 2, 1 }, { 0, 4, 2 }, { 0, 6, 3 }, { 0, 8, 4 }, { 0, 10, 5 }, { 0, 12, 6 }, { 0, 14, 7 }, + { 0, 16, 8 }, { 0, 20, 9 }, { 0, 22, 10 }, { 0, 24, 11 }, { 0, 26, 12 }, { 0, 28, 13 }, { 0, 30, 14 }, { 0, 32, 15 }, + { 0, 34, 16 }, { 0, 36, 17 }, { 0, 38, 18 }, { 0, 40, 19 }, { 0, 42, 20 }, { 0, 44, 21 }, { 0, 46, 22 }, { 0, 48, 23 }, + { 0, 52, 24 }, { 0, 54, 25 }, { 0, 56, 26 }, { 0, 58, 27 }, { 0, 60, 28 }, { 0, 62, 29 }, { 0, 64, 30 }, { 0, 66, 31 }, + { 0, 68, 32 }, { 0, 70, 33 }, { 0, 72, 34 }, { 0, 74, 35 }, { 0, 76, 36 }, { 0, 78, 37 }, { 0, 80, 38 }, { 0, 84, 39 }, + { 0, 86, 40 }, { 0, 88, 41 }, { 0, 90, 42 }, { 0, 92, 43 }, { 0, 94, 44 }, { 0, 96, 45 }, { 0, 98, 46 }, { 0, 100, 47 }, + { 0, 102, 48 }, { 0, 104, 49 }, { 0, 106, 50 }, { 0, 108, 51 }, { 0, 110, 52 }, { 0, 112, 53 }, { 0, 116, 54 }, { 0, 118, 55 }, + { 0, 120, 56 }, { 0, 122, 57 }, { 0, 124, 58 }, { 0, 126, 59 }, { 0, 128, 60 }, { 0, 130, 61 }, { 0, 132, 62 }, { 0, 134, 63 }, + { 0, 136, 64 }, { 0, 138, 65 }, { 0, 140, 66 }, { 0, 142, 67 }, { 0, 144, 68 }, { 0, 148, 69 }, { 0, 150, 70 }, { 0, 152, 71 }, + { 0, 154, 72 }, { 0, 156, 73 }, { 0, 158, 74 }, { 0, 160, 75 }, { 0, 162, 76 }, { 0, 164, 77 }, { 0, 166, 78 }, { 0, 168, 79 }, + { 0, 170, 80 }, { 0, 172, 81 }, { 0, 174, 82 }, { 0, 176, 83 }, { 0, 180, 84 }, { 0, 182, 85 }, { 0, 184, 86 }, { 0, 186, 87 }, + { 0, 188, 88 }, { 0, 190, 89 }, { 0, 192, 90 }, { 0, 194, 91 }, { 0, 196, 92 }, { 0, 198, 93 }, { 0, 200, 94 }, { 0, 202, 95 }, + { 0, 204, 96 }, { 0, 206, 97 }, { 0, 208, 98 }, { 0, 212, 99 }, { 0, 214, 100 }, { 0, 216, 101 }, { 0, 218, 102 }, { 0, 220, 103 }, + { 0, 222, 104 }, { 0, 224, 105 }, { 0, 226, 106 }, { 0, 228, 107 }, { 0, 230, 108 }, { 0, 232, 109 }, { 0, 234, 110 }, { 0, 236, 111 }, + { 0, 238, 112 }, { 0, 240, 113 }, { 0, 244, 114 }, { 0, 246, 115 }, { 0, 248, 116 }, { 0, 250, 117 }, { 0, 252, 118 }, { 0, 254, 119 }, + { 2, 254, 120 }, { 4, 254, 121 }, { 6, 254, 122 }, { 8, 254, 123 }, { 10, 254, 124 }, { 12, 252, 125 }, { 14, 252, 126 }, { 14, 254, 127 }, + { 16, 254, 128 }, { 18, 254, 129 }, { 20, 254, 130 }, { 22, 254, 131 }, { 24, 254, 132 }, { 26, 254, 133 }, { 28, 254, 134 }, { 30, 254, 135 }, + { 32, 254, 136 }, { 34, 254, 137 }, { 36, 254, 138 }, { 38, 254, 139 }, { 40, 254, 140 }, { 42, 254, 141 }, { 44, 252, 142 }, { 46, 252, 143 }, + { 46, 254, 144 }, { 48, 254, 145 }, { 50, 254, 146 }, { 52, 254, 147 }, { 54, 254, 148 }, { 56, 254, 149 }, { 58, 254, 150 }, { 60, 254, 151 }, + { 62, 254, 152 }, { 64, 254, 153 }, { 66, 254, 154 }, { 68, 254, 155 }, { 70, 254, 156 }, { 72, 254, 157 }, { 74, 254, 158 }, { 76, 252, 159 }, + { 78, 252, 160 }, { 78, 254, 161 }, { 80, 254, 162 }, { 82, 254, 163 }, { 84, 254, 164 }, { 86, 254, 165 }, { 88, 254, 166 }, { 90, 254, 167 }, + { 92, 254, 168 }, { 94, 254, 169 }, { 96, 254, 170 }, { 98, 254, 171 }, { 100, 254, 172 }, { 102, 254, 173 }, { 104, 254, 174 }, { 106, 254, 175 }, + { 108, 252, 176 }, { 110, 252, 177 }, { 110, 254, 178 }, { 112, 254, 179 }, { 114, 254, 180 }, { 116, 254, 181 }, { 118, 254, 182 }, { 120, 254, 183 }, + { 122, 254, 184 }, { 124, 254, 185 }, { 126, 254, 186 }, { 128, 254, 187 }, { 130, 254, 188 }, { 132, 254, 189 }, { 134, 254, 190 }, { 136, 254, 191 }, + { 138, 254, 192 }, { 140, 252, 193 }, { 142, 252, 194 }, { 142, 254, 195 }, { 144, 254, 196 }, { 146, 254, 197 }, { 148, 254, 198 }, { 150, 254, 199 }, + { 152, 254, 200 }, { 154, 254, 201 }, { 156, 254, 202 }, { 158, 254, 203 }, { 160, 254, 204 }, { 162, 254, 205 }, { 164, 254, 206 }, { 166, 254, 207 }, + { 168, 254, 208 }, { 170, 254, 209 }, { 172, 252, 210 }, { 174, 252, 211 }, { 174, 254, 212 }, { 176, 254, 213 }, { 178, 254, 214 }, { 180, 254, 215 }, + { 182, 254, 216 }, { 184, 254, 217 }, { 186, 254, 218 }, { 188, 254, 219 }, { 190, 254, 220 }, { 192, 254, 221 }, { 194, 254, 222 }, { 196, 254, 223 }, + { 198, 254, 224 }, { 200, 254, 225 }, { 202, 254, 226 }, { 204, 252, 227 }, { 206, 252, 228 }, { 206, 254, 229 }, { 208, 254, 230 }, { 210, 254, 231 }, + { 212, 254, 232 }, { 214, 254, 233 }, { 216, 254, 234 }, { 218, 254, 235 }, { 220, 254, 236 }, { 222, 254, 237 }, { 224, 254, 238 }, { 226, 254, 239 }, + { 228, 254, 240 }, { 230, 254, 241 }, { 232, 254, 242 }, { 234, 254, 243 }, { 236, 252, 244 }, { 238, 252, 245 }, { 238, 254, 246 }, { 240, 254, 247 }, + { 242, 254, 248 }, { 244, 254, 249 }, { 246, 254, 250 }, { 248, 254, 251 }, { 250, 254, 252 }, { 252, 254, 253 }, { 254, 254, 254 }, { 254, 254, 254 }, + } +}; + +Table g_mode6_p1_i1= +{ + 1, + 1, + { + { 1, 1, 1 }, { 1, 1, 1 }, { 1, 9, 2 }, { 1, 25, 3 }, { 1, 41, 4 }, { 1, 57, 5 }, { 1, 73, 6 }, { 1, 89, 7 }, + { 1, 105, 8 }, { 1, 121, 9 }, { 1, 137, 10 }, { 1, 153, 11 }, { 1, 169, 12 }, { 1, 185, 13 }, { 1, 201, 14 }, { 1, 217, 15 }, + { 1, 233, 16 }, { 1, 249, 17 }, { 3, 235, 18 }, { 3, 251, 19 }, { 5, 237, 20 }, { 5, 253, 21 }, { 7, 239, 22 }, { 7, 255, 23 }, + { 9, 241, 24 }, { 11, 227, 25 }, { 11, 243, 26 }, { 13, 229, 27 }, { 13, 245, 28 }, { 15, 231, 29 }, { 15, 247, 30 }, { 17, 233, 31 }, + { 17, 249, 32 }, { 19, 235, 33 }, { 19, 251, 34 }, { 21, 237, 35 }, { 21, 253, 36 }, { 23, 239, 37 }, { 23, 255, 38 }, { 25, 241, 39 }, + { 27, 227, 40 }, { 27, 243, 41 }, { 29, 229, 42 }, { 29, 245, 43 }, { 31, 231, 44 }, { 31, 247, 45 }, { 33, 233, 46 }, { 33, 249, 47 }, + { 35, 235, 48 }, { 35, 251, 49 }, { 37, 237, 50 }, { 37, 253, 51 }, { 39, 239, 52 }, { 39, 255, 53 }, { 41, 241, 54 }, { 43, 227, 55 }, + { 43, 243, 56 }, { 45, 229, 57 }, { 45, 245, 58 }, { 47, 231, 59 }, { 47, 247, 60 }, { 49, 233, 61 }, { 49, 249, 62 }, { 51, 235, 63 }, + { 51, 251, 64 }, { 53, 237, 65 }, { 53, 253, 66 }, { 55, 239, 67 }, { 55, 255, 68 }, { 57, 241, 69 }, { 59, 227, 70 }, { 59, 243, 71 }, + { 61, 229, 72 }, { 61, 245, 73 }, { 63, 231, 74 }, { 63, 247, 75 }, { 65, 233, 76 }, { 65, 249, 77 }, { 67, 235, 78 }, { 67, 251, 79 }, + { 69, 237, 80 }, { 69, 253, 81 }, { 71, 239, 82 }, { 71, 255, 83 }, { 73, 241, 84 }, { 75, 227, 85 }, { 75, 243, 86 }, { 77, 229, 87 }, + { 77, 245, 88 }, { 79, 231, 89 }, { 79, 247, 90 }, { 81, 233, 91 }, { 81, 249, 92 }, { 83, 235, 93 }, { 83, 251, 94 }, { 85, 237, 95 }, + { 85, 253, 96 }, { 87, 239, 97 }, { 87, 255, 98 }, { 89, 241, 99 }, { 91, 227, 100 }, { 91, 243, 101 }, { 93, 229, 102 }, { 93, 245, 103 }, + { 95, 231, 104 }, { 95, 247, 105 }, { 97, 233, 106 }, { 97, 249, 107 }, { 99, 235, 108 }, { 99, 251, 109 }, { 101, 237, 110 }, { 101, 253, 111 }, + { 103, 239, 112 }, { 103, 255, 113 }, { 105, 241, 114 }, { 107, 227, 115 }, { 107, 243, 116 }, { 109, 229, 117 }, { 109, 245, 118 }, { 111, 231, 119 }, + { 111, 247, 120 }, { 113, 233, 121 }, { 113, 249, 122 }, { 115, 235, 123 }, { 115, 251, 124 }, { 117, 237, 125 }, { 117, 253, 126 }, { 119, 239, 127 }, + { 119, 255, 128 }, { 121, 241, 129 }, { 123, 227, 130 }, { 123, 243, 131 }, { 125, 229, 132 }, { 125, 245, 133 }, { 127, 231, 134 }, { 127, 247, 135 }, + { 129, 233, 136 }, { 129, 249, 137 }, { 131, 235, 138 }, { 131, 251, 139 }, { 133, 237, 140 }, { 133, 253, 141 }, { 135, 239, 142 }, { 135, 255, 143 }, + { 137, 241, 144 }, { 139, 227, 145 }, { 139, 243, 146 }, { 141, 229, 147 }, { 141, 245, 148 }, { 143, 231, 149 }, { 143, 247, 150 }, { 145, 233, 151 }, + { 145, 249, 152 }, { 147, 235, 153 }, { 147, 251, 154 }, { 149, 237, 155 }, { 149, 253, 156 }, { 151, 239, 157 }, { 151, 255, 158 }, { 153, 241, 159 }, + { 155, 227, 160 }, { 155, 243, 161 }, { 157, 229, 162 }, { 157, 245, 163 }, { 159, 231, 164 }, { 159, 247, 165 }, { 161, 233, 166 }, { 161, 249, 167 }, + { 163, 235, 168 }, { 163, 251, 169 }, { 165, 237, 170 }, { 165, 253, 171 }, { 167, 239, 172 }, { 167, 255, 173 }, { 169, 241, 174 }, { 171, 227, 175 }, + { 171, 243, 176 }, { 173, 229, 177 }, { 173, 245, 178 }, { 175, 231, 179 }, { 175, 247, 180 }, { 177, 233, 181 }, { 177, 249, 182 }, { 179, 235, 183 }, + { 179, 251, 184 }, { 181, 237, 185 }, { 181, 253, 186 }, { 183, 239, 187 }, { 183, 255, 188 }, { 185, 241, 189 }, { 187, 227, 190 }, { 187, 243, 191 }, + { 189, 229, 192 }, { 189, 245, 193 }, { 191, 231, 194 }, { 191, 247, 195 }, { 193, 233, 196 }, { 193, 249, 197 }, { 195, 235, 198 }, { 195, 251, 199 }, + { 197, 237, 200 }, { 197, 253, 201 }, { 199, 239, 202 }, { 199, 255, 203 }, { 201, 241, 204 }, { 203, 227, 205 }, { 203, 243, 206 }, { 205, 229, 207 }, + { 205, 245, 208 }, { 207, 231, 209 }, { 207, 247, 210 }, { 209, 233, 211 }, { 209, 249, 212 }, { 211, 235, 213 }, { 211, 251, 214 }, { 213, 237, 215 }, + { 213, 253, 216 }, { 215, 239, 217 }, { 215, 255, 218 }, { 217, 241, 219 }, { 219, 227, 220 }, { 219, 243, 221 }, { 221, 229, 222 }, { 221, 245, 223 }, + { 223, 231, 224 }, { 223, 247, 225 }, { 225, 233, 226 }, { 225, 249, 227 }, { 227, 235, 228 }, { 227, 251, 229 }, { 229, 237, 230 }, { 229, 253, 231 }, + { 231, 239, 232 }, { 231, 255, 233 }, { 233, 241, 234 }, { 235, 227, 235 }, { 235, 243, 236 }, { 237, 229, 237 }, { 237, 245, 238 }, { 239, 231, 239 }, + { 239, 247, 240 }, { 241, 233, 241 }, { 241, 249, 242 }, { 243, 235, 243 }, { 243, 251, 244 }, { 245, 237, 245 }, { 245, 253, 246 }, { 247, 239, 247 }, + { 247, 255, 248 }, { 249, 241, 249 }, { 251, 227, 250 }, { 251, 243, 251 }, { 253, 229, 252 }, { 253, 245, 253 }, { 255, 231, 254 }, { 255, 247, 255 }, + } +}; + +Table g_mode6_p1_i2= +{ + 2, + 1, + { + { 1, 1, 1 }, { 1, 1, 1 }, { 1, 5, 2 }, { 1, 13, 3 }, { 1, 19, 4 }, { 1, 27, 5 }, { 1, 33, 6 }, { 1, 41, 7 }, + { 1, 49, 8 }, { 1, 55, 9 }, { 1, 63, 10 }, { 1, 69, 11 }, { 1, 77, 12 }, { 1, 83, 13 }, { 1, 91, 14 }, { 1, 97, 15 }, + { 1, 105, 16 }, { 1, 113, 17 }, { 1, 119, 18 }, { 1, 127, 19 }, { 1, 133, 20 }, { 1, 141, 21 }, { 1, 147, 22 }, { 1, 155, 23 }, + { 1, 161, 24 }, { 1, 169, 25 }, { 1, 177, 26 }, { 1, 183, 27 }, { 1, 191, 28 }, { 1, 197, 29 }, { 1, 205, 30 }, { 1, 211, 31 }, + { 1, 219, 32 }, { 1, 225, 33 }, { 1, 233, 34 }, { 1, 241, 35 }, { 1, 247, 36 }, { 1, 255, 37 }, { 3, 249, 38 }, { 5, 245, 39 }, + { 5, 251, 40 }, { 7, 247, 41 }, { 7, 253, 42 }, { 9, 249, 43 }, { 9, 255, 44 }, { 11, 251, 45 }, { 13, 245, 46 }, { 13, 253, 47 }, + { 15, 247, 48 }, { 15, 255, 49 }, { 17, 249, 50 }, { 19, 243, 51 }, { 19, 251, 52 }, { 21, 245, 53 }, { 21, 253, 54 }, { 23, 247, 55 }, + { 23, 255, 56 }, { 25, 249, 57 }, { 27, 245, 58 }, { 27, 251, 59 }, { 29, 247, 60 }, { 29, 253, 61 }, { 31, 249, 62 }, { 31, 255, 63 }, + { 33, 251, 64 }, { 35, 245, 65 }, { 35, 253, 66 }, { 37, 247, 67 }, { 37, 255, 68 }, { 39, 249, 69 }, { 41, 245, 70 }, { 41, 251, 71 }, + { 43, 247, 72 }, { 43, 253, 73 }, { 45, 249, 74 }, { 45, 255, 75 }, { 47, 251, 76 }, { 49, 245, 77 }, { 49, 253, 78 }, { 51, 247, 79 }, + { 51, 255, 80 }, { 53, 249, 81 }, { 55, 245, 82 }, { 55, 251, 83 }, { 57, 247, 84 }, { 57, 253, 85 }, { 59, 249, 86 }, { 59, 255, 87 }, + { 61, 251, 88 }, { 63, 245, 89 }, { 63, 253, 90 }, { 65, 247, 91 }, { 65, 255, 92 }, { 67, 249, 93 }, { 69, 245, 94 }, { 69, 251, 95 }, + { 71, 247, 96 }, { 71, 253, 97 }, { 73, 249, 98 }, { 73, 255, 99 }, { 75, 251, 100 }, { 77, 245, 101 }, { 77, 253, 102 }, { 79, 247, 103 }, + { 79, 255, 104 }, { 81, 249, 105 }, { 83, 243, 106 }, { 83, 251, 107 }, { 85, 245, 108 }, { 85, 253, 109 }, { 87, 247, 110 }, { 87, 255, 111 }, + { 89, 249, 112 }, { 91, 245, 113 }, { 91, 251, 114 }, { 93, 247, 115 }, { 93, 253, 116 }, { 95, 249, 117 }, { 95, 255, 118 }, { 97, 251, 119 }, + { 99, 245, 120 }, { 99, 253, 121 }, { 101, 247, 122 }, { 101, 255, 123 }, { 103, 249, 124 }, { 105, 245, 125 }, { 105, 251, 126 }, { 107, 247, 127 }, + { 107, 253, 128 }, { 109, 249, 129 }, { 109, 255, 130 }, { 111, 251, 131 }, { 113, 245, 132 }, { 113, 253, 133 }, { 115, 247, 134 }, { 115, 255, 135 }, + { 117, 249, 136 }, { 119, 245, 137 }, { 119, 251, 138 }, { 121, 247, 139 }, { 121, 253, 140 }, { 123, 249, 141 }, { 123, 255, 142 }, { 125, 251, 143 }, + { 127, 245, 144 }, { 127, 253, 145 }, { 129, 247, 146 }, { 129, 255, 147 }, { 131, 249, 148 }, { 133, 245, 149 }, { 133, 251, 150 }, { 135, 247, 151 }, + { 135, 253, 152 }, { 137, 249, 153 }, { 137, 255, 154 }, { 139, 251, 155 }, { 141, 245, 156 }, { 141, 253, 157 }, { 143, 247, 158 }, { 143, 255, 159 }, + { 145, 249, 160 }, { 147, 243, 161 }, { 147, 251, 162 }, { 149, 245, 163 }, { 149, 253, 164 }, { 151, 247, 165 }, { 151, 255, 166 }, { 153, 249, 167 }, + { 155, 245, 168 }, { 155, 251, 169 }, { 157, 247, 170 }, { 157, 253, 171 }, { 159, 249, 172 }, { 159, 255, 173 }, { 161, 251, 174 }, { 163, 245, 175 }, + { 163, 253, 176 }, { 165, 247, 177 }, { 165, 255, 178 }, { 167, 249, 179 }, { 169, 245, 180 }, { 169, 251, 181 }, { 171, 247, 182 }, { 171, 253, 183 }, + { 173, 249, 184 }, { 173, 255, 185 }, { 175, 251, 186 }, { 177, 245, 187 }, { 177, 253, 188 }, { 179, 247, 189 }, { 179, 255, 190 }, { 181, 249, 191 }, + { 183, 245, 192 }, { 183, 251, 193 }, { 185, 247, 194 }, { 185, 253, 195 }, { 187, 249, 196 }, { 187, 255, 197 }, { 189, 251, 198 }, { 191, 245, 199 }, + { 191, 253, 200 }, { 193, 247, 201 }, { 193, 255, 202 }, { 195, 249, 203 }, { 197, 245, 204 }, { 197, 251, 205 }, { 199, 247, 206 }, { 199, 253, 207 }, + { 201, 249, 208 }, { 201, 255, 209 }, { 203, 251, 210 }, { 205, 245, 211 }, { 205, 253, 212 }, { 207, 247, 213 }, { 207, 255, 214 }, { 209, 249, 215 }, + { 211, 243, 216 }, { 211, 251, 217 }, { 213, 245, 218 }, { 213, 253, 219 }, { 215, 247, 220 }, { 215, 255, 221 }, { 217, 249, 222 }, { 219, 245, 223 }, + { 219, 251, 224 }, { 221, 247, 225 }, { 221, 253, 226 }, { 223, 249, 227 }, { 223, 255, 228 }, { 225, 251, 229 }, { 227, 245, 230 }, { 227, 253, 231 }, + { 229, 247, 232 }, { 229, 255, 233 }, { 231, 249, 234 }, { 233, 245, 235 }, { 233, 251, 236 }, { 235, 247, 237 }, { 235, 253, 238 }, { 237, 249, 239 }, + { 237, 255, 240 }, { 239, 251, 241 }, { 241, 245, 242 }, { 241, 253, 243 }, { 243, 247, 244 }, { 243, 255, 245 }, { 245, 249, 246 }, { 247, 245, 247 }, + { 247, 251, 248 }, { 249, 247, 249 }, { 249, 253, 250 }, { 251, 249, 251 }, { 251, 255, 252 }, { 253, 251, 253 }, { 255, 245, 254 }, { 255, 253, 255 }, + } +}; + +Table g_mode6_p1_i3= +{ + 3, + 1, + { + { 1, 1, 1 }, { 1, 1, 1 }, { 1, 5, 2 }, { 1, 9, 3 }, { 1, 15, 4 }, { 1, 19, 5 }, { 1, 25, 6 }, { 1, 29, 7 }, + { 1, 33, 8 }, { 1, 39, 9 }, { 1, 43, 10 }, { 1, 49, 11 }, { 1, 53, 12 }, { 1, 59, 13 }, { 1, 63, 14 }, { 1, 69, 15 }, + { 1, 73, 16 }, { 1, 79, 17 }, { 1, 83, 18 }, { 1, 89, 19 }, { 1, 93, 20 }, { 1, 97, 21 }, { 1, 103, 22 }, { 1, 107, 23 }, + { 1, 113, 24 }, { 1, 117, 25 }, { 1, 123, 26 }, { 1, 127, 27 }, { 1, 133, 28 }, { 1, 137, 29 }, { 1, 143, 30 }, { 1, 147, 31 }, + { 1, 153, 32 }, { 1, 157, 33 }, { 1, 161, 34 }, { 1, 167, 35 }, { 1, 171, 36 }, { 1, 177, 37 }, { 1, 181, 38 }, { 1, 187, 39 }, + { 1, 191, 40 }, { 1, 197, 41 }, { 1, 201, 42 }, { 1, 207, 43 }, { 1, 211, 44 }, { 1, 217, 45 }, { 1, 221, 46 }, { 1, 225, 47 }, + { 1, 231, 48 }, { 1, 235, 49 }, { 1, 241, 50 }, { 1, 245, 51 }, { 1, 251, 52 }, { 1, 255, 53 }, { 3, 253, 54 }, { 5, 249, 55 }, + { 5, 255, 56 }, { 7, 251, 57 }, { 9, 249, 58 }, { 9, 253, 59 }, { 11, 251, 60 }, { 11, 255, 61 }, { 13, 253, 62 }, { 15, 249, 63 }, + { 15, 255, 64 }, { 17, 251, 65 }, { 19, 249, 66 }, { 19, 253, 67 }, { 21, 251, 68 }, { 21, 255, 69 }, { 23, 253, 70 }, { 25, 249, 71 }, + { 25, 255, 72 }, { 27, 251, 73 }, { 29, 249, 74 }, { 29, 253, 75 }, { 31, 251, 76 }, { 31, 255, 77 }, { 33, 253, 78 }, { 35, 251, 79 }, + { 35, 255, 80 }, { 37, 253, 81 }, { 39, 249, 82 }, { 39, 255, 83 }, { 41, 251, 84 }, { 43, 249, 85 }, { 43, 253, 86 }, { 45, 251, 87 }, + { 45, 255, 88 }, { 47, 253, 89 }, { 49, 249, 90 }, { 49, 255, 91 }, { 51, 251, 92 }, { 53, 249, 93 }, { 53, 253, 94 }, { 55, 251, 95 }, + { 55, 255, 96 }, { 57, 253, 97 }, { 59, 249, 98 }, { 59, 255, 99 }, { 61, 251, 100 }, { 63, 249, 101 }, { 63, 253, 102 }, { 65, 251, 103 }, + { 65, 255, 104 }, { 67, 253, 105 }, { 69, 249, 106 }, { 69, 255, 107 }, { 71, 251, 108 }, { 73, 249, 109 }, { 73, 253, 110 }, { 75, 251, 111 }, + { 75, 255, 112 }, { 77, 253, 113 }, { 79, 249, 114 }, { 79, 255, 115 }, { 81, 251, 116 }, { 83, 249, 117 }, { 83, 253, 118 }, { 85, 251, 119 }, + { 85, 255, 120 }, { 87, 253, 121 }, { 89, 249, 122 }, { 89, 255, 123 }, { 91, 251, 124 }, { 93, 249, 125 }, { 93, 253, 126 }, { 95, 251, 127 }, + { 95, 255, 128 }, { 97, 253, 129 }, { 99, 251, 130 }, { 99, 255, 131 }, { 101, 253, 132 }, { 103, 249, 133 }, { 103, 255, 134 }, { 105, 251, 135 }, + { 107, 249, 136 }, { 107, 253, 137 }, { 109, 251, 138 }, { 109, 255, 139 }, { 111, 253, 140 }, { 113, 249, 141 }, { 113, 255, 142 }, { 115, 251, 143 }, + { 117, 249, 144 }, { 117, 253, 145 }, { 119, 251, 146 }, { 119, 255, 147 }, { 121, 253, 148 }, { 123, 249, 149 }, { 123, 255, 150 }, { 125, 251, 151 }, + { 127, 249, 152 }, { 127, 253, 153 }, { 129, 251, 154 }, { 129, 255, 155 }, { 131, 253, 156 }, { 133, 249, 157 }, { 133, 255, 158 }, { 135, 251, 159 }, + { 137, 249, 160 }, { 137, 253, 161 }, { 139, 251, 162 }, { 139, 255, 163 }, { 141, 253, 164 }, { 143, 249, 165 }, { 143, 255, 166 }, { 145, 251, 167 }, + { 147, 249, 168 }, { 147, 253, 169 }, { 149, 251, 170 }, { 149, 255, 171 }, { 151, 253, 172 }, { 153, 249, 173 }, { 153, 255, 174 }, { 155, 251, 175 }, + { 157, 249, 176 }, { 157, 253, 177 }, { 159, 251, 178 }, { 159, 255, 179 }, { 161, 253, 180 }, { 163, 251, 181 }, { 163, 255, 182 }, { 165, 253, 183 }, + { 167, 249, 184 }, { 167, 255, 185 }, { 169, 251, 186 }, { 171, 249, 187 }, { 171, 253, 188 }, { 173, 251, 189 }, { 173, 255, 190 }, { 175, 253, 191 }, + { 177, 249, 192 }, { 177, 255, 193 }, { 179, 251, 194 }, { 181, 249, 195 }, { 181, 253, 196 }, { 183, 251, 197 }, { 183, 255, 198 }, { 185, 253, 199 }, + { 187, 249, 200 }, { 187, 255, 201 }, { 189, 251, 202 }, { 191, 249, 203 }, { 191, 253, 204 }, { 193, 251, 205 }, { 193, 255, 206 }, { 195, 253, 207 }, + { 197, 249, 208 }, { 197, 255, 209 }, { 199, 251, 210 }, { 201, 249, 211 }, { 201, 253, 212 }, { 203, 251, 213 }, { 203, 255, 214 }, { 205, 253, 215 }, + { 207, 249, 216 }, { 207, 255, 217 }, { 209, 251, 218 }, { 211, 249, 219 }, { 211, 253, 220 }, { 213, 251, 221 }, { 213, 255, 222 }, { 215, 253, 223 }, + { 217, 249, 224 }, { 217, 255, 225 }, { 219, 251, 226 }, { 221, 249, 227 }, { 221, 253, 228 }, { 223, 251, 229 }, { 223, 255, 230 }, { 225, 253, 231 }, + { 227, 251, 232 }, { 227, 255, 233 }, { 229, 253, 234 }, { 231, 249, 235 }, { 231, 255, 236 }, { 233, 251, 237 }, { 235, 249, 238 }, { 235, 253, 239 }, + { 237, 251, 240 }, { 237, 255, 241 }, { 239, 253, 242 }, { 241, 249, 243 }, { 241, 255, 244 }, { 243, 251, 245 }, { 245, 249, 246 }, { 245, 253, 247 }, + { 247, 251, 248 }, { 247, 255, 249 }, { 249, 253, 250 }, { 251, 249, 251 }, { 251, 255, 252 }, { 253, 251, 253 }, { 255, 249, 254 }, { 255, 253, 255 }, + } +}; + +Table g_mode6_p1_i4= +{ + 4, + 1, + { + { 1, 1, 1 }, { 1, 1, 1 }, { 1, 3, 2 }, { 1, 7, 3 }, { 1, 11, 4 }, { 1, 15, 5 }, { 1, 19, 6 }, { 1, 23, 7 }, + { 1, 27, 8 }, { 1, 31, 9 }, { 1, 33, 10 }, { 1, 37, 11 }, { 1, 41, 12 }, { 1, 45, 13 }, { 1, 49, 14 }, { 1, 53, 15 }, + { 1, 57, 16 }, { 1, 61, 17 }, { 1, 65, 18 }, { 1, 67, 19 }, { 1, 71, 20 }, { 1, 75, 21 }, { 1, 79, 22 }, { 1, 83, 23 }, + { 1, 87, 24 }, { 1, 91, 25 }, { 1, 95, 26 }, { 1, 97, 27 }, { 1, 101, 28 }, { 1, 105, 29 }, { 1, 109, 30 }, { 1, 113, 31 }, + { 1, 117, 32 }, { 1, 121, 33 }, { 1, 125, 34 }, { 1, 129, 35 }, { 1, 131, 36 }, { 1, 135, 37 }, { 1, 139, 38 }, { 1, 143, 39 }, + { 1, 147, 40 }, { 1, 151, 41 }, { 1, 155, 42 }, { 1, 159, 43 }, { 1, 161, 44 }, { 1, 165, 45 }, { 1, 169, 46 }, { 1, 173, 47 }, + { 1, 177, 48 }, { 1, 181, 49 }, { 1, 185, 50 }, { 1, 189, 51 }, { 1, 193, 52 }, { 1, 195, 53 }, { 1, 199, 54 }, { 1, 203, 55 }, + { 1, 207, 56 }, { 1, 211, 57 }, { 1, 215, 58 }, { 1, 219, 59 }, { 1, 223, 60 }, { 1, 225, 61 }, { 1, 229, 62 }, { 1, 233, 63 }, + { 1, 237, 64 }, { 1, 241, 65 }, { 1, 245, 66 }, { 1, 249, 67 }, { 1, 253, 68 }, { 3, 251, 69 }, { 3, 255, 70 }, { 5, 253, 71 }, + { 7, 251, 72 }, { 7, 255, 73 }, { 9, 253, 74 }, { 11, 251, 75 }, { 11, 255, 76 }, { 13, 253, 77 }, { 15, 251, 78 }, { 15, 255, 79 }, + { 17, 253, 80 }, { 19, 251, 81 }, { 19, 255, 82 }, { 21, 253, 83 }, { 23, 251, 84 }, { 23, 255, 85 }, { 25, 253, 86 }, { 27, 251, 87 }, + { 27, 255, 88 }, { 29, 253, 89 }, { 31, 253, 90 }, { 31, 255, 91 }, { 33, 255, 92 }, { 35, 253, 93 }, { 37, 251, 94 }, { 37, 255, 95 }, + { 39, 253, 96 }, { 41, 251, 97 }, { 41, 255, 98 }, { 43, 253, 99 }, { 45, 251, 100 }, { 45, 255, 101 }, { 47, 253, 102 }, { 49, 251, 103 }, + { 49, 255, 104 }, { 51, 253, 105 }, { 53, 251, 106 }, { 53, 255, 107 }, { 55, 253, 108 }, { 57, 251, 109 }, { 57, 255, 110 }, { 59, 253, 111 }, + { 61, 253, 112 }, { 61, 255, 113 }, { 63, 255, 114 }, { 65, 253, 115 }, { 67, 251, 116 }, { 67, 255, 117 }, { 69, 253, 118 }, { 71, 251, 119 }, + { 71, 255, 120 }, { 73, 253, 121 }, { 75, 251, 122 }, { 75, 255, 123 }, { 77, 253, 124 }, { 79, 251, 125 }, { 79, 255, 126 }, { 81, 253, 127 }, + { 83, 251, 128 }, { 83, 255, 129 }, { 85, 253, 130 }, { 87, 251, 131 }, { 87, 255, 132 }, { 89, 253, 133 }, { 91, 251, 134 }, { 91, 255, 135 }, + { 93, 253, 136 }, { 95, 253, 137 }, { 95, 255, 138 }, { 97, 255, 139 }, { 99, 253, 140 }, { 101, 251, 141 }, { 101, 255, 142 }, { 103, 253, 143 }, + { 105, 251, 144 }, { 105, 255, 145 }, { 107, 253, 146 }, { 109, 251, 147 }, { 109, 255, 148 }, { 111, 253, 149 }, { 113, 251, 150 }, { 113, 255, 151 }, + { 115, 253, 152 }, { 117, 251, 153 }, { 117, 255, 154 }, { 119, 253, 155 }, { 121, 251, 156 }, { 121, 255, 157 }, { 123, 253, 158 }, { 125, 253, 159 }, + { 125, 255, 160 }, { 127, 255, 161 }, { 129, 253, 162 }, { 131, 251, 163 }, { 131, 255, 164 }, { 133, 253, 165 }, { 135, 251, 166 }, { 135, 255, 167 }, + { 137, 253, 168 }, { 139, 251, 169 }, { 139, 255, 170 }, { 141, 253, 171 }, { 143, 251, 172 }, { 143, 255, 173 }, { 145, 253, 174 }, { 147, 251, 175 }, + { 147, 255, 176 }, { 149, 253, 177 }, { 151, 251, 178 }, { 151, 255, 179 }, { 153, 253, 180 }, { 155, 251, 181 }, { 155, 255, 182 }, { 157, 253, 183 }, + { 159, 253, 184 }, { 159, 255, 185 }, { 161, 255, 186 }, { 163, 253, 187 }, { 165, 251, 188 }, { 165, 255, 189 }, { 167, 253, 190 }, { 169, 251, 191 }, + { 169, 255, 192 }, { 171, 253, 193 }, { 173, 251, 194 }, { 173, 255, 195 }, { 175, 253, 196 }, { 177, 251, 197 }, { 177, 255, 198 }, { 179, 253, 199 }, + { 181, 251, 200 }, { 181, 255, 201 }, { 183, 253, 202 }, { 185, 251, 203 }, { 185, 255, 204 }, { 187, 253, 205 }, { 189, 253, 206 }, { 189, 255, 207 }, + { 191, 255, 208 }, { 193, 253, 209 }, { 195, 251, 210 }, { 195, 255, 211 }, { 197, 253, 212 }, { 199, 251, 213 }, { 199, 255, 214 }, { 201, 253, 215 }, + { 203, 251, 216 }, { 203, 255, 217 }, { 205, 253, 218 }, { 207, 251, 219 }, { 207, 255, 220 }, { 209, 253, 221 }, { 211, 251, 222 }, { 211, 255, 223 }, + { 213, 253, 224 }, { 215, 251, 225 }, { 215, 255, 226 }, { 217, 253, 227 }, { 219, 251, 228 }, { 219, 255, 229 }, { 221, 253, 230 }, { 223, 253, 231 }, + { 223, 255, 232 }, { 225, 255, 233 }, { 227, 253, 234 }, { 229, 251, 235 }, { 229, 255, 236 }, { 231, 253, 237 }, { 233, 251, 238 }, { 233, 255, 239 }, + { 235, 253, 240 }, { 237, 251, 241 }, { 237, 255, 242 }, { 239, 253, 243 }, { 241, 251, 244 }, { 241, 255, 245 }, { 243, 253, 246 }, { 245, 251, 247 }, + { 245, 255, 248 }, { 247, 253, 249 }, { 249, 251, 250 }, { 249, 255, 251 }, { 251, 253, 252 }, { 253, 253, 253 }, { 253, 255, 254 }, { 255, 255, 255 }, + } +}; + +Table g_mode6_p1_i5= +{ + 5, + 1, + { + { 1, 1, 1 }, { 1, 1, 1 }, { 1, 3, 2 }, { 1, 7, 3 }, { 1, 9, 4 }, { 1, 13, 5 }, { 1, 15, 6 }, { 1, 19, 7 }, + { 1, 21, 8 }, { 1, 25, 9 }, { 1, 27, 10 }, { 1, 31, 11 }, { 1, 33, 12 }, { 1, 37, 13 }, { 1, 41, 14 }, { 1, 43, 15 }, + { 1, 47, 16 }, { 1, 49, 17 }, { 1, 53, 18 }, { 1, 55, 19 }, { 1, 59, 20 }, { 1, 61, 21 }, { 1, 65, 22 }, { 1, 67, 23 }, + { 1, 71, 24 }, { 1, 73, 25 }, { 1, 77, 26 }, { 1, 79, 27 }, { 1, 83, 28 }, { 1, 85, 29 }, { 1, 89, 30 }, { 1, 91, 31 }, + { 1, 95, 32 }, { 1, 97, 33 }, { 1, 101, 34 }, { 1, 105, 35 }, { 1, 107, 36 }, { 1, 111, 37 }, { 1, 113, 38 }, { 1, 117, 39 }, + { 1, 119, 40 }, { 1, 123, 41 }, { 1, 125, 42 }, { 1, 129, 43 }, { 1, 131, 44 }, { 1, 135, 45 }, { 1, 137, 46 }, { 1, 141, 47 }, + { 1, 143, 48 }, { 1, 147, 49 }, { 1, 149, 50 }, { 1, 153, 51 }, { 1, 155, 52 }, { 1, 159, 53 }, { 1, 161, 54 }, { 1, 165, 55 }, + { 1, 169, 56 }, { 1, 171, 57 }, { 1, 175, 58 }, { 1, 177, 59 }, { 1, 181, 60 }, { 1, 183, 61 }, { 1, 187, 62 }, { 1, 189, 63 }, + { 1, 193, 64 }, { 1, 195, 65 }, { 1, 199, 66 }, { 1, 201, 67 }, { 1, 205, 68 }, { 1, 207, 69 }, { 1, 211, 70 }, { 1, 213, 71 }, + { 1, 217, 72 }, { 1, 219, 73 }, { 1, 223, 74 }, { 1, 225, 75 }, { 1, 229, 76 }, { 1, 233, 77 }, { 1, 235, 78 }, { 1, 239, 79 }, + { 1, 241, 80 }, { 1, 245, 81 }, { 1, 247, 82 }, { 1, 251, 83 }, { 1, 253, 84 }, { 3, 253, 85 }, { 3, 255, 86 }, { 5, 255, 87 }, + { 7, 253, 88 }, { 9, 253, 89 }, { 9, 255, 90 }, { 11, 255, 91 }, { 13, 253, 92 }, { 15, 253, 93 }, { 15, 255, 94 }, { 17, 255, 95 }, + { 19, 253, 96 }, { 21, 253, 97 }, { 21, 255, 98 }, { 23, 255, 99 }, { 25, 253, 100 }, { 27, 251, 101 }, { 27, 255, 102 }, { 29, 253, 103 }, + { 31, 253, 104 }, { 31, 255, 105 }, { 33, 255, 106 }, { 35, 253, 107 }, { 37, 253, 108 }, { 37, 255, 109 }, { 39, 255, 110 }, { 41, 253, 111 }, + { 43, 253, 112 }, { 43, 255, 113 }, { 45, 255, 114 }, { 47, 253, 115 }, { 49, 253, 116 }, { 49, 255, 117 }, { 51, 255, 118 }, { 53, 253, 119 }, + { 55, 253, 120 }, { 55, 255, 121 }, { 57, 255, 122 }, { 59, 253, 123 }, { 61, 253, 124 }, { 61, 255, 125 }, { 63, 255, 126 }, { 65, 253, 127 }, + { 67, 253, 128 }, { 67, 255, 129 }, { 69, 255, 130 }, { 71, 253, 131 }, { 73, 253, 132 }, { 73, 255, 133 }, { 75, 255, 134 }, { 77, 253, 135 }, + { 79, 253, 136 }, { 79, 255, 137 }, { 81, 255, 138 }, { 83, 253, 139 }, { 85, 253, 140 }, { 85, 255, 141 }, { 87, 255, 142 }, { 89, 253, 143 }, + { 91, 251, 144 }, { 91, 255, 145 }, { 93, 253, 146 }, { 95, 253, 147 }, { 95, 255, 148 }, { 97, 255, 149 }, { 99, 253, 150 }, { 101, 253, 151 }, + { 101, 255, 152 }, { 103, 255, 153 }, { 105, 253, 154 }, { 107, 253, 155 }, { 107, 255, 156 }, { 109, 255, 157 }, { 111, 253, 158 }, { 113, 253, 159 }, + { 113, 255, 160 }, { 115, 255, 161 }, { 117, 253, 162 }, { 119, 253, 163 }, { 119, 255, 164 }, { 121, 255, 165 }, { 123, 253, 166 }, { 125, 253, 167 }, + { 125, 255, 168 }, { 127, 255, 169 }, { 129, 253, 170 }, { 131, 253, 171 }, { 131, 255, 172 }, { 133, 255, 173 }, { 135, 253, 174 }, { 137, 253, 175 }, + { 137, 255, 176 }, { 139, 255, 177 }, { 141, 253, 178 }, { 143, 253, 179 }, { 143, 255, 180 }, { 145, 255, 181 }, { 147, 253, 182 }, { 149, 253, 183 }, + { 149, 255, 184 }, { 151, 255, 185 }, { 153, 253, 186 }, { 155, 251, 187 }, { 155, 255, 188 }, { 157, 253, 189 }, { 159, 253, 190 }, { 159, 255, 191 }, + { 161, 255, 192 }, { 163, 253, 193 }, { 165, 253, 194 }, { 165, 255, 195 }, { 167, 255, 196 }, { 169, 253, 197 }, { 171, 253, 198 }, { 171, 255, 199 }, + { 173, 255, 200 }, { 175, 253, 201 }, { 177, 253, 202 }, { 177, 255, 203 }, { 179, 255, 204 }, { 181, 253, 205 }, { 183, 253, 206 }, { 183, 255, 207 }, + { 185, 255, 208 }, { 187, 253, 209 }, { 189, 253, 210 }, { 189, 255, 211 }, { 191, 255, 212 }, { 193, 253, 213 }, { 195, 253, 214 }, { 195, 255, 215 }, + { 197, 255, 216 }, { 199, 253, 217 }, { 201, 253, 218 }, { 201, 255, 219 }, { 203, 255, 220 }, { 205, 253, 221 }, { 207, 253, 222 }, { 207, 255, 223 }, + { 209, 255, 224 }, { 211, 253, 225 }, { 213, 253, 226 }, { 213, 255, 227 }, { 215, 255, 228 }, { 217, 253, 229 }, { 219, 251, 230 }, { 219, 255, 231 }, + { 221, 253, 232 }, { 223, 253, 233 }, { 223, 255, 234 }, { 225, 255, 235 }, { 227, 253, 236 }, { 229, 253, 237 }, { 229, 255, 238 }, { 231, 255, 239 }, + { 233, 253, 240 }, { 235, 253, 241 }, { 235, 255, 242 }, { 237, 255, 243 }, { 239, 253, 244 }, { 241, 253, 245 }, { 241, 255, 246 }, { 243, 255, 247 }, + { 245, 253, 248 }, { 247, 253, 249 }, { 247, 255, 250 }, { 249, 255, 251 }, { 251, 253, 252 }, { 253, 253, 253 }, { 253, 255, 254 }, { 255, 255, 255 }, + } +}; + +Table g_mode6_p1_i6= +{ + 6, + 1, + { + { 1, 1, 1 }, { 1, 1, 1 }, { 1, 3, 2 }, { 1, 5, 3 }, { 1, 9, 4 }, { 1, 11, 5 }, { 1, 13, 6 }, { 1, 15, 7 }, + { 1, 17, 8 }, { 1, 21, 9 }, { 1, 23, 10 }, { 1, 25, 11 }, { 1, 27, 12 }, { 1, 31, 13 }, { 1, 33, 14 }, { 1, 35, 15 }, + { 1, 37, 16 }, { 1, 41, 17 }, { 1, 43, 18 }, { 1, 45, 19 }, { 1, 47, 20 }, { 1, 49, 21 }, { 1, 53, 22 }, { 1, 55, 23 }, + { 1, 57, 24 }, { 1, 59, 25 }, { 1, 63, 26 }, { 1, 65, 27 }, { 1, 67, 28 }, { 1, 69, 29 }, { 1, 73, 30 }, { 1, 75, 31 }, + { 1, 77, 32 }, { 1, 79, 33 }, { 1, 81, 34 }, { 1, 85, 35 }, { 1, 87, 36 }, { 1, 89, 37 }, { 1, 91, 38 }, { 1, 95, 39 }, + { 1, 97, 40 }, { 1, 99, 41 }, { 1, 101, 42 }, { 1, 105, 43 }, { 1, 107, 44 }, { 1, 109, 45 }, { 1, 111, 46 }, { 1, 113, 47 }, + { 1, 117, 48 }, { 1, 119, 49 }, { 1, 121, 50 }, { 1, 123, 51 }, { 1, 127, 52 }, { 1, 129, 53 }, { 1, 131, 54 }, { 1, 133, 55 }, + { 1, 137, 56 }, { 1, 139, 57 }, { 1, 141, 58 }, { 1, 143, 59 }, { 1, 145, 60 }, { 1, 149, 61 }, { 1, 151, 62 }, { 1, 153, 63 }, + { 1, 155, 64 }, { 1, 159, 65 }, { 1, 161, 66 }, { 1, 163, 67 }, { 1, 165, 68 }, { 1, 169, 69 }, { 1, 171, 70 }, { 1, 173, 71 }, + { 1, 175, 72 }, { 1, 177, 73 }, { 1, 181, 74 }, { 1, 183, 75 }, { 1, 185, 76 }, { 1, 187, 77 }, { 1, 191, 78 }, { 1, 193, 79 }, + { 1, 195, 80 }, { 1, 197, 81 }, { 1, 201, 82 }, { 1, 203, 83 }, { 1, 205, 84 }, { 1, 207, 85 }, { 1, 209, 86 }, { 1, 213, 87 }, + { 1, 215, 88 }, { 1, 217, 89 }, { 1, 219, 90 }, { 1, 223, 91 }, { 1, 225, 92 }, { 1, 227, 93 }, { 1, 229, 94 }, { 1, 233, 95 }, + { 1, 235, 96 }, { 1, 237, 97 }, { 1, 239, 98 }, { 1, 241, 99 }, { 1, 245, 100 }, { 1, 247, 101 }, { 1, 249, 102 }, { 1, 251, 103 }, + { 1, 255, 104 }, { 3, 253, 105 }, { 5, 253, 106 }, { 5, 255, 107 }, { 7, 255, 108 }, { 9, 255, 109 }, { 11, 255, 110 }, { 13, 253, 111 }, + { 15, 253, 112 }, { 15, 255, 113 }, { 17, 255, 114 }, { 19, 255, 115 }, { 21, 255, 116 }, { 23, 255, 117 }, { 25, 253, 118 }, { 27, 253, 119 }, + { 27, 255, 120 }, { 29, 255, 121 }, { 31, 255, 122 }, { 33, 255, 123 }, { 35, 253, 124 }, { 37, 253, 125 }, { 37, 255, 126 }, { 39, 255, 127 }, + { 41, 255, 128 }, { 43, 255, 129 }, { 45, 253, 130 }, { 47, 253, 131 }, { 47, 255, 132 }, { 49, 255, 133 }, { 51, 255, 134 }, { 53, 255, 135 }, + { 55, 255, 136 }, { 57, 253, 137 }, { 59, 253, 138 }, { 59, 255, 139 }, { 61, 255, 140 }, { 63, 255, 141 }, { 65, 255, 142 }, { 67, 253, 143 }, + { 69, 253, 144 }, { 69, 255, 145 }, { 71, 255, 146 }, { 73, 255, 147 }, { 75, 255, 148 }, { 77, 253, 149 }, { 79, 253, 150 }, { 79, 255, 151 }, + { 81, 255, 152 }, { 83, 255, 153 }, { 85, 255, 154 }, { 87, 255, 155 }, { 89, 253, 156 }, { 91, 253, 157 }, { 91, 255, 158 }, { 93, 255, 159 }, + { 95, 255, 160 }, { 97, 255, 161 }, { 99, 253, 162 }, { 101, 253, 163 }, { 101, 255, 164 }, { 103, 255, 165 }, { 105, 255, 166 }, { 107, 255, 167 }, + { 109, 253, 168 }, { 111, 253, 169 }, { 111, 255, 170 }, { 113, 255, 171 }, { 115, 255, 172 }, { 117, 255, 173 }, { 119, 255, 174 }, { 121, 253, 175 }, + { 123, 253, 176 }, { 123, 255, 177 }, { 125, 255, 178 }, { 127, 255, 179 }, { 129, 255, 180 }, { 131, 253, 181 }, { 133, 253, 182 }, { 133, 255, 183 }, + { 135, 255, 184 }, { 137, 255, 185 }, { 139, 255, 186 }, { 141, 253, 187 }, { 143, 253, 188 }, { 143, 255, 189 }, { 145, 255, 190 }, { 147, 255, 191 }, + { 149, 255, 192 }, { 151, 255, 193 }, { 153, 253, 194 }, { 155, 253, 195 }, { 155, 255, 196 }, { 157, 255, 197 }, { 159, 255, 198 }, { 161, 255, 199 }, + { 163, 253, 200 }, { 165, 253, 201 }, { 165, 255, 202 }, { 167, 255, 203 }, { 169, 255, 204 }, { 171, 255, 205 }, { 173, 253, 206 }, { 175, 253, 207 }, + { 175, 255, 208 }, { 177, 255, 209 }, { 179, 255, 210 }, { 181, 255, 211 }, { 183, 255, 212 }, { 185, 253, 213 }, { 187, 253, 214 }, { 187, 255, 215 }, + { 189, 255, 216 }, { 191, 255, 217 }, { 193, 255, 218 }, { 195, 253, 219 }, { 197, 253, 220 }, { 197, 255, 221 }, { 199, 255, 222 }, { 201, 255, 223 }, + { 203, 255, 224 }, { 205, 253, 225 }, { 207, 253, 226 }, { 207, 255, 227 }, { 209, 255, 228 }, { 211, 255, 229 }, { 213, 255, 230 }, { 215, 255, 231 }, + { 217, 253, 232 }, { 219, 253, 233 }, { 219, 255, 234 }, { 221, 255, 235 }, { 223, 255, 236 }, { 225, 255, 237 }, { 227, 253, 238 }, { 229, 253, 239 }, + { 229, 255, 240 }, { 231, 255, 241 }, { 233, 255, 242 }, { 235, 255, 243 }, { 237, 253, 244 }, { 239, 253, 245 }, { 239, 255, 246 }, { 241, 255, 247 }, + { 243, 255, 248 }, { 245, 255, 249 }, { 247, 255, 250 }, { 249, 253, 251 }, { 251, 253, 252 }, { 251, 255, 253 }, { 253, 255, 254 }, { 255, 255, 255 }, + } +}; + +Table g_mode6_p1_i7= +{ + 7, + 1, + { + { 1, 1, 1 }, { 1, 1, 1 }, { 1, 3, 2 }, { 1, 5, 3 }, { 1, 7, 4 }, { 1, 9, 5 }, { 1, 11, 6 }, { 1, 13, 7 }, + { 1, 15, 8 }, { 1, 17, 9 }, { 1, 21, 10 }, { 1, 23, 11 }, { 1, 25, 12 }, { 1, 27, 13 }, { 1, 29, 14 }, { 1, 31, 15 }, + { 1, 33, 16 }, { 1, 35, 17 }, { 1, 37, 18 }, { 1, 39, 19 }, { 1, 41, 20 }, { 1, 43, 21 }, { 1, 45, 22 }, { 1, 47, 23 }, + { 1, 49, 24 }, { 1, 53, 25 }, { 1, 55, 26 }, { 1, 57, 27 }, { 1, 59, 28 }, { 1, 61, 29 }, { 1, 63, 30 }, { 1, 65, 31 }, + { 1, 67, 32 }, { 1, 69, 33 }, { 1, 71, 34 }, { 1, 73, 35 }, { 1, 75, 36 }, { 1, 77, 37 }, { 1, 79, 38 }, { 1, 81, 39 }, + { 1, 85, 40 }, { 1, 87, 41 }, { 1, 89, 42 }, { 1, 91, 43 }, { 1, 93, 44 }, { 1, 95, 45 }, { 1, 97, 46 }, { 1, 99, 47 }, + { 1, 101, 48 }, { 1, 103, 49 }, { 1, 105, 50 }, { 1, 107, 51 }, { 1, 109, 52 }, { 1, 111, 53 }, { 1, 113, 54 }, { 1, 117, 55 }, + { 1, 119, 56 }, { 1, 121, 57 }, { 1, 123, 58 }, { 1, 125, 59 }, { 1, 127, 60 }, { 1, 129, 61 }, { 1, 131, 62 }, { 1, 133, 63 }, + { 1, 135, 64 }, { 1, 137, 65 }, { 1, 139, 66 }, { 1, 141, 67 }, { 1, 143, 68 }, { 1, 145, 69 }, { 1, 149, 70 }, { 1, 151, 71 }, + { 1, 153, 72 }, { 1, 155, 73 }, { 1, 157, 74 }, { 1, 159, 75 }, { 1, 161, 76 }, { 1, 163, 77 }, { 1, 165, 78 }, { 1, 167, 79 }, + { 1, 169, 80 }, { 1, 171, 81 }, { 1, 173, 82 }, { 1, 175, 83 }, { 1, 177, 84 }, { 1, 181, 85 }, { 1, 183, 86 }, { 1, 185, 87 }, + { 1, 187, 88 }, { 1, 189, 89 }, { 1, 191, 90 }, { 1, 193, 91 }, { 1, 195, 92 }, { 1, 197, 93 }, { 1, 199, 94 }, { 1, 201, 95 }, + { 1, 203, 96 }, { 1, 205, 97 }, { 1, 207, 98 }, { 1, 209, 99 }, { 1, 213, 100 }, { 1, 215, 101 }, { 1, 217, 102 }, { 1, 219, 103 }, + { 1, 221, 104 }, { 1, 223, 105 }, { 1, 225, 106 }, { 1, 227, 107 }, { 1, 229, 108 }, { 1, 231, 109 }, { 1, 233, 110 }, { 1, 235, 111 }, + { 1, 237, 112 }, { 1, 239, 113 }, { 1, 241, 114 }, { 1, 245, 115 }, { 1, 247, 116 }, { 1, 249, 117 }, { 1, 251, 118 }, { 1, 253, 119 }, + { 1, 255, 120 }, { 3, 255, 121 }, { 5, 255, 122 }, { 7, 255, 123 }, { 9, 255, 124 }, { 11, 255, 125 }, { 13, 253, 126 }, { 15, 253, 127 }, + { 15, 255, 128 }, { 17, 255, 129 }, { 19, 255, 130 }, { 21, 255, 131 }, { 23, 255, 132 }, { 25, 255, 133 }, { 27, 255, 134 }, { 29, 255, 135 }, + { 31, 255, 136 }, { 33, 255, 137 }, { 35, 255, 138 }, { 37, 255, 139 }, { 39, 255, 140 }, { 41, 255, 141 }, { 43, 255, 142 }, { 45, 253, 143 }, + { 47, 253, 144 }, { 47, 255, 145 }, { 49, 255, 146 }, { 51, 255, 147 }, { 53, 255, 148 }, { 55, 255, 149 }, { 57, 255, 150 }, { 59, 255, 151 }, + { 61, 255, 152 }, { 63, 255, 153 }, { 65, 255, 154 }, { 67, 255, 155 }, { 69, 255, 156 }, { 71, 255, 157 }, { 73, 255, 158 }, { 75, 255, 159 }, + { 77, 253, 160 }, { 79, 253, 161 }, { 79, 255, 162 }, { 81, 255, 163 }, { 83, 255, 164 }, { 85, 255, 165 }, { 87, 255, 166 }, { 89, 255, 167 }, + { 91, 255, 168 }, { 93, 255, 169 }, { 95, 255, 170 }, { 97, 255, 171 }, { 99, 255, 172 }, { 101, 255, 173 }, { 103, 255, 174 }, { 105, 255, 175 }, + { 107, 255, 176 }, { 109, 253, 177 }, { 111, 253, 178 }, { 111, 255, 179 }, { 113, 255, 180 }, { 115, 255, 181 }, { 117, 255, 182 }, { 119, 255, 183 }, + { 121, 255, 184 }, { 123, 255, 185 }, { 125, 255, 186 }, { 127, 255, 187 }, { 129, 255, 188 }, { 131, 255, 189 }, { 133, 255, 190 }, { 135, 255, 191 }, + { 137, 255, 192 }, { 139, 255, 193 }, { 141, 253, 194 }, { 143, 253, 195 }, { 143, 255, 196 }, { 145, 255, 197 }, { 147, 255, 198 }, { 149, 255, 199 }, + { 151, 255, 200 }, { 153, 255, 201 }, { 155, 255, 202 }, { 157, 255, 203 }, { 159, 255, 204 }, { 161, 255, 205 }, { 163, 255, 206 }, { 165, 255, 207 }, + { 167, 255, 208 }, { 169, 255, 209 }, { 171, 255, 210 }, { 173, 253, 211 }, { 175, 253, 212 }, { 175, 255, 213 }, { 177, 255, 214 }, { 179, 255, 215 }, + { 181, 255, 216 }, { 183, 255, 217 }, { 185, 255, 218 }, { 187, 255, 219 }, { 189, 255, 220 }, { 191, 255, 221 }, { 193, 255, 222 }, { 195, 255, 223 }, + { 197, 255, 224 }, { 199, 255, 225 }, { 201, 255, 226 }, { 203, 255, 227 }, { 205, 253, 228 }, { 207, 253, 229 }, { 207, 255, 230 }, { 209, 255, 231 }, + { 211, 255, 232 }, { 213, 255, 233 }, { 215, 255, 234 }, { 217, 255, 235 }, { 219, 255, 236 }, { 221, 255, 237 }, { 223, 255, 238 }, { 225, 255, 239 }, + { 227, 255, 240 }, { 229, 255, 241 }, { 231, 255, 242 }, { 233, 255, 243 }, { 235, 255, 244 }, { 237, 253, 245 }, { 239, 253, 246 }, { 239, 255, 247 }, + { 241, 255, 248 }, { 243, 255, 249 }, { 245, 255, 250 }, { 247, 255, 251 }, { 249, 255, 252 }, { 251, 255, 253 }, { 253, 255, 254 }, { 255, 255, 255 }, + } +}; + +Table g_mode7_p00= +{ + 1, + 0, + { + { 0, 0, 0 }, { 0, 2, 1 }, { 0, 6, 2 }, { 0, 8, 3 }, { 0, 12, 4 }, { 0, 14, 5 }, { 0, 18, 6 }, { 0, 20, 7 }, + { 0, 24, 8 }, { 0, 26, 9 }, { 0, 30, 10 }, { 0, 32, 11 }, { 0, 36, 12 }, { 0, 40, 13 }, { 0, 42, 14 }, { 0, 46, 15 }, + { 0, 48, 16 }, { 0, 52, 17 }, { 0, 54, 18 }, { 0, 58, 19 }, { 0, 60, 20 }, { 0, 64, 21 }, { 0, 66, 22 }, { 0, 70, 23 }, + { 0, 72, 24 }, { 0, 76, 25 }, { 0, 78, 26 }, { 0, 82, 27 }, { 0, 84, 28 }, { 0, 88, 29 }, { 0, 90, 30 }, { 0, 94, 31 }, + { 0, 96, 32 }, { 0, 100, 33 }, { 0, 104, 34 }, { 0, 106, 35 }, { 0, 110, 36 }, { 0, 112, 37 }, { 0, 116, 38 }, { 0, 118, 39 }, + { 0, 122, 40 }, { 0, 124, 41 }, { 0, 128, 42 }, { 0, 130, 43 }, { 0, 134, 44 }, { 0, 136, 45 }, { 0, 140, 46 }, { 0, 142, 47 }, + { 0, 146, 48 }, { 0, 148, 49 }, { 0, 152, 50 }, { 0, 154, 51 }, { 0, 158, 52 }, { 0, 160, 53 }, { 0, 164, 54 }, { 0, 168, 55 }, + { 0, 170, 56 }, { 0, 174, 57 }, { 0, 176, 58 }, { 0, 180, 59 }, { 0, 182, 60 }, { 0, 186, 61 }, { 0, 188, 62 }, { 0, 192, 63 }, + { 0, 194, 64 }, { 0, 198, 65 }, { 0, 200, 66 }, { 0, 204, 67 }, { 0, 206, 68 }, { 0, 210, 69 }, { 0, 212, 70 }, { 0, 216, 71 }, + { 0, 218, 72 }, { 0, 222, 73 }, { 0, 224, 74 }, { 0, 228, 75 }, { 0, 232, 76 }, { 0, 234, 77 }, { 0, 238, 78 }, { 0, 240, 79 }, + { 0, 244, 80 }, { 0, 246, 81 }, { 0, 250, 82 }, { 0, 252, 83 }, { 2, 252, 84 }, { 2, 254, 85 }, { 4, 254, 86 }, { 6, 252, 87 }, + { 8, 252, 88 }, { 8, 254, 89 }, { 10, 254, 90 }, { 12, 252, 91 }, { 14, 252, 92 }, { 14, 254, 93 }, { 16, 254, 94 }, { 18, 252, 95 }, + { 20, 252, 96 }, { 20, 254, 97 }, { 22, 254, 98 }, { 24, 252, 99 }, { 26, 250, 100 }, { 26, 254, 101 }, { 28, 252, 102 }, { 30, 252, 103 }, + { 30, 254, 104 }, { 32, 254, 105 }, { 34, 252, 106 }, { 36, 252, 107 }, { 36, 254, 108 }, { 38, 254, 109 }, { 40, 252, 110 }, { 42, 252, 111 }, + { 42, 254, 112 }, { 44, 254, 113 }, { 46, 252, 114 }, { 48, 252, 115 }, { 48, 254, 116 }, { 50, 254, 117 }, { 52, 252, 118 }, { 54, 252, 119 }, + { 54, 254, 120 }, { 56, 254, 121 }, { 58, 252, 122 }, { 60, 252, 123 }, { 60, 254, 124 }, { 62, 254, 125 }, { 64, 252, 126 }, { 66, 252, 127 }, + { 66, 254, 128 }, { 68, 254, 129 }, { 70, 252, 130 }, { 72, 252, 131 }, { 72, 254, 132 }, { 74, 254, 133 }, { 76, 252, 134 }, { 78, 252, 135 }, + { 78, 254, 136 }, { 80, 254, 137 }, { 82, 252, 138 }, { 84, 252, 139 }, { 84, 254, 140 }, { 86, 254, 141 }, { 88, 252, 142 }, { 90, 250, 143 }, + { 90, 254, 144 }, { 92, 252, 145 }, { 94, 252, 146 }, { 94, 254, 147 }, { 96, 254, 148 }, { 98, 252, 149 }, { 100, 252, 150 }, { 100, 254, 151 }, + { 102, 254, 152 }, { 104, 252, 153 }, { 106, 252, 154 }, { 106, 254, 155 }, { 108, 254, 156 }, { 110, 252, 157 }, { 112, 252, 158 }, { 112, 254, 159 }, + { 114, 254, 160 }, { 116, 252, 161 }, { 118, 252, 162 }, { 118, 254, 163 }, { 120, 254, 164 }, { 122, 252, 165 }, { 124, 252, 166 }, { 124, 254, 167 }, + { 126, 254, 168 }, { 128, 252, 169 }, { 130, 252, 170 }, { 130, 254, 171 }, { 132, 254, 172 }, { 134, 252, 173 }, { 136, 252, 174 }, { 136, 254, 175 }, + { 138, 254, 176 }, { 140, 252, 177 }, { 142, 252, 178 }, { 142, 254, 179 }, { 144, 254, 180 }, { 146, 252, 181 }, { 148, 252, 182 }, { 148, 254, 183 }, + { 150, 254, 184 }, { 152, 252, 185 }, { 154, 250, 186 }, { 154, 254, 187 }, { 156, 252, 188 }, { 158, 252, 189 }, { 158, 254, 190 }, { 160, 254, 191 }, + { 162, 252, 192 }, { 164, 252, 193 }, { 164, 254, 194 }, { 166, 254, 195 }, { 168, 252, 196 }, { 170, 252, 197 }, { 170, 254, 198 }, { 172, 254, 199 }, + { 174, 252, 200 }, { 176, 252, 201 }, { 176, 254, 202 }, { 178, 254, 203 }, { 180, 252, 204 }, { 182, 252, 205 }, { 182, 254, 206 }, { 184, 254, 207 }, + { 186, 252, 208 }, { 188, 252, 209 }, { 188, 254, 210 }, { 190, 254, 211 }, { 192, 252, 212 }, { 194, 252, 213 }, { 194, 254, 214 }, { 196, 254, 215 }, + { 198, 252, 216 }, { 200, 252, 217 }, { 200, 254, 218 }, { 202, 254, 219 }, { 204, 252, 220 }, { 206, 252, 221 }, { 206, 254, 222 }, { 208, 254, 223 }, + { 210, 252, 224 }, { 212, 252, 225 }, { 212, 254, 226 }, { 214, 254, 227 }, { 216, 252, 228 }, { 218, 250, 229 }, { 218, 254, 230 }, { 220, 252, 231 }, + { 222, 252, 232 }, { 222, 254, 233 }, { 224, 254, 234 }, { 226, 252, 235 }, { 228, 252, 236 }, { 228, 254, 237 }, { 230, 254, 238 }, { 232, 252, 239 }, + { 234, 252, 240 }, { 234, 254, 241 }, { 236, 254, 242 }, { 238, 252, 243 }, { 240, 252, 244 }, { 240, 254, 245 }, { 242, 254, 246 }, { 244, 252, 247 }, + { 246, 252, 248 }, { 246, 254, 249 }, { 248, 254, 250 }, { 250, 252, 251 }, { 252, 252, 252 }, { 252, 254, 253 }, { 254, 254, 254 }, { 254, 254, 254 }, + } +}; + +Table g_mode7_p01= +{ + 1, + 2, + { + { 0, 1, 0 }, { 0, 3, 1 }, { 0, 5, 2 }, { 0, 9, 3 }, { 0, 11, 4 }, { 0, 15, 5 }, { 0, 17, 6 }, { 0, 21, 7 }, + { 0, 23, 8 }, { 0, 27, 9 }, { 0, 29, 10 }, { 0, 33, 11 }, { 0, 37, 12 }, { 0, 39, 13 }, { 0, 43, 14 }, { 0, 45, 15 }, + { 0, 49, 16 }, { 0, 51, 17 }, { 0, 55, 18 }, { 0, 57, 19 }, { 0, 61, 20 }, { 0, 63, 21 }, { 0, 67, 22 }, { 0, 69, 23 }, + { 0, 73, 24 }, { 0, 75, 25 }, { 0, 79, 26 }, { 0, 81, 27 }, { 0, 85, 28 }, { 0, 87, 29 }, { 0, 91, 30 }, { 0, 93, 31 }, + { 0, 97, 32 }, { 0, 101, 33 }, { 0, 103, 34 }, { 0, 107, 35 }, { 0, 109, 36 }, { 0, 113, 37 }, { 0, 115, 38 }, { 0, 119, 39 }, + { 0, 121, 40 }, { 0, 125, 41 }, { 0, 127, 42 }, { 0, 131, 43 }, { 0, 133, 44 }, { 0, 137, 45 }, { 0, 139, 46 }, { 0, 143, 47 }, + { 0, 145, 48 }, { 0, 149, 49 }, { 0, 151, 50 }, { 0, 155, 51 }, { 0, 157, 52 }, { 0, 161, 53 }, { 0, 165, 54 }, { 0, 167, 55 }, + { 0, 171, 56 }, { 0, 173, 57 }, { 0, 177, 58 }, { 0, 179, 59 }, { 0, 183, 60 }, { 0, 185, 61 }, { 0, 189, 62 }, { 0, 191, 63 }, + { 0, 195, 64 }, { 0, 197, 65 }, { 0, 201, 66 }, { 0, 203, 67 }, { 0, 207, 68 }, { 0, 209, 69 }, { 0, 213, 70 }, { 0, 215, 71 }, + { 0, 219, 72 }, { 0, 221, 73 }, { 0, 225, 74 }, { 0, 229, 75 }, { 0, 231, 76 }, { 0, 235, 77 }, { 0, 237, 78 }, { 0, 241, 79 }, + { 0, 243, 80 }, { 0, 247, 81 }, { 0, 249, 82 }, { 0, 253, 83 }, { 0, 255, 84 }, { 2, 255, 85 }, { 4, 253, 86 }, { 6, 253, 87 }, + { 6, 255, 88 }, { 8, 255, 89 }, { 10, 253, 90 }, { 12, 253, 91 }, { 12, 255, 92 }, { 14, 255, 93 }, { 16, 253, 94 }, { 18, 253, 95 }, + { 18, 255, 96 }, { 20, 255, 97 }, { 22, 253, 98 }, { 24, 253, 99 }, { 24, 255, 100 }, { 26, 255, 101 }, { 28, 253, 102 }, { 30, 251, 103 }, + { 30, 255, 104 }, { 32, 253, 105 }, { 34, 253, 106 }, { 34, 255, 107 }, { 36, 255, 108 }, { 38, 253, 109 }, { 40, 253, 110 }, { 40, 255, 111 }, + { 42, 255, 112 }, { 44, 253, 113 }, { 46, 253, 114 }, { 46, 255, 115 }, { 48, 255, 116 }, { 50, 253, 117 }, { 52, 253, 118 }, { 52, 255, 119 }, + { 54, 255, 120 }, { 56, 253, 121 }, { 58, 253, 122 }, { 58, 255, 123 }, { 60, 255, 124 }, { 62, 253, 125 }, { 64, 253, 126 }, { 64, 255, 127 }, + { 66, 255, 128 }, { 68, 253, 129 }, { 70, 253, 130 }, { 70, 255, 131 }, { 72, 255, 132 }, { 74, 253, 133 }, { 76, 253, 134 }, { 76, 255, 135 }, + { 78, 255, 136 }, { 80, 253, 137 }, { 82, 253, 138 }, { 82, 255, 139 }, { 84, 255, 140 }, { 86, 253, 141 }, { 88, 253, 142 }, { 88, 255, 143 }, + { 90, 255, 144 }, { 92, 253, 145 }, { 94, 251, 146 }, { 94, 255, 147 }, { 96, 253, 148 }, { 98, 253, 149 }, { 98, 255, 150 }, { 100, 255, 151 }, + { 102, 253, 152 }, { 104, 253, 153 }, { 104, 255, 154 }, { 106, 255, 155 }, { 108, 253, 156 }, { 110, 253, 157 }, { 110, 255, 158 }, { 112, 255, 159 }, + { 114, 253, 160 }, { 116, 253, 161 }, { 116, 255, 162 }, { 118, 255, 163 }, { 120, 253, 164 }, { 122, 253, 165 }, { 122, 255, 166 }, { 124, 255, 167 }, + { 126, 253, 168 }, { 128, 253, 169 }, { 128, 255, 170 }, { 130, 255, 171 }, { 132, 253, 172 }, { 134, 253, 173 }, { 134, 255, 174 }, { 136, 255, 175 }, + { 138, 253, 176 }, { 140, 253, 177 }, { 140, 255, 178 }, { 142, 255, 179 }, { 144, 253, 180 }, { 146, 253, 181 }, { 146, 255, 182 }, { 148, 255, 183 }, + { 150, 253, 184 }, { 152, 253, 185 }, { 152, 255, 186 }, { 154, 255, 187 }, { 156, 253, 188 }, { 158, 251, 189 }, { 158, 255, 190 }, { 160, 253, 191 }, + { 162, 253, 192 }, { 162, 255, 193 }, { 164, 255, 194 }, { 166, 253, 195 }, { 168, 253, 196 }, { 168, 255, 197 }, { 170, 255, 198 }, { 172, 253, 199 }, + { 174, 253, 200 }, { 174, 255, 201 }, { 176, 255, 202 }, { 178, 253, 203 }, { 180, 253, 204 }, { 180, 255, 205 }, { 182, 255, 206 }, { 184, 253, 207 }, + { 186, 253, 208 }, { 186, 255, 209 }, { 188, 255, 210 }, { 190, 253, 211 }, { 192, 253, 212 }, { 192, 255, 213 }, { 194, 255, 214 }, { 196, 253, 215 }, + { 198, 253, 216 }, { 198, 255, 217 }, { 200, 255, 218 }, { 202, 253, 219 }, { 204, 253, 220 }, { 204, 255, 221 }, { 206, 255, 222 }, { 208, 253, 223 }, + { 210, 253, 224 }, { 210, 255, 225 }, { 212, 255, 226 }, { 214, 253, 227 }, { 216, 253, 228 }, { 216, 255, 229 }, { 218, 255, 230 }, { 220, 253, 231 }, + { 222, 251, 232 }, { 222, 255, 233 }, { 224, 253, 234 }, { 226, 253, 235 }, { 226, 255, 236 }, { 228, 255, 237 }, { 230, 253, 238 }, { 232, 253, 239 }, + { 232, 255, 240 }, { 234, 255, 241 }, { 236, 253, 242 }, { 238, 253, 243 }, { 238, 255, 244 }, { 240, 255, 245 }, { 242, 253, 246 }, { 244, 253, 247 }, + { 244, 255, 248 }, { 246, 255, 249 }, { 248, 253, 250 }, { 250, 253, 251 }, { 250, 255, 252 }, { 252, 255, 253 }, { 254, 253, 254 }, { 254, 253, 254 }, + } +}; + +Table g_mode7_p10= +{ + 1, + 1, + { + { 1, 0, 1 }, { 1, 0, 1 }, { 1, 4, 2 }, { 1, 6, 3 }, { 1, 10, 4 }, { 1, 12, 5 }, { 1, 16, 6 }, { 1, 18, 7 }, + { 1, 22, 8 }, { 1, 24, 9 }, { 1, 28, 10 }, { 1, 30, 11 }, { 1, 34, 12 }, { 1, 38, 13 }, { 1, 40, 14 }, { 1, 44, 15 }, + { 1, 46, 16 }, { 1, 50, 17 }, { 1, 52, 18 }, { 1, 56, 19 }, { 1, 58, 20 }, { 1, 62, 21 }, { 1, 64, 22 }, { 1, 68, 23 }, + { 1, 70, 24 }, { 1, 74, 25 }, { 1, 76, 26 }, { 1, 80, 27 }, { 1, 82, 28 }, { 1, 86, 29 }, { 1, 88, 30 }, { 1, 92, 31 }, + { 1, 94, 32 }, { 1, 98, 33 }, { 1, 102, 34 }, { 1, 104, 35 }, { 1, 108, 36 }, { 1, 110, 37 }, { 1, 114, 38 }, { 1, 116, 39 }, + { 1, 120, 40 }, { 1, 122, 41 }, { 1, 126, 42 }, { 1, 128, 43 }, { 1, 132, 44 }, { 1, 134, 45 }, { 1, 138, 46 }, { 1, 140, 47 }, + { 1, 144, 48 }, { 1, 146, 49 }, { 1, 150, 50 }, { 1, 152, 51 }, { 1, 156, 52 }, { 1, 158, 53 }, { 1, 162, 54 }, { 1, 166, 55 }, + { 1, 168, 56 }, { 1, 172, 57 }, { 1, 174, 58 }, { 1, 178, 59 }, { 1, 180, 60 }, { 1, 184, 61 }, { 1, 186, 62 }, { 1, 190, 63 }, + { 1, 192, 64 }, { 1, 196, 65 }, { 1, 198, 66 }, { 1, 202, 67 }, { 1, 204, 68 }, { 1, 208, 69 }, { 1, 210, 70 }, { 1, 214, 71 }, + { 1, 216, 72 }, { 1, 220, 73 }, { 1, 222, 74 }, { 1, 226, 75 }, { 1, 230, 76 }, { 1, 232, 77 }, { 1, 236, 78 }, { 1, 238, 79 }, + { 1, 242, 80 }, { 1, 244, 81 }, { 1, 248, 82 }, { 1, 250, 83 }, { 1, 254, 84 }, { 3, 252, 85 }, { 5, 252, 86 }, { 5, 254, 87 }, + { 7, 254, 88 }, { 9, 252, 89 }, { 11, 252, 90 }, { 11, 254, 91 }, { 13, 254, 92 }, { 15, 252, 93 }, { 17, 252, 94 }, { 17, 254, 95 }, + { 19, 254, 96 }, { 21, 252, 97 }, { 23, 252, 98 }, { 23, 254, 99 }, { 25, 254, 100 }, { 27, 252, 101 }, { 29, 250, 102 }, { 29, 254, 103 }, + { 31, 252, 104 }, { 33, 252, 105 }, { 33, 254, 106 }, { 35, 254, 107 }, { 37, 252, 108 }, { 39, 252, 109 }, { 39, 254, 110 }, { 41, 254, 111 }, + { 43, 252, 112 }, { 45, 252, 113 }, { 45, 254, 114 }, { 47, 254, 115 }, { 49, 252, 116 }, { 51, 252, 117 }, { 51, 254, 118 }, { 53, 254, 119 }, + { 55, 252, 120 }, { 57, 252, 121 }, { 57, 254, 122 }, { 59, 254, 123 }, { 61, 252, 124 }, { 63, 252, 125 }, { 63, 254, 126 }, { 65, 254, 127 }, + { 67, 252, 128 }, { 69, 252, 129 }, { 69, 254, 130 }, { 71, 254, 131 }, { 73, 252, 132 }, { 75, 252, 133 }, { 75, 254, 134 }, { 77, 254, 135 }, + { 79, 252, 136 }, { 81, 252, 137 }, { 81, 254, 138 }, { 83, 254, 139 }, { 85, 252, 140 }, { 87, 252, 141 }, { 87, 254, 142 }, { 89, 254, 143 }, + { 91, 252, 144 }, { 93, 250, 145 }, { 93, 254, 146 }, { 95, 252, 147 }, { 97, 252, 148 }, { 97, 254, 149 }, { 99, 254, 150 }, { 101, 252, 151 }, + { 103, 252, 152 }, { 103, 254, 153 }, { 105, 254, 154 }, { 107, 252, 155 }, { 109, 252, 156 }, { 109, 254, 157 }, { 111, 254, 158 }, { 113, 252, 159 }, + { 115, 252, 160 }, { 115, 254, 161 }, { 117, 254, 162 }, { 119, 252, 163 }, { 121, 252, 164 }, { 121, 254, 165 }, { 123, 254, 166 }, { 125, 252, 167 }, + { 127, 252, 168 }, { 127, 254, 169 }, { 129, 254, 170 }, { 131, 252, 171 }, { 133, 252, 172 }, { 133, 254, 173 }, { 135, 254, 174 }, { 137, 252, 175 }, + { 139, 252, 176 }, { 139, 254, 177 }, { 141, 254, 178 }, { 143, 252, 179 }, { 145, 252, 180 }, { 145, 254, 181 }, { 147, 254, 182 }, { 149, 252, 183 }, + { 151, 252, 184 }, { 151, 254, 185 }, { 153, 254, 186 }, { 155, 252, 187 }, { 157, 250, 188 }, { 157, 254, 189 }, { 159, 252, 190 }, { 161, 252, 191 }, + { 161, 254, 192 }, { 163, 254, 193 }, { 165, 252, 194 }, { 167, 252, 195 }, { 167, 254, 196 }, { 169, 254, 197 }, { 171, 252, 198 }, { 173, 252, 199 }, + { 173, 254, 200 }, { 175, 254, 201 }, { 177, 252, 202 }, { 179, 252, 203 }, { 179, 254, 204 }, { 181, 254, 205 }, { 183, 252, 206 }, { 185, 252, 207 }, + { 185, 254, 208 }, { 187, 254, 209 }, { 189, 252, 210 }, { 191, 252, 211 }, { 191, 254, 212 }, { 193, 254, 213 }, { 195, 252, 214 }, { 197, 252, 215 }, + { 197, 254, 216 }, { 199, 254, 217 }, { 201, 252, 218 }, { 203, 252, 219 }, { 203, 254, 220 }, { 205, 254, 221 }, { 207, 252, 222 }, { 209, 252, 223 }, + { 209, 254, 224 }, { 211, 254, 225 }, { 213, 252, 226 }, { 215, 252, 227 }, { 215, 254, 228 }, { 217, 254, 229 }, { 219, 252, 230 }, { 221, 250, 231 }, + { 221, 254, 232 }, { 223, 252, 233 }, { 225, 252, 234 }, { 225, 254, 235 }, { 227, 254, 236 }, { 229, 252, 237 }, { 231, 252, 238 }, { 231, 254, 239 }, + { 233, 254, 240 }, { 235, 252, 241 }, { 237, 252, 242 }, { 237, 254, 243 }, { 239, 254, 244 }, { 241, 252, 245 }, { 243, 252, 246 }, { 243, 254, 247 }, + { 245, 254, 248 }, { 247, 252, 249 }, { 249, 252, 250 }, { 249, 254, 251 }, { 251, 254, 252 }, { 253, 252, 253 }, { 255, 252, 254 }, { 255, 254, 255 }, + } +}; + +Table g_mode7_p11= +{ + 1, + 3, + { + { 1, 1, 1 }, { 1, 1, 1 }, { 1, 3, 2 }, { 1, 7, 3 }, { 1, 9, 4 }, { 1, 13, 5 }, { 1, 15, 6 }, { 1, 19, 7 }, + { 1, 21, 8 }, { 1, 25, 9 }, { 1, 27, 10 }, { 1, 31, 11 }, { 1, 33, 12 }, { 1, 37, 13 }, { 1, 41, 14 }, { 1, 43, 15 }, + { 1, 47, 16 }, { 1, 49, 17 }, { 1, 53, 18 }, { 1, 55, 19 }, { 1, 59, 20 }, { 1, 61, 21 }, { 1, 65, 22 }, { 1, 67, 23 }, + { 1, 71, 24 }, { 1, 73, 25 }, { 1, 77, 26 }, { 1, 79, 27 }, { 1, 83, 28 }, { 1, 85, 29 }, { 1, 89, 30 }, { 1, 91, 31 }, + { 1, 95, 32 }, { 1, 97, 33 }, { 1, 101, 34 }, { 1, 105, 35 }, { 1, 107, 36 }, { 1, 111, 37 }, { 1, 113, 38 }, { 1, 117, 39 }, + { 1, 119, 40 }, { 1, 123, 41 }, { 1, 125, 42 }, { 1, 129, 43 }, { 1, 131, 44 }, { 1, 135, 45 }, { 1, 137, 46 }, { 1, 141, 47 }, + { 1, 143, 48 }, { 1, 147, 49 }, { 1, 149, 50 }, { 1, 153, 51 }, { 1, 155, 52 }, { 1, 159, 53 }, { 1, 161, 54 }, { 1, 165, 55 }, + { 1, 169, 56 }, { 1, 171, 57 }, { 1, 175, 58 }, { 1, 177, 59 }, { 1, 181, 60 }, { 1, 183, 61 }, { 1, 187, 62 }, { 1, 189, 63 }, + { 1, 193, 64 }, { 1, 195, 65 }, { 1, 199, 66 }, { 1, 201, 67 }, { 1, 205, 68 }, { 1, 207, 69 }, { 1, 211, 70 }, { 1, 213, 71 }, + { 1, 217, 72 }, { 1, 219, 73 }, { 1, 223, 74 }, { 1, 225, 75 }, { 1, 229, 76 }, { 1, 233, 77 }, { 1, 235, 78 }, { 1, 239, 79 }, + { 1, 241, 80 }, { 1, 245, 81 }, { 1, 247, 82 }, { 1, 251, 83 }, { 1, 253, 84 }, { 3, 253, 85 }, { 3, 255, 86 }, { 5, 255, 87 }, + { 7, 253, 88 }, { 9, 253, 89 }, { 9, 255, 90 }, { 11, 255, 91 }, { 13, 253, 92 }, { 15, 253, 93 }, { 15, 255, 94 }, { 17, 255, 95 }, + { 19, 253, 96 }, { 21, 253, 97 }, { 21, 255, 98 }, { 23, 255, 99 }, { 25, 253, 100 }, { 27, 251, 101 }, { 27, 255, 102 }, { 29, 253, 103 }, + { 31, 253, 104 }, { 31, 255, 105 }, { 33, 255, 106 }, { 35, 253, 107 }, { 37, 253, 108 }, { 37, 255, 109 }, { 39, 255, 110 }, { 41, 253, 111 }, + { 43, 253, 112 }, { 43, 255, 113 }, { 45, 255, 114 }, { 47, 253, 115 }, { 49, 253, 116 }, { 49, 255, 117 }, { 51, 255, 118 }, { 53, 253, 119 }, + { 55, 253, 120 }, { 55, 255, 121 }, { 57, 255, 122 }, { 59, 253, 123 }, { 61, 253, 124 }, { 61, 255, 125 }, { 63, 255, 126 }, { 65, 253, 127 }, + { 67, 253, 128 }, { 67, 255, 129 }, { 69, 255, 130 }, { 71, 253, 131 }, { 73, 253, 132 }, { 73, 255, 133 }, { 75, 255, 134 }, { 77, 253, 135 }, + { 79, 253, 136 }, { 79, 255, 137 }, { 81, 255, 138 }, { 83, 253, 139 }, { 85, 253, 140 }, { 85, 255, 141 }, { 87, 255, 142 }, { 89, 253, 143 }, + { 91, 251, 144 }, { 91, 255, 145 }, { 93, 253, 146 }, { 95, 253, 147 }, { 95, 255, 148 }, { 97, 255, 149 }, { 99, 253, 150 }, { 101, 253, 151 }, + { 101, 255, 152 }, { 103, 255, 153 }, { 105, 253, 154 }, { 107, 253, 155 }, { 107, 255, 156 }, { 109, 255, 157 }, { 111, 253, 158 }, { 113, 253, 159 }, + { 113, 255, 160 }, { 115, 255, 161 }, { 117, 253, 162 }, { 119, 253, 163 }, { 119, 255, 164 }, { 121, 255, 165 }, { 123, 253, 166 }, { 125, 253, 167 }, + { 125, 255, 168 }, { 127, 255, 169 }, { 129, 253, 170 }, { 131, 253, 171 }, { 131, 255, 172 }, { 133, 255, 173 }, { 135, 253, 174 }, { 137, 253, 175 }, + { 137, 255, 176 }, { 139, 255, 177 }, { 141, 253, 178 }, { 143, 253, 179 }, { 143, 255, 180 }, { 145, 255, 181 }, { 147, 253, 182 }, { 149, 253, 183 }, + { 149, 255, 184 }, { 151, 255, 185 }, { 153, 253, 186 }, { 155, 251, 187 }, { 155, 255, 188 }, { 157, 253, 189 }, { 159, 253, 190 }, { 159, 255, 191 }, + { 161, 255, 192 }, { 163, 253, 193 }, { 165, 253, 194 }, { 165, 255, 195 }, { 167, 255, 196 }, { 169, 253, 197 }, { 171, 253, 198 }, { 171, 255, 199 }, + { 173, 255, 200 }, { 175, 253, 201 }, { 177, 253, 202 }, { 177, 255, 203 }, { 179, 255, 204 }, { 181, 253, 205 }, { 183, 253, 206 }, { 183, 255, 207 }, + { 185, 255, 208 }, { 187, 253, 209 }, { 189, 253, 210 }, { 189, 255, 211 }, { 191, 255, 212 }, { 193, 253, 213 }, { 195, 253, 214 }, { 195, 255, 215 }, + { 197, 255, 216 }, { 199, 253, 217 }, { 201, 253, 218 }, { 201, 255, 219 }, { 203, 255, 220 }, { 205, 253, 221 }, { 207, 253, 222 }, { 207, 255, 223 }, + { 209, 255, 224 }, { 211, 253, 225 }, { 213, 253, 226 }, { 213, 255, 227 }, { 215, 255, 228 }, { 217, 253, 229 }, { 219, 251, 230 }, { 219, 255, 231 }, + { 221, 253, 232 }, { 223, 253, 233 }, { 223, 255, 234 }, { 225, 255, 235 }, { 227, 253, 236 }, { 229, 253, 237 }, { 229, 255, 238 }, { 231, 255, 239 }, + { 233, 253, 240 }, { 235, 253, 241 }, { 235, 255, 242 }, { 237, 255, 243 }, { 239, 253, 244 }, { 241, 253, 245 }, { 241, 255, 246 }, { 243, 255, 247 }, + { 245, 253, 248 }, { 247, 253, 249 }, { 247, 255, 250 }, { 249, 255, 251 }, { 251, 253, 252 }, { 253, 253, 253 }, { 253, 255, 254 }, { 255, 255, 255 }, + } +}; + +}}} diff --git a/thirdparty/cvtt/LICENSE.txt b/thirdparty/cvtt/LICENSE.txt new file mode 100644 index 0000000000..6964f6e43f --- /dev/null +++ b/thirdparty/cvtt/LICENSE.txt @@ -0,0 +1,45 @@ +Convection Texture Tools Stand-Alone Kernels
+
+Copyright (c) 2018 Eric Lasota
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject
+to the following conditions:
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************
+
+Based on DirectX Texture Library
+
+Copyright (c) 2018 Microsoft Corp
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this
+software and associated documentation files (the "Software"), to deal in the Software
+without restriction, including without limitation the rights to use, copy, modify,
+merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice shall be included in all copies
+or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
+OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
\ No newline at end of file diff --git a/thirdparty/fonts/NotoSansDevanagariUI_Regular.ttf b/thirdparty/fonts/NotoSansDevanagariUI_Regular.ttf Binary files differnew file mode 100644 index 0000000000..1f9fb2e857 --- /dev/null +++ b/thirdparty/fonts/NotoSansDevanagariUI_Regular.ttf diff --git a/thirdparty/glad/glad.c b/thirdparty/glad/glad.c index 8f8b2189ec..35469e9031 100644 --- a/thirdparty/glad/glad.c +++ b/thirdparty/glad/glad.c @@ -1,6 +1,6 @@ /* - OpenGL loader generated by glad 0.1.20a0 on Fri May 4 21:44:11 2018. + OpenGL loader generated by glad 0.1.25 on Sat Jul 28 10:59:43 2018. Language/Generator: C/C++ Specification: gl @@ -56,8 +56,9 @@ int open_gl(void) { #ifndef IS_UWP libGL = LoadLibraryW(L"opengl32.dll"); if(libGL != NULL) { - gladGetProcAddressPtr = (PFNWGLGETPROCADDRESSPROC_PRIVATE)GetProcAddress( - libGL, "wglGetProcAddress"); + void (* tmp)(void); + tmp = (void(*)(void)) GetProcAddress(libGL, "wglGetProcAddress"); + gladGetProcAddressPtr = (PFNWGLGETPROCADDRESSPROC_PRIVATE) tmp; return gladGetProcAddressPtr != NULL; } #endif @@ -76,7 +77,7 @@ void close_gl(void) { #include <dlfcn.h> static void* libGL; -#ifndef __APPLE__ +#if !defined(__APPLE__) && !defined(__HAIKU__) typedef void* (APIENTRYP PFNGLXGETPROCADDRESSPROC_PRIVATE)(const char*); static PFNGLXGETPROCADDRESSPROC_PRIVATE gladGetProcAddressPtr; #endif @@ -99,7 +100,7 @@ int open_gl(void) { libGL = dlopen(NAMES[index], RTLD_NOW | RTLD_GLOBAL); if(libGL != NULL) { -#ifdef __APPLE__ +#if defined(__APPLE__) || defined(__HAIKU__) return 1; #else gladGetProcAddressPtr = (PFNGLXGETPROCADDRESSPROC_PRIVATE)dlsym(libGL, @@ -126,7 +127,7 @@ void* get_proc(const char *namez) { void* result = NULL; if(libGL == NULL) return NULL; -#ifndef __APPLE__ +#if !defined(__APPLE__) && !defined(__HAIKU__) if(gladGetProcAddressPtr != NULL) { result = gladGetProcAddressPtr(namez); } @@ -164,7 +165,7 @@ static int max_loaded_minor; static const char *exts = NULL; static int num_exts_i = 0; -static const char **exts_i = NULL; +static char **exts_i = NULL; static int get_exts(void) { #ifdef _GLAD_IS_SOME_NEW_VERSION @@ -178,7 +179,7 @@ static int get_exts(void) { num_exts_i = 0; glGetIntegerv(GL_NUM_EXTENSIONS, &num_exts_i); if (num_exts_i > 0) { - exts_i = (const char **)realloc((void *)exts_i, (size_t)num_exts_i * (sizeof *exts_i)); + exts_i = (char **)realloc((void *)exts_i, (size_t)num_exts_i * (sizeof *exts_i)); } if (exts_i == NULL) { @@ -191,11 +192,7 @@ static int get_exts(void) { char *local_str = (char*)malloc((len+1) * sizeof(char)); if(local_str != NULL) { -#if _MSC_VER >= 1400 - strncpy_s(local_str, len+1, gl_str_tmp, len); -#else - strncpy(local_str, gl_str_tmp, len+1); -#endif + memcpy(local_str, gl_str_tmp, (len+1) * sizeof(char)); } exts_i[index] = local_str; } diff --git a/thirdparty/glad/glad/glad.h b/thirdparty/glad/glad/glad.h index 4eebad4f2f..4d92d33b37 100644 --- a/thirdparty/glad/glad/glad.h +++ b/thirdparty/glad/glad/glad.h @@ -1,6 +1,6 @@ /* - OpenGL loader generated by glad 0.1.20a0 on Fri May 4 21:44:11 2018. + OpenGL loader generated by glad 0.1.25 on Sat Jul 28 10:59:43 2018. Language/Generator: C/C++ Specification: gl @@ -156,16 +156,8 @@ typedef unsigned int GLhandleARB; typedef unsigned short GLhalfARB; typedef unsigned short GLhalf; typedef GLint GLfixed; -#if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ > 1060) -typedef long GLintptr; -#else -typedef ptrdiff_t GLintptr; -#endif -#if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ > 1060) -typedef long GLsizeiptr; -#else -typedef ptrdiff_t GLsizeiptr; -#endif +typedef khronos_intptr_t GLintptr; +typedef khronos_ssize_t GLsizeiptr; typedef int64_t GLint64; typedef uint64_t GLuint64; #if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ > 1060) diff --git a/thirdparty/libpng/LICENSE b/thirdparty/libpng/LICENSE index 4cda4fa0ad..6ee9c8f554 100644 --- a/thirdparty/libpng/LICENSE +++ b/thirdparty/libpng/LICENSE @@ -10,8 +10,8 @@ this sentence. This code is released under the libpng license. -libpng versions 1.0.7, July 1, 2000 through 1.6.34, September 29, 2017 are -Copyright (c) 2000-2002, 2004, 2006-2017 Glenn Randers-Pehrson, are +libpng versions 1.0.7, July 1, 2000 through 1.6.35, July 15, 2018 are +Copyright (c) 2000-2002, 2004, 2006-2018 Glenn Randers-Pehrson, are derived from libpng-1.0.6, and are distributed according to the same disclaimer and license as libpng-1.0.6 with the following individuals added to the list of Contributing Authors: @@ -130,4 +130,4 @@ any encryption software. See the EAR, paragraphs 734.3(b)(3) and Glenn Randers-Pehrson glennrp at users.sourceforge.net -September 29, 2017 +July 15, 2018 diff --git a/thirdparty/libpng/png.c b/thirdparty/libpng/png.c index ff02c56518..a25afebcc8 100644 --- a/thirdparty/libpng/png.c +++ b/thirdparty/libpng/png.c @@ -1,8 +1,8 @@ /* png.c - location for general purpose libpng functions * - * Last changed in libpng 1.6.33 [September 28, 2017] - * Copyright (c) 1998-2002,2004,2006-2017 Glenn Randers-Pehrson + * Last changed in libpng 1.6.35 [July 15, 2018] + * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) * @@ -14,7 +14,7 @@ #include "pngpriv.h" /* Generate a compiler error if there is an old png.h in the search path. */ -typedef png_libpng_version_1_6_34 Your_png_h_is_not_version_1_6_34; +typedef png_libpng_version_1_6_35 Your_png_h_is_not_version_1_6_35; #ifdef __GNUC__ /* The version tests may need to be added to, but the problem warning has @@ -71,7 +71,7 @@ png_set_sig_bytes(png_structrp png_ptr, int num_bytes) * PNG signature (this is the same behavior as strcmp, memcmp, etc). */ int PNGAPI -png_sig_cmp(png_const_bytep sig, png_size_t start, png_size_t num_to_check) +png_sig_cmp(png_const_bytep sig, size_t start, size_t num_to_check) { png_byte png_signature[8] = {137, 80, 78, 71, 13, 10, 26, 10}; @@ -136,7 +136,7 @@ png_reset_crc(png_structrp png_ptr) * trouble of calculating it. */ void /* PRIVATE */ -png_calculate_crc(png_structrp png_ptr, png_const_bytep ptr, png_size_t length) +png_calculate_crc(png_structrp png_ptr, png_const_bytep ptr, size_t length) { int need_crc = 1; @@ -421,7 +421,7 @@ png_destroy_info_struct(png_const_structrp png_ptr, png_infopp info_ptr_ptr) * those cases where it does anything other than a memset. */ PNG_FUNCTION(void,PNGAPI -png_info_init_3,(png_infopp ptr_ptr, png_size_t png_info_struct_size), +png_info_init_3,(png_infopp ptr_ptr, size_t png_info_struct_size), PNG_DEPRECATED) { png_inforp info_ptr = *ptr_ptr; @@ -816,15 +816,15 @@ png_get_copyright(png_const_structrp png_ptr) #else # ifdef __STDC__ return PNG_STRING_NEWLINE \ - "libpng version 1.6.34 - September 29, 2017" PNG_STRING_NEWLINE \ - "Copyright (c) 1998-2002,2004,2006-2017 Glenn Randers-Pehrson" \ + "libpng version 1.6.35 - July 15, 2018" PNG_STRING_NEWLINE \ + "Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson" \ PNG_STRING_NEWLINE \ "Copyright (c) 1996-1997 Andreas Dilger" PNG_STRING_NEWLINE \ "Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc." \ PNG_STRING_NEWLINE; # else - return "libpng version 1.6.34 - September 29, 2017\ - Copyright (c) 1998-2002,2004,2006-2017 Glenn Randers-Pehrson\ + return "libpng version 1.6.35 - July 15, 2018\ + Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson\ Copyright (c) 1996-1997 Andreas Dilger\ Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc."; # endif @@ -942,7 +942,7 @@ png_handle_as_unknown(png_const_structrp png_ptr, png_const_bytep chunk_name) /* The code is the fifth byte after each four byte string. Historically this * code was always searched from the end of the list, this is no longer - * necessary because the 'set' routine handles duplicate entries correcty. + * necessary because the 'set' routine handles duplicate entries correctly. */ do /* num_chunk_list > 0, so at least one */ { @@ -2067,7 +2067,7 @@ png_icc_check_header(png_const_structrp png_ptr, png_colorspacerp colorspace, */ /* Data checks (could be skipped). These checks must be independent of the - * version number; however, the version number doesn't accomodate changes in + * version number; however, the version number doesn't accommodate changes in * the header fields (just the known tags and the interpretation of the * data.) */ @@ -2707,7 +2707,7 @@ png_check_IHDR(png_const_structrp png_ptr, #if defined(PNG_sCAL_SUPPORTED) || defined(PNG_pCAL_SUPPORTED) /* ASCII to fp functions */ -/* Check an ASCII formated floating point value, see the more detailed +/* Check an ASCII formatted floating point value, see the more detailed * comments in pngpriv.h */ /* The following is used internally to preserve the sticky flags */ @@ -2715,11 +2715,11 @@ png_check_IHDR(png_const_structrp png_ptr, #define png_fp_set(state, value) ((state) = (value) | ((state) & PNG_FP_STICKY)) int /* PRIVATE */ -png_check_fp_number(png_const_charp string, png_size_t size, int *statep, +png_check_fp_number(png_const_charp string, size_t size, int *statep, png_size_tp whereami) { int state = *statep; - png_size_t i = *whereami; + size_t i = *whereami; while (i < size) { @@ -2842,10 +2842,10 @@ PNG_FP_End: /* The same but for a complete string. */ int -png_check_fp_string(png_const_charp string, png_size_t size) +png_check_fp_string(png_const_charp string, size_t size) { int state=0; - png_size_t char_index=0; + size_t char_index=0; if (png_check_fp_number(string, size, &state, &char_index) != 0 && (char_index == size || string[char_index] == 0)) @@ -2906,7 +2906,7 @@ png_pow10(int power) #pragma GCC diagnostic warning "-Wstrict-overflow=2" #endif /* GCC_STRICT_OVERFLOW */ void /* PRIVATE */ -png_ascii_from_fp(png_const_structrp png_ptr, png_charp ascii, png_size_t size, +png_ascii_from_fp(png_const_structrp png_ptr, png_charp ascii, size_t size, double fp, unsigned int precision) { /* We use standard functions from math.h, but not printf because @@ -3237,7 +3237,7 @@ png_ascii_from_fp(png_const_structrp png_ptr, png_charp ascii, png_size_t size, */ void /* PRIVATE */ png_ascii_from_fixed(png_const_structrp png_ptr, png_charp ascii, - png_size_t size, png_fixed_point fp) + size_t size, png_fixed_point fp) { /* Require space for 10 decimal digits, a decimal point, a minus sign and a * trailing \0, 13 characters: @@ -4344,7 +4344,7 @@ png_set_option(png_structrp png_ptr, int option, int onoff) png_uint_32 setting = (2U + (onoff != 0)) << option; png_uint_32 current = png_ptr->options; - png_ptr->options = (png_uint_32)(((current & ~mask) | setting) & 0xff); + png_ptr->options = (png_uint_32)((current & ~mask) | setting); return (int)(current & mask) >> option; } diff --git a/thirdparty/libpng/png.h b/thirdparty/libpng/png.h index 4c873f5c22..19e464cc17 100644 --- a/thirdparty/libpng/png.h +++ b/thirdparty/libpng/png.h @@ -1,9 +1,9 @@ /* png.h - header file for PNG reference library * - * libpng version 1.6.34, September 29, 2017 + * libpng version 1.6.35, July 15, 2018 * - * Copyright (c) 1998-2002,2004,2006-2017 Glenn Randers-Pehrson + * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) * @@ -12,7 +12,7 @@ * Authors and maintainers: * libpng versions 0.71, May 1995, through 0.88, January 1996: Guy Schalnat * libpng versions 0.89, June 1996, through 0.96, May 1997: Andreas Dilger - * libpng versions 0.97, January 1998, through 1.6.34, September 29, 2017: + * libpng versions 0.97, January 1998, through 1.6.35, July 15, 2018: * Glenn Randers-Pehrson. * See also "Contributing Authors", below. */ @@ -25,8 +25,8 @@ * * This code is released under the libpng license. * - * libpng versions 1.0.7, July 1, 2000 through 1.6.34, September 29, 2017 are - * Copyright (c) 2000-2002, 2004, 2006-2017 Glenn Randers-Pehrson, are + * libpng versions 1.0.7, July 1, 2000 through 1.6.35, July 15, 2018 are + * Copyright (c) 2000-2002, 2004, 2006-2018 Glenn Randers-Pehrson, are * derived from libpng-1.0.6, and are distributed according to the same * disclaimer and license as libpng-1.0.6 with the following individuals * added to the list of Contributing Authors: @@ -213,7 +213,7 @@ * ... * 1.5.30 15 10527 15.so.15.30[.0] * ... - * 1.6.34 16 10633 16.so.16.34[.0] + * 1.6.35 16 10635 16.so.16.35[.0] * * Henceforth the source version will match the shared-library major * and minor numbers; the shared-library major version number will be @@ -241,13 +241,13 @@ * Y2K compliance in libpng: * ========================= * - * September 29, 2017 + * July 15, 2018 * * Since the PNG Development group is an ad-hoc body, we can't make * an official declaration. * * This is your unofficial assurance that libpng from version 0.71 and - * upward through 1.6.34 are Y2K compliant. It is my belief that + * upward through 1.6.35 are Y2K compliant. It is my belief that * earlier versions were also Y2K compliant. * * Libpng only has two year fields. One is a 2-byte unsigned integer @@ -309,8 +309,8 @@ */ /* Version information for png.h - this should match the version in png.c */ -#define PNG_LIBPNG_VER_STRING "1.6.34" -#define PNG_HEADER_VERSION_STRING " libpng version 1.6.34 - September 29, 2017\n" +#define PNG_LIBPNG_VER_STRING "1.6.35" +#define PNG_HEADER_VERSION_STRING " libpng version 1.6.35 - July 15, 2018\n" #define PNG_LIBPNG_VER_SONUM 16 #define PNG_LIBPNG_VER_DLLNUM 16 @@ -318,13 +318,13 @@ /* These should match the first 3 components of PNG_LIBPNG_VER_STRING: */ #define PNG_LIBPNG_VER_MAJOR 1 #define PNG_LIBPNG_VER_MINOR 6 -#define PNG_LIBPNG_VER_RELEASE 34 +#define PNG_LIBPNG_VER_RELEASE 35 /* This should match the numeric part of the final component of * PNG_LIBPNG_VER_STRING, omitting any leading zero: */ -#define PNG_LIBPNG_VER_BUILD 0 +#define PNG_LIBPNG_VER_BUILD 02 /* Release Status */ #define PNG_LIBPNG_BUILD_ALPHA 1 @@ -341,7 +341,7 @@ #define PNG_LIBPNG_BUILD_SPECIAL 32 /* Cannot be OR'ed with PNG_LIBPNG_BUILD_PRIVATE */ -#define PNG_LIBPNG_BUILD_BASE_TYPE PNG_LIBPNG_BUILD_STABLE +#define PNG_LIBPNG_BUILD_BASE_TYPE PNG_LIBPNG_BUILD_BETA /* Careful here. At one time, Guy wanted to use 082, but that would be octal. * We must not include leading zeros. @@ -349,7 +349,7 @@ * version 1.0.0 was mis-numbered 100 instead of 10000). From * version 1.0.1 it's xxyyzz, where x=major, y=minor, z=release */ -#define PNG_LIBPNG_VER 10634 /* 1.6.34 */ +#define PNG_LIBPNG_VER 10635 /* 1.6.35 */ /* Library configuration: these options cannot be changed after * the library has been built. @@ -459,7 +459,7 @@ extern "C" { /* This triggers a compiler error in png.c, if png.c and png.h * do not agree upon the version number. */ -typedef char* png_libpng_version_1_6_34; +typedef char* png_libpng_version_1_6_35; /* Basic control structions. Read libpng-manual.txt or libpng.3 for more info. * @@ -600,8 +600,8 @@ typedef struct png_text_struct png_charp key; /* keyword, 1-79 character description of "text" */ png_charp text; /* comment, may be an empty string (ie "") or a NULL pointer */ - png_size_t text_length; /* length of the text string */ - png_size_t itxt_length; /* length of the itxt string */ + size_t text_length; /* length of the text string */ + size_t itxt_length; /* length of the itxt string */ png_charp lang; /* language code, 0-79 characters or a NULL pointer */ png_charp lang_key; /* keyword translated UTF-8 string, 0 or more @@ -654,7 +654,7 @@ typedef struct png_unknown_chunk_t { png_byte name[5]; /* Textual chunk name with '\0' terminator */ png_byte *data; /* Data, should not be modified on read! */ - png_size_t size; + size_t size; /* On write 'location' must be set using the flag values listed below. * Notice that on read it is set by libpng however the values stored have @@ -679,7 +679,7 @@ typedef png_unknown_chunk * * png_unknown_chunkpp; /* Maximum positive integer used in PNG is (2^31)-1 */ #define PNG_UINT_31_MAX ((png_uint_32)0x7fffffffL) #define PNG_UINT_32_MAX ((png_uint_32)(-1)) -#define PNG_SIZE_MAX ((png_size_t)(-1)) +#define PNG_SIZE_MAX ((size_t)(-1)) /* These are constants for fixed point values encoded in the * PNG specification manner (x100000) @@ -785,7 +785,7 @@ typedef png_unknown_chunk * * png_unknown_chunkpp; typedef struct png_row_info_struct { png_uint_32 width; /* width of row */ - png_size_t rowbytes; /* number of bytes in row */ + size_t rowbytes; /* number of bytes in row */ png_byte color_type; /* color type of row */ png_byte bit_depth; /* bit depth of row */ png_byte channels; /* number of channels (1, 2, 3, or 4) */ @@ -804,7 +804,7 @@ typedef png_row_info * * png_row_infopp; * expected to return the read data in the buffer. */ typedef PNG_CALLBACK(void, *png_error_ptr, (png_structp, png_const_charp)); -typedef PNG_CALLBACK(void, *png_rw_ptr, (png_structp, png_bytep, png_size_t)); +typedef PNG_CALLBACK(void, *png_rw_ptr, (png_structp, png_bytep, size_t)); typedef PNG_CALLBACK(void, *png_flush_ptr, (png_structp)); typedef PNG_CALLBACK(void, *png_read_status_ptr, (png_structp, png_uint_32, int)); @@ -941,8 +941,8 @@ PNG_EXPORT(2, void, png_set_sig_bytes, (png_structrp png_ptr, int num_bytes)); * signature, and non-zero otherwise. Having num_to_check == 0 or * start > 7 will always fail (ie return non-zero). */ -PNG_EXPORT(3, int, png_sig_cmp, (png_const_bytep sig, png_size_t start, - png_size_t num_to_check)); +PNG_EXPORT(3, int, png_sig_cmp, (png_const_bytep sig, size_t start, + size_t num_to_check)); /* Simple signature checking function. This is the same as calling * png_check_sig(sig, n) := !png_sig_cmp(sig, 0, n). @@ -961,11 +961,11 @@ PNG_EXPORTA(5, png_structp, png_create_write_struct, png_error_ptr warn_fn), PNG_ALLOCATED); -PNG_EXPORT(6, png_size_t, png_get_compression_buffer_size, +PNG_EXPORT(6, size_t, png_get_compression_buffer_size, (png_const_structrp png_ptr)); PNG_EXPORT(7, void, png_set_compression_buffer_size, (png_structrp png_ptr, - png_size_t size)); + size_t size)); /* Moved from pngconf.h in 1.4.0 and modified to ensure setjmp/longjmp * match up. @@ -1018,7 +1018,7 @@ PNG_EXPORT(13, void, png_write_sig, (png_structrp png_ptr)); /* Write a PNG chunk - size, type, (optional) data, CRC. */ PNG_EXPORT(14, void, png_write_chunk, (png_structrp png_ptr, png_const_bytep - chunk_name, png_const_bytep data, png_size_t length)); + chunk_name, png_const_bytep data, size_t length)); /* Write the start of a PNG chunk - length and chunk name. */ PNG_EXPORT(15, void, png_write_chunk_start, (png_structrp png_ptr, @@ -1026,7 +1026,7 @@ PNG_EXPORT(15, void, png_write_chunk_start, (png_structrp png_ptr, /* Write the data of a PNG chunk started with png_write_chunk_start(). */ PNG_EXPORT(16, void, png_write_chunk_data, (png_structrp png_ptr, - png_const_bytep data, png_size_t length)); + png_const_bytep data, size_t length)); /* Finish a chunk started with png_write_chunk_start() (includes CRC). */ PNG_EXPORT(17, void, png_write_chunk_end, (png_structrp png_ptr)); @@ -1040,7 +1040,7 @@ PNG_EXPORTA(18, png_infop, png_create_info_struct, (png_const_structrp png_ptr), * the API will be removed in the future. */ PNG_EXPORTA(19, void, png_info_init_3, (png_infopp info_ptr, - png_size_t png_info_struct_size), PNG_DEPRECATED); + size_t png_info_struct_size), PNG_DEPRECATED); /* Writes all the PNG information before the image. */ PNG_EXPORT(20, void, png_write_info_before_PLTE, @@ -1137,7 +1137,7 @@ PNG_EXPORT(35, void, png_build_grayscale_palette, (int bit_depth, * corresponding composited pixel, and the color channels are unassociated * (not premultiplied). The gamma encoded color channels must be scaled * according to the contribution and to do this it is necessary to undo - * the encoding, scale the color values, perform the composition and reencode + * the encoding, scale the color values, perform the composition and re-encode * the values. This is the 'PNG' mode. * * The alternative is to 'associate' the alpha with the color information by @@ -1193,7 +1193,7 @@ PNG_FIXED_EXPORT(228, void, png_set_alpha_mode_fixed, (png_structrp png_ptr, * * png_set_alpha_mode(pp, PNG_ALPHA_PNG, PNG_GAMMA_MAC); * In this case the output is assumed to be something like an sRGB conformant - * display preceeded by a power-law lookup table of power 1.45. This is how + * display preceded by a power-law lookup table of power 1.45. This is how * early Mac systems behaved. * * png_set_alpha_mode(pp, PNG_ALPHA_STANDARD, PNG_GAMMA_LINEAR); @@ -1240,7 +1240,7 @@ PNG_FIXED_EXPORT(228, void, png_set_alpha_mode_fixed, (png_structrp png_ptr, * * When the default gamma of PNG files doesn't match the output gamma. * If you have PNG files with no gamma information png_set_alpha_mode allows - * you to provide a default gamma, but it also sets the ouput gamma to the + * you to provide a default gamma, but it also sets the output gamma to the * matching value. If you know your PNG files have a gamma that doesn't * match the output you can take advantage of the fact that * png_set_alpha_mode always sets the output gamma but only sets the PNG @@ -1691,7 +1691,7 @@ PNG_EXPORT(218, png_byte, png_get_current_pass_number, (png_const_structrp)); * chunk will cause an error at this point unless it is to be saved. * positive: The chunk was handled, libpng will ignore/discard it. * - * See "INTERACTION WTIH USER CHUNK CALLBACKS" below for important notes about + * See "INTERACTION WITH USER CHUNK CALLBACKS" below for important notes about * how this behavior will change in libpng 1.7 */ PNG_EXPORT(88, void, png_set_read_user_chunk_fn, (png_structrp png_ptr, @@ -1716,7 +1716,7 @@ PNG_EXPORT(91, png_voidp, png_get_progressive_ptr, /* Function to be called when data becomes available */ PNG_EXPORT(92, void, png_process_data, (png_structrp png_ptr, - png_inforp info_ptr, png_bytep buffer, png_size_t buffer_size)); + png_inforp info_ptr, png_bytep buffer, size_t buffer_size)); /* A function which may be called *only* within png_process_data to stop the * processing of any more data. The function returns the number of bytes @@ -1725,7 +1725,7 @@ PNG_EXPORT(92, void, png_process_data, (png_structrp png_ptr, * 'save' is set to true the routine will first save all the pending data and * will always return 0. */ -PNG_EXPORT(219, png_size_t, png_process_data_pause, (png_structrp, int save)); +PNG_EXPORT(219, size_t, png_process_data_pause, (png_structrp, int save)); /* A function which may be called *only* outside (after) a call to * png_process_data. It returns the number of bytes of data to skip in the @@ -1870,7 +1870,7 @@ PNG_EXPORT(110, png_uint_32, png_get_valid, (png_const_structrp png_ptr, png_const_inforp info_ptr, png_uint_32 flag)); /* Returns number of bytes needed to hold a transformed row. */ -PNG_EXPORT(111, png_size_t, png_get_rowbytes, (png_const_structrp png_ptr, +PNG_EXPORT(111, size_t, png_get_rowbytes, (png_const_structrp png_ptr, png_const_inforp info_ptr)); #ifdef PNG_INFO_IMAGE_SUPPORTED @@ -2239,7 +2239,7 @@ PNG_EXPORT(171, void, png_set_sCAL_s, (png_const_structrp png_ptr, * to specifying "NEVER", however when "AS_DEFAULT" is used for specific chunks * it simply resets the behavior to the libpng default. * - * INTERACTION WTIH USER CHUNK CALLBACKS: + * INTERACTION WITH USER CHUNK CALLBACKS: * The per-chunk handling is always used when there is a png_user_chunk_ptr * callback and the callback returns 0; the chunk is then always stored *unless* * it is critical and the per-chunk setting is other than ALWAYS. Notice that @@ -2658,7 +2658,7 @@ PNG_EXPORT(243, int, png_get_palette_max, (png_const_structp png_ptr, * The simplified API hides the details of both libpng and the PNG file format * itself. It allows PNG files to be read into a very limited number of * in-memory bitmap formats or to be written from the same formats. If these - * formats do not accomodate your needs then you can, and should, use the more + * formats do not accommodate your needs then you can, and should, use the more * sophisticated APIs above - these support a wide variety of in-memory formats * and a wide variety of sophisticated transformations to those formats as well * as a wide variety of APIs to manipulate ancillary information. @@ -3020,7 +3020,7 @@ PNG_EXPORT(235, int, png_image_begin_read_from_stdio, (png_imagep image, #endif /* STDIO */ PNG_EXPORT(236, int, png_image_begin_read_from_memory, (png_imagep image, - png_const_voidp memory, png_size_t size)); + png_const_voidp memory, size_t size)); /* The PNG header is read from the given memory buffer. */ PNG_EXPORT(237, int, png_image_finish_read, (png_imagep image, @@ -3133,7 +3133,7 @@ PNG_EXPORT(245, int, png_image_write_to_memory, (png_imagep image, void *memory, * than or equal to the original value. * * If the function returns false and *memory_bytes was not changed an error - * occured during write. If *memory_bytes was changed, or is not 0 if + * occurred during write. If *memory_bytes was changed, or is not 0 if * 'memory' was NULL, the write would have succeeded but for the memory * buffer being too small. *memory_bytes contains the required number of * bytes and will be bigger that the original value. @@ -3217,7 +3217,7 @@ PNG_EXPORT(245, int, png_image_write_to_memory, (png_imagep image, void *memory, * option and 'onoff' is 0 (off) or non-0 (on). The value returned is given * by the PNG_OPTION_ defines below. * - * HARDWARE: normally hardware capabilites, such as the Intel SSE instructions, + * HARDWARE: normally hardware capabilities, such as the Intel SSE instructions, * are detected at run time, however sometimes it may be impossible * to do this in user mode, in which case it is necessary to discover * the capabilities in an OS specific way. Such capabilities are diff --git a/thirdparty/libpng/pngconf.h b/thirdparty/libpng/pngconf.h index d13b13e57a..a4646bab85 100644 --- a/thirdparty/libpng/pngconf.h +++ b/thirdparty/libpng/pngconf.h @@ -1,9 +1,9 @@ /* pngconf.h - machine configurable file for libpng * - * libpng version 1.6.34, September 29, 2017 + * libpng version 1.6.35, July 15, 2018 * - * Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson + * Copyright (c) 1998-2002,2004,2006-2016,2018 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) * @@ -127,7 +127,7 @@ * * These cases only differ if the operating system does not use the C * calling convention, at present this just means the above cases - * (x86 DOS/Windows sytems) and, even then, this does not apply to + * (x86 DOS/Windows systems) and, even then, this does not apply to * Cygwin running on those systems. * * Note that the value must be defined in pnglibconf.h so that what @@ -515,8 +515,10 @@ # error "libpng requires an unsigned 32-bit (or more) type" #endif -/* Prior to 1.6.0 it was possible to disable the use of size_t, 1.6.0, however, - * requires an ISOC90 compiler and relies on consistent behavior of sizeof. +/* Prior to 1.6.0, it was possible to disable the use of size_t and ptrdiff_t. + * From 1.6.0 onwards, an ISO C90 compiler, as well as a standard-compliant + * behavior of sizeof and ptrdiff_t are required. + * The legacy typedefs are provided here for backwards compatibility. */ typedef size_t png_size_t; typedef ptrdiff_t png_ptrdiff_t; @@ -537,13 +539,12 @@ typedef ptrdiff_t png_ptrdiff_t; # endif #endif -/* png_alloc_size_t is guaranteed to be no smaller than png_size_t, and no - * smaller than png_uint_32. Casts from png_size_t or png_uint_32 to - * png_alloc_size_t are not necessary; in fact, it is recommended not to use - * them at all so that the compiler can complain when something turns out to be - * problematic. +/* png_alloc_size_t is guaranteed to be no smaller than size_t, and no smaller + * than png_uint_32. Casts from size_t or png_uint_32 to png_alloc_size_t are + * not necessary; in fact, it is recommended not to use them at all, so that + * the compiler can complain when something turns out to be problematic. * - * Casts in the other direction (from png_alloc_size_t to png_size_t or + * Casts in the other direction (from png_alloc_size_t to size_t or * png_uint_32) should be explicitly applied; however, we do not expect to * encounter practical situations that require such conversions. * @@ -553,7 +554,7 @@ typedef ptrdiff_t png_ptrdiff_t; #ifdef PNG_SMALL_SIZE_T typedef png_uint_32 png_alloc_size_t; #else - typedef png_size_t png_alloc_size_t; + typedef size_t png_alloc_size_t; #endif /* Prior to 1.6.0 libpng offered limited support for Microsoft C compiler @@ -589,8 +590,8 @@ typedef char * png_charp; typedef const char * png_const_charp; typedef png_fixed_point * png_fixed_point_p; typedef const png_fixed_point * png_const_fixed_point_p; -typedef png_size_t * png_size_tp; -typedef const png_size_t * png_const_size_tp; +typedef size_t * png_size_tp; +typedef const size_t * png_const_size_tp; #ifdef PNG_STDIO_SUPPORTED typedef FILE * png_FILE_p; diff --git a/thirdparty/libpng/pngget.c b/thirdparty/libpng/pngget.c index 26e9fb1c35..2325508f1d 100644 --- a/thirdparty/libpng/pngget.c +++ b/thirdparty/libpng/pngget.c @@ -1,8 +1,8 @@ /* pngget.c - retrieval of values from info struct * - * Last changed in libpng 1.6.32 [August 24, 2017] - * Copyright (c) 1998-2002,2004,2006-2017 Glenn Randers-Pehrson + * Last changed in libpng 1.6.35 [July 15, 2018] + * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) * @@ -26,7 +26,7 @@ png_get_valid(png_const_structrp png_ptr, png_const_inforp info_ptr, return(0); } -png_size_t PNGAPI +size_t PNGAPI png_get_rowbytes(png_const_structrp png_ptr, png_const_inforp info_ptr) { if (png_ptr != NULL && info_ptr != NULL) @@ -367,7 +367,7 @@ png_get_y_pixels_per_inch(png_const_structrp png_ptr, png_const_inforp info_ptr) static png_fixed_point png_fixed_inches_from_microns(png_const_structrp png_ptr, png_int_32 microns) { - /* Convert from metres * 1,000,000 to inches * 100,000, meters to + /* Convert from meters * 1,000,000 to inches * 100,000, meters to * inches is simply *(100/2.54), so we want *(10/2.54) == 500/127. * Notice that this can overflow - a warning is output and 0 is * returned. @@ -741,8 +741,7 @@ png_get_iCCP(png_const_structrp png_ptr, png_inforp info_ptr, if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_iCCP) != 0 && - name != NULL && compression_type != NULL && profile != NULL && - proflen != NULL) + name != NULL && profile != NULL && proflen != NULL) { *name = info_ptr->iccp_name; *profile = info_ptr->iccp_profile; @@ -750,11 +749,13 @@ png_get_iCCP(png_const_structrp png_ptr, png_inforp info_ptr, /* This is somewhat irrelevant since the profile data returned has * actually been uncompressed. */ - *compression_type = PNG_COMPRESSION_TYPE_BASE; + if (compression_type != NULL) + *compression_type = PNG_COMPRESSION_TYPE_BASE; return (PNG_INFO_iCCP); } return (0); + } #endif @@ -1164,7 +1165,7 @@ png_get_user_chunk_ptr(png_const_structrp png_ptr) } #endif -png_size_t PNGAPI +size_t PNGAPI png_get_compression_buffer_size(png_const_structrp png_ptr) { if (png_ptr == NULL) diff --git a/thirdparty/libpng/pnginfo.h b/thirdparty/libpng/pnginfo.h index d5f6149dbd..2fcf868dac 100644 --- a/thirdparty/libpng/pnginfo.h +++ b/thirdparty/libpng/pnginfo.h @@ -1,8 +1,8 @@ /* pnginfo.h - header file for PNG reference library * - * Last changed in libpng 1.6.1 [March 28, 2013] - * Copyright (c) 1998-2002,2004,2006-2013 Glenn Randers-Pehrson + * Last changed in libpng 1.6.35 [July 15, 2018] + * Copyright (c) 1998-2002,2004,2006-2013,2018 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) * @@ -55,10 +55,10 @@ struct png_info_def { /* The following are necessary for every PNG file */ - png_uint_32 width; /* width of image in pixels (from IHDR) */ - png_uint_32 height; /* height of image in pixels (from IHDR) */ - png_uint_32 valid; /* valid chunk data (see PNG_INFO_ below) */ - png_size_t rowbytes; /* bytes needed to hold an untransformed row */ + png_uint_32 width; /* width of image in pixels (from IHDR) */ + png_uint_32 height; /* height of image in pixels (from IHDR) */ + png_uint_32 valid; /* valid chunk data (see PNG_INFO_ below) */ + size_t rowbytes; /* bytes needed to hold an untransformed row */ png_colorp palette; /* array of color values (valid & PNG_INFO_PLTE) */ png_uint_16 num_palette; /* number of color entries in "palette" (PLTE) */ png_uint_16 num_trans; /* number of transparent palette color (tRNS) */ @@ -247,7 +247,7 @@ defined(PNG_READ_BACKGROUND_SUPPORTED) /* The sCAL chunk describes the actual physical dimensions of the * subject matter of the graphic. The chunk contains a unit specification * a byte value, and two ASCII strings representing floating-point - * values. The values are width and height corresponsing to one pixel + * values. The values are width and height corresponding to one pixel * in the image. Data values are valid if (valid & PNG_INFO_sCAL) is * non-zero. */ diff --git a/thirdparty/libpng/pnglibconf.h b/thirdparty/libpng/pnglibconf.h index 53b5e442c4..00acecc69b 100644 --- a/thirdparty/libpng/pnglibconf.h +++ b/thirdparty/libpng/pnglibconf.h @@ -1,10 +1,10 @@ -/* libpng 1.6.34 STANDARD API DEFINITION */ +/* libpng 1.6.35 STANDARD API DEFINITION */ /* pnglibconf.h - library build configuration */ -/* Libpng version 1.6.34 - September 29, 2017 */ +/* Libpng version 1.6.35 - July 15, 2018 */ -/* Copyright (c) 1998-2017 Glenn Randers-Pehrson */ +/* Copyright (c) 1998-2018 Glenn Randers-Pehrson */ /* This code is released under the libpng license. */ /* For conditions of distribution and use, see the disclaimer */ diff --git a/thirdparty/libpng/pngpread.c b/thirdparty/libpng/pngpread.c index fbe361dc34..c4ba51c4d4 100644 --- a/thirdparty/libpng/pngpread.c +++ b/thirdparty/libpng/pngpread.c @@ -1,8 +1,8 @@ /* pngpread.c - read a png file in push mode * - * Last changed in libpng 1.6.32 [August 24, 2017] - * Copyright (c) 1998-2002,2004,2006-2017 Glenn Randers-Pehrson + * Last changed in libpng 1.6.35 [July 15, 2018] + * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) * @@ -34,7 +34,7 @@ if (png_ptr->buffer_size < N) \ void PNGAPI png_process_data(png_structrp png_ptr, png_inforp info_ptr, - png_bytep buffer, png_size_t buffer_size) + png_bytep buffer, size_t buffer_size) { if (png_ptr == NULL || info_ptr == NULL) return; @@ -47,7 +47,7 @@ png_process_data(png_structrp png_ptr, png_inforp info_ptr, } } -png_size_t PNGAPI +size_t PNGAPI png_process_data_pause(png_structrp png_ptr, int save) { if (png_ptr != NULL) @@ -60,7 +60,7 @@ png_process_data_pause(png_structrp png_ptr, int save) else { /* This includes any pending saved bytes: */ - png_size_t remaining = png_ptr->buffer_size; + size_t remaining = png_ptr->buffer_size; png_ptr->buffer_size = 0; /* So subtract the saved buffer size, unless all the data @@ -133,8 +133,8 @@ png_process_some_data(png_structrp png_ptr, png_inforp info_ptr) void /* PRIVATE */ png_push_read_sig(png_structrp png_ptr, png_inforp info_ptr) { - png_size_t num_checked = png_ptr->sig_bytes, /* SAFE, does not exceed 8 */ - num_to_check = 8 - num_checked; + size_t num_checked = png_ptr->sig_bytes; /* SAFE, does not exceed 8 */ + size_t num_to_check = 8 - num_checked; if (png_ptr->buffer_size < num_to_check) { @@ -418,7 +418,7 @@ png_push_read_chunk(png_structrp png_ptr, png_inforp info_ptr) } void PNGCBAPI -png_push_fill_buffer(png_structp png_ptr, png_bytep buffer, png_size_t length) +png_push_fill_buffer(png_structp png_ptr, png_bytep buffer, size_t length) { png_bytep ptr; @@ -428,7 +428,7 @@ png_push_fill_buffer(png_structp png_ptr, png_bytep buffer, png_size_t length) ptr = buffer; if (png_ptr->save_buffer_size != 0) { - png_size_t save_size; + size_t save_size; if (length < png_ptr->save_buffer_size) save_size = length; @@ -445,7 +445,7 @@ png_push_fill_buffer(png_structp png_ptr, png_bytep buffer, png_size_t length) } if (length != 0 && png_ptr->current_buffer_size != 0) { - png_size_t save_size; + size_t save_size; if (length < png_ptr->current_buffer_size) save_size = length; @@ -467,7 +467,7 @@ png_push_save_buffer(png_structrp png_ptr) { if (png_ptr->save_buffer_ptr != png_ptr->save_buffer) { - png_size_t i, istop; + size_t i, istop; png_bytep sp; png_bytep dp; @@ -482,7 +482,7 @@ png_push_save_buffer(png_structrp png_ptr) if (png_ptr->save_buffer_size + png_ptr->current_buffer_size > png_ptr->save_buffer_max) { - png_size_t new_max; + size_t new_max; png_bytep old_buffer; if (png_ptr->save_buffer_size > PNG_SIZE_MAX - @@ -494,7 +494,7 @@ png_push_save_buffer(png_structrp png_ptr) new_max = png_ptr->save_buffer_size + png_ptr->current_buffer_size + 256; old_buffer = png_ptr->save_buffer; png_ptr->save_buffer = (png_bytep)png_malloc_warn(png_ptr, - (png_size_t)new_max); + (size_t)new_max); if (png_ptr->save_buffer == NULL) { @@ -522,7 +522,7 @@ png_push_save_buffer(png_structrp png_ptr) void /* PRIVATE */ png_push_restore_buffer(png_structrp png_ptr, png_bytep buffer, - png_size_t buffer_length) + size_t buffer_length) { png_ptr->current_buffer = buffer; png_ptr->current_buffer_size = buffer_length; @@ -562,7 +562,7 @@ png_push_read_IDAT(png_structrp png_ptr) if (png_ptr->idat_size != 0 && png_ptr->save_buffer_size != 0) { - png_size_t save_size = png_ptr->save_buffer_size; + size_t save_size = png_ptr->save_buffer_size; png_uint_32 idat_size = png_ptr->idat_size; /* We want the smaller of 'idat_size' and 'current_buffer_size', but they @@ -572,7 +572,7 @@ png_push_read_IDAT(png_structrp png_ptr) * will break on either 16-bit or 64-bit platforms. */ if (idat_size < save_size) - save_size = (png_size_t)idat_size; + save_size = (size_t)idat_size; else idat_size = (png_uint_32)save_size; @@ -589,7 +589,7 @@ png_push_read_IDAT(png_structrp png_ptr) if (png_ptr->idat_size != 0 && png_ptr->current_buffer_size != 0) { - png_size_t save_size = png_ptr->current_buffer_size; + size_t save_size = png_ptr->current_buffer_size; png_uint_32 idat_size = png_ptr->idat_size; /* We want the smaller of 'idat_size' and 'current_buffer_size', but they @@ -598,7 +598,7 @@ png_push_read_IDAT(png_structrp png_ptr) * larger - this cannot overflow. */ if (idat_size < save_size) - save_size = (png_size_t)idat_size; + save_size = (size_t)idat_size; else idat_size = (png_uint_32)save_size; @@ -625,7 +625,7 @@ png_push_read_IDAT(png_structrp png_ptr) void /* PRIVATE */ png_process_IDAT_data(png_structrp png_ptr, png_bytep buffer, - png_size_t buffer_length) + size_t buffer_length) { /* The caller checks for a non-zero buffer length. */ if (!(buffer_length > 0) || buffer == NULL) diff --git a/thirdparty/libpng/pngpriv.h b/thirdparty/libpng/pngpriv.h index 1f2e90f2b3..3581f67919 100644 --- a/thirdparty/libpng/pngpriv.h +++ b/thirdparty/libpng/pngpriv.h @@ -1,8 +1,8 @@ /* pngpriv.h - private declarations for use inside libpng * - * Last changed in libpng 1.6.32 [August 24, 2017] - * Copyright (c) 1998-2002,2004,2006-2017 Glenn Randers-Pehrson + * Last changed in libpng 1.6.35 [July 15, 2018] + * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) * @@ -210,7 +210,11 @@ defined(__SSE2__) || defined(_M_X64) || defined(_M_AMD64) || \ (defined(_M_IX86_FP) && _M_IX86_FP >= 2) # define PNG_INTEL_SSE_OPT 1 +# else +# define PNG_INTEL_SSE_OPT 0 # endif +# else +# define PNG_INTEL_SSE_OPT 0 # endif #endif @@ -234,6 +238,8 @@ # if PNG_INTEL_SSE_IMPLEMENTATION > 0 # define PNG_FILTER_OPTIMIZATIONS png_init_filter_functions_sse2 # endif +#else +# define PNG_INTEL_SSE_IMPLEMENTATION 0 #endif #if PNG_MIPS_MSA_OPT > 0 @@ -728,8 +734,8 @@ /* Added to libpng-1.2.6 JB */ #define PNG_ROWBYTES(pixel_bits, width) \ ((pixel_bits) >= 8 ? \ - ((png_size_t)(width) * (((png_size_t)(pixel_bits)) >> 3)) : \ - (( ((png_size_t)(width) * ((png_size_t)(pixel_bits))) + 7) >> 3) ) + ((size_t)(width) * (((size_t)(pixel_bits)) >> 3)) : \ + (( ((size_t)(width) * ((size_t)(pixel_bits))) + 7) >> 3) ) /* This returns the number of trailing bits in the last byte of a row, 0 if the * last byte is completely full of pixels. It is, in principle, (pixel_bits x @@ -917,7 +923,7 @@ * PNG files the -I directives must match. * * The most likely explanation is that you passed a -I in CFLAGS. This will - * not work; all the preprocessor directories and in particular all the -I + * not work; all the preprocessor directives and in particular all the -I * directives must be in CPPFLAGS. */ #endif @@ -1046,15 +1052,15 @@ PNG_INTERNAL_FUNCTION(void,png_zfree,(voidpf png_ptr, voidpf ptr),PNG_EMPTY); */ PNG_INTERNAL_FUNCTION(void PNGCBAPI,png_default_read_data,(png_structp png_ptr, - png_bytep data, png_size_t length),PNG_EMPTY); + png_bytep data, size_t length),PNG_EMPTY); #ifdef PNG_PROGRESSIVE_READ_SUPPORTED PNG_INTERNAL_FUNCTION(void PNGCBAPI,png_push_fill_buffer,(png_structp png_ptr, - png_bytep buffer, png_size_t length),PNG_EMPTY); + png_bytep buffer, size_t length),PNG_EMPTY); #endif PNG_INTERNAL_FUNCTION(void PNGCBAPI,png_default_write_data,(png_structp png_ptr, - png_bytep data, png_size_t length),PNG_EMPTY); + png_bytep data, size_t length),PNG_EMPTY); #ifdef PNG_WRITE_FLUSH_SUPPORTED # ifdef PNG_STDIO_SUPPORTED @@ -1068,7 +1074,7 @@ PNG_INTERNAL_FUNCTION(void,png_reset_crc,(png_structrp png_ptr),PNG_EMPTY); /* Write the "data" buffer to whatever output you are using */ PNG_INTERNAL_FUNCTION(void,png_write_data,(png_structrp png_ptr, - png_const_bytep data, png_size_t length),PNG_EMPTY); + png_const_bytep data, size_t length),PNG_EMPTY); /* Read and check the PNG file signature */ PNG_INTERNAL_FUNCTION(void,png_read_sig,(png_structrp png_ptr, @@ -1080,7 +1086,7 @@ PNG_INTERNAL_FUNCTION(png_uint_32,png_read_chunk_header,(png_structrp png_ptr), /* Read data from whatever input you are using into the "data" buffer */ PNG_INTERNAL_FUNCTION(void,png_read_data,(png_structrp png_ptr, png_bytep data, - png_size_t length),PNG_EMPTY); + size_t length),PNG_EMPTY); /* Read bytes into buf, and update png_ptr->crc */ PNG_INTERNAL_FUNCTION(void,png_crc_read,(png_structrp png_ptr, png_bytep buf, @@ -1098,7 +1104,7 @@ PNG_INTERNAL_FUNCTION(int,png_crc_error,(png_structrp png_ptr),PNG_EMPTY); * since this is the maximum buffer size we can specify. */ PNG_INTERNAL_FUNCTION(void,png_calculate_crc,(png_structrp png_ptr, - png_const_bytep ptr, png_size_t length),PNG_EMPTY); + png_const_bytep ptr, size_t length),PNG_EMPTY); #ifdef PNG_WRITE_FLUSH_SUPPORTED PNG_INTERNAL_FUNCTION(void,png_flush,(png_structrp png_ptr),PNG_EMPTY); @@ -1181,7 +1187,7 @@ PNG_INTERNAL_FUNCTION(void,png_write_hIST,(png_structrp png_ptr, /* Chunks that have keywords */ #ifdef PNG_WRITE_tEXt_SUPPORTED PNG_INTERNAL_FUNCTION(void,png_write_tEXt,(png_structrp png_ptr, - png_const_charp key, png_const_charp text, png_size_t text_len),PNG_EMPTY); + png_const_charp key, png_const_charp text, size_t text_len),PNG_EMPTY); #endif #ifdef PNG_WRITE_zTXt_SUPPORTED @@ -1574,10 +1580,10 @@ PNG_INTERNAL_FUNCTION(void,png_push_check_crc,(png_structrp png_ptr),PNG_EMPTY); PNG_INTERNAL_FUNCTION(void,png_push_save_buffer,(png_structrp png_ptr), PNG_EMPTY); PNG_INTERNAL_FUNCTION(void,png_push_restore_buffer,(png_structrp png_ptr, - png_bytep buffer, png_size_t buffer_length),PNG_EMPTY); + png_bytep buffer, size_t buffer_length),PNG_EMPTY); PNG_INTERNAL_FUNCTION(void,png_push_read_IDAT,(png_structrp png_ptr),PNG_EMPTY); PNG_INTERNAL_FUNCTION(void,png_process_IDAT_data,(png_structrp png_ptr, - png_bytep buffer, png_size_t buffer_length),PNG_EMPTY); + png_bytep buffer, size_t buffer_length),PNG_EMPTY); PNG_INTERNAL_FUNCTION(void,png_push_process_row,(png_structrp png_ptr), PNG_EMPTY); PNG_INTERNAL_FUNCTION(void,png_push_handle_unknown,(png_structrp png_ptr, @@ -1847,13 +1853,13 @@ PNG_INTERNAL_FUNCTION(void,png_chunk_report,(png_const_structrp png_ptr, #ifdef PNG_FLOATING_POINT_SUPPORTED PNG_INTERNAL_FUNCTION(void,png_ascii_from_fp,(png_const_structrp png_ptr, - png_charp ascii, png_size_t size, double fp, unsigned int precision), + png_charp ascii, size_t size, double fp, unsigned int precision), PNG_EMPTY); #endif /* FLOATING_POINT */ #ifdef PNG_FIXED_POINT_SUPPORTED PNG_INTERNAL_FUNCTION(void,png_ascii_from_fixed,(png_const_structrp png_ptr, - png_charp ascii, png_size_t size, png_fixed_point fp),PNG_EMPTY); + png_charp ascii, size_t size, png_fixed_point fp),PNG_EMPTY); #endif /* FIXED_POINT */ #endif /* sCAL */ @@ -1946,7 +1952,7 @@ PNG_INTERNAL_FUNCTION(void,png_ascii_from_fixed,(png_const_structrp png_ptr, * the problem character.) This has not been tested within libpng. */ PNG_INTERNAL_FUNCTION(int,png_check_fp_number,(png_const_charp string, - png_size_t size, int *statep, png_size_tp whereami),PNG_EMPTY); + size_t size, int *statep, png_size_tp whereami),PNG_EMPTY); /* This is the same but it checks a complete string and returns true * only if it just contains a floating point number. As of 1.5.4 this @@ -1955,7 +1961,7 @@ PNG_INTERNAL_FUNCTION(int,png_check_fp_number,(png_const_charp string, * for negative or zero values using the sticky flag. */ PNG_INTERNAL_FUNCTION(int,png_check_fp_string,(png_const_charp string, - png_size_t size),PNG_EMPTY); + size_t size),PNG_EMPTY); #endif /* pCAL || sCAL */ #if defined(PNG_GAMMA_SUPPORTED) ||\ @@ -2030,7 +2036,7 @@ typedef struct png_control png_voidp error_buf; /* Always a jmp_buf at present. */ png_const_bytep memory; /* Memory buffer. */ - png_size_t size; /* Size of the memory buffer. */ + size_t size; /* Size of the memory buffer. */ unsigned int for_write :1; /* Otherwise it is a read structure */ unsigned int owned_file :1; /* We own the file in io_ptr */ diff --git a/thirdparty/libpng/pngread.c b/thirdparty/libpng/pngread.c index da32e9ad9c..bff7503ee3 100644 --- a/thirdparty/libpng/pngread.c +++ b/thirdparty/libpng/pngread.c @@ -1,8 +1,8 @@ /* pngread.c - read a PNG file * - * Last changed in libpng 1.6.33 [September 28, 2017] - * Copyright (c) 1998-2002,2004,2006-2017 Glenn Randers-Pehrson + * Last changed in libpng 1.6.35 [July 15, 2018] + * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) * @@ -1532,7 +1532,7 @@ png_image_begin_read_from_file(png_imagep image, const char *file_name) #endif /* STDIO */ static void PNGCBAPI -png_image_memory_read(png_structp png_ptr, png_bytep out, png_size_t need) +png_image_memory_read(png_structp png_ptr, png_bytep out, size_t need) { if (png_ptr != NULL) { @@ -1543,7 +1543,7 @@ png_image_memory_read(png_structp png_ptr, png_bytep out, png_size_t need) if (cp != NULL) { png_const_bytep memory = cp->memory; - png_size_t size = cp->size; + size_t size = cp->size; if (memory != NULL && size >= need) { @@ -1562,7 +1562,7 @@ png_image_memory_read(png_structp png_ptr, png_bytep out, png_size_t need) } int PNGAPI png_image_begin_read_from_memory(png_imagep image, - png_const_voidp memory, png_size_t size) + png_const_voidp memory, size_t size) { if (image != NULL && image->version == PNG_IMAGE_VERSION) { @@ -4150,7 +4150,7 @@ png_image_finish_read(png_imagep image, png_const_colorp background, * * NOTE: this will be changed in 1.7 because PNG_IMAGE_BUFFER_SIZE * will be changed to use png_alloc_size_t; bigger images can be - * accomodated on 64-bit systems. + * accommodated on 64-bit systems. */ if (image->height <= 0xffffffffU/PNG_IMAGE_PIXEL_COMPONENT_SIZE(image->format)/check) diff --git a/thirdparty/libpng/pngrio.c b/thirdparty/libpng/pngrio.c index 7e26e855ca..372221483f 100644 --- a/thirdparty/libpng/pngrio.c +++ b/thirdparty/libpng/pngrio.c @@ -1,8 +1,8 @@ /* pngrio.c - functions for data input * - * Last changed in libpng 1.6.24 [August 4, 2016] - * Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson + * Last changed in libpng 1.6.35 [July 15, 2018] + * Copyright (c) 1998-2002,2004,2006-2016,2018 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) * @@ -29,7 +29,7 @@ * to read more than 64K on a 16-bit machine. */ void /* PRIVATE */ -png_read_data(png_structrp png_ptr, png_bytep data, png_size_t length) +png_read_data(png_structrp png_ptr, png_bytep data, size_t length) { png_debug1(4, "reading %d bytes", (int)length); @@ -47,14 +47,14 @@ png_read_data(png_structrp png_ptr, png_bytep data, png_size_t length) * than changing the library. */ void PNGCBAPI -png_default_read_data(png_structp png_ptr, png_bytep data, png_size_t length) +png_default_read_data(png_structp png_ptr, png_bytep data, size_t length) { - png_size_t check; + size_t check; if (png_ptr == NULL) return; - /* fread() returns 0 on error, so it is OK to store this in a png_size_t + /* fread() returns 0 on error, so it is OK to store this in a size_t * instead of an int, which is what fread() actually returns. */ check = fread(data, 1, length, png_voidcast(png_FILE_p, png_ptr->io_ptr)); diff --git a/thirdparty/libpng/pngrtran.c b/thirdparty/libpng/pngrtran.c index c189650313..67d1f249a6 100644 --- a/thirdparty/libpng/pngrtran.c +++ b/thirdparty/libpng/pngrtran.c @@ -1,8 +1,8 @@ /* pngrtran.c - transforms the data in a row for PNG readers * - * Last changed in libpng 1.6.33 [September 28, 2017] - * Copyright (c) 1998-2002,2004,2006-2017 Glenn Randers-Pehrson + * Last changed in libpng 1.6.35 [July 15, 2018] + * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) * @@ -292,7 +292,7 @@ png_set_alpha_mode_fixed(png_structrp png_ptr, int mode, * who use the inverse of the gamma value accidentally! Since some of these * values are reasonable this may have to be changed: * - * 1.6.x: changed from 0.07..3 to 0.01..100 (to accomodate the optimal 16-bit + * 1.6.x: changed from 0.07..3 to 0.01..100 (to accommodate the optimal 16-bit * gamma of 36, and its reciprocal.) */ if (output_gamma < 1000 || output_gamma > 10000000) @@ -747,7 +747,7 @@ png_set_quantize(png_structrp png_ptr, png_colorp palette, int num_red = (1 << PNG_QUANTIZE_RED_BITS); int num_green = (1 << PNG_QUANTIZE_GREEN_BITS); int num_blue = (1 << PNG_QUANTIZE_BLUE_BITS); - png_size_t num_entries = ((png_size_t)1 << total_bits); + size_t num_entries = ((size_t)1 << total_bits); png_ptr->palette_lookup = (png_bytep)png_calloc(png_ptr, (png_alloc_size_t)(num_entries * (sizeof (png_byte)))); @@ -1317,7 +1317,7 @@ png_init_read_transformations(png_structrp png_ptr) else if (png_ptr->screen_gamma != 0) /* The converse - assume the file matches the screen, note that this - * perhaps undesireable default can (from 1.5.4) be changed by calling + * perhaps undesirable default can (from 1.5.4) be changed by calling * png_set_alpha_mode (even if the alpha handling mode isn't required * or isn't changed from the default.) */ @@ -1885,7 +1885,7 @@ png_init_read_transformations(png_structrp png_ptr) png_ptr->transformations &= ~PNG_SHIFT; - /* significant bits can be in the range 1 to 7 for a meaninful result, if + /* significant bits can be in the range 1 to 7 for a meaningful result, if * the number of significant bits is 0 then no shift is done (this is an * error condition which is silently ignored.) */ @@ -2151,8 +2151,8 @@ png_do_unpack(png_row_infop row_info, png_bytep row) { case 1: { - png_bytep sp = row + (png_size_t)((row_width - 1) >> 3); - png_bytep dp = row + (png_size_t)row_width - 1; + png_bytep sp = row + (size_t)((row_width - 1) >> 3); + png_bytep dp = row + (size_t)row_width - 1; png_uint_32 shift = 7U - ((row_width + 7U) & 0x07); for (i = 0; i < row_width; i++) { @@ -2175,8 +2175,8 @@ png_do_unpack(png_row_infop row_info, png_bytep row) case 2: { - png_bytep sp = row + (png_size_t)((row_width - 1) >> 2); - png_bytep dp = row + (png_size_t)row_width - 1; + png_bytep sp = row + (size_t)((row_width - 1) >> 2); + png_bytep dp = row + (size_t)row_width - 1; png_uint_32 shift = ((3U - ((row_width + 3U) & 0x03)) << 1); for (i = 0; i < row_width; i++) { @@ -2198,8 +2198,8 @@ png_do_unpack(png_row_infop row_info, png_bytep row) case 4: { - png_bytep sp = row + (png_size_t)((row_width - 1) >> 1); - png_bytep dp = row + (png_size_t)row_width - 1; + png_bytep sp = row + (size_t)((row_width - 1) >> 1); + png_bytep dp = row + (size_t)row_width - 1; png_uint_32 shift = ((1U - ((row_width + 1U) & 0x01)) << 2); for (i = 0; i < row_width; i++) { @@ -2463,95 +2463,94 @@ png_do_chop(png_row_infop row_info, png_bytep row) static void png_do_read_swap_alpha(png_row_infop row_info, png_bytep row) { + png_uint_32 row_width = row_info->width; + png_debug(1, "in png_do_read_swap_alpha"); + if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) { - png_uint_32 row_width = row_info->width; - if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + /* This converts from RGBA to ARGB */ + if (row_info->bit_depth == 8) { - /* This converts from RGBA to ARGB */ - if (row_info->bit_depth == 8) - { - png_bytep sp = row + row_info->rowbytes; - png_bytep dp = sp; - png_byte save; - png_uint_32 i; + png_bytep sp = row + row_info->rowbytes; + png_bytep dp = sp; + png_byte save; + png_uint_32 i; - for (i = 0; i < row_width; i++) - { - save = *(--sp); - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = save; - } + for (i = 0; i < row_width; i++) + { + save = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = save; } + } #ifdef PNG_READ_16BIT_SUPPORTED - /* This converts from RRGGBBAA to AARRGGBB */ - else - { - png_bytep sp = row + row_info->rowbytes; - png_bytep dp = sp; - png_byte save[2]; - png_uint_32 i; + /* This converts from RRGGBBAA to AARRGGBB */ + else + { + png_bytep sp = row + row_info->rowbytes; + png_bytep dp = sp; + png_byte save[2]; + png_uint_32 i; - for (i = 0; i < row_width; i++) - { - save[0] = *(--sp); - save[1] = *(--sp); - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = save[0]; - *(--dp) = save[1]; - } + for (i = 0; i < row_width; i++) + { + save[0] = *(--sp); + save[1] = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = save[0]; + *(--dp) = save[1]; } -#endif } +#endif + } - else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + { + /* This converts from GA to AG */ + if (row_info->bit_depth == 8) { - /* This converts from GA to AG */ - if (row_info->bit_depth == 8) - { - png_bytep sp = row + row_info->rowbytes; - png_bytep dp = sp; - png_byte save; - png_uint_32 i; + png_bytep sp = row + row_info->rowbytes; + png_bytep dp = sp; + png_byte save; + png_uint_32 i; - for (i = 0; i < row_width; i++) - { - save = *(--sp); - *(--dp) = *(--sp); - *(--dp) = save; - } + for (i = 0; i < row_width; i++) + { + save = *(--sp); + *(--dp) = *(--sp); + *(--dp) = save; } + } #ifdef PNG_READ_16BIT_SUPPORTED - /* This converts from GGAA to AAGG */ - else - { - png_bytep sp = row + row_info->rowbytes; - png_bytep dp = sp; - png_byte save[2]; - png_uint_32 i; + /* This converts from GGAA to AAGG */ + else + { + png_bytep sp = row + row_info->rowbytes; + png_bytep dp = sp; + png_byte save[2]; + png_uint_32 i; - for (i = 0; i < row_width; i++) - { - save[0] = *(--sp); - save[1] = *(--sp); - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = save[0]; - *(--dp) = save[1]; - } + for (i = 0; i < row_width; i++) + { + save[0] = *(--sp); + save[1] = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = save[0]; + *(--dp) = save[1]; } -#endif } +#endif } } #endif @@ -2681,8 +2680,8 @@ png_do_read_filler(png_row_infop row_info, png_bytep row, if ((flags & PNG_FLAG_FILLER_AFTER) != 0) { /* This changes the data from G to GX */ - png_bytep sp = row + (png_size_t)row_width; - png_bytep dp = sp + (png_size_t)row_width; + png_bytep sp = row + (size_t)row_width; + png_bytep dp = sp + (size_t)row_width; for (i = 1; i < row_width; i++) { *(--dp) = lo_filler; @@ -2697,8 +2696,8 @@ png_do_read_filler(png_row_infop row_info, png_bytep row, else { /* This changes the data from G to XG */ - png_bytep sp = row + (png_size_t)row_width; - png_bytep dp = sp + (png_size_t)row_width; + png_bytep sp = row + (size_t)row_width; + png_bytep dp = sp + (size_t)row_width; for (i = 0; i < row_width; i++) { *(--dp) = *(--sp); @@ -2716,8 +2715,8 @@ png_do_read_filler(png_row_infop row_info, png_bytep row, if ((flags & PNG_FLAG_FILLER_AFTER) != 0) { /* This changes the data from GG to GGXX */ - png_bytep sp = row + (png_size_t)row_width * 2; - png_bytep dp = sp + (png_size_t)row_width * 2; + png_bytep sp = row + (size_t)row_width * 2; + png_bytep dp = sp + (size_t)row_width * 2; for (i = 1; i < row_width; i++) { *(--dp) = lo_filler; @@ -2735,8 +2734,8 @@ png_do_read_filler(png_row_infop row_info, png_bytep row, else { /* This changes the data from GG to XXGG */ - png_bytep sp = row + (png_size_t)row_width * 2; - png_bytep dp = sp + (png_size_t)row_width * 2; + png_bytep sp = row + (size_t)row_width * 2; + png_bytep dp = sp + (size_t)row_width * 2; for (i = 0; i < row_width; i++) { *(--dp) = *(--sp); @@ -2758,8 +2757,8 @@ png_do_read_filler(png_row_infop row_info, png_bytep row, if ((flags & PNG_FLAG_FILLER_AFTER) != 0) { /* This changes the data from RGB to RGBX */ - png_bytep sp = row + (png_size_t)row_width * 3; - png_bytep dp = sp + (png_size_t)row_width; + png_bytep sp = row + (size_t)row_width * 3; + png_bytep dp = sp + (size_t)row_width; for (i = 1; i < row_width; i++) { *(--dp) = lo_filler; @@ -2776,8 +2775,8 @@ png_do_read_filler(png_row_infop row_info, png_bytep row, else { /* This changes the data from RGB to XRGB */ - png_bytep sp = row + (png_size_t)row_width * 3; - png_bytep dp = sp + (png_size_t)row_width; + png_bytep sp = row + (size_t)row_width * 3; + png_bytep dp = sp + (size_t)row_width; for (i = 0; i < row_width; i++) { *(--dp) = *(--sp); @@ -2797,8 +2796,8 @@ png_do_read_filler(png_row_infop row_info, png_bytep row, if ((flags & PNG_FLAG_FILLER_AFTER) != 0) { /* This changes the data from RRGGBB to RRGGBBXX */ - png_bytep sp = row + (png_size_t)row_width * 6; - png_bytep dp = sp + (png_size_t)row_width * 2; + png_bytep sp = row + (size_t)row_width * 6; + png_bytep dp = sp + (size_t)row_width * 2; for (i = 1; i < row_width; i++) { *(--dp) = lo_filler; @@ -2820,8 +2819,8 @@ png_do_read_filler(png_row_infop row_info, png_bytep row, else { /* This changes the data from RRGGBB to XXRRGGBB */ - png_bytep sp = row + (png_size_t)row_width * 6; - png_bytep dp = sp + (png_size_t)row_width * 2; + png_bytep sp = row + (size_t)row_width * 6; + png_bytep dp = sp + (size_t)row_width * 2; for (i = 0; i < row_width; i++) { *(--dp) = *(--sp); @@ -2862,8 +2861,8 @@ png_do_gray_to_rgb(png_row_infop row_info, png_bytep row) if (row_info->bit_depth == 8) { /* This changes G to RGB */ - png_bytep sp = row + (png_size_t)row_width - 1; - png_bytep dp = sp + (png_size_t)row_width * 2; + png_bytep sp = row + (size_t)row_width - 1; + png_bytep dp = sp + (size_t)row_width * 2; for (i = 0; i < row_width; i++) { *(dp--) = *sp; @@ -2875,8 +2874,8 @@ png_do_gray_to_rgb(png_row_infop row_info, png_bytep row) else { /* This changes GG to RRGGBB */ - png_bytep sp = row + (png_size_t)row_width * 2 - 1; - png_bytep dp = sp + (png_size_t)row_width * 4; + png_bytep sp = row + (size_t)row_width * 2 - 1; + png_bytep dp = sp + (size_t)row_width * 4; for (i = 0; i < row_width; i++) { *(dp--) = *sp; @@ -2894,8 +2893,8 @@ png_do_gray_to_rgb(png_row_infop row_info, png_bytep row) if (row_info->bit_depth == 8) { /* This changes GA to RGBA */ - png_bytep sp = row + (png_size_t)row_width * 2 - 1; - png_bytep dp = sp + (png_size_t)row_width * 2; + png_bytep sp = row + (size_t)row_width * 2 - 1; + png_bytep dp = sp + (size_t)row_width * 2; for (i = 0; i < row_width; i++) { *(dp--) = *(sp--); @@ -2908,8 +2907,8 @@ png_do_gray_to_rgb(png_row_infop row_info, png_bytep row) else { /* This changes GGAA to RRGGBBAA */ - png_bytep sp = row + (png_size_t)row_width * 4 - 1; - png_bytep dp = sp + (png_size_t)row_width * 4; + png_bytep sp = row + (size_t)row_width * 4 - 1; + png_bytep dp = sp + (size_t)row_width * 4; for (i = 0; i < row_width; i++) { *(dp--) = *(sp--); @@ -2980,7 +2979,7 @@ png_do_gray_to_rgb(png_row_infop row_info, png_bytep row) * values this results in an implicit assumption that the original PNG RGB * values were linear. * - * Other integer coefficents can be used via png_set_rgb_to_gray(). Because + * Other integer coefficients can be used via png_set_rgb_to_gray(). Because * the API takes just red and green coefficients the blue coefficient is * calculated to make the sum 32768. This will result in different rounding * to that used above. @@ -3209,720 +3208,718 @@ png_do_compose(png_row_infop row_info, png_bytep row, png_structrp png_ptr) png_debug(1, "in png_do_compose"); + switch (row_info->color_type) { - switch (row_info->color_type) + case PNG_COLOR_TYPE_GRAY: { - case PNG_COLOR_TYPE_GRAY: + switch (row_info->bit_depth) { - switch (row_info->bit_depth) + case 1: + { + sp = row; + shift = 7; + for (i = 0; i < row_width; i++) + { + if ((png_uint_16)((*sp >> shift) & 0x01) + == png_ptr->trans_color.gray) + { + unsigned int tmp = *sp & (0x7f7f >> (7 - shift)); + tmp |= + (unsigned int)(png_ptr->background.gray << shift); + *sp = (png_byte)(tmp & 0xff); + } + + if (shift == 0) + { + shift = 7; + sp++; + } + + else + shift--; + } + break; + } + + case 2: { - case 1: +#ifdef PNG_READ_GAMMA_SUPPORTED + if (gamma_table != NULL) { sp = row; - shift = 7; + shift = 6; for (i = 0; i < row_width; i++) { - if ((png_uint_16)((*sp >> shift) & 0x01) - == png_ptr->trans_color.gray) + if ((png_uint_16)((*sp >> shift) & 0x03) + == png_ptr->trans_color.gray) { - unsigned int tmp = *sp & (0x7f7f >> (7 - shift)); + unsigned int tmp = *sp & (0x3f3f >> (6 - shift)); tmp |= - (unsigned int)(png_ptr->background.gray << shift); + (unsigned int)png_ptr->background.gray << shift; + *sp = (png_byte)(tmp & 0xff); + } + + else + { + unsigned int p = (*sp >> shift) & 0x03; + unsigned int g = (gamma_table [p | (p << 2) | + (p << 4) | (p << 6)] >> 6) & 0x03; + unsigned int tmp = *sp & (0x3f3f >> (6 - shift)); + tmp |= (unsigned int)(g << shift); *sp = (png_byte)(tmp & 0xff); } if (shift == 0) { - shift = 7; + shift = 6; sp++; } else - shift--; + shift -= 2; } - break; } - case 2: + else +#endif { -#ifdef PNG_READ_GAMMA_SUPPORTED - if (gamma_table != NULL) + sp = row; + shift = 6; + for (i = 0; i < row_width; i++) { - sp = row; - shift = 6; - for (i = 0; i < row_width; i++) + if ((png_uint_16)((*sp >> shift) & 0x03) + == png_ptr->trans_color.gray) { - if ((png_uint_16)((*sp >> shift) & 0x03) - == png_ptr->trans_color.gray) - { - unsigned int tmp = *sp & (0x3f3f >> (6 - shift)); - tmp |= - (unsigned int)png_ptr->background.gray << shift; - *sp = (png_byte)(tmp & 0xff); - } - - else - { - unsigned int p = (*sp >> shift) & 0x03; - unsigned int g = (gamma_table [p | (p << 2) | - (p << 4) | (p << 6)] >> 6) & 0x03; - unsigned int tmp = *sp & (0x3f3f >> (6 - shift)); - tmp |= (unsigned int)(g << shift); - *sp = (png_byte)(tmp & 0xff); - } - - if (shift == 0) - { - shift = 6; - sp++; - } - - else - shift -= 2; + unsigned int tmp = *sp & (0x3f3f >> (6 - shift)); + tmp |= + (unsigned int)png_ptr->background.gray << shift; + *sp = (png_byte)(tmp & 0xff); } - } - else -#endif - { - sp = row; - shift = 6; - for (i = 0; i < row_width; i++) + if (shift == 0) { - if ((png_uint_16)((*sp >> shift) & 0x03) - == png_ptr->trans_color.gray) - { - unsigned int tmp = *sp & (0x3f3f >> (6 - shift)); - tmp |= - (unsigned int)png_ptr->background.gray << shift; - *sp = (png_byte)(tmp & 0xff); - } - - if (shift == 0) - { - shift = 6; - sp++; - } - - else - shift -= 2; + shift = 6; + sp++; } + + else + shift -= 2; } - break; } + break; + } - case 4: - { + case 4: + { #ifdef PNG_READ_GAMMA_SUPPORTED - if (gamma_table != NULL) + if (gamma_table != NULL) + { + sp = row; + shift = 4; + for (i = 0; i < row_width; i++) { - sp = row; - shift = 4; - for (i = 0; i < row_width; i++) + if ((png_uint_16)((*sp >> shift) & 0x0f) + == png_ptr->trans_color.gray) { - if ((png_uint_16)((*sp >> shift) & 0x0f) - == png_ptr->trans_color.gray) - { - unsigned int tmp = *sp & (0x0f0f >> (4 - shift)); - tmp |= - (unsigned int)(png_ptr->background.gray << shift); - *sp = (png_byte)(tmp & 0xff); - } - - else - { - unsigned int p = (*sp >> shift) & 0x0f; - unsigned int g = (gamma_table[p | (p << 4)] >> 4) & - 0x0f; - unsigned int tmp = *sp & (0x0f0f >> (4 - shift)); - tmp |= (unsigned int)(g << shift); - *sp = (png_byte)(tmp & 0xff); - } - - if (shift == 0) - { - shift = 4; - sp++; - } - - else - shift -= 4; + unsigned int tmp = *sp & (0x0f0f >> (4 - shift)); + tmp |= + (unsigned int)(png_ptr->background.gray << shift); + *sp = (png_byte)(tmp & 0xff); } - } - else -#endif - { - sp = row; - shift = 4; - for (i = 0; i < row_width; i++) + else { - if ((png_uint_16)((*sp >> shift) & 0x0f) - == png_ptr->trans_color.gray) - { - unsigned int tmp = *sp & (0x0f0f >> (4 - shift)); - tmp |= - (unsigned int)(png_ptr->background.gray << shift); - *sp = (png_byte)(tmp & 0xff); - } - - if (shift == 0) - { - shift = 4; - sp++; - } - - else - shift -= 4; + unsigned int p = (*sp >> shift) & 0x0f; + unsigned int g = (gamma_table[p | (p << 4)] >> 4) & + 0x0f; + unsigned int tmp = *sp & (0x0f0f >> (4 - shift)); + tmp |= (unsigned int)(g << shift); + *sp = (png_byte)(tmp & 0xff); } - } - break; - } - case 8: - { -#ifdef PNG_READ_GAMMA_SUPPORTED - if (gamma_table != NULL) - { - sp = row; - for (i = 0; i < row_width; i++, sp++) - { - if (*sp == png_ptr->trans_color.gray) - *sp = (png_byte)png_ptr->background.gray; - - else - *sp = gamma_table[*sp]; - } - } - else -#endif - { - sp = row; - for (i = 0; i < row_width; i++, sp++) + if (shift == 0) { - if (*sp == png_ptr->trans_color.gray) - *sp = (png_byte)png_ptr->background.gray; + shift = 4; + sp++; } + + else + shift -= 4; } - break; } - case 16: + else +#endif { -#ifdef PNG_READ_GAMMA_SUPPORTED - if (gamma_16 != NULL) + sp = row; + shift = 4; + for (i = 0; i < row_width; i++) { - sp = row; - for (i = 0; i < row_width; i++, sp += 2) + if ((png_uint_16)((*sp >> shift) & 0x0f) + == png_ptr->trans_color.gray) { - png_uint_16 v; - - v = (png_uint_16)(((*sp) << 8) + *(sp + 1)); - - if (v == png_ptr->trans_color.gray) - { - /* Background is already in screen gamma */ - *sp = (png_byte)((png_ptr->background.gray >> 8) - & 0xff); - *(sp + 1) = (png_byte)(png_ptr->background.gray - & 0xff); - } - - else - { - v = gamma_16[*(sp + 1) >> gamma_shift][*sp]; - *sp = (png_byte)((v >> 8) & 0xff); - *(sp + 1) = (png_byte)(v & 0xff); - } + unsigned int tmp = *sp & (0x0f0f >> (4 - shift)); + tmp |= + (unsigned int)(png_ptr->background.gray << shift); + *sp = (png_byte)(tmp & 0xff); } - } - else -#endif - { - sp = row; - for (i = 0; i < row_width; i++, sp += 2) - { - png_uint_16 v; - v = (png_uint_16)(((*sp) << 8) + *(sp + 1)); - - if (v == png_ptr->trans_color.gray) - { - *sp = (png_byte)((png_ptr->background.gray >> 8) - & 0xff); - *(sp + 1) = (png_byte)(png_ptr->background.gray - & 0xff); - } + if (shift == 0) + { + shift = 4; + sp++; } + + else + shift -= 4; } - break; } - - default: - break; + break; } - break; - } - case PNG_COLOR_TYPE_RGB: - { - if (row_info->bit_depth == 8) + case 8: { #ifdef PNG_READ_GAMMA_SUPPORTED if (gamma_table != NULL) { sp = row; - for (i = 0; i < row_width; i++, sp += 3) + for (i = 0; i < row_width; i++, sp++) { - if (*sp == png_ptr->trans_color.red && - *(sp + 1) == png_ptr->trans_color.green && - *(sp + 2) == png_ptr->trans_color.blue) - { - *sp = (png_byte)png_ptr->background.red; - *(sp + 1) = (png_byte)png_ptr->background.green; - *(sp + 2) = (png_byte)png_ptr->background.blue; - } + if (*sp == png_ptr->trans_color.gray) + *sp = (png_byte)png_ptr->background.gray; else - { *sp = gamma_table[*sp]; - *(sp + 1) = gamma_table[*(sp + 1)]; - *(sp + 2) = gamma_table[*(sp + 2)]; - } } } else #endif { sp = row; - for (i = 0; i < row_width; i++, sp += 3) + for (i = 0; i < row_width; i++, sp++) { - if (*sp == png_ptr->trans_color.red && - *(sp + 1) == png_ptr->trans_color.green && - *(sp + 2) == png_ptr->trans_color.blue) - { - *sp = (png_byte)png_ptr->background.red; - *(sp + 1) = (png_byte)png_ptr->background.green; - *(sp + 2) = (png_byte)png_ptr->background.blue; - } + if (*sp == png_ptr->trans_color.gray) + *sp = (png_byte)png_ptr->background.gray; } } + break; } - else /* if (row_info->bit_depth == 16) */ + + case 16: { #ifdef PNG_READ_GAMMA_SUPPORTED if (gamma_16 != NULL) { sp = row; - for (i = 0; i < row_width; i++, sp += 6) + for (i = 0; i < row_width; i++, sp += 2) { - png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1)); - - png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8) - + *(sp + 3)); + png_uint_16 v; - png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8) - + *(sp + 5)); + v = (png_uint_16)(((*sp) << 8) + *(sp + 1)); - if (r == png_ptr->trans_color.red && - g == png_ptr->trans_color.green && - b == png_ptr->trans_color.blue) + if (v == png_ptr->trans_color.gray) { /* Background is already in screen gamma */ - *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff); - *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff); - *(sp + 2) = (png_byte)((png_ptr->background.green >> 8) - & 0xff); - *(sp + 3) = (png_byte)(png_ptr->background.green - & 0xff); - *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8) - & 0xff); - *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff); + *sp = (png_byte)((png_ptr->background.gray >> 8) + & 0xff); + *(sp + 1) = (png_byte)(png_ptr->background.gray + & 0xff); } else { - png_uint_16 v = gamma_16[*(sp + 1) >> gamma_shift][*sp]; + v = gamma_16[*(sp + 1) >> gamma_shift][*sp]; *sp = (png_byte)((v >> 8) & 0xff); *(sp + 1) = (png_byte)(v & 0xff); - - v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)]; - *(sp + 2) = (png_byte)((v >> 8) & 0xff); - *(sp + 3) = (png_byte)(v & 0xff); - - v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)]; - *(sp + 4) = (png_byte)((v >> 8) & 0xff); - *(sp + 5) = (png_byte)(v & 0xff); } } } - else #endif { sp = row; - for (i = 0; i < row_width; i++, sp += 6) + for (i = 0; i < row_width; i++, sp += 2) { - png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1)); - - png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8) - + *(sp + 3)); + png_uint_16 v; - png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8) - + *(sp + 5)); + v = (png_uint_16)(((*sp) << 8) + *(sp + 1)); - if (r == png_ptr->trans_color.red && - g == png_ptr->trans_color.green && - b == png_ptr->trans_color.blue) + if (v == png_ptr->trans_color.gray) { - *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff); - *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff); - *(sp + 2) = (png_byte)((png_ptr->background.green >> 8) - & 0xff); - *(sp + 3) = (png_byte)(png_ptr->background.green - & 0xff); - *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8) - & 0xff); - *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff); + *sp = (png_byte)((png_ptr->background.gray >> 8) + & 0xff); + *(sp + 1) = (png_byte)(png_ptr->background.gray + & 0xff); } } } + break; } - break; + + default: + break; } + break; + } - case PNG_COLOR_TYPE_GRAY_ALPHA: + case PNG_COLOR_TYPE_RGB: + { + if (row_info->bit_depth == 8) { - if (row_info->bit_depth == 8) - { #ifdef PNG_READ_GAMMA_SUPPORTED - if (gamma_to_1 != NULL && gamma_from_1 != NULL && - gamma_table != NULL) + if (gamma_table != NULL) + { + sp = row; + for (i = 0; i < row_width; i++, sp += 3) { - sp = row; - for (i = 0; i < row_width; i++, sp += 2) + if (*sp == png_ptr->trans_color.red && + *(sp + 1) == png_ptr->trans_color.green && + *(sp + 2) == png_ptr->trans_color.blue) { - png_uint_16 a = *(sp + 1); + *sp = (png_byte)png_ptr->background.red; + *(sp + 1) = (png_byte)png_ptr->background.green; + *(sp + 2) = (png_byte)png_ptr->background.blue; + } - if (a == 0xff) - *sp = gamma_table[*sp]; + else + { + *sp = gamma_table[*sp]; + *(sp + 1) = gamma_table[*(sp + 1)]; + *(sp + 2) = gamma_table[*(sp + 2)]; + } + } + } + else +#endif + { + sp = row; + for (i = 0; i < row_width; i++, sp += 3) + { + if (*sp == png_ptr->trans_color.red && + *(sp + 1) == png_ptr->trans_color.green && + *(sp + 2) == png_ptr->trans_color.blue) + { + *sp = (png_byte)png_ptr->background.red; + *(sp + 1) = (png_byte)png_ptr->background.green; + *(sp + 2) = (png_byte)png_ptr->background.blue; + } + } + } + } + else /* if (row_info->bit_depth == 16) */ + { +#ifdef PNG_READ_GAMMA_SUPPORTED + if (gamma_16 != NULL) + { + sp = row; + for (i = 0; i < row_width; i++, sp += 6) + { + png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1)); - else if (a == 0) - { - /* Background is already in screen gamma */ - *sp = (png_byte)png_ptr->background.gray; - } + png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8) + + *(sp + 3)); - else - { - png_byte v, w; + png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8) + + *(sp + 5)); - v = gamma_to_1[*sp]; - png_composite(w, v, a, png_ptr->background_1.gray); - if (optimize == 0) - w = gamma_from_1[w]; - *sp = w; - } + if (r == png_ptr->trans_color.red && + g == png_ptr->trans_color.green && + b == png_ptr->trans_color.blue) + { + /* Background is already in screen gamma */ + *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff); + *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff); + *(sp + 2) = (png_byte)((png_ptr->background.green >> 8) + & 0xff); + *(sp + 3) = (png_byte)(png_ptr->background.green + & 0xff); + *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8) + & 0xff); + *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff); + } + + else + { + png_uint_16 v = gamma_16[*(sp + 1) >> gamma_shift][*sp]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + + v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)]; + *(sp + 2) = (png_byte)((v >> 8) & 0xff); + *(sp + 3) = (png_byte)(v & 0xff); + + v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)]; + *(sp + 4) = (png_byte)((v >> 8) & 0xff); + *(sp + 5) = (png_byte)(v & 0xff); } } - else + } + + else #endif + { + sp = row; + for (i = 0; i < row_width; i++, sp += 6) { - sp = row; - for (i = 0; i < row_width; i++, sp += 2) + png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1)); + + png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8) + + *(sp + 3)); + + png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8) + + *(sp + 5)); + + if (r == png_ptr->trans_color.red && + g == png_ptr->trans_color.green && + b == png_ptr->trans_color.blue) { - png_byte a = *(sp + 1); + *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff); + *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff); + *(sp + 2) = (png_byte)((png_ptr->background.green >> 8) + & 0xff); + *(sp + 3) = (png_byte)(png_ptr->background.green + & 0xff); + *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8) + & 0xff); + *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff); + } + } + } + } + break; + } - if (a == 0) - *sp = (png_byte)png_ptr->background.gray; + case PNG_COLOR_TYPE_GRAY_ALPHA: + { + if (row_info->bit_depth == 8) + { +#ifdef PNG_READ_GAMMA_SUPPORTED + if (gamma_to_1 != NULL && gamma_from_1 != NULL && + gamma_table != NULL) + { + sp = row; + for (i = 0; i < row_width; i++, sp += 2) + { + png_uint_16 a = *(sp + 1); + + if (a == 0xff) + *sp = gamma_table[*sp]; + + else if (a == 0) + { + /* Background is already in screen gamma */ + *sp = (png_byte)png_ptr->background.gray; + } + + else + { + png_byte v, w; - else if (a < 0xff) - png_composite(*sp, *sp, a, png_ptr->background.gray); + v = gamma_to_1[*sp]; + png_composite(w, v, a, png_ptr->background_1.gray); + if (optimize == 0) + w = gamma_from_1[w]; + *sp = w; } } } - else /* if (png_ptr->bit_depth == 16) */ + else +#endif { + sp = row; + for (i = 0; i < row_width; i++, sp += 2) + { + png_byte a = *(sp + 1); + + if (a == 0) + *sp = (png_byte)png_ptr->background.gray; + + else if (a < 0xff) + png_composite(*sp, *sp, a, png_ptr->background.gray); + } + } + } + else /* if (png_ptr->bit_depth == 16) */ + { #ifdef PNG_READ_GAMMA_SUPPORTED - if (gamma_16 != NULL && gamma_16_from_1 != NULL && - gamma_16_to_1 != NULL) + if (gamma_16 != NULL && gamma_16_from_1 != NULL && + gamma_16_to_1 != NULL) + { + sp = row; + for (i = 0; i < row_width; i++, sp += 4) { - sp = row; - for (i = 0; i < row_width; i++, sp += 4) + png_uint_16 a = (png_uint_16)(((*(sp + 2)) << 8) + + *(sp + 3)); + + if (a == (png_uint_16)0xffff) { - png_uint_16 a = (png_uint_16)(((*(sp + 2)) << 8) - + *(sp + 3)); + png_uint_16 v; - if (a == (png_uint_16)0xffff) - { - png_uint_16 v; + v = gamma_16[*(sp + 1) >> gamma_shift][*sp]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + } - v = gamma_16[*(sp + 1) >> gamma_shift][*sp]; - *sp = (png_byte)((v >> 8) & 0xff); - *(sp + 1) = (png_byte)(v & 0xff); - } + else if (a == 0) + { + /* Background is already in screen gamma */ + *sp = (png_byte)((png_ptr->background.gray >> 8) + & 0xff); + *(sp + 1) = (png_byte)(png_ptr->background.gray & 0xff); + } - else if (a == 0) - { - /* Background is already in screen gamma */ - *sp = (png_byte)((png_ptr->background.gray >> 8) - & 0xff); - *(sp + 1) = (png_byte)(png_ptr->background.gray & 0xff); - } + else + { + png_uint_16 g, v, w; + g = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp]; + png_composite_16(v, g, a, png_ptr->background_1.gray); + if (optimize != 0) + w = v; else - { - png_uint_16 g, v, w; - - g = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp]; - png_composite_16(v, g, a, png_ptr->background_1.gray); - if (optimize != 0) - w = v; - else - w = gamma_16_from_1[(v & 0xff) >> - gamma_shift][v >> 8]; - *sp = (png_byte)((w >> 8) & 0xff); - *(sp + 1) = (png_byte)(w & 0xff); - } + w = gamma_16_from_1[(v & 0xff) >> + gamma_shift][v >> 8]; + *sp = (png_byte)((w >> 8) & 0xff); + *(sp + 1) = (png_byte)(w & 0xff); } } - else + } + else #endif + { + sp = row; + for (i = 0; i < row_width; i++, sp += 4) { - sp = row; - for (i = 0; i < row_width; i++, sp += 4) - { - png_uint_16 a = (png_uint_16)(((*(sp + 2)) << 8) - + *(sp + 3)); + png_uint_16 a = (png_uint_16)(((*(sp + 2)) << 8) + + *(sp + 3)); - if (a == 0) - { - *sp = (png_byte)((png_ptr->background.gray >> 8) - & 0xff); - *(sp + 1) = (png_byte)(png_ptr->background.gray & 0xff); - } + if (a == 0) + { + *sp = (png_byte)((png_ptr->background.gray >> 8) + & 0xff); + *(sp + 1) = (png_byte)(png_ptr->background.gray & 0xff); + } - else if (a < 0xffff) - { - png_uint_16 g, v; + else if (a < 0xffff) + { + png_uint_16 g, v; - g = (png_uint_16)(((*sp) << 8) + *(sp + 1)); - png_composite_16(v, g, a, png_ptr->background.gray); - *sp = (png_byte)((v >> 8) & 0xff); - *(sp + 1) = (png_byte)(v & 0xff); - } + g = (png_uint_16)(((*sp) << 8) + *(sp + 1)); + png_composite_16(v, g, a, png_ptr->background.gray); + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); } } } - break; } + break; + } - case PNG_COLOR_TYPE_RGB_ALPHA: + case PNG_COLOR_TYPE_RGB_ALPHA: + { + if (row_info->bit_depth == 8) { - if (row_info->bit_depth == 8) - { #ifdef PNG_READ_GAMMA_SUPPORTED - if (gamma_to_1 != NULL && gamma_from_1 != NULL && - gamma_table != NULL) + if (gamma_to_1 != NULL && gamma_from_1 != NULL && + gamma_table != NULL) + { + sp = row; + for (i = 0; i < row_width; i++, sp += 4) { - sp = row; - for (i = 0; i < row_width; i++, sp += 4) + png_byte a = *(sp + 3); + + if (a == 0xff) { - png_byte a = *(sp + 3); + *sp = gamma_table[*sp]; + *(sp + 1) = gamma_table[*(sp + 1)]; + *(sp + 2) = gamma_table[*(sp + 2)]; + } - if (a == 0xff) - { - *sp = gamma_table[*sp]; - *(sp + 1) = gamma_table[*(sp + 1)]; - *(sp + 2) = gamma_table[*(sp + 2)]; - } + else if (a == 0) + { + /* Background is already in screen gamma */ + *sp = (png_byte)png_ptr->background.red; + *(sp + 1) = (png_byte)png_ptr->background.green; + *(sp + 2) = (png_byte)png_ptr->background.blue; + } - else if (a == 0) - { - /* Background is already in screen gamma */ - *sp = (png_byte)png_ptr->background.red; - *(sp + 1) = (png_byte)png_ptr->background.green; - *(sp + 2) = (png_byte)png_ptr->background.blue; - } + else + { + png_byte v, w; - else - { - png_byte v, w; - - v = gamma_to_1[*sp]; - png_composite(w, v, a, png_ptr->background_1.red); - if (optimize == 0) w = gamma_from_1[w]; - *sp = w; - - v = gamma_to_1[*(sp + 1)]; - png_composite(w, v, a, png_ptr->background_1.green); - if (optimize == 0) w = gamma_from_1[w]; - *(sp + 1) = w; - - v = gamma_to_1[*(sp + 2)]; - png_composite(w, v, a, png_ptr->background_1.blue); - if (optimize == 0) w = gamma_from_1[w]; - *(sp + 2) = w; - } + v = gamma_to_1[*sp]; + png_composite(w, v, a, png_ptr->background_1.red); + if (optimize == 0) w = gamma_from_1[w]; + *sp = w; + + v = gamma_to_1[*(sp + 1)]; + png_composite(w, v, a, png_ptr->background_1.green); + if (optimize == 0) w = gamma_from_1[w]; + *(sp + 1) = w; + + v = gamma_to_1[*(sp + 2)]; + png_composite(w, v, a, png_ptr->background_1.blue); + if (optimize == 0) w = gamma_from_1[w]; + *(sp + 2) = w; } } - else + } + else #endif + { + sp = row; + for (i = 0; i < row_width; i++, sp += 4) { - sp = row; - for (i = 0; i < row_width; i++, sp += 4) - { - png_byte a = *(sp + 3); + png_byte a = *(sp + 3); - if (a == 0) - { - *sp = (png_byte)png_ptr->background.red; - *(sp + 1) = (png_byte)png_ptr->background.green; - *(sp + 2) = (png_byte)png_ptr->background.blue; - } + if (a == 0) + { + *sp = (png_byte)png_ptr->background.red; + *(sp + 1) = (png_byte)png_ptr->background.green; + *(sp + 2) = (png_byte)png_ptr->background.blue; + } - else if (a < 0xff) - { - png_composite(*sp, *sp, a, png_ptr->background.red); + else if (a < 0xff) + { + png_composite(*sp, *sp, a, png_ptr->background.red); - png_composite(*(sp + 1), *(sp + 1), a, - png_ptr->background.green); + png_composite(*(sp + 1), *(sp + 1), a, + png_ptr->background.green); - png_composite(*(sp + 2), *(sp + 2), a, - png_ptr->background.blue); - } + png_composite(*(sp + 2), *(sp + 2), a, + png_ptr->background.blue); } } } - else /* if (row_info->bit_depth == 16) */ - { + } + else /* if (row_info->bit_depth == 16) */ + { #ifdef PNG_READ_GAMMA_SUPPORTED - if (gamma_16 != NULL && gamma_16_from_1 != NULL && - gamma_16_to_1 != NULL) + if (gamma_16 != NULL && gamma_16_from_1 != NULL && + gamma_16_to_1 != NULL) + { + sp = row; + for (i = 0; i < row_width; i++, sp += 8) { - sp = row; - for (i = 0; i < row_width; i++, sp += 8) - { - png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6)) - << 8) + (png_uint_16)(*(sp + 7))); + png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6)) + << 8) + (png_uint_16)(*(sp + 7))); - if (a == (png_uint_16)0xffff) - { - png_uint_16 v; + if (a == (png_uint_16)0xffff) + { + png_uint_16 v; - v = gamma_16[*(sp + 1) >> gamma_shift][*sp]; - *sp = (png_byte)((v >> 8) & 0xff); - *(sp + 1) = (png_byte)(v & 0xff); + v = gamma_16[*(sp + 1) >> gamma_shift][*sp]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); - v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)]; - *(sp + 2) = (png_byte)((v >> 8) & 0xff); - *(sp + 3) = (png_byte)(v & 0xff); + v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)]; + *(sp + 2) = (png_byte)((v >> 8) & 0xff); + *(sp + 3) = (png_byte)(v & 0xff); - v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)]; - *(sp + 4) = (png_byte)((v >> 8) & 0xff); - *(sp + 5) = (png_byte)(v & 0xff); - } + v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)]; + *(sp + 4) = (png_byte)((v >> 8) & 0xff); + *(sp + 5) = (png_byte)(v & 0xff); + } - else if (a == 0) - { - /* Background is already in screen gamma */ - *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff); - *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff); - *(sp + 2) = (png_byte)((png_ptr->background.green >> 8) - & 0xff); - *(sp + 3) = (png_byte)(png_ptr->background.green - & 0xff); - *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8) - & 0xff); - *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff); - } + else if (a == 0) + { + /* Background is already in screen gamma */ + *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff); + *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff); + *(sp + 2) = (png_byte)((png_ptr->background.green >> 8) + & 0xff); + *(sp + 3) = (png_byte)(png_ptr->background.green + & 0xff); + *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8) + & 0xff); + *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff); + } - else - { - png_uint_16 v, w; - - v = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp]; - png_composite_16(w, v, a, png_ptr->background_1.red); - if (optimize == 0) - w = gamma_16_from_1[((w & 0xff) >> gamma_shift)][w >> - 8]; - *sp = (png_byte)((w >> 8) & 0xff); - *(sp + 1) = (png_byte)(w & 0xff); - - v = gamma_16_to_1[*(sp + 3) >> gamma_shift][*(sp + 2)]; - png_composite_16(w, v, a, png_ptr->background_1.green); - if (optimize == 0) - w = gamma_16_from_1[((w & 0xff) >> gamma_shift)][w >> - 8]; - - *(sp + 2) = (png_byte)((w >> 8) & 0xff); - *(sp + 3) = (png_byte)(w & 0xff); - - v = gamma_16_to_1[*(sp + 5) >> gamma_shift][*(sp + 4)]; - png_composite_16(w, v, a, png_ptr->background_1.blue); - if (optimize == 0) - w = gamma_16_from_1[((w & 0xff) >> gamma_shift)][w >> - 8]; - - *(sp + 4) = (png_byte)((w >> 8) & 0xff); - *(sp + 5) = (png_byte)(w & 0xff); - } + else + { + png_uint_16 v, w; + + v = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp]; + png_composite_16(w, v, a, png_ptr->background_1.red); + if (optimize == 0) + w = gamma_16_from_1[((w & 0xff) >> gamma_shift)][w >> + 8]; + *sp = (png_byte)((w >> 8) & 0xff); + *(sp + 1) = (png_byte)(w & 0xff); + + v = gamma_16_to_1[*(sp + 3) >> gamma_shift][*(sp + 2)]; + png_composite_16(w, v, a, png_ptr->background_1.green); + if (optimize == 0) + w = gamma_16_from_1[((w & 0xff) >> gamma_shift)][w >> + 8]; + + *(sp + 2) = (png_byte)((w >> 8) & 0xff); + *(sp + 3) = (png_byte)(w & 0xff); + + v = gamma_16_to_1[*(sp + 5) >> gamma_shift][*(sp + 4)]; + png_composite_16(w, v, a, png_ptr->background_1.blue); + if (optimize == 0) + w = gamma_16_from_1[((w & 0xff) >> gamma_shift)][w >> + 8]; + + *(sp + 4) = (png_byte)((w >> 8) & 0xff); + *(sp + 5) = (png_byte)(w & 0xff); } } + } - else + else #endif + { + sp = row; + for (i = 0; i < row_width; i++, sp += 8) { - sp = row; - for (i = 0; i < row_width; i++, sp += 8) - { - png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6)) - << 8) + (png_uint_16)(*(sp + 7))); + png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6)) + << 8) + (png_uint_16)(*(sp + 7))); - if (a == 0) - { - *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff); - *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff); - *(sp + 2) = (png_byte)((png_ptr->background.green >> 8) - & 0xff); - *(sp + 3) = (png_byte)(png_ptr->background.green - & 0xff); - *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8) - & 0xff); - *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff); - } + if (a == 0) + { + *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff); + *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff); + *(sp + 2) = (png_byte)((png_ptr->background.green >> 8) + & 0xff); + *(sp + 3) = (png_byte)(png_ptr->background.green + & 0xff); + *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8) + & 0xff); + *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff); + } - else if (a < 0xffff) - { - png_uint_16 v; + else if (a < 0xffff) + { + png_uint_16 v; - png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1)); - png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8) - + *(sp + 3)); - png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8) - + *(sp + 5)); + png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1)); + png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8) + + *(sp + 3)); + png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8) + + *(sp + 5)); - png_composite_16(v, r, a, png_ptr->background.red); - *sp = (png_byte)((v >> 8) & 0xff); - *(sp + 1) = (png_byte)(v & 0xff); + png_composite_16(v, r, a, png_ptr->background.red); + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); - png_composite_16(v, g, a, png_ptr->background.green); - *(sp + 2) = (png_byte)((v >> 8) & 0xff); - *(sp + 3) = (png_byte)(v & 0xff); + png_composite_16(v, g, a, png_ptr->background.green); + *(sp + 2) = (png_byte)((v >> 8) & 0xff); + *(sp + 3) = (png_byte)(v & 0xff); - png_composite_16(v, b, a, png_ptr->background.blue); - *(sp + 4) = (png_byte)((v >> 8) & 0xff); - *(sp + 5) = (png_byte)(v & 0xff); - } + png_composite_16(v, b, a, png_ptr->background.blue); + *(sp + 4) = (png_byte)((v >> 8) & 0xff); + *(sp + 5) = (png_byte)(v & 0xff); } } } - break; } - - default: - break; + break; } + + default: + break; } } #endif /* READ_BACKGROUND || READ_ALPHA_MODE */ @@ -4220,8 +4217,8 @@ png_do_expand_palette(png_row_infop row_info, png_bytep row, { case 1: { - sp = row + (png_size_t)((row_width - 1) >> 3); - dp = row + (png_size_t)row_width - 1; + sp = row + (size_t)((row_width - 1) >> 3); + dp = row + (size_t)row_width - 1; shift = 7 - (int)((row_width + 7) & 0x07); for (i = 0; i < row_width; i++) { @@ -4247,8 +4244,8 @@ png_do_expand_palette(png_row_infop row_info, png_bytep row, case 2: { - sp = row + (png_size_t)((row_width - 1) >> 2); - dp = row + (png_size_t)row_width - 1; + sp = row + (size_t)((row_width - 1) >> 2); + dp = row + (size_t)row_width - 1; shift = (int)((3 - ((row_width + 3) & 0x03)) << 1); for (i = 0; i < row_width; i++) { @@ -4270,8 +4267,8 @@ png_do_expand_palette(png_row_infop row_info, png_bytep row, case 4: { - sp = row + (png_size_t)((row_width - 1) >> 1); - dp = row + (png_size_t)row_width - 1; + sp = row + (size_t)((row_width - 1) >> 1); + dp = row + (size_t)row_width - 1; shift = (int)((row_width & 0x01) << 2); for (i = 0; i < row_width; i++) { @@ -4304,8 +4301,8 @@ png_do_expand_palette(png_row_infop row_info, png_bytep row, { if (num_trans > 0) { - sp = row + (png_size_t)row_width - 1; - dp = row + ((png_size_t)row_width << 2) - 1; + sp = row + (size_t)row_width - 1; + dp = row + ((size_t)row_width << 2) - 1; for (i = 0; i < row_width; i++) { @@ -4329,8 +4326,8 @@ png_do_expand_palette(png_row_infop row_info, png_bytep row, else { - sp = row + (png_size_t)row_width - 1; - dp = row + (png_size_t)(row_width * 3) - 1; + sp = row + (size_t)row_width - 1; + dp = row + (size_t)(row_width * 3) - 1; for (i = 0; i < row_width; i++) { @@ -4365,195 +4362,130 @@ png_do_expand(png_row_infop row_info, png_bytep row, png_debug(1, "in png_do_expand"); + if (row_info->color_type == PNG_COLOR_TYPE_GRAY) { - if (row_info->color_type == PNG_COLOR_TYPE_GRAY) - { - unsigned int gray = trans_color != NULL ? trans_color->gray : 0; + unsigned int gray = trans_color != NULL ? trans_color->gray : 0; - if (row_info->bit_depth < 8) + if (row_info->bit_depth < 8) + { + switch (row_info->bit_depth) { - switch (row_info->bit_depth) + case 1: { - case 1: + gray = (gray & 0x01) * 0xff; + sp = row + (size_t)((row_width - 1) >> 3); + dp = row + (size_t)row_width - 1; + shift = 7 - (int)((row_width + 7) & 0x07); + for (i = 0; i < row_width; i++) { - gray = (gray & 0x01) * 0xff; - sp = row + (png_size_t)((row_width - 1) >> 3); - dp = row + (png_size_t)row_width - 1; - shift = 7 - (int)((row_width + 7) & 0x07); - for (i = 0; i < row_width; i++) - { - if ((*sp >> shift) & 0x01) - *dp = 0xff; - - else - *dp = 0; - - if (shift == 7) - { - shift = 0; - sp--; - } - - else - shift++; + if ((*sp >> shift) & 0x01) + *dp = 0xff; - dp--; - } - break; - } + else + *dp = 0; - case 2: - { - gray = (gray & 0x03) * 0x55; - sp = row + (png_size_t)((row_width - 1) >> 2); - dp = row + (png_size_t)row_width - 1; - shift = (int)((3 - ((row_width + 3) & 0x03)) << 1); - for (i = 0; i < row_width; i++) + if (shift == 7) { - value = (*sp >> shift) & 0x03; - *dp = (png_byte)(value | (value << 2) | (value << 4) | - (value << 6)); - if (shift == 6) - { - shift = 0; - sp--; - } - - else - shift += 2; - - dp--; + shift = 0; + sp--; } - break; - } - - case 4: - { - gray = (gray & 0x0f) * 0x11; - sp = row + (png_size_t)((row_width - 1) >> 1); - dp = row + (png_size_t)row_width - 1; - shift = (int)((1 - ((row_width + 1) & 0x01)) << 2); - for (i = 0; i < row_width; i++) - { - value = (*sp >> shift) & 0x0f; - *dp = (png_byte)(value | (value << 4)); - if (shift == 4) - { - shift = 0; - sp--; - } - else - shift = 4; + else + shift++; - dp--; - } - break; + dp--; } - - default: - break; + break; } - row_info->bit_depth = 8; - row_info->pixel_depth = 8; - row_info->rowbytes = row_width; - } - - if (trans_color != NULL) - { - if (row_info->bit_depth == 8) + case 2: { - gray = gray & 0xff; - sp = row + (png_size_t)row_width - 1; - dp = row + ((png_size_t)row_width << 1) - 1; - + gray = (gray & 0x03) * 0x55; + sp = row + (size_t)((row_width - 1) >> 2); + dp = row + (size_t)row_width - 1; + shift = (int)((3 - ((row_width + 3) & 0x03)) << 1); for (i = 0; i < row_width; i++) { - if ((*sp & 0xffU) == gray) - *dp-- = 0; + value = (*sp >> shift) & 0x03; + *dp = (png_byte)(value | (value << 2) | (value << 4) | + (value << 6)); + if (shift == 6) + { + shift = 0; + sp--; + } else - *dp-- = 0xff; + shift += 2; - *dp-- = *sp--; + dp--; } + break; } - else if (row_info->bit_depth == 16) + case 4: { - unsigned int gray_high = (gray >> 8) & 0xff; - unsigned int gray_low = gray & 0xff; - sp = row + row_info->rowbytes - 1; - dp = row + (row_info->rowbytes << 1) - 1; + gray = (gray & 0x0f) * 0x11; + sp = row + (size_t)((row_width - 1) >> 1); + dp = row + (size_t)row_width - 1; + shift = (int)((1 - ((row_width + 1) & 0x01)) << 2); for (i = 0; i < row_width; i++) { - if ((*(sp - 1) & 0xffU) == gray_high && - (*(sp) & 0xffU) == gray_low) + value = (*sp >> shift) & 0x0f; + *dp = (png_byte)(value | (value << 4)); + if (shift == 4) { - *dp-- = 0; - *dp-- = 0; + shift = 0; + sp--; } else - { - *dp-- = 0xff; - *dp-- = 0xff; - } + shift = 4; - *dp-- = *sp--; - *dp-- = *sp--; + dp--; } + break; } - row_info->color_type = PNG_COLOR_TYPE_GRAY_ALPHA; - row_info->channels = 2; - row_info->pixel_depth = (png_byte)(row_info->bit_depth << 1); - row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, - row_width); + default: + break; } + + row_info->bit_depth = 8; + row_info->pixel_depth = 8; + row_info->rowbytes = row_width; } - else if (row_info->color_type == PNG_COLOR_TYPE_RGB && - trans_color != NULL) + + if (trans_color != NULL) { if (row_info->bit_depth == 8) { - png_byte red = (png_byte)(trans_color->red & 0xff); - png_byte green = (png_byte)(trans_color->green & 0xff); - png_byte blue = (png_byte)(trans_color->blue & 0xff); - sp = row + (png_size_t)row_info->rowbytes - 1; - dp = row + ((png_size_t)row_width << 2) - 1; + gray = gray & 0xff; + sp = row + (size_t)row_width - 1; + dp = row + ((size_t)row_width << 1) - 1; + for (i = 0; i < row_width; i++) { - if (*(sp - 2) == red && *(sp - 1) == green && *(sp) == blue) + if ((*sp & 0xffU) == gray) *dp-- = 0; else *dp-- = 0xff; *dp-- = *sp--; - *dp-- = *sp--; - *dp-- = *sp--; } } + else if (row_info->bit_depth == 16) { - png_byte red_high = (png_byte)((trans_color->red >> 8) & 0xff); - png_byte green_high = (png_byte)((trans_color->green >> 8) & 0xff); - png_byte blue_high = (png_byte)((trans_color->blue >> 8) & 0xff); - png_byte red_low = (png_byte)(trans_color->red & 0xff); - png_byte green_low = (png_byte)(trans_color->green & 0xff); - png_byte blue_low = (png_byte)(trans_color->blue & 0xff); + unsigned int gray_high = (gray >> 8) & 0xff; + unsigned int gray_low = gray & 0xff; sp = row + row_info->rowbytes - 1; - dp = row + ((png_size_t)row_width << 3) - 1; + dp = row + (row_info->rowbytes << 1) - 1; for (i = 0; i < row_width; i++) { - if (*(sp - 5) == red_high && - *(sp - 4) == red_low && - *(sp - 3) == green_high && - *(sp - 2) == green_low && - *(sp - 1) == blue_high && - *(sp ) == blue_low) + if ((*(sp - 1) & 0xffU) == gray_high && + (*(sp) & 0xffU) == gray_low) { *dp-- = 0; *dp-- = 0; @@ -4567,18 +4499,81 @@ png_do_expand(png_row_infop row_info, png_bytep row, *dp-- = *sp--; *dp-- = *sp--; - *dp-- = *sp--; - *dp-- = *sp--; - *dp-- = *sp--; - *dp-- = *sp--; } } - row_info->color_type = PNG_COLOR_TYPE_RGB_ALPHA; - row_info->channels = 4; - row_info->pixel_depth = (png_byte)(row_info->bit_depth << 2); - row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width); + + row_info->color_type = PNG_COLOR_TYPE_GRAY_ALPHA; + row_info->channels = 2; + row_info->pixel_depth = (png_byte)(row_info->bit_depth << 1); + row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, + row_width); } } + else if (row_info->color_type == PNG_COLOR_TYPE_RGB && + trans_color != NULL) + { + if (row_info->bit_depth == 8) + { + png_byte red = (png_byte)(trans_color->red & 0xff); + png_byte green = (png_byte)(trans_color->green & 0xff); + png_byte blue = (png_byte)(trans_color->blue & 0xff); + sp = row + (size_t)row_info->rowbytes - 1; + dp = row + ((size_t)row_width << 2) - 1; + for (i = 0; i < row_width; i++) + { + if (*(sp - 2) == red && *(sp - 1) == green && *(sp) == blue) + *dp-- = 0; + + else + *dp-- = 0xff; + + *dp-- = *sp--; + *dp-- = *sp--; + *dp-- = *sp--; + } + } + else if (row_info->bit_depth == 16) + { + png_byte red_high = (png_byte)((trans_color->red >> 8) & 0xff); + png_byte green_high = (png_byte)((trans_color->green >> 8) & 0xff); + png_byte blue_high = (png_byte)((trans_color->blue >> 8) & 0xff); + png_byte red_low = (png_byte)(trans_color->red & 0xff); + png_byte green_low = (png_byte)(trans_color->green & 0xff); + png_byte blue_low = (png_byte)(trans_color->blue & 0xff); + sp = row + row_info->rowbytes - 1; + dp = row + ((size_t)row_width << 3) - 1; + for (i = 0; i < row_width; i++) + { + if (*(sp - 5) == red_high && + *(sp - 4) == red_low && + *(sp - 3) == green_high && + *(sp - 2) == green_low && + *(sp - 1) == blue_high && + *(sp ) == blue_low) + { + *dp-- = 0; + *dp-- = 0; + } + + else + { + *dp-- = 0xff; + *dp-- = 0xff; + } + + *dp-- = *sp--; + *dp-- = *sp--; + *dp-- = *sp--; + *dp-- = *sp--; + *dp-- = *sp--; + *dp-- = *sp--; + } + } + row_info->color_type = PNG_COLOR_TYPE_RGB_ALPHA; + row_info->channels = 4; + row_info->pixel_depth = (png_byte)(row_info->bit_depth << 2); + row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width); + } } #endif @@ -4760,8 +4755,7 @@ png_do_read_transformations(png_structrp png_ptr, png_row_infop row_info) &(png_ptr->trans_color)); else - png_do_expand(row_info, png_ptr->row_buf + 1, - NULL); + png_do_expand(row_info, png_ptr->row_buf + 1, NULL); } } #endif @@ -4985,7 +4979,7 @@ png_do_read_transformations(png_structrp png_ptr, png_row_infop row_info) (png_ptr, /* png_ptr */ row_info, /* row_info: */ /* png_uint_32 width; width of row */ - /* png_size_t rowbytes; number of bytes in row */ + /* size_t rowbytes; number of bytes in row */ /* png_byte color_type; color type of pixels */ /* png_byte bit_depth; bit depth of samples */ /* png_byte channels; number of channels (1-4) */ diff --git a/thirdparty/libpng/pngrutil.c b/thirdparty/libpng/pngrutil.c index 8692933bd8..7001f1976e 100644 --- a/thirdparty/libpng/pngrutil.c +++ b/thirdparty/libpng/pngrutil.c @@ -1,8 +1,8 @@ /* pngrutil.c - utilities to read a PNG file * - * Last changed in libpng 1.6.33 [September 28, 2017] - * Copyright (c) 1998-2002,2004,2006-2017 Glenn Randers-Pehrson + * Last changed in libpng 1.6.35 [July 15, 2018] + * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) * @@ -102,7 +102,7 @@ png_get_int_32)(png_const_bytep buf) png_uint_16 (PNGAPI png_get_uint_16)(png_const_bytep buf) { - /* ANSI-C requires an int value to accomodate at least 16 bits so this + /* ANSI-C requires an int value to accommodate at least 16 bits so this * works and allows the compiler not to worry about possible narrowing * on 32-bit systems. (Pre-ANSI systems did not make integers smaller * than 16 bits either.) @@ -120,7 +120,7 @@ png_get_uint_16)(png_const_bytep buf) void /* PRIVATE */ png_read_sig(png_structrp png_ptr, png_inforp info_ptr) { - png_size_t num_checked, num_to_check; + size_t num_checked, num_to_check; /* Exit if the user application does not expect a signature. */ if (png_ptr->sig_bytes >= 8) @@ -1648,7 +1648,7 @@ png_handle_sPLT(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) int entry_size, i; png_uint_32 skip = 0; png_uint_32 dl; - png_size_t max_dl; + size_t max_dl; png_debug(1, "in png_handle_sPLT"); @@ -1997,6 +1997,15 @@ png_handle_bKGD(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) else if ((png_ptr->color_type & PNG_COLOR_MASK_COLOR) == 0) /* GRAY */ { + if (png_ptr->bit_depth <= 8) + { + if (buf[0] != 0 || buf[1] >= (unsigned int)(1 << png_ptr->bit_depth)) + { + png_chunk_benign_error(png_ptr, "invalid gray level"); + return; + } + } + background.index = 0; background.red = background.green = @@ -2006,6 +2015,15 @@ png_handle_bKGD(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) else { + if (png_ptr->bit_depth <= 8) + { + if (buf[0] != 0 || buf[2] != 0 || buf[4] != 0) + { + png_chunk_benign_error(png_ptr, "invalid color"); + return; + } + } + background.index = 0; background.red = png_get_uint_16(buf); background.green = png_get_uint_16(buf + 2); @@ -2359,7 +2377,7 @@ void /* PRIVATE */ png_handle_sCAL(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) { png_bytep buffer; - png_size_t i; + size_t i; int state; png_debug(1, "in png_handle_sCAL"); @@ -2429,7 +2447,7 @@ png_handle_sCAL(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) else { - png_size_t heighti = i; + size_t heighti = i; state = 0; if (png_check_fp_number((png_const_charp)buffer, length, @@ -2867,7 +2885,7 @@ png_cache_unknown_chunk(png_structrp png_ptr, png_uint_32 length) { PNG_CSTRING_FROM_CHUNK(png_ptr->unknown_chunk.name, png_ptr->chunk_name); /* The following is safe because of the PNG_SIZE_MAX init above */ - png_ptr->unknown_chunk.size = (png_size_t)length/*SAFE*/; + png_ptr->unknown_chunk.size = (size_t)length/*SAFE*/; /* 'mode' is a flag array, only the bottom four bits matter here */ png_ptr->unknown_chunk.location = (png_byte)png_ptr->mode/*SAFE*/; @@ -3149,10 +3167,13 @@ png_check_chunk_length(png_const_structrp png_ptr, const png_uint_32 length) { png_alloc_size_t idat_limit = PNG_UINT_31_MAX; size_t row_factor = - (png_ptr->width * png_ptr->channels * (png_ptr->bit_depth > 8? 2: 1) - + 1 + (png_ptr->interlaced? 6: 0)); + (size_t)png_ptr->width + * (size_t)png_ptr->channels + * (png_ptr->bit_depth > 8? 2: 1) + + 1 + + (png_ptr->interlaced? 6: 0); if (png_ptr->height > PNG_UINT_32_MAX/row_factor) - idat_limit=PNG_UINT_31_MAX; + idat_limit = PNG_UINT_31_MAX; else idat_limit = png_ptr->height * row_factor; row_factor = row_factor > 32566? 32566 : row_factor; @@ -3679,8 +3700,8 @@ png_do_read_interlace(png_row_infop row_info, png_bytep row, int pass, { case 1: { - png_bytep sp = row + (png_size_t)((row_info->width - 1) >> 3); - png_bytep dp = row + (png_size_t)((final_width - 1) >> 3); + png_bytep sp = row + (size_t)((row_info->width - 1) >> 3); + png_bytep dp = row + (size_t)((final_width - 1) >> 3); unsigned int sshift, dshift; unsigned int s_start, s_end; int s_inc; @@ -3806,8 +3827,8 @@ png_do_read_interlace(png_row_infop row_info, png_bytep row, int pass, case 4: { - png_bytep sp = row + (png_size_t)((row_info->width - 1) >> 1); - png_bytep dp = row + (png_size_t)((final_width - 1) >> 1); + png_bytep sp = row + (size_t)((row_info->width - 1) >> 1); + png_bytep dp = row + (size_t)((final_width - 1) >> 1); unsigned int sshift, dshift; unsigned int s_start, s_end; int s_inc; @@ -3869,12 +3890,12 @@ png_do_read_interlace(png_row_infop row_info, png_bytep row, int pass, default: { - png_size_t pixel_bytes = (row_info->pixel_depth >> 3); + size_t pixel_bytes = (row_info->pixel_depth >> 3); - png_bytep sp = row + (png_size_t)(row_info->width - 1) + png_bytep sp = row + (size_t)(row_info->width - 1) * pixel_bytes; - png_bytep dp = row + (png_size_t)(final_width - 1) * pixel_bytes; + png_bytep dp = row + (size_t)(final_width - 1) * pixel_bytes; int jstop = (int)png_pass_inc[pass]; png_uint_32 i; @@ -3911,8 +3932,8 @@ static void png_read_filter_row_sub(png_row_infop row_info, png_bytep row, png_const_bytep prev_row) { - png_size_t i; - png_size_t istop = row_info->rowbytes; + size_t i; + size_t istop = row_info->rowbytes; unsigned int bpp = (row_info->pixel_depth + 7) >> 3; png_bytep rp = row + bpp; @@ -3929,8 +3950,8 @@ static void png_read_filter_row_up(png_row_infop row_info, png_bytep row, png_const_bytep prev_row) { - png_size_t i; - png_size_t istop = row_info->rowbytes; + size_t i; + size_t istop = row_info->rowbytes; png_bytep rp = row; png_const_bytep pp = prev_row; @@ -3945,11 +3966,11 @@ static void png_read_filter_row_avg(png_row_infop row_info, png_bytep row, png_const_bytep prev_row) { - png_size_t i; + size_t i; png_bytep rp = row; png_const_bytep pp = prev_row; unsigned int bpp = (row_info->pixel_depth + 7) >> 3; - png_size_t istop = row_info->rowbytes - bpp; + size_t istop = row_info->rowbytes - bpp; for (i = 0; i < bpp; i++) { @@ -4385,7 +4406,7 @@ png_read_start_row(png_structrp png_ptr) static PNG_CONST png_byte png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2}; unsigned int max_pixel_depth; - png_size_t row_bytes; + size_t row_bytes; png_debug(1, "in png_read_start_row"); diff --git a/thirdparty/libpng/pngset.c b/thirdparty/libpng/pngset.c index 6f3a1ee11e..7cf54d9248 100644 --- a/thirdparty/libpng/pngset.c +++ b/thirdparty/libpng/pngset.c @@ -1,8 +1,8 @@ /* pngset.c - storage of image information into info struct * - * Last changed in libpng 1.6.32 [August 24, 2017] - * Copyright (c) 1998-2017 Glenn Randers-Pehrson + * Last changed in libpng 1.6.35 [July 15, 2018] + * Copyright (c) 1998-2018 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) * @@ -313,7 +313,7 @@ png_set_pCAL(png_const_structrp png_ptr, png_inforp info_ptr, png_const_charp purpose, png_int_32 X0, png_int_32 X1, int type, int nparams, png_const_charp units, png_charpp params) { - png_size_t length; + size_t length; int i; png_debug1(1, "in %s storage function", "pCAL"); @@ -390,7 +390,7 @@ png_set_pCAL(png_const_structrp png_ptr, png_inforp info_ptr, memcpy(info_ptr->pcal_units, units, length); info_ptr->pcal_params = png_voidcast(png_charpp, png_malloc_warn(png_ptr, - (png_size_t)(((unsigned int)nparams + 1) * (sizeof (png_charp))))); + (size_t)(((unsigned int)nparams + 1) * (sizeof (png_charp))))); if (info_ptr->pcal_params == NULL) { @@ -430,7 +430,7 @@ void PNGAPI png_set_sCAL_s(png_const_structrp png_ptr, png_inforp info_ptr, int unit, png_const_charp swidth, png_const_charp sheight) { - png_size_t lengthw = 0, lengthh = 0; + size_t lengthw = 0, lengthh = 0; png_debug1(1, "in %s storage function", "sCAL"); @@ -691,7 +691,7 @@ png_set_iCCP(png_const_structrp png_ptr, png_inforp info_ptr, { png_charp new_iccp_name; png_bytep new_iccp_profile; - png_size_t length; + size_t length; png_debug1(1, "in %s storage function", "iCCP"); @@ -1018,7 +1018,7 @@ png_set_tRNS(png_structrp png_ptr, png_inforp info_ptr, /* Changed from num_trans to PNG_MAX_PALETTE_LENGTH in version 1.2.1 */ info_ptr->trans_alpha = png_voidcast(png_bytep, png_malloc(png_ptr, PNG_MAX_PALETTE_LENGTH)); - memcpy(info_ptr->trans_alpha, trans_alpha, (png_size_t)num_trans); + memcpy(info_ptr->trans_alpha, trans_alpha, (size_t)num_trans); } png_ptr->trans_alpha = info_ptr->trans_alpha; } @@ -1098,7 +1098,7 @@ png_set_sPLT(png_const_structrp png_ptr, do { - png_size_t length; + size_t length; /* Skip invalid input entries */ if (entries->name == NULL || entries->entries == NULL) @@ -1563,7 +1563,7 @@ png_set_rows(png_const_structrp png_ptr, png_inforp info_ptr, #endif void PNGAPI -png_set_compression_buffer_size(png_structrp png_ptr, png_size_t size) +png_set_compression_buffer_size(png_structrp png_ptr, size_t size) { if (png_ptr == NULL) return; diff --git a/thirdparty/libpng/pngstruct.h b/thirdparty/libpng/pngstruct.h index d83f971253..699e8ac68a 100644 --- a/thirdparty/libpng/pngstruct.h +++ b/thirdparty/libpng/pngstruct.h @@ -1,8 +1,8 @@ /* pngstruct.h - header file for PNG reference library * - * Last changed in libpng 1.6.32 [August 24, 2017] - * Copyright (c) 1998-2002,2004,2006-2017 Glenn Randers-Pehrson + * Last changed in libpng 1.6.35 [July 15, 2018] + * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) * @@ -47,7 +47,7 @@ /* zlib.h declares a magic type 'uInt' that limits the amount of data that zlib * can handle at once. This type need be no larger than 16 bits (so maximum of * 65535), this define allows us to discover how big it is, but limited by the - * maximuum for png_size_t. The value can be overriden in a library build + * maximum for size_t. The value can be overridden in a library build * (pngusr.h, or set it in CPPFLAGS) and it works to set it to a considerably * lower value (e.g. 255 works). A lower value may help memory usage (slightly) * and may even improve performance on some systems (and degrade it on others.) @@ -214,7 +214,7 @@ struct png_struct_def png_uint_32 height; /* height of image in pixels */ png_uint_32 num_rows; /* number of rows in current pass */ png_uint_32 usr_width; /* width of row at start of write */ - png_size_t rowbytes; /* size of row in bytes */ + size_t rowbytes; /* size of row in bytes */ png_uint_32 iwidth; /* width of current interlaced row in pixels */ png_uint_32 row_number; /* current row in interlace pass */ png_uint_32 chunk_name; /* PNG_CHUNK() id of current chunk */ @@ -232,7 +232,7 @@ struct png_struct_def png_bytep try_row; /* buffer to save trial row when filtering */ png_bytep tst_row; /* buffer to save best trial row when filtering */ #endif - png_size_t info_rowbytes; /* Added in 1.5.4: cache of updated row bytes */ + size_t info_rowbytes; /* Added in 1.5.4: cache of updated row bytes */ png_uint_32 idat_size; /* current IDAT size for read */ png_uint_32 crc; /* current chunk CRC value */ @@ -307,7 +307,7 @@ struct png_struct_def #endif #if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED) - png_color_8 shift; /* shift for significant bit tranformation */ + png_color_8 shift; /* shift for significant bit transformation */ #endif #if defined(PNG_tRNS_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) \ @@ -328,10 +328,10 @@ struct png_struct_def png_bytep current_buffer; /* buffer for recently used data */ png_uint_32 push_length; /* size of current input chunk */ png_uint_32 skip_length; /* bytes to skip in input data */ - png_size_t save_buffer_size; /* amount of data now in save_buffer */ - png_size_t save_buffer_max; /* total size of save_buffer */ - png_size_t buffer_size; /* total amount of available input data */ - png_size_t current_buffer_size; /* amount of data now in current_buffer */ + size_t save_buffer_size; /* amount of data now in save_buffer */ + size_t save_buffer_max; /* total size of save_buffer */ + size_t buffer_size; /* total amount of available input data */ + size_t current_buffer_size; /* amount of data now in current_buffer */ int process_mode; /* what push library is currently doing */ int cur_palette; /* current push library palette index */ @@ -451,7 +451,7 @@ struct png_struct_def #endif /* New member added in libpng-1.2.26 */ - png_size_t old_big_row_buf_size; + size_t old_big_row_buf_size; #ifdef PNG_READ_SUPPORTED /* New member added in libpng-1.2.30 */ diff --git a/thirdparty/libpng/pngtrans.c b/thirdparty/libpng/pngtrans.c index 6882f0fd7b..de84aa6d6b 100644 --- a/thirdparty/libpng/pngtrans.c +++ b/thirdparty/libpng/pngtrans.c @@ -1,8 +1,8 @@ /* pngtrans.c - transforms the data in a row (used by both readers and writers) * - * Last changed in libpng 1.6.33 [September 28, 2017] - * Copyright (c) 1998-2002,2004,2006-2017 Glenn Randers-Pehrson + * Last changed in libpng 1.6.35 [July 15, 2018] + * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) * @@ -269,8 +269,8 @@ png_do_invert(png_row_infop row_info, png_bytep row) if (row_info->color_type == PNG_COLOR_TYPE_GRAY) { png_bytep rp = row; - png_size_t i; - png_size_t istop = row_info->rowbytes; + size_t i; + size_t istop = row_info->rowbytes; for (i = 0; i < istop; i++) { @@ -283,8 +283,8 @@ png_do_invert(png_row_infop row_info, png_bytep row) row_info->bit_depth == 8) { png_bytep rp = row; - png_size_t i; - png_size_t istop = row_info->rowbytes; + size_t i; + size_t istop = row_info->rowbytes; for (i = 0; i < istop; i += 2) { @@ -298,8 +298,8 @@ png_do_invert(png_row_infop row_info, png_bytep row) row_info->bit_depth == 16) { png_bytep rp = row; - png_size_t i; - png_size_t istop = row_info->rowbytes; + size_t i; + size_t istop = row_info->rowbytes; for (i = 0; i < istop; i += 4) { @@ -609,7 +609,7 @@ png_do_strip_channel(png_row_infop row_info, png_bytep row, int at_start) return; /* The filler channel has gone already */ /* Fix the rowbytes value. */ - row_info->rowbytes = (png_size_t)(dp-row); + row_info->rowbytes = (size_t)(dp-row); } #endif diff --git a/thirdparty/libpng/pngwio.c b/thirdparty/libpng/pngwio.c index 37c7c3a7f0..e5391687a2 100644 --- a/thirdparty/libpng/pngwio.c +++ b/thirdparty/libpng/pngwio.c @@ -1,8 +1,8 @@ /* pngwio.c - functions for data output * - * Last changed in libpng 1.6.24 [August 4, 2016] - * Copyright (c) 1998-2002,2004,2006-2014,2016 Glenn Randers-Pehrson + * Last changed in libpng 1.6.35 [July 15, 2018] + * Copyright (c) 1998-2002,2004,2006-2014,2016,2018 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) * @@ -30,7 +30,7 @@ */ void /* PRIVATE */ -png_write_data(png_structrp png_ptr, png_const_bytep data, png_size_t length) +png_write_data(png_structrp png_ptr, png_const_bytep data, size_t length) { /* NOTE: write_data_fn must not change the buffer! */ if (png_ptr->write_data_fn != NULL ) @@ -48,9 +48,9 @@ png_write_data(png_structrp png_ptr, png_const_bytep data, png_size_t length) * than changing the library. */ void PNGCBAPI -png_default_write_data(png_structp png_ptr, png_bytep data, png_size_t length) +png_default_write_data(png_structp png_ptr, png_bytep data, size_t length) { - png_size_t check; + size_t check; if (png_ptr == NULL) return; diff --git a/thirdparty/libpng/pngwrite.c b/thirdparty/libpng/pngwrite.c index a16d77ce00..5bd87f373e 100644 --- a/thirdparty/libpng/pngwrite.c +++ b/thirdparty/libpng/pngwrite.c @@ -1,8 +1,8 @@ /* pngwrite.c - general routines to write a PNG file * - * Last changed in libpng 1.6.32 [August 24, 2017] - * Copyright (c) 1998-2002,2004,2006-2017 Glenn Randers-Pehrson + * Last changed in libpng 1.6.35 [July 15, 2018] + * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) * @@ -1636,7 +1636,7 @@ png_write_image_16bit(png_voidp argument) * calculation can be done to 15 bits of accuracy; however, the output needs to * be scaled in the range 0..255*65535, so include that scaling here. */ -# define UNP_RECIPROCAL(alpha) ((((0xffff*0xff)<<7)+(alpha>>1))/alpha) +# define UNP_RECIPROCAL(alpha) ((((0xffff*0xff)<<7)+((alpha)>>1))/(alpha)) static png_byte png_unpremultiply(png_uint_32 component, png_uint_32 alpha, @@ -2162,8 +2162,7 @@ png_image_write_main(png_voidp argument) static void (PNGCBAPI -image_memory_write)(png_structp png_ptr, png_bytep/*const*/ data, - png_size_t size) +image_memory_write)(png_structp png_ptr, png_bytep/*const*/ data, size_t size) { png_image_write_control *display = png_voidcast(png_image_write_control*, png_ptr->io_ptr/*backdoor: png_get_io_ptr(png_ptr)*/); diff --git a/thirdparty/libpng/pngwtran.c b/thirdparty/libpng/pngwtran.c index 377b43e5ca..3a1e0a21d2 100644 --- a/thirdparty/libpng/pngwtran.c +++ b/thirdparty/libpng/pngwtran.c @@ -1,8 +1,8 @@ /* pngwtran.c - transforms the data in a row for PNG writers * - * Last changed in libpng 1.6.26 [October 20, 2016] - * Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson + * Last changed in libpng 1.6.35 [July 15, 2018] + * Copyright (c) 1998-2002,2004,2006-2016,2018 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) * @@ -212,9 +212,9 @@ png_do_shift(png_row_infop row_info, png_bytep row, if (row_info->bit_depth < 8) { png_bytep bp = row; - png_size_t i; + size_t i; unsigned int mask; - png_size_t row_bytes = row_info->rowbytes; + size_t row_bytes = row_info->rowbytes; if (bit_depth->gray == 1 && row_info->bit_depth == 2) mask = 0x55; @@ -514,7 +514,7 @@ png_do_write_transformations(png_structrp png_ptr, png_row_infop row_info) (png_ptr, /* png_ptr */ row_info, /* row_info: */ /* png_uint_32 width; width of row */ - /* png_size_t rowbytes; number of bytes in row */ + /* size_t rowbytes; number of bytes in row */ /* png_byte color_type; color type of pixels */ /* png_byte bit_depth; bit depth of samples */ /* png_byte channels; number of channels (1-4) */ diff --git a/thirdparty/libpng/pngwutil.c b/thirdparty/libpng/pngwutil.c index 0d4fb1336c..ab431e712c 100644 --- a/thirdparty/libpng/pngwutil.c +++ b/thirdparty/libpng/pngwutil.c @@ -1,8 +1,8 @@ /* pngwutil.c - utilities to write a PNG file * - * Last changed in libpng 1.6.32 [August 24, 2017] - * Copyright (c) 1998-2002,2004,2006-2017 Glenn Randers-Pehrson + * Last changed in libpng 1.6.35 [July 15, 2018] + * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) * @@ -59,7 +59,7 @@ png_write_sig(png_structrp png_ptr) /* Write the rest of the 8 byte signature */ png_write_data(png_ptr, &png_signature[png_ptr->sig_bytes], - (png_size_t)(8 - png_ptr->sig_bytes)); + (size_t)(8 - png_ptr->sig_bytes)); if (png_ptr->sig_bytes < 3) png_ptr->mode |= PNG_HAVE_PNG_SIGNATURE; @@ -124,8 +124,7 @@ png_write_chunk_start(png_structrp png_ptr, png_const_bytep chunk_string, * given to png_write_chunk_header(). */ void PNGAPI -png_write_chunk_data(png_structrp png_ptr, png_const_bytep data, - png_size_t length) +png_write_chunk_data(png_structrp png_ptr, png_const_bytep data, size_t length) { /* Write the data, and run the CRC over it */ if (png_ptr == NULL) @@ -160,7 +159,7 @@ png_write_chunk_end(png_structrp png_ptr) /* Write the crc in a single operation */ png_save_uint_32(buf, png_ptr->crc); - png_write_data(png_ptr, buf, (png_size_t)4); + png_write_data(png_ptr, buf, 4); } /* Write a PNG chunk all at once. The type is an array of ASCII characters @@ -174,7 +173,7 @@ png_write_chunk_end(png_structrp png_ptr) */ static void png_write_complete_chunk(png_structrp png_ptr, png_uint_32 chunk_name, - png_const_bytep data, png_size_t length) + png_const_bytep data, size_t length) { if (png_ptr == NULL) return; @@ -191,7 +190,7 @@ png_write_complete_chunk(png_structrp png_ptr, png_uint_32 chunk_name, /* This is the API that calls the internal function above. */ void PNGAPI png_write_chunk(png_structrp png_ptr, png_const_bytep chunk_string, - png_const_bytep data, png_size_t length) + png_const_bytep data, size_t length) { png_write_complete_chunk(png_ptr, PNG_CHUNK_FROM_STRING(chunk_string), data, length); @@ -820,7 +819,7 @@ png_write_IHDR(png_structrp png_ptr, png_uint_32 width, png_uint_32 height, buf[12] = (png_byte)interlace_type; /* Write the chunk */ - png_write_complete_chunk(png_ptr, png_IHDR, buf, (png_size_t)13); + png_write_complete_chunk(png_ptr, png_IHDR, buf, 13); if ((png_ptr->do_filter) == PNG_NO_FILTERS) { @@ -889,7 +888,7 @@ png_write_PLTE(png_structrp png_ptr, png_const_colorp palette, buf[0] = pal_ptr->red; buf[1] = pal_ptr->green; buf[2] = pal_ptr->blue; - png_write_chunk_data(png_ptr, buf, (png_size_t)3); + png_write_chunk_data(png_ptr, buf, 3); } #else @@ -903,7 +902,7 @@ png_write_PLTE(png_structrp png_ptr, png_const_colorp palette, buf[0] = pal_ptr[i].red; buf[1] = pal_ptr[i].green; buf[2] = pal_ptr[i].blue; - png_write_chunk_data(png_ptr, buf, (png_size_t)3); + png_write_chunk_data(png_ptr, buf, 3); } #endif @@ -1075,7 +1074,7 @@ png_write_IEND(png_structrp png_ptr) { png_debug(1, "in png_write_IEND"); - png_write_complete_chunk(png_ptr, png_IEND, NULL, (png_size_t)0); + png_write_complete_chunk(png_ptr, png_IEND, NULL, 0); png_ptr->mode |= PNG_HAVE_IEND; } @@ -1090,7 +1089,7 @@ png_write_gAMA_fixed(png_structrp png_ptr, png_fixed_point file_gamma) /* file_gamma is saved in 1/100,000ths */ png_save_uint_32(buf, (png_uint_32)file_gamma); - png_write_complete_chunk(png_ptr, png_gAMA, buf, (png_size_t)4); + png_write_complete_chunk(png_ptr, png_gAMA, buf, 4); } #endif @@ -1108,7 +1107,7 @@ png_write_sRGB(png_structrp png_ptr, int srgb_intent) "Invalid sRGB rendering intent specified"); buf[0]=(png_byte)srgb_intent; - png_write_complete_chunk(png_ptr, png_sRGB, buf, (png_size_t)1); + png_write_complete_chunk(png_ptr, png_sRGB, buf, 1); } #endif @@ -1182,8 +1181,8 @@ png_write_sPLT(png_structrp png_ptr, png_const_sPLT_tp spalette) png_uint_32 name_len; png_byte new_name[80]; png_byte entrybuf[10]; - png_size_t entry_size = (spalette->depth == 8 ? 6 : 10); - png_size_t palette_size = entry_size * (png_size_t)spalette->nentries; + size_t entry_size = (spalette->depth == 8 ? 6 : 10); + size_t palette_size = entry_size * (size_t)spalette->nentries; png_sPLT_entryp ep; #ifndef PNG_POINTER_INDEXING_SUPPORTED int i; @@ -1200,10 +1199,9 @@ png_write_sPLT(png_structrp png_ptr, png_const_sPLT_tp spalette) png_write_chunk_header(png_ptr, png_sPLT, (png_uint_32)(name_len + 2 + palette_size)); - png_write_chunk_data(png_ptr, (png_bytep)new_name, - (png_size_t)(name_len + 1)); + png_write_chunk_data(png_ptr, (png_bytep)new_name, (size_t)(name_len + 1)); - png_write_chunk_data(png_ptr, &spalette->depth, (png_size_t)1); + png_write_chunk_data(png_ptr, &spalette->depth, 1); /* Loop through each palette entry, writing appropriately */ #ifdef PNG_POINTER_INDEXING_SUPPORTED @@ -1265,7 +1263,7 @@ void /* PRIVATE */ png_write_sBIT(png_structrp png_ptr, png_const_color_8p sbit, int color_type) { png_byte buf[4]; - png_size_t size; + size_t size; png_debug(1, "in png_write_sBIT"); @@ -1365,7 +1363,7 @@ png_write_tRNS(png_structrp png_ptr, png_const_bytep trans_alpha, /* Write the chunk out as it is */ png_write_complete_chunk(png_ptr, png_tRNS, trans_alpha, - (png_size_t)num_trans); + (size_t)num_trans); } else if (color_type == PNG_COLOR_TYPE_GRAY) @@ -1380,7 +1378,7 @@ png_write_tRNS(png_structrp png_ptr, png_const_bytep trans_alpha, } png_save_uint_16(buf, tran->gray); - png_write_complete_chunk(png_ptr, png_tRNS, buf, (png_size_t)2); + png_write_complete_chunk(png_ptr, png_tRNS, buf, 2); } else if (color_type == PNG_COLOR_TYPE_RGB) @@ -1400,7 +1398,7 @@ png_write_tRNS(png_structrp png_ptr, png_const_bytep trans_alpha, return; } - png_write_complete_chunk(png_ptr, png_tRNS, buf, (png_size_t)6); + png_write_complete_chunk(png_ptr, png_tRNS, buf, 6); } else @@ -1433,7 +1431,7 @@ png_write_bKGD(png_structrp png_ptr, png_const_color_16p back, int color_type) } buf[0] = back->index; - png_write_complete_chunk(png_ptr, png_bKGD, buf, (png_size_t)1); + png_write_complete_chunk(png_ptr, png_bKGD, buf, 1); } else if ((color_type & PNG_COLOR_MASK_COLOR) != 0) @@ -1454,7 +1452,7 @@ png_write_bKGD(png_structrp png_ptr, png_const_color_16p back, int color_type) return; } - png_write_complete_chunk(png_ptr, png_bKGD, buf, (png_size_t)6); + png_write_complete_chunk(png_ptr, png_bKGD, buf, 6); } else @@ -1468,7 +1466,7 @@ png_write_bKGD(png_structrp png_ptr, png_const_color_16p back, int color_type) } png_save_uint_16(buf, back->gray); - png_write_complete_chunk(png_ptr, png_bKGD, buf, (png_size_t)2); + png_write_complete_chunk(png_ptr, png_bKGD, buf, 2); } } #endif @@ -1488,7 +1486,7 @@ png_write_eXIf(png_structrp png_ptr, png_bytep exif, int num_exif) for (i = 0; i < num_exif; i++) { buf[0] = exif[i]; - png_write_chunk_data(png_ptr, buf, (png_size_t)1); + png_write_chunk_data(png_ptr, buf, 1); } png_write_chunk_end(png_ptr); @@ -1519,7 +1517,7 @@ png_write_hIST(png_structrp png_ptr, png_const_uint_16p hist, int num_hist) for (i = 0; i < num_hist; i++) { png_save_uint_16(buf, hist[i]); - png_write_chunk_data(png_ptr, buf, (png_size_t)2); + png_write_chunk_data(png_ptr, buf, 2); } png_write_chunk_end(png_ptr); @@ -1530,7 +1528,7 @@ png_write_hIST(png_structrp png_ptr, png_const_uint_16p hist, int num_hist) /* Write a tEXt chunk */ void /* PRIVATE */ png_write_tEXt(png_structrp png_ptr, png_const_charp key, png_const_charp text, - png_size_t text_len) + size_t text_len) { png_uint_32 key_len; png_byte new_key[80]; @@ -1627,7 +1625,7 @@ png_write_iTXt(png_structrp png_ptr, int compression, png_const_charp key, png_const_charp lang, png_const_charp lang_key, png_const_charp text) { png_uint_32 key_len, prefix_len; - png_size_t lang_len, lang_key_len; + size_t lang_len, lang_key_len; png_byte new_key[82]; compression_state comp; @@ -1737,7 +1735,7 @@ png_write_oFFs(png_structrp png_ptr, png_int_32 x_offset, png_int_32 y_offset, png_save_int_32(buf + 4, y_offset); buf[8] = (png_byte)unit_type; - png_write_complete_chunk(png_ptr, png_oFFs, buf, (png_size_t)9); + png_write_complete_chunk(png_ptr, png_oFFs, buf, 9); } #endif #ifdef PNG_WRITE_pCAL_SUPPORTED @@ -1748,7 +1746,7 @@ png_write_pCAL(png_structrp png_ptr, png_charp purpose, png_int_32 X0, png_charpp params) { png_uint_32 purpose_len; - png_size_t units_len, total_len; + size_t units_len, total_len; png_size_tp params_len; png_byte buf[10]; png_byte new_purpose[80]; @@ -1772,7 +1770,7 @@ png_write_pCAL(png_structrp png_ptr, png_charp purpose, png_int_32 X0, total_len = purpose_len + units_len + 10; params_len = (png_size_tp)png_malloc(png_ptr, - (png_alloc_size_t)((png_alloc_size_t)nparams * (sizeof (png_size_t)))); + (png_alloc_size_t)((png_alloc_size_t)nparams * (sizeof (size_t)))); /* Find the length of each parameter, making sure we don't count the * null terminator for the last parameter. @@ -1792,8 +1790,8 @@ png_write_pCAL(png_structrp png_ptr, png_charp purpose, png_int_32 X0, png_save_int_32(buf + 4, X1); buf[8] = (png_byte)type; buf[9] = (png_byte)nparams; - png_write_chunk_data(png_ptr, buf, (png_size_t)10); - png_write_chunk_data(png_ptr, (png_const_bytep)units, (png_size_t)units_len); + png_write_chunk_data(png_ptr, buf, 10); + png_write_chunk_data(png_ptr, (png_const_bytep)units, (size_t)units_len); for (i = 0; i < nparams; i++) { @@ -1812,7 +1810,7 @@ png_write_sCAL_s(png_structrp png_ptr, int unit, png_const_charp width, png_const_charp height) { png_byte buf[64]; - png_size_t wlen, hlen, total_len; + size_t wlen, hlen, total_len; png_debug(1, "in png_write_sCAL_s"); @@ -1853,7 +1851,7 @@ png_write_pHYs(png_structrp png_ptr, png_uint_32 x_pixels_per_unit, png_save_uint_32(buf + 4, y_pixels_per_unit); buf[8] = (png_byte)unit_type; - png_write_complete_chunk(png_ptr, png_pHYs, buf, (png_size_t)9); + png_write_complete_chunk(png_ptr, png_pHYs, buf, 9); } #endif @@ -1883,7 +1881,7 @@ png_write_tIME(png_structrp png_ptr, png_const_timep mod_time) buf[5] = mod_time->minute; buf[6] = mod_time->second; - png_write_complete_chunk(png_ptr, png_tIME, buf, (png_size_t)7); + png_write_complete_chunk(png_ptr, png_tIME, buf, 7); } #endif @@ -2073,8 +2071,8 @@ png_write_finish_row(png_structrp png_ptr) { if (png_ptr->prev_row != NULL) memset(png_ptr->prev_row, 0, - (png_size_t)(PNG_ROWBYTES(png_ptr->usr_channels* - png_ptr->usr_bit_depth, png_ptr->width)) + 1); + PNG_ROWBYTES(png_ptr->usr_channels * + png_ptr->usr_bit_depth, png_ptr->width) + 1); return; } @@ -2130,7 +2128,7 @@ png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass) for (i = png_pass_start[pass]; i < row_width; i += png_pass_inc[pass]) { - sp = row + (png_size_t)(i >> 3); + sp = row + (size_t)(i >> 3); value = (int)(*sp >> (7 - (int)(i & 0x07))) & 0x01; d |= (value << shift); @@ -2168,7 +2166,7 @@ png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass) for (i = png_pass_start[pass]; i < row_width; i += png_pass_inc[pass]) { - sp = row + (png_size_t)(i >> 2); + sp = row + (size_t)(i >> 2); value = (*sp >> ((3 - (int)(i & 0x03)) << 1)) & 0x03; d |= (value << shift); @@ -2204,7 +2202,7 @@ png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass) for (i = png_pass_start[pass]; i < row_width; i += png_pass_inc[pass]) { - sp = row + (png_size_t)(i >> 1); + sp = row + (size_t)(i >> 1); value = (*sp >> ((1 - (int)(i & 0x01)) << 2)) & 0x0f; d |= (value << shift); @@ -2230,7 +2228,7 @@ png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass) png_bytep dp; png_uint_32 i; png_uint_32 row_width = row_info->width; - png_size_t pixel_bytes; + size_t pixel_bytes; /* Start at the beginning */ dp = row; @@ -2243,7 +2241,7 @@ png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass) i += png_pass_inc[pass]) { /* Find out where the original pixel is */ - sp = row + (png_size_t)i * pixel_bytes; + sp = row + (size_t)i * pixel_bytes; /* Move the pixel */ if (dp != sp) @@ -2274,16 +2272,16 @@ png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass) */ static void /* PRIVATE */ png_write_filtered_row(png_structrp png_ptr, png_bytep filtered_row, - png_size_t row_bytes); + size_t row_bytes); #ifdef PNG_WRITE_FILTER_SUPPORTED -static png_size_t /* PRIVATE */ +static size_t /* PRIVATE */ png_setup_sub_row(png_structrp png_ptr, const png_uint_32 bpp, - const png_size_t row_bytes, const png_size_t lmins) + size_t row_bytes, size_t lmins) { png_bytep rp, dp, lp; - png_size_t i; - png_size_t sum = 0; + size_t i; + size_t sum = 0; unsigned int v; png_ptr->try_row[0] = PNG_FILTER_VALUE_SUB; @@ -2318,10 +2316,10 @@ png_setup_sub_row(png_structrp png_ptr, const png_uint_32 bpp, static void /* PRIVATE */ png_setup_sub_row_only(png_structrp png_ptr, const png_uint_32 bpp, - const png_size_t row_bytes) + size_t row_bytes) { png_bytep rp, dp, lp; - png_size_t i; + size_t i; png_ptr->try_row[0] = PNG_FILTER_VALUE_SUB; @@ -2338,13 +2336,12 @@ png_setup_sub_row_only(png_structrp png_ptr, const png_uint_32 bpp, } } -static png_size_t /* PRIVATE */ -png_setup_up_row(png_structrp png_ptr, const png_size_t row_bytes, - const png_size_t lmins) +static size_t /* PRIVATE */ +png_setup_up_row(png_structrp png_ptr, size_t row_bytes, size_t lmins) { png_bytep rp, dp, pp; - png_size_t i; - png_size_t sum = 0; + size_t i; + size_t sum = 0; unsigned int v; png_ptr->try_row[0] = PNG_FILTER_VALUE_UP; @@ -2367,10 +2364,10 @@ png_setup_up_row(png_structrp png_ptr, const png_size_t row_bytes, return (sum); } static void /* PRIVATE */ -png_setup_up_row_only(png_structrp png_ptr, const png_size_t row_bytes) +png_setup_up_row_only(png_structrp png_ptr, size_t row_bytes) { png_bytep rp, dp, pp; - png_size_t i; + size_t i; png_ptr->try_row[0] = PNG_FILTER_VALUE_UP; @@ -2382,13 +2379,13 @@ png_setup_up_row_only(png_structrp png_ptr, const png_size_t row_bytes) } } -static png_size_t /* PRIVATE */ +static size_t /* PRIVATE */ png_setup_avg_row(png_structrp png_ptr, const png_uint_32 bpp, - const png_size_t row_bytes, const png_size_t lmins) + size_t row_bytes, size_t lmins) { png_bytep rp, dp, pp, lp; png_uint_32 i; - png_size_t sum = 0; + size_t sum = 0; unsigned int v; png_ptr->try_row[0] = PNG_FILTER_VALUE_AVG; @@ -2424,7 +2421,7 @@ png_setup_avg_row(png_structrp png_ptr, const png_uint_32 bpp, } static void /* PRIVATE */ png_setup_avg_row_only(png_structrp png_ptr, const png_uint_32 bpp, - const png_size_t row_bytes) + size_t row_bytes) { png_bytep rp, dp, pp, lp; png_uint_32 i; @@ -2444,13 +2441,13 @@ png_setup_avg_row_only(png_structrp png_ptr, const png_uint_32 bpp, } } -static png_size_t /* PRIVATE */ +static size_t /* PRIVATE */ png_setup_paeth_row(png_structrp png_ptr, const png_uint_32 bpp, - const png_size_t row_bytes, const png_size_t lmins) + size_t row_bytes, size_t lmins) { png_bytep rp, dp, pp, cp, lp; - png_size_t i; - png_size_t sum = 0; + size_t i; + size_t sum = 0; unsigned int v; png_ptr->try_row[0] = PNG_FILTER_VALUE_PAETH; @@ -2507,10 +2504,10 @@ png_setup_paeth_row(png_structrp png_ptr, const png_uint_32 bpp, } static void /* PRIVATE */ png_setup_paeth_row_only(png_structrp png_ptr, const png_uint_32 bpp, - const png_size_t row_bytes) + size_t row_bytes) { png_bytep rp, dp, pp, cp, lp; - png_size_t i; + size_t i; png_ptr->try_row[0] = PNG_FILTER_VALUE_PAETH; @@ -2559,8 +2556,8 @@ png_write_find_filter(png_structrp png_ptr, png_row_infop row_info) png_bytep row_buf; png_bytep best_row; png_uint_32 bpp; - png_size_t mins; - png_size_t row_bytes = row_info->rowbytes; + size_t mins; + size_t row_bytes = row_info->rowbytes; png_debug(1, "in png_write_find_filter"); @@ -2615,8 +2612,8 @@ png_write_find_filter(png_structrp png_ptr, png_row_infop row_info) * 'none' filter. */ png_bytep rp; - png_size_t sum = 0; - png_size_t i; + size_t sum = 0; + size_t i; unsigned int v; { @@ -2644,8 +2641,8 @@ png_write_find_filter(png_structrp png_ptr, png_row_infop row_info) else if ((filter_to_do & PNG_FILTER_SUB) != 0) { - png_size_t sum; - png_size_t lmins = mins; + size_t sum; + size_t lmins = mins; sum = png_setup_sub_row(png_ptr, bpp, row_bytes, lmins); @@ -2670,8 +2667,8 @@ png_write_find_filter(png_structrp png_ptr, png_row_infop row_info) else if ((filter_to_do & PNG_FILTER_UP) != 0) { - png_size_t sum; - png_size_t lmins = mins; + size_t sum; + size_t lmins = mins; sum = png_setup_up_row(png_ptr, row_bytes, lmins); @@ -2696,8 +2693,8 @@ png_write_find_filter(png_structrp png_ptr, png_row_infop row_info) else if ((filter_to_do & PNG_FILTER_AVG) != 0) { - png_size_t sum; - png_size_t lmins = mins; + size_t sum; + size_t lmins = mins; sum= png_setup_avg_row(png_ptr, bpp, row_bytes, lmins); @@ -2722,8 +2719,8 @@ png_write_find_filter(png_structrp png_ptr, png_row_infop row_info) else if ((filter_to_do & PNG_FILTER_PAETH) != 0) { - png_size_t sum; - png_size_t lmins = mins; + size_t sum; + size_t lmins = mins; sum = png_setup_paeth_row(png_ptr, bpp, row_bytes, lmins); @@ -2748,7 +2745,7 @@ png_write_find_filter(png_structrp png_ptr, png_row_infop row_info) /* Do the actual writing of a previously filtered row. */ static void png_write_filtered_row(png_structrp png_ptr, png_bytep filtered_row, - png_size_t full_row_length/*includes filter byte*/) + size_t full_row_length/*includes filter byte*/) { png_debug(1, "in png_write_filtered_row"); diff --git a/thirdparty/libvpx/vpx_config.h b/thirdparty/libvpx/vpx_config.h index fb9e13c4ad..6caec50c81 100644 --- a/thirdparty/libvpx/vpx_config.h +++ b/thirdparty/libvpx/vpx_config.h @@ -67,6 +67,12 @@ #define CONFIG_BIG_ENDIAN 0 //TODO: Autodetect +#ifdef __EMSCRIPTEN__ +#define CONFIG_MULTITHREAD 0 +#else +#define CONFIG_MULTITHREAD 1 +#endif + #ifdef _WIN32 #define HAVE_PTHREAD_H 0 #define HAVE_UNISTD_H 0 @@ -95,7 +101,6 @@ #define CONFIG_RUNTIME_CPU_DETECT 1 #define CONFIG_POSTPROC 0 #define CONFIG_VP9_POSTPROC 0 -#define CONFIG_MULTITHREAD 1 #define CONFIG_INTERNAL_STATS 0 #define CONFIG_VP8_ENCODER 0 #define CONFIG_VP8_DECODER 1 diff --git a/thirdparty/libwebsockets/lws_config.h b/thirdparty/libwebsockets/lws_config.h index 7185a806a5..e5e15cc2fd 100644 --- a/thirdparty/libwebsockets/lws_config.h +++ b/thirdparty/libwebsockets/lws_config.h @@ -174,7 +174,7 @@ #define LWS_HAVE_MALLOC_H #endif -#if !defined(IPHONE_ENABLED) && !defined(OSX_ENABLED) +#if !defined(IPHONE_ENABLED) && !defined(OSX_ENABLED) && !defined(__HAIKU__) #define LWS_HAVE_PIPE2 #endif diff --git a/thirdparty/libwebsockets/lws_config_private.h b/thirdparty/libwebsockets/lws_config_private.h index 9d04078fef..b26d225afa 100644 --- a/thirdparty/libwebsockets/lws_config_private.h +++ b/thirdparty/libwebsockets/lws_config_private.h @@ -81,7 +81,7 @@ /* Define to 1 if you have the <sys/prctl.h> header file. */ #define LWS_HAVE_SYS_PRCTL_H -#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED) || defined(__FreeBSD__) || defined(__OpenBSD__) +#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__HAIKU__) #undef LWS_HAVE_SYS_PRCTL_H #endif diff --git a/thirdparty/mbedtls/1453.diff b/thirdparty/mbedtls/1453.diff index acc3654cd4..6630ad861f 100644 --- a/thirdparty/mbedtls/1453.diff +++ b/thirdparty/mbedtls/1453.diff @@ -1,7 +1,7 @@ -diff --git a/thirdparty/mbedtls/library/entropy_poll.c b/thirdparty/mbedtls/library/entropy_poll.c +diff --git a/library/entropy_poll.c b/library/entropy_poll.c index 67900c46c8..cefe882d2a 100644 ---- a/thirdparty/mbedtls/library/entropy_poll.c -+++ b/thirdparty/mbedtls/library/entropy_poll.c +--- a/library/entropy_poll.c ++++ b/library/entropy_poll.c @@ -54,28 +54,43 @@ #define _WIN32_WINNT 0x0400 #endif @@ -53,11 +53,11 @@ index 67900c46c8..cefe882d2a 100644 *olen = len; return( 0 ); -diff --git a/thirdparty/mbedtls/library/x509_crt.c b/thirdparty/mbedtls/library/x509_crt.c -index afff4e18bf..7960fa1a1a 100644 ---- a/thirdparty/mbedtls/library/x509_crt.c -+++ b/thirdparty/mbedtls/library/x509_crt.c -@@ -64,6 +64,19 @@ +diff --git a/library/x509_crt.c b/library/x509_crt.c +index 290c1eb3d1..3cf1743821 100644 +--- a/library/x509_crt.c ++++ b/library/x509_crt.c +@@ -65,6 +65,19 @@ #if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) #include <windows.h> @@ -77,20 +77,20 @@ index afff4e18bf..7960fa1a1a 100644 #else #include <time.h> #endif -@@ -1130,6 +1143,7 @@ int mbedtls_x509_crt_parse_path( mbedtls_x509_crt *chain, const char *path ) +@@ -1126,6 +1139,7 @@ int mbedtls_x509_crt_parse_path( mbedtls_x509_crt *chain, const char *path ) char filename[MAX_PATH]; char *p; size_t len = strlen( path ); -+ int lengthAsInt = 0; ++ int length_as_int = 0; WIN32_FIND_DATAW file_data; HANDLE hFind; -@@ -1144,7 +1158,18 @@ int mbedtls_x509_crt_parse_path( mbedtls_x509_crt *chain, const char *path ) +@@ -1140,7 +1154,18 @@ int mbedtls_x509_crt_parse_path( mbedtls_x509_crt *chain, const char *path ) p = filename + len; filename[len++] = '*'; - w_ret = MultiByteToWideChar( CP_ACP, 0, filename, (int)len, szDir, -+ if ( FAILED ( SizeTToInt( len, &lengthAsInt ) ) ) ++ if ( FAILED ( SizeTToInt( len, &length_as_int ) ) ) + return( MBEDTLS_ERR_X509_FILE_IO_ERROR ); + + /* @@ -101,20 +101,20 @@ index afff4e18bf..7960fa1a1a 100644 + * incoming string are less than MAX_PATH to avoid a buffer overrun with + * MultiByteToWideChar(). + */ -+ w_ret = MultiByteToWideChar( CP_ACP, 0, filename, lengthAsInt, szDir, ++ w_ret = MultiByteToWideChar( CP_ACP, 0, filename, length_as_int, szDir, MAX_PATH - 3 ); if( w_ret == 0 ) return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); -@@ -1161,8 +1186,11 @@ int mbedtls_x509_crt_parse_path( mbedtls_x509_crt *chain, const char *path ) +@@ -1157,8 +1182,11 @@ int mbedtls_x509_crt_parse_path( mbedtls_x509_crt *chain, const char *path ) if( file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) continue; -+ if ( FAILED( SizeTToInt( wcslen( file_data.cFileName ), &lengthAsInt ) ) ) ++ if ( FAILED( SizeTToInt( wcslen( file_data.cFileName ), &length_as_int ) ) ) + return( MBEDTLS_ERR_X509_FILE_IO_ERROR ); + w_ret = WideCharToMultiByte( CP_ACP, 0, file_data.cFileName, - lstrlenW( file_data.cFileName ), -+ lengthAsInt, ++ length_as_int, p, (int) len - 1, NULL, NULL ); if( w_ret == 0 ) diff --git a/thirdparty/mbedtls/include/mbedtls/aes.h b/thirdparty/mbedtls/include/mbedtls/aes.h index 46016dcb7f..f6603d5962 100644 --- a/thirdparty/mbedtls/include/mbedtls/aes.h +++ b/thirdparty/mbedtls/include/mbedtls/aes.h @@ -1,7 +1,9 @@ /** * \file aes.h * - * \brief The Advanced Encryption Standard (AES) specifies a FIPS-approved + * \brief This file contains AES definitions and functions. + * + * The Advanced Encryption Standard (AES) specifies a FIPS-approved * cryptographic algorithm that can be used to protect electronic * data. * @@ -11,7 +13,13 @@ * <em>ISO/IEC 18033-2:2006: Information technology -- Security * techniques -- Encryption algorithms -- Part 2: Asymmetric * ciphers</em>. + * + * The AES-XTS block mode is standardized by NIST SP 800-38E + * <https://nvlpubs.nist.gov/nistpubs/legacy/sp/nistspecialpublication800-38e.pdf> + * and described in detail by IEEE P1619 + * <https://ieeexplore.ieee.org/servlet/opac?punumber=4375278>. */ + /* Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved. * SPDX-License-Identifier: Apache-2.0 * @@ -50,7 +58,8 @@ #define MBEDTLS_ERR_AES_INVALID_KEY_LENGTH -0x0020 /**< Invalid key length. */ #define MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH -0x0022 /**< Invalid data input length. */ -/* Error codes in range 0x0023-0x0025 */ +/* Error codes in range 0x0021-0x0025 */ +#define MBEDTLS_ERR_AES_BAD_INPUT_DATA -0x0021 /**< Invalid input data. */ #define MBEDTLS_ERR_AES_FEATURE_UNAVAILABLE -0x0023 /**< Feature not available. For example, an unsupported AES key size. */ #define MBEDTLS_ERR_AES_HW_ACCEL_FAILED -0x0025 /**< AES hardware accelerator failed. */ @@ -59,14 +68,14 @@ #define inline __inline #endif -#if !defined(MBEDTLS_AES_ALT) -// Regular implementation -// - #ifdef __cplusplus extern "C" { #endif +#if !defined(MBEDTLS_AES_ALT) +// Regular implementation +// + /** * \brief The AES context-type definition. */ @@ -85,6 +94,23 @@ typedef struct } mbedtls_aes_context; +#if defined(MBEDTLS_CIPHER_MODE_XTS) +/** + * \brief The AES XTS context-type definition. + */ +typedef struct +{ + mbedtls_aes_context crypt; /*!< The AES context to use for AES block + encryption or decryption. */ + mbedtls_aes_context tweak; /*!< The AES context used for tweak + computation. */ +} mbedtls_aes_xts_context; +#endif /* MBEDTLS_CIPHER_MODE_XTS */ + +#else /* MBEDTLS_AES_ALT */ +#include "aes_alt.h" +#endif /* MBEDTLS_AES_ALT */ + /** * \brief This function initializes the specified AES context. * @@ -102,6 +128,25 @@ void mbedtls_aes_init( mbedtls_aes_context *ctx ); */ void mbedtls_aes_free( mbedtls_aes_context *ctx ); +#if defined(MBEDTLS_CIPHER_MODE_XTS) +/** + * \brief This function initializes the specified AES XTS context. + * + * It must be the first API called before using + * the context. + * + * \param ctx The AES XTS context to initialize. + */ +void mbedtls_aes_xts_init( mbedtls_aes_xts_context *ctx ); + +/** + * \brief This function releases and clears the specified AES XTS context. + * + * \param ctx The AES XTS context to clear. + */ +void mbedtls_aes_xts_free( mbedtls_aes_xts_context *ctx ); +#endif /* MBEDTLS_CIPHER_MODE_XTS */ + /** * \brief This function sets the encryption key. * @@ -112,8 +157,8 @@ void mbedtls_aes_free( mbedtls_aes_context *ctx ); * <li>192 bits</li> * <li>256 bits</li></ul> * - * \return \c 0 on success or #MBEDTLS_ERR_AES_INVALID_KEY_LENGTH - * on failure. + * \return \c 0 on success. + * \return #MBEDTLS_ERR_AES_INVALID_KEY_LENGTH on failure. */ int mbedtls_aes_setkey_enc( mbedtls_aes_context *ctx, const unsigned char *key, unsigned int keybits ); @@ -128,11 +173,50 @@ int mbedtls_aes_setkey_enc( mbedtls_aes_context *ctx, const unsigned char *key, * <li>192 bits</li> * <li>256 bits</li></ul> * - * \return \c 0 on success, or #MBEDTLS_ERR_AES_INVALID_KEY_LENGTH on failure. + * \return \c 0 on success. + * \return #MBEDTLS_ERR_AES_INVALID_KEY_LENGTH on failure. */ int mbedtls_aes_setkey_dec( mbedtls_aes_context *ctx, const unsigned char *key, unsigned int keybits ); +#if defined(MBEDTLS_CIPHER_MODE_XTS) +/** + * \brief This function prepares an XTS context for encryption and + * sets the encryption key. + * + * \param ctx The AES XTS context to which the key should be bound. + * \param key The encryption key. This is comprised of the XTS key1 + * concatenated with the XTS key2. + * \param keybits The size of \p key passed in bits. Valid options are: + * <ul><li>256 bits (each of key1 and key2 is a 128-bit key)</li> + * <li>512 bits (each of key1 and key2 is a 256-bit key)</li></ul> + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_AES_INVALID_KEY_LENGTH on failure. + */ +int mbedtls_aes_xts_setkey_enc( mbedtls_aes_xts_context *ctx, + const unsigned char *key, + unsigned int keybits ); + +/** + * \brief This function prepares an XTS context for decryption and + * sets the decryption key. + * + * \param ctx The AES XTS context to which the key should be bound. + * \param key The decryption key. This is comprised of the XTS key1 + * concatenated with the XTS key2. + * \param keybits The size of \p key passed in bits. Valid options are: + * <ul><li>256 bits (each of key1 and key2 is a 128-bit key)</li> + * <li>512 bits (each of key1 and key2 is a 256-bit key)</li></ul> + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_AES_INVALID_KEY_LENGTH on failure. + */ +int mbedtls_aes_xts_setkey_dec( mbedtls_aes_xts_context *ctx, + const unsigned char *key, + unsigned int keybits ); +#endif /* MBEDTLS_CIPHER_MODE_XTS */ + /** * \brief This function performs an AES single-block encryption or * decryption operation. @@ -192,7 +276,8 @@ int mbedtls_aes_crypt_ecb( mbedtls_aes_context *ctx, * \param input The buffer holding the input data. * \param output The buffer holding the output data. * - * \return \c 0 on success, or #MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH + * \return \c 0 on success. + * \return #MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH * on failure. */ int mbedtls_aes_crypt_cbc( mbedtls_aes_context *ctx, @@ -203,6 +288,49 @@ int mbedtls_aes_crypt_cbc( mbedtls_aes_context *ctx, unsigned char *output ); #endif /* MBEDTLS_CIPHER_MODE_CBC */ +#if defined(MBEDTLS_CIPHER_MODE_XTS) +/** + * \brief This function performs an AES-XTS encryption or decryption + * operation for an entire XTS data unit. + * + * AES-XTS encrypts or decrypts blocks based on their location as + * defined by a data unit number. The data unit number must be + * provided by \p data_unit. + * + * NIST SP 800-38E limits the maximum size of a data unit to 2^20 + * AES blocks. If the data unit is larger than this, this function + * returns #MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH. + * + * \param ctx The AES XTS context to use for AES XTS operations. + * \param mode The AES operation: #MBEDTLS_AES_ENCRYPT or + * #MBEDTLS_AES_DECRYPT. + * \param length The length of a data unit in bytes. This can be any + * length between 16 bytes and 2^24 bytes inclusive + * (between 1 and 2^20 block cipher blocks). + * \param data_unit The address of the data unit encoded as an array of 16 + * bytes in little-endian format. For disk encryption, this + * is typically the index of the block device sector that + * contains the data. + * \param input The buffer holding the input data (which is an entire + * data unit). This function reads \p length bytes from \p + * input. + * \param output The buffer holding the output data (which is an entire + * data unit). This function writes \p length bytes to \p + * output. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH if \p length is + * smaller than an AES block in size (16 bytes) or if \p + * length is larger than 2^20 blocks (16 MiB). + */ +int mbedtls_aes_crypt_xts( mbedtls_aes_xts_context *ctx, + int mode, + size_t length, + const unsigned char data_unit[16], + const unsigned char *input, + unsigned char *output ); +#endif /* MBEDTLS_CIPHER_MODE_XTS */ + #if defined(MBEDTLS_CIPHER_MODE_CFB) /** * \brief This function performs an AES-CFB128 encryption or decryption @@ -286,6 +414,56 @@ int mbedtls_aes_crypt_cfb8( mbedtls_aes_context *ctx, unsigned char *output ); #endif /*MBEDTLS_CIPHER_MODE_CFB */ +#if defined(MBEDTLS_CIPHER_MODE_OFB) +/** + * \brief This function performs an AES-OFB (Output Feedback Mode) + * encryption or decryption operation. + * + * For OFB, you must set up the context with + * mbedtls_aes_setkey_enc(), regardless of whether you are + * performing an encryption or decryption operation. This is + * because OFB mode uses the same key schedule for encryption and + * decryption. + * + * The OFB operation is identical for encryption or decryption, + * therefore no operation mode needs to be specified. + * + * \note Upon exit, the content of iv, the Initialisation Vector, is + * updated so that you can call the same function again on the next + * block(s) of data and get the same result as if it was encrypted + * in one call. This allows a "streaming" usage, by initialising + * iv_off to 0 before the first call, and preserving its value + * between calls. + * + * For non-streaming use, the iv should be initialised on each call + * to a unique value, and iv_off set to 0 on each call. + * + * If you need to retain the contents of the initialisation vector, + * you must either save it manually or use the cipher module + * instead. + * + * \warning For the OFB mode, the initialisation vector must be unique + * every encryption operation. Reuse of an initialisation vector + * will compromise security. + * + * \param ctx The AES context to use for encryption or decryption. + * \param length The length of the input data. + * \param iv_off The offset in IV (updated after use). + * \param iv The initialization vector (updated after use). + * \param input The buffer holding the input data. + * \param output The buffer holding the output data. + * + * \return \c 0 on success. + */ +int mbedtls_aes_crypt_ofb( mbedtls_aes_context *ctx, + size_t length, + size_t *iv_off, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ); + +#endif /* MBEDTLS_CIPHER_MODE_OFB */ + #if defined(MBEDTLS_CIPHER_MODE_CTR) /** * \brief This function performs an AES-CTR encryption or decryption @@ -300,7 +478,49 @@ int mbedtls_aes_crypt_cfb8( mbedtls_aes_context *ctx, * must use the context initialized with mbedtls_aes_setkey_enc() * for both #MBEDTLS_AES_ENCRYPT and #MBEDTLS_AES_DECRYPT. * - * \warning You must keep the maximum use of your counter in mind. + * \warning You must never reuse a nonce value with the same key. Doing so + * would void the encryption for the two messages encrypted with + * the same nonce and key. + * + * There are two common strategies for managing nonces with CTR: + * + * 1. You can handle everything as a single message processed over + * successive calls to this function. In that case, you want to + * set \p nonce_counter and \p nc_off to 0 for the first call, and + * then preserve the values of \p nonce_counter, \p nc_off and \p + * stream_block across calls to this function as they will be + * updated by this function. + * + * With this strategy, you must not encrypt more than 2**128 + * blocks of data with the same key. + * + * 2. You can encrypt separate messages by dividing the \p + * nonce_counter buffer in two areas: the first one used for a + * per-message nonce, handled by yourself, and the second one + * updated by this function internally. + * + * For example, you might reserve the first 12 bytes for the + * per-message nonce, and the last 4 bytes for internal use. In that + * case, before calling this function on a new message you need to + * set the first 12 bytes of \p nonce_counter to your chosen nonce + * value, the last 4 to 0, and \p nc_off to 0 (which will cause \p + * stream_block to be ignored). That way, you can encrypt at most + * 2**96 messages of up to 2**32 blocks each with the same key. + * + * The per-message nonce (or information sufficient to reconstruct + * it) needs to be communicated with the ciphertext and must be unique. + * The recommended way to ensure uniqueness is to use a message + * counter. An alternative is to generate random nonces, but this + * limits the number of messages that can be securely encrypted: + * for example, with 96-bit random nonces, you should not encrypt + * more than 2**32 messages with the same key. + * + * Note that for both stategies, sizes are measured in blocks and + * that an AES block is 16 bytes. + * + * \warning Upon return, \p stream_block contains sensitive data. Its + * content must not be written to insecure storage and should be + * securely discarded as soon as it's no longer needed. * * \param ctx The AES context to use for encryption or decryption. * \param length The length of the input data. @@ -313,7 +533,7 @@ int mbedtls_aes_crypt_cfb8( mbedtls_aes_context *ctx, * \param input The buffer holding the input data. * \param output The buffer holding the output data. * - * \return \c 0 on success. + * \return \c 0 on success. */ int mbedtls_aes_crypt_ctr( mbedtls_aes_context *ctx, size_t length, @@ -391,22 +611,11 @@ MBEDTLS_DEPRECATED void mbedtls_aes_decrypt( mbedtls_aes_context *ctx, #undef MBEDTLS_DEPRECATED #endif /* !MBEDTLS_DEPRECATED_REMOVED */ -#ifdef __cplusplus -} -#endif - -#else /* MBEDTLS_AES_ALT */ -#include "aes_alt.h" -#endif /* MBEDTLS_AES_ALT */ - -#ifdef __cplusplus -extern "C" { -#endif - /** * \brief Checkup routine. * - * \return \c 0 on success, or \c 1 on failure. + * \return \c 0 on success. + * \return \c 1 on failure. */ int mbedtls_aes_self_test( int verbose ); diff --git a/thirdparty/mbedtls/include/mbedtls/arc4.h b/thirdparty/mbedtls/include/mbedtls/arc4.h index f9d93f822f..f11fc5be0a 100644 --- a/thirdparty/mbedtls/include/mbedtls/arc4.h +++ b/thirdparty/mbedtls/include/mbedtls/arc4.h @@ -38,14 +38,14 @@ #define MBEDTLS_ERR_ARC4_HW_ACCEL_FAILED -0x0019 /**< ARC4 hardware accelerator failed. */ -#if !defined(MBEDTLS_ARC4_ALT) -// Regular implementation -// - #ifdef __cplusplus extern "C" { #endif +#if !defined(MBEDTLS_ARC4_ALT) +// Regular implementation +// + /** * \brief ARC4 context structure * @@ -61,6 +61,10 @@ typedef struct } mbedtls_arc4_context; +#else /* MBEDTLS_ARC4_ALT */ +#include "arc4_alt.h" +#endif /* MBEDTLS_ARC4_ALT */ + /** * \brief Initialize ARC4 context * @@ -118,18 +122,6 @@ void mbedtls_arc4_setup( mbedtls_arc4_context *ctx, const unsigned char *key, int mbedtls_arc4_crypt( mbedtls_arc4_context *ctx, size_t length, const unsigned char *input, unsigned char *output ); -#ifdef __cplusplus -} -#endif - -#else /* MBEDTLS_ARC4_ALT */ -#include "arc4_alt.h" -#endif /* MBEDTLS_ARC4_ALT */ - -#ifdef __cplusplus -extern "C" { -#endif - /** * \brief Checkup routine * diff --git a/thirdparty/mbedtls/include/mbedtls/aria.h b/thirdparty/mbedtls/include/mbedtls/aria.h new file mode 100644 index 0000000000..bae0621b23 --- /dev/null +++ b/thirdparty/mbedtls/include/mbedtls/aria.h @@ -0,0 +1,331 @@ +/** + * \file aria.h + * + * \brief ARIA block cipher + * + * The ARIA algorithm is a symmetric block cipher that can encrypt and + * decrypt information. It is defined by the Korean Agency for + * Technology and Standards (KATS) in <em>KS X 1213:2004</em> (in + * Korean, but see http://210.104.33.10/ARIA/index-e.html in English) + * and also described by the IETF in <em>RFC 5794</em>. + */ +/* Copyright (C) 2006-2018, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +#ifndef MBEDTLS_ARIA_H +#define MBEDTLS_ARIA_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include <stddef.h> +#include <stdint.h> + +#define MBEDTLS_ARIA_ENCRYPT 1 /**< ARIA encryption. */ +#define MBEDTLS_ARIA_DECRYPT 0 /**< ARIA decryption. */ + +#define MBEDTLS_ARIA_BLOCKSIZE 16 /**< ARIA block size in bytes. */ +#define MBEDTLS_ARIA_MAX_ROUNDS 16 /**< Maxiumum number of rounds in ARIA. */ +#define MBEDTLS_ARIA_MAX_KEYSIZE 32 /**< Maximum size of an ARIA key in bytes. */ + +#define MBEDTLS_ERR_ARIA_INVALID_KEY_LENGTH -0x005C /**< Invalid key length. */ +#define MBEDTLS_ERR_ARIA_INVALID_INPUT_LENGTH -0x005E /**< Invalid data input length. */ +#define MBEDTLS_ERR_ARIA_FEATURE_UNAVAILABLE -0x005A /**< Feature not available. For example, an unsupported ARIA key size. */ +#define MBEDTLS_ERR_ARIA_HW_ACCEL_FAILED -0x0058 /**< ARIA hardware accelerator failed. */ + +#if !defined(MBEDTLS_ARIA_ALT) +// Regular implementation +// + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief The ARIA context-type definition. + */ +typedef struct +{ + unsigned char nr; /*!< The number of rounds (12, 14 or 16) */ + /*! The ARIA round keys. */ + uint32_t rk[MBEDTLS_ARIA_MAX_ROUNDS + 1][MBEDTLS_ARIA_BLOCKSIZE / 4]; +} +mbedtls_aria_context; + +#else /* MBEDTLS_ARIA_ALT */ +#include "aria_alt.h" +#endif /* MBEDTLS_ARIA_ALT */ + +/** + * \brief This function initializes the specified ARIA context. + * + * It must be the first API called before using + * the context. + * + * \param ctx The ARIA context to initialize. + */ +void mbedtls_aria_init( mbedtls_aria_context *ctx ); + +/** + * \brief This function releases and clears the specified ARIA context. + * + * \param ctx The ARIA context to clear. + */ +void mbedtls_aria_free( mbedtls_aria_context *ctx ); + +/** + * \brief This function sets the encryption key. + * + * \param ctx The ARIA context to which the key should be bound. + * \param key The encryption key. + * \param keybits The size of data passed in bits. Valid options are: + * <ul><li>128 bits</li> + * <li>192 bits</li> + * <li>256 bits</li></ul> + * + * \return \c 0 on success or #MBEDTLS_ERR_ARIA_INVALID_KEY_LENGTH + * on failure. + */ +int mbedtls_aria_setkey_enc( mbedtls_aria_context *ctx, + const unsigned char *key, + unsigned int keybits ); + +/** + * \brief This function sets the decryption key. + * + * \param ctx The ARIA context to which the key should be bound. + * \param key The decryption key. + * \param keybits The size of data passed. Valid options are: + * <ul><li>128 bits</li> + * <li>192 bits</li> + * <li>256 bits</li></ul> + * + * \return \c 0 on success, or #MBEDTLS_ERR_ARIA_INVALID_KEY_LENGTH on failure. + */ +int mbedtls_aria_setkey_dec( mbedtls_aria_context *ctx, + const unsigned char *key, + unsigned int keybits ); + +/** + * \brief This function performs an ARIA single-block encryption or + * decryption operation. + * + * It performs encryption or decryption (depending on whether + * the key was set for encryption on decryption) on the input + * data buffer defined in the \p input parameter. + * + * mbedtls_aria_init(), and either mbedtls_aria_setkey_enc() or + * mbedtls_aria_setkey_dec() must be called before the first + * call to this API with the same context. + * + * \param ctx The ARIA context to use for encryption or decryption. + * \param input The 16-Byte buffer holding the input data. + * \param output The 16-Byte buffer holding the output data. + + * \return \c 0 on success. + */ +int mbedtls_aria_crypt_ecb( mbedtls_aria_context *ctx, + const unsigned char input[MBEDTLS_ARIA_BLOCKSIZE], + unsigned char output[MBEDTLS_ARIA_BLOCKSIZE] ); + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +/** + * \brief This function performs an ARIA-CBC encryption or decryption operation + * on full blocks. + * + * It performs the operation defined in the \p mode + * parameter (encrypt/decrypt), on the input data buffer defined in + * the \p input parameter. + * + * It can be called as many times as needed, until all the input + * data is processed. mbedtls_aria_init(), and either + * mbedtls_aria_setkey_enc() or mbedtls_aria_setkey_dec() must be called + * before the first call to this API with the same context. + * + * \note This function operates on aligned blocks, that is, the input size + * must be a multiple of the ARIA block size of 16 Bytes. + * + * \note Upon exit, the content of the IV is updated so that you can + * call the same function again on the next + * block(s) of data and get the same result as if it was + * encrypted in one call. This allows a "streaming" usage. + * If you need to retain the contents of the IV, you should + * either save it manually or use the cipher module instead. + * + * + * \param ctx The ARIA context to use for encryption or decryption. + * \param mode The ARIA operation: #MBEDTLS_ARIA_ENCRYPT or + * #MBEDTLS_ARIA_DECRYPT. + * \param length The length of the input data in Bytes. This must be a + * multiple of the block size (16 Bytes). + * \param iv Initialization vector (updated after use). + * \param input The buffer holding the input data. + * \param output The buffer holding the output data. + * + * \return \c 0 on success, or #MBEDTLS_ERR_ARIA_INVALID_INPUT_LENGTH + * on failure. + */ +int mbedtls_aria_crypt_cbc( mbedtls_aria_context *ctx, + int mode, + size_t length, + unsigned char iv[MBEDTLS_ARIA_BLOCKSIZE], + const unsigned char *input, + unsigned char *output ); +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) +/** + * \brief This function performs an ARIA-CFB128 encryption or decryption + * operation. + * + * It performs the operation defined in the \p mode + * parameter (encrypt or decrypt), on the input data buffer + * defined in the \p input parameter. + * + * For CFB, you must set up the context with mbedtls_aria_setkey_enc(), + * regardless of whether you are performing an encryption or decryption + * operation, that is, regardless of the \p mode parameter. This is + * because CFB mode uses the same key schedule for encryption and + * decryption. + * + * \note Upon exit, the content of the IV is updated so that you can + * call the same function again on the next + * block(s) of data and get the same result as if it was + * encrypted in one call. This allows a "streaming" usage. + * If you need to retain the contents of the + * IV, you must either save it manually or use the cipher + * module instead. + * + * + * \param ctx The ARIA context to use for encryption or decryption. + * \param mode The ARIA operation: #MBEDTLS_ARIA_ENCRYPT or + * #MBEDTLS_ARIA_DECRYPT. + * \param length The length of the input data. + * \param iv_off The offset in IV (updated after use). + * \param iv The initialization vector (updated after use). + * \param input The buffer holding the input data. + * \param output The buffer holding the output data. + * + * \return \c 0 on success. + */ +int mbedtls_aria_crypt_cfb128( mbedtls_aria_context *ctx, + int mode, + size_t length, + size_t *iv_off, + unsigned char iv[MBEDTLS_ARIA_BLOCKSIZE], + const unsigned char *input, + unsigned char *output ); +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +/** + * \brief This function performs an ARIA-CTR encryption or decryption + * operation. + * + * This function performs the operation defined in the \p mode + * parameter (encrypt/decrypt), on the input data buffer + * defined in the \p input parameter. + * + * Due to the nature of CTR, you must use the same key schedule + * for both encryption and decryption operations. Therefore, you + * must use the context initialized with mbedtls_aria_setkey_enc() + * for both #MBEDTLS_ARIA_ENCRYPT and #MBEDTLS_ARIA_DECRYPT. + * + * \warning You must never reuse a nonce value with the same key. Doing so + * would void the encryption for the two messages encrypted with + * the same nonce and key. + * + * There are two common strategies for managing nonces with CTR: + * + * 1. You can handle everything as a single message processed over + * successive calls to this function. In that case, you want to + * set \p nonce_counter and \p nc_off to 0 for the first call, and + * then preserve the values of \p nonce_counter, \p nc_off and \p + * stream_block across calls to this function as they will be + * updated by this function. + * + * With this strategy, you must not encrypt more than 2**128 + * blocks of data with the same key. + * + * 2. You can encrypt separate messages by dividing the \p + * nonce_counter buffer in two areas: the first one used for a + * per-message nonce, handled by yourself, and the second one + * updated by this function internally. + * + * For example, you might reserve the first 12 bytes for the + * per-message nonce, and the last 4 bytes for internal use. In that + * case, before calling this function on a new message you need to + * set the first 12 bytes of \p nonce_counter to your chosen nonce + * value, the last 4 to 0, and \p nc_off to 0 (which will cause \p + * stream_block to be ignored). That way, you can encrypt at most + * 2**96 messages of up to 2**32 blocks each with the same key. + * + * The per-message nonce (or information sufficient to reconstruct + * it) needs to be communicated with the ciphertext and must be unique. + * The recommended way to ensure uniqueness is to use a message + * counter. An alternative is to generate random nonces, but this + * limits the number of messages that can be securely encrypted: + * for example, with 96-bit random nonces, you should not encrypt + * more than 2**32 messages with the same key. + * + * Note that for both stategies, sizes are measured in blocks and + * that an ARIA block is 16 bytes. + * + * \warning Upon return, \p stream_block contains sensitive data. Its + * content must not be written to insecure storage and should be + * securely discarded as soon as it's no longer needed. + * + * \param ctx The ARIA context to use for encryption or decryption. + * \param length The length of the input data. + * \param nc_off The offset in the current \p stream_block, for + * resuming within the current cipher stream. The + * offset pointer should be 0 at the start of a stream. + * \param nonce_counter The 128-bit nonce and counter. + * \param stream_block The saved stream block for resuming. This is + * overwritten by the function. + * \param input The buffer holding the input data. + * \param output The buffer holding the output data. + * + * \return \c 0 on success. + */ +int mbedtls_aria_crypt_ctr( mbedtls_aria_context *ctx, + size_t length, + size_t *nc_off, + unsigned char nonce_counter[MBEDTLS_ARIA_BLOCKSIZE], + unsigned char stream_block[MBEDTLS_ARIA_BLOCKSIZE], + const unsigned char *input, + unsigned char *output ); +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + +#if defined(MBEDTLS_SELF_TEST) +/** + * \brief Checkup routine. + * + * \return \c 0 on success, or \c 1 on failure. + */ +int mbedtls_aria_self_test( int verbose ); +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + +#endif /* aria.h */ diff --git a/thirdparty/mbedtls/include/mbedtls/bignum.h b/thirdparty/mbedtls/include/mbedtls/bignum.h index 3bf02a7ee1..31383b1eb5 100644 --- a/thirdparty/mbedtls/include/mbedtls/bignum.h +++ b/thirdparty/mbedtls/include/mbedtls/bignum.h @@ -204,6 +204,8 @@ void mbedtls_mpi_free( mbedtls_mpi *X ); /** * \brief Enlarge to the specified number of limbs * + * This function does nothing if the MPI is already large enough. + * * \param X MPI to grow * \param nblimbs The target number of limbs * @@ -215,19 +217,23 @@ int mbedtls_mpi_grow( mbedtls_mpi *X, size_t nblimbs ); /** * \brief Resize down, keeping at least the specified number of limbs * + * If \c X is smaller than \c nblimbs, it is resized up + * instead. + * * \param X MPI to shrink * \param nblimbs The minimum number of limbs to keep * * \return 0 if successful, * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + * (this can only happen when resizing up). */ int mbedtls_mpi_shrink( mbedtls_mpi *X, size_t nblimbs ); /** * \brief Copy the contents of Y into X * - * \param X Destination MPI - * \param Y Source MPI + * \param X Destination MPI. It is enlarged if necessary. + * \param Y Source MPI. * * \return 0 if successful, * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed diff --git a/thirdparty/mbedtls/include/mbedtls/blowfish.h b/thirdparty/mbedtls/include/mbedtls/blowfish.h index c0ef5a04cc..985faa43f0 100644 --- a/thirdparty/mbedtls/include/mbedtls/blowfish.h +++ b/thirdparty/mbedtls/include/mbedtls/blowfish.h @@ -44,14 +44,14 @@ #define MBEDTLS_ERR_BLOWFISH_HW_ACCEL_FAILED -0x0017 /**< Blowfish hardware accelerator failed. */ #define MBEDTLS_ERR_BLOWFISH_INVALID_INPUT_LENGTH -0x0018 /**< Invalid data input length. */ -#if !defined(MBEDTLS_BLOWFISH_ALT) -// Regular implementation -// - #ifdef __cplusplus extern "C" { #endif +#if !defined(MBEDTLS_BLOWFISH_ALT) +// Regular implementation +// + /** * \brief Blowfish context structure */ @@ -62,6 +62,10 @@ typedef struct } mbedtls_blowfish_context; +#else /* MBEDTLS_BLOWFISH_ALT */ +#include "blowfish_alt.h" +#endif /* MBEDTLS_BLOWFISH_ALT */ + /** * \brief Initialize Blowfish context * @@ -170,7 +174,46 @@ int mbedtls_blowfish_crypt_cfb64( mbedtls_blowfish_context *ctx, /** * \brief Blowfish-CTR buffer encryption/decryption * - * Warning: You have to keep the maximum use of your counter in mind! + * \warning You must never reuse a nonce value with the same key. Doing so + * would void the encryption for the two messages encrypted with + * the same nonce and key. + * + * There are two common strategies for managing nonces with CTR: + * + * 1. You can handle everything as a single message processed over + * successive calls to this function. In that case, you want to + * set \p nonce_counter and \p nc_off to 0 for the first call, and + * then preserve the values of \p nonce_counter, \p nc_off and \p + * stream_block across calls to this function as they will be + * updated by this function. + * + * With this strategy, you must not encrypt more than 2**64 + * blocks of data with the same key. + * + * 2. You can encrypt separate messages by dividing the \p + * nonce_counter buffer in two areas: the first one used for a + * per-message nonce, handled by yourself, and the second one + * updated by this function internally. + * + * For example, you might reserve the first 4 bytes for the + * per-message nonce, and the last 4 bytes for internal use. In that + * case, before calling this function on a new message you need to + * set the first 4 bytes of \p nonce_counter to your chosen nonce + * value, the last 4 to 0, and \p nc_off to 0 (which will cause \p + * stream_block to be ignored). That way, you can encrypt at most + * 2**32 messages of up to 2**32 blocks each with the same key. + * + * The per-message nonce (or information sufficient to reconstruct + * it) needs to be communicated with the ciphertext and must be unique. + * The recommended way to ensure uniqueness is to use a message + * counter. + * + * Note that for both stategies, sizes are measured in blocks and + * that a Blowfish block is 8 bytes. + * + * \warning Upon return, \p stream_block contains sensitive data. Its + * content must not be written to insecure storage and should be + * securely discarded as soon as it's no longer needed. * * \param ctx Blowfish context * \param length The length of the data @@ -198,8 +241,4 @@ int mbedtls_blowfish_crypt_ctr( mbedtls_blowfish_context *ctx, } #endif -#else /* MBEDTLS_BLOWFISH_ALT */ -#include "blowfish_alt.h" -#endif /* MBEDTLS_BLOWFISH_ALT */ - #endif /* blowfish.h */ diff --git a/thirdparty/mbedtls/include/mbedtls/bn_mul.h b/thirdparty/mbedtls/include/mbedtls/bn_mul.h index 354c1cc1ab..b587317d95 100644 --- a/thirdparty/mbedtls/include/mbedtls/bn_mul.h +++ b/thirdparty/mbedtls/include/mbedtls/bn_mul.h @@ -49,7 +49,14 @@ /* armcc5 --gnu defines __GNUC__ but doesn't support GNU's extended asm */ #if defined(__GNUC__) && \ ( !defined(__ARMCC_VERSION) || __ARMCC_VERSION >= 6000000 ) -#if defined(__i386__) + +/* + * Disable use of the i386 assembly code below if option -O0, to disable all + * compiler optimisations, is passed, detected with __OPTIMIZE__ + * This is done as the number of registers used in the assembly code doesn't + * work with the -O0 option. + */ +#if defined(__i386__) && defined(__OPTIMIZE__) #define MULADDC_INIT \ asm( \ @@ -142,7 +149,7 @@ "movl %%esi, %3 \n\t" \ : "=m" (t), "=m" (c), "=m" (d), "=m" (s) \ : "m" (t), "m" (s), "m" (d), "m" (c), "m" (b) \ - : "eax", "ecx", "edx", "esi", "edi" \ + : "eax", "ebx", "ecx", "edx", "esi", "edi" \ ); #else @@ -154,7 +161,7 @@ "movl %%esi, %3 \n\t" \ : "=m" (t), "=m" (c), "=m" (d), "=m" (s) \ : "m" (t), "m" (s), "m" (d), "m" (c), "m" (b) \ - : "eax", "ecx", "edx", "esi", "edi" \ + : "eax", "ebx", "ecx", "edx", "esi", "edi" \ ); #endif /* SSE2 */ #endif /* i386 */ @@ -521,7 +528,7 @@ "swi r3, %2 \n\t" \ : "=m" (c), "=m" (d), "=m" (s) \ : "m" (s), "m" (d), "m" (c), "m" (b) \ - : "r3", "r4" "r5", "r6", "r7", "r8", \ + : "r3", "r4", "r5", "r6", "r7", "r8", \ "r9", "r10", "r11", "r12", "r13" \ ); diff --git a/thirdparty/mbedtls/include/mbedtls/camellia.h b/thirdparty/mbedtls/include/mbedtls/camellia.h index cf07629d9b..7e4721af78 100644 --- a/thirdparty/mbedtls/include/mbedtls/camellia.h +++ b/thirdparty/mbedtls/include/mbedtls/camellia.h @@ -40,14 +40,14 @@ #define MBEDTLS_ERR_CAMELLIA_INVALID_INPUT_LENGTH -0x0026 /**< Invalid data input length. */ #define MBEDTLS_ERR_CAMELLIA_HW_ACCEL_FAILED -0x0027 /**< Camellia hardware accelerator failed. */ -#if !defined(MBEDTLS_CAMELLIA_ALT) -// Regular implementation -// - #ifdef __cplusplus extern "C" { #endif +#if !defined(MBEDTLS_CAMELLIA_ALT) +// Regular implementation +// + /** * \brief CAMELLIA context structure */ @@ -58,6 +58,10 @@ typedef struct } mbedtls_camellia_context; +#else /* MBEDTLS_CAMELLIA_ALT */ +#include "camellia_alt.h" +#endif /* MBEDTLS_CAMELLIA_ALT */ + /** * \brief Initialize CAMELLIA context * @@ -183,12 +187,54 @@ int mbedtls_camellia_crypt_cfb128( mbedtls_camellia_context *ctx, /** * \brief CAMELLIA-CTR buffer encryption/decryption * - * Warning: You have to keep the maximum use of your counter in mind! - * * Note: Due to the nature of CTR you should use the same key schedule for * both encryption and decryption. So a context initialized with * mbedtls_camellia_setkey_enc() for both MBEDTLS_CAMELLIA_ENCRYPT and MBEDTLS_CAMELLIA_DECRYPT. * + * \warning You must never reuse a nonce value with the same key. Doing so + * would void the encryption for the two messages encrypted with + * the same nonce and key. + * + * There are two common strategies for managing nonces with CTR: + * + * 1. You can handle everything as a single message processed over + * successive calls to this function. In that case, you want to + * set \p nonce_counter and \p nc_off to 0 for the first call, and + * then preserve the values of \p nonce_counter, \p nc_off and \p + * stream_block across calls to this function as they will be + * updated by this function. + * + * With this strategy, you must not encrypt more than 2**128 + * blocks of data with the same key. + * + * 2. You can encrypt separate messages by dividing the \p + * nonce_counter buffer in two areas: the first one used for a + * per-message nonce, handled by yourself, and the second one + * updated by this function internally. + * + * For example, you might reserve the first 12 bytes for the + * per-message nonce, and the last 4 bytes for internal use. In that + * case, before calling this function on a new message you need to + * set the first 12 bytes of \p nonce_counter to your chosen nonce + * value, the last 4 to 0, and \p nc_off to 0 (which will cause \p + * stream_block to be ignored). That way, you can encrypt at most + * 2**96 messages of up to 2**32 blocks each with the same key. + * + * The per-message nonce (or information sufficient to reconstruct + * it) needs to be communicated with the ciphertext and must be unique. + * The recommended way to ensure uniqueness is to use a message + * counter. An alternative is to generate random nonces, but this + * limits the number of messages that can be securely encrypted: + * for example, with 96-bit random nonces, you should not encrypt + * more than 2**32 messages with the same key. + * + * Note that for both stategies, sizes are measured in blocks and + * that a CAMELLIA block is 16 bytes. + * + * \warning Upon return, \p stream_block contains sensitive data. Its + * content must not be written to insecure storage and should be + * securely discarded as soon as it's no longer needed. + * * \param ctx CAMELLIA context * \param length The length of the data * \param nc_off The offset in the current stream_block (for resuming @@ -211,18 +257,6 @@ int mbedtls_camellia_crypt_ctr( mbedtls_camellia_context *ctx, unsigned char *output ); #endif /* MBEDTLS_CIPHER_MODE_CTR */ -#ifdef __cplusplus -} -#endif - -#else /* MBEDTLS_CAMELLIA_ALT */ -#include "camellia_alt.h" -#endif /* MBEDTLS_CAMELLIA_ALT */ - -#ifdef __cplusplus -extern "C" { -#endif - /** * \brief Checkup routine * diff --git a/thirdparty/mbedtls/include/mbedtls/ccm.h b/thirdparty/mbedtls/include/mbedtls/ccm.h index 630b7fdf6c..5d727e7cca 100644 --- a/thirdparty/mbedtls/include/mbedtls/ccm.h +++ b/thirdparty/mbedtls/include/mbedtls/ccm.h @@ -1,8 +1,11 @@ /** * \file ccm.h * - * \brief CCM combines Counter mode encryption with CBC-MAC authentication - * for 128-bit block ciphers. + * \brief This file provides an API for the CCM authenticated encryption + * mode for block ciphers. + * + * CCM combines Counter mode encryption with CBC-MAC authentication + * for 128-bit block ciphers. * * Input to CCM includes the following elements: * <ul><li>Payload - data that is both authenticated and encrypted.</li> @@ -11,6 +14,18 @@ * <li>Nonce - A unique value that is assigned to the payload and the * associated data.</li></ul> * + * Definition of CCM: + * http://csrc.nist.gov/publications/nistpubs/800-38C/SP800-38C_updated-July20_2007.pdf + * RFC 3610 "Counter with CBC-MAC (CCM)" + * + * Related: + * RFC 5116 "An Interface and Algorithms for Authenticated Encryption" + * + * Definition of CCM*: + * IEEE 802.15.4 - IEEE Standard for Local and metropolitan area networks + * Integer representation is fixed most-significant-octet-first order and + * the representation of octets is most-significant-bit-first order. This is + * consistent with RFC 3610. */ /* * Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved @@ -40,14 +55,15 @@ #define MBEDTLS_ERR_CCM_AUTH_FAILED -0x000F /**< Authenticated decryption failed. */ #define MBEDTLS_ERR_CCM_HW_ACCEL_FAILED -0x0011 /**< CCM hardware accelerator failed. */ -#if !defined(MBEDTLS_CCM_ALT) -// Regular implementation -// #ifdef __cplusplus extern "C" { #endif +#if !defined(MBEDTLS_CCM_ALT) +// Regular implementation +// + /** * \brief The CCM context-type definition. The CCM context is passed * to the APIs called. @@ -57,6 +73,10 @@ typedef struct { } mbedtls_ccm_context; +#else /* MBEDTLS_CCM_ALT */ +#include "ccm_alt.h" +#endif /* MBEDTLS_CCM_ALT */ + /** * \brief This function initializes the specified CCM context, * to make references valid, and prepare the context @@ -75,7 +95,8 @@ void mbedtls_ccm_init( mbedtls_ccm_context *ctx ); * \param key The encryption key. * \param keybits The key size in bits. This must be acceptable by the cipher. * - * \return \c 0 on success, or a cipher-specific error code. + * \return \c 0 on success. + * \return A CCM or cipher-specific error code on failure. */ int mbedtls_ccm_setkey( mbedtls_ccm_context *ctx, mbedtls_cipher_id_t cipher, @@ -93,29 +114,73 @@ void mbedtls_ccm_free( mbedtls_ccm_context *ctx ); /** * \brief This function encrypts a buffer using CCM. * + * \note The tag is written to a separate buffer. To concatenate + * the \p tag with the \p output, as done in <em>RFC-3610: + * Counter with CBC-MAC (CCM)</em>, use + * \p tag = \p output + \p length, and make sure that the + * output buffer is at least \p length + \p tag_len wide. + * * \param ctx The CCM context to use for encryption. * \param length The length of the input data in Bytes. * \param iv Initialization vector (nonce). - * \param iv_len The length of the IV in Bytes: 7, 8, 9, 10, 11, 12, or 13. + * \param iv_len The length of the nonce in Bytes: 7, 8, 9, 10, 11, 12, + * or 13. The length L of the message length field is + * 15 - \p iv_len. * \param add The additional data field. * \param add_len The length of additional data in Bytes. * Must be less than 2^16 - 2^8. * \param input The buffer holding the input data. * \param output The buffer holding the output data. * Must be at least \p length Bytes wide. - * \param tag The buffer holding the tag. - * \param tag_len The length of the tag to generate in Bytes: + * \param tag The buffer holding the authentication field. + * \param tag_len The length of the authentication field to generate in Bytes: * 4, 6, 8, 10, 12, 14 or 16. * + * \return \c 0 on success. + * \return A CCM or cipher-specific error code on failure. + */ +int mbedtls_ccm_encrypt_and_tag( mbedtls_ccm_context *ctx, size_t length, + const unsigned char *iv, size_t iv_len, + const unsigned char *add, size_t add_len, + const unsigned char *input, unsigned char *output, + unsigned char *tag, size_t tag_len ); + +/** + * \brief This function encrypts a buffer using CCM*. + * * \note The tag is written to a separate buffer. To concatenate * the \p tag with the \p output, as done in <em>RFC-3610: * Counter with CBC-MAC (CCM)</em>, use * \p tag = \p output + \p length, and make sure that the * output buffer is at least \p length + \p tag_len wide. * + * \note When using this function in a variable tag length context, + * the tag length has to be encoded into the \p iv passed to + * this function. + * + * \param ctx The CCM context to use for encryption. + * \param length The length of the input data in Bytes. + * \param iv Initialization vector (nonce). + * \param iv_len The length of the nonce in Bytes: 7, 8, 9, 10, 11, 12, + * or 13. The length L of the message length field is + * 15 - \p iv_len. + * \param add The additional data field. + * \param add_len The length of additional data in Bytes. + * Must be less than 2^16 - 2^8. + * \param input The buffer holding the input data. + * \param output The buffer holding the output data. + * Must be at least \p length Bytes wide. + * \param tag The buffer holding the authentication field. + * \param tag_len The length of the authentication field to generate in Bytes: + * 0, 4, 6, 8, 10, 12, 14 or 16. + * + * \warning Passing 0 as \p tag_len means that the message is no + * longer authenticated. + * * \return \c 0 on success. + * \return A CCM or cipher-specific error code on failure. */ -int mbedtls_ccm_encrypt_and_tag( mbedtls_ccm_context *ctx, size_t length, +int mbedtls_ccm_star_encrypt_and_tag( mbedtls_ccm_context *ctx, size_t length, const unsigned char *iv, size_t iv_len, const unsigned char *add, size_t add_len, const unsigned char *input, unsigned char *output, @@ -127,20 +192,23 @@ int mbedtls_ccm_encrypt_and_tag( mbedtls_ccm_context *ctx, size_t length, * * \param ctx The CCM context to use for decryption. * \param length The length of the input data in Bytes. - * \param iv Initialization vector. - * \param iv_len The length of the IV in Bytes: 7, 8, 9, 10, 11, 12, or 13. + * \param iv Initialization vector (nonce). + * \param iv_len The length of the nonce in Bytes: 7, 8, 9, 10, 11, 12, + * or 13. The length L of the message length field is + * 15 - \p iv_len. * \param add The additional data field. * \param add_len The length of additional data in Bytes. * Must be less than 2^16 - 2^8. * \param input The buffer holding the input data. * \param output The buffer holding the output data. * Must be at least \p length Bytes wide. - * \param tag The buffer holding the tag. - * \param tag_len The length of the tag in Bytes. + * \param tag The buffer holding the authentication field. + * \param tag_len The length of the authentication field in Bytes. * 4, 6, 8, 10, 12, 14 or 16. * - * \return 0 if successful and authenticated, or - * #MBEDTLS_ERR_CCM_AUTH_FAILED if the tag does not match. + * \return \c 0 on success. This indicates that the message is authentic. + * \return #MBEDTLS_ERR_CCM_AUTH_FAILED if the tag does not match. + * \return A cipher-specific error code on calculation failure. */ int mbedtls_ccm_auth_decrypt( mbedtls_ccm_context *ctx, size_t length, const unsigned char *iv, size_t iv_len, @@ -148,23 +216,50 @@ int mbedtls_ccm_auth_decrypt( mbedtls_ccm_context *ctx, size_t length, const unsigned char *input, unsigned char *output, const unsigned char *tag, size_t tag_len ); -#ifdef __cplusplus -} -#endif - -#else /* MBEDTLS_CCM_ALT */ -#include "ccm_alt.h" -#endif /* MBEDTLS_CCM_ALT */ - -#ifdef __cplusplus -extern "C" { -#endif +/** + * \brief This function performs a CCM* authenticated decryption of a + * buffer. + * + * \note When using this function in a variable tag length context, + * the tag length has to be decoded from \p iv and passed to + * this function as \p tag_len. (\p tag needs to be adjusted + * accordingly.) + * + * \param ctx The CCM context to use for decryption. + * \param length The length of the input data in Bytes. + * \param iv Initialization vector (nonce). + * \param iv_len The length of the nonce in Bytes: 7, 8, 9, 10, 11, 12, + * or 13. The length L of the message length field is + * 15 - \p iv_len. + * \param add The additional data field. + * \param add_len The length of additional data in Bytes. + * Must be less than 2^16 - 2^8. + * \param input The buffer holding the input data. + * \param output The buffer holding the output data. + * Must be at least \p length Bytes wide. + * \param tag The buffer holding the authentication field. + * \param tag_len The length of the authentication field in Bytes. + * 0, 4, 6, 8, 10, 12, 14 or 16. + * + * \warning Passing 0 as \p tag_len means that the message is no + * longer authenticated. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CCM_AUTH_FAILED if the tag does not match. + * \return A cipher-specific error code on calculation failure. + */ +int mbedtls_ccm_star_auth_decrypt( mbedtls_ccm_context *ctx, size_t length, + const unsigned char *iv, size_t iv_len, + const unsigned char *add, size_t add_len, + const unsigned char *input, unsigned char *output, + const unsigned char *tag, size_t tag_len ); #if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C) /** * \brief The CCM checkup routine. * - * \return \c 0 on success, or \c 1 on failure. + * \return \c 0 on success. + * \return \c 1 on failure. */ int mbedtls_ccm_self_test( int verbose ); #endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */ diff --git a/thirdparty/mbedtls/include/mbedtls/chacha20.h b/thirdparty/mbedtls/include/mbedtls/chacha20.h new file mode 100644 index 0000000000..47bd7d38b9 --- /dev/null +++ b/thirdparty/mbedtls/include/mbedtls/chacha20.h @@ -0,0 +1,212 @@ +/** + * \file chacha20.h + * + * \brief This file contains ChaCha20 definitions and functions. + * + * ChaCha20 is a stream cipher that can encrypt and decrypt + * information. ChaCha was created by Daniel Bernstein as a variant of + * its Salsa cipher https://cr.yp.to/chacha/chacha-20080128.pdf + * ChaCha20 is the variant with 20 rounds, that was also standardized + * in RFC 7539. + * + * \author Daniel King <damaki.gh@gmail.com> + */ + +/* Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of Mbed TLS (https://tls.mbed.org) + */ + +#ifndef MBEDTLS_CHACHA20_H +#define MBEDTLS_CHACHA20_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include <stdint.h> +#include <stddef.h> + +#define MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA -0x0051 /**< Invalid input parameter(s). */ +#define MBEDTLS_ERR_CHACHA20_FEATURE_UNAVAILABLE -0x0053 /**< Feature not available. For example, s part of the API is not implemented. */ +#define MBEDTLS_ERR_CHACHA20_HW_ACCEL_FAILED -0x0055 /**< Chacha20 hardware accelerator failed. */ + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(MBEDTLS_CHACHA20_ALT) + +typedef struct +{ + uint32_t state[16]; /*! The state (before round operations). */ + uint8_t keystream8[64]; /*! Leftover keystream bytes. */ + size_t keystream_bytes_used; /*! Number of keystream bytes already used. */ +} +mbedtls_chacha20_context; + +#else /* MBEDTLS_CHACHA20_ALT */ +#include "chacha20_alt.h" +#endif /* MBEDTLS_CHACHA20_ALT */ + +/** + * \brief This function initializes the specified ChaCha20 context. + * + * It must be the first API called before using + * the context. + * + * It is usually followed by calls to + * \c mbedtls_chacha20_setkey() and + * \c mbedtls_chacha20_starts(), then one or more calls to + * to \c mbedtls_chacha20_update(), and finally to + * \c mbedtls_chacha20_free(). + * + * \param ctx The ChaCha20 context to initialize. + */ +void mbedtls_chacha20_init( mbedtls_chacha20_context *ctx ); + +/** + * \brief This function releases and clears the specified ChaCha20 context. + * + * \param ctx The ChaCha20 context to clear. + */ +void mbedtls_chacha20_free( mbedtls_chacha20_context *ctx ); + +/** + * \brief This function sets the encryption/decryption key. + * + * \note After using this function, you must also call + * \c mbedtls_chacha20_starts() to set a nonce before you + * start encrypting/decrypting data with + * \c mbedtls_chacha_update(). + * + * \param ctx The ChaCha20 context to which the key should be bound. + * \param key The encryption/decryption key. Must be 32 bytes in length. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA if ctx or key is NULL. + */ +int mbedtls_chacha20_setkey( mbedtls_chacha20_context *ctx, + const unsigned char key[32] ); + +/** + * \brief This function sets the nonce and initial counter value. + * + * \note A ChaCha20 context can be re-used with the same key by + * calling this function to change the nonce. + * + * \warning You must never use the same nonce twice with the same key. + * This would void any confidentiality guarantees for the + * messages encrypted with the same nonce and key. + * + * \param ctx The ChaCha20 context to which the nonce should be bound. + * \param nonce The nonce. Must be 12 bytes in size. + * \param counter The initial counter value. This is usually 0. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA if ctx or nonce is + * NULL. + */ +int mbedtls_chacha20_starts( mbedtls_chacha20_context* ctx, + const unsigned char nonce[12], + uint32_t counter ); + +/** + * \brief This function encrypts or decrypts data. + * + * Since ChaCha20 is a stream cipher, the same operation is + * used for encrypting and decrypting data. + * + * \note The \p input and \p output pointers must either be equal or + * point to non-overlapping buffers. + * + * \note \c mbedtls_chacha20_setkey() and + * \c mbedtls_chacha20_starts() must be called at least once + * to setup the context before this function can be called. + * + * \note This function can be called multiple times in a row in + * order to encrypt of decrypt data piecewise with the same + * key and nonce. + * + * \param ctx The ChaCha20 context to use for encryption or decryption. + * \param size The length of the input data in bytes. + * \param input The buffer holding the input data. + * This pointer can be NULL if size == 0. + * \param output The buffer holding the output data. + * Must be able to hold \p size bytes. + * This pointer can be NULL if size == 0. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA if the ctx, input, or + * output pointers are NULL. + */ +int mbedtls_chacha20_update( mbedtls_chacha20_context *ctx, + size_t size, + const unsigned char *input, + unsigned char *output ); + +/** + * \brief This function encrypts or decrypts data with ChaCha20 and + * the given key and nonce. + * + * Since ChaCha20 is a stream cipher, the same operation is + * used for encrypting and decrypting data. + * + * \warning You must never use the same (key, nonce) pair more than + * once. This would void any confidentiality guarantees for + * the messages encrypted with the same nonce and key. + * + * \note The \p input and \p output pointers must either be equal or + * point to non-overlapping buffers. + * + * \param key The encryption/decryption key. Must be 32 bytes in length. + * \param nonce The nonce. Must be 12 bytes in size. + * \param counter The initial counter value. This is usually 0. + * \param size The length of the input data in bytes. + * \param input The buffer holding the input data. + * This pointer can be NULL if size == 0. + * \param output The buffer holding the output data. + * Must be able to hold \p size bytes. + * This pointer can be NULL if size == 0. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA if key, nonce, input, + * or output is NULL. + */ +int mbedtls_chacha20_crypt( const unsigned char key[32], + const unsigned char nonce[12], + uint32_t counter, + size_t size, + const unsigned char* input, + unsigned char* output ); + +#if defined(MBEDTLS_SELF_TEST) +/** + * \brief The ChaCha20 checkup routine. + * + * \return \c 0 on success. + * \return \c 1 on failure. + */ +int mbedtls_chacha20_self_test( int verbose ); +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_CHACHA20_H */ diff --git a/thirdparty/mbedtls/include/mbedtls/chachapoly.h b/thirdparty/mbedtls/include/mbedtls/chachapoly.h new file mode 100644 index 0000000000..42b2b230c5 --- /dev/null +++ b/thirdparty/mbedtls/include/mbedtls/chachapoly.h @@ -0,0 +1,355 @@ +/** + * \file chachapoly.h + * + * \brief This file contains the AEAD-ChaCha20-Poly1305 definitions and + * functions. + * + * ChaCha20-Poly1305 is an algorithm for Authenticated Encryption + * with Associated Data (AEAD) that can be used to encrypt and + * authenticate data. It is based on ChaCha20 and Poly1305 by Daniel + * Bernstein and was standardized in RFC 7539. + * + * \author Daniel King <damaki.gh@gmail.com> + */ + +/* Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of Mbed TLS (https://tls.mbed.org) + */ + +#ifndef MBEDTLS_CHACHAPOLY_H +#define MBEDTLS_CHACHAPOLY_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +/* for shared error codes */ +#include "poly1305.h" + +#define MBEDTLS_ERR_CHACHAPOLY_BAD_STATE -0x0054 /**< The requested operation is not permitted in the current state. */ +#define MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED -0x0056 /**< Authenticated decryption failed: data was not authentic. */ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum +{ + MBEDTLS_CHACHAPOLY_ENCRYPT, /**< The mode value for performing encryption. */ + MBEDTLS_CHACHAPOLY_DECRYPT /**< The mode value for performing decryption. */ +} +mbedtls_chachapoly_mode_t; + +#if !defined(MBEDTLS_CHACHAPOLY_ALT) + +#include "chacha20.h" + +typedef struct +{ + mbedtls_chacha20_context chacha20_ctx; /**< The ChaCha20 context. */ + mbedtls_poly1305_context poly1305_ctx; /**< The Poly1305 context. */ + uint64_t aad_len; /**< The length (bytes) of the Additional Authenticated Data. */ + uint64_t ciphertext_len; /**< The length (bytes) of the ciphertext. */ + int state; /**< The current state of the context. */ + mbedtls_chachapoly_mode_t mode; /**< Cipher mode (encrypt or decrypt). */ +} +mbedtls_chachapoly_context; + +#else /* !MBEDTLS_CHACHAPOLY_ALT */ +#include "chachapoly_alt.h" +#endif /* !MBEDTLS_CHACHAPOLY_ALT */ + +/** + * \brief This function initializes the specified ChaCha20-Poly1305 context. + * + * It must be the first API called before using + * the context. It must be followed by a call to + * \c mbedtls_chachapoly_setkey() before any operation can be + * done, and to \c mbedtls_chachapoly_free() once all + * operations with that context have been finished. + * + * In order to encrypt or decrypt full messages at once, for + * each message you should make a single call to + * \c mbedtls_chachapoly_crypt_and_tag() or + * \c mbedtls_chachapoly_auth_decrypt(). + * + * In order to encrypt messages piecewise, for each + * message you should make a call to + * \c mbedtls_chachapoly_starts(), then 0 or more calls to + * \c mbedtls_chachapoly_update_aad(), then 0 or more calls to + * \c mbedtls_chachapoly_update(), then one call to + * \c mbedtls_chachapoly_finish(). + * + * \warning Decryption with the piecewise API is discouraged! Always + * use \c mbedtls_chachapoly_auth_decrypt() when possible! + * + * If however this is not possible because the data is too + * large to fit in memory, you need to: + * + * - call \c mbedtls_chachapoly_starts() and (if needed) + * \c mbedtls_chachapoly_update_aad() as above, + * - call \c mbedtls_chachapoly_update() multiple times and + * ensure its output (the plaintext) is NOT used in any other + * way than placing it in temporary storage at this point, + * - call \c mbedtls_chachapoly_finish() to compute the + * authentication tag and compared it in constant time to the + * tag received with the ciphertext. + * + * If the tags are not equal, you must immediately discard + * all previous outputs of \c mbedtls_chachapoly_update(), + * otherwise you can now safely use the plaintext. + * + * \param ctx The ChachaPoly context to initialize. + */ +void mbedtls_chachapoly_init( mbedtls_chachapoly_context *ctx ); + +/** + * \brief This function releases and clears the specified ChaCha20-Poly1305 context. + * + * \param ctx The ChachaPoly context to clear. + */ +void mbedtls_chachapoly_free( mbedtls_chachapoly_context *ctx ); + +/** + * \brief This function sets the ChaCha20-Poly1305 symmetric encryption key. + * + * \param ctx The ChaCha20-Poly1305 context to which the key should be + * bound. + * \param key The 256-bit (32 bytes) key. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA + * if \p ctx or \p key are NULL. + */ +int mbedtls_chachapoly_setkey( mbedtls_chachapoly_context *ctx, + const unsigned char key[32] ); + +/** + * \brief This function starts a ChaCha20-Poly1305 encryption or + * decryption operation. + * + * \warning You must never use the same nonce twice with the same key. + * This would void any confidentiality and authenticity + * guarantees for the messages encrypted with the same nonce + * and key. + * + * \note If the context is being used for AAD only (no data to + * encrypt or decrypt) then \p mode can be set to any value. + * + * \warning Decryption with the piecewise API is discouraged, see the + * warning on \c mbedtls_chachapoly_init(). + * + * \param ctx The ChaCha20-Poly1305 context. + * \param nonce The nonce/IV to use for the message. Must be 12 bytes. + * \param mode The operation to perform: #MBEDTLS_CHACHAPOLY_ENCRYPT or + * #MBEDTLS_CHACHAPOLY_DECRYPT (discouraged, see warning). + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA + * if \p ctx or \p mac are NULL. + */ +int mbedtls_chachapoly_starts( mbedtls_chachapoly_context *ctx, + const unsigned char nonce[12], + mbedtls_chachapoly_mode_t mode ); + +/** + * \brief This function feeds additional data to be authenticated + * into an ongoing ChaCha20-Poly1305 operation. + * + * The Additional Authenticated Data (AAD), also called + * Associated Data (AD) is only authenticated but not + * encrypted nor included in the encrypted output. It is + * usually transmitted separately from the ciphertext or + * computed locally by each party. + * + * \note This function is called before data is encrypted/decrypted. + * I.e. call this function to process the AAD before calling + * \c mbedtls_chachapoly_update(). + * + * You may call this function multiple times to process + * an arbitrary amount of AAD. It is permitted to call + * this function 0 times, if no AAD is used. + * + * This function cannot be called any more if data has + * been processed by \c mbedtls_chachapoly_update(), + * or if the context has been finished. + * + * \warning Decryption with the piecewise API is discouraged, see the + * warning on \c mbedtls_chachapoly_init(). + * + * \param ctx The ChaCha20-Poly1305 context to use. + * \param aad_len The length (in bytes) of the AAD. The length has no + * restrictions. + * \param aad Buffer containing the AAD. + * This pointer can be NULL if aad_len == 0. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA + * if \p ctx or \p aad are NULL. + * \return #MBEDTLS_ERR_CHACHAPOLY_BAD_STATE + * if the operations has not been started or has been + * finished, or if the AAD has been finished. + */ +int mbedtls_chachapoly_update_aad( mbedtls_chachapoly_context *ctx, + const unsigned char *aad, + size_t aad_len ); + +/** + * \brief Thus function feeds data to be encrypted or decrypted + * into an on-going ChaCha20-Poly1305 + * operation. + * + * The direction (encryption or decryption) depends on the + * mode that was given when calling + * \c mbedtls_chachapoly_starts(). + * + * You may call this function multiple times to process + * an arbitrary amount of data. It is permitted to call + * this function 0 times, if no data is to be encrypted + * or decrypted. + * + * \warning Decryption with the piecewise API is discouraged, see the + * warning on \c mbedtls_chachapoly_init(). + * + * \param ctx The ChaCha20-Poly1305 context to use. + * \param len The length (in bytes) of the data to encrypt or decrypt. + * \param input The buffer containing the data to encrypt or decrypt. + * This pointer can be NULL if len == 0. + * \param output The buffer to where the encrypted or decrypted data is written. + * Must be able to hold \p len bytes. + * This pointer can be NULL if len == 0. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA + * if \p ctx, \p input, or \p output are NULL. + * \return #MBEDTLS_ERR_CHACHAPOLY_BAD_STATE + * if the operation has not been started or has been + * finished. + */ +int mbedtls_chachapoly_update( mbedtls_chachapoly_context *ctx, + size_t len, + const unsigned char *input, + unsigned char *output ); + +/** + * \brief This function finished the ChaCha20-Poly1305 operation and + * generates the MAC (authentication tag). + * + * \param ctx The ChaCha20-Poly1305 context to use. + * \param mac The buffer to where the 128-bit (16 bytes) MAC is written. + * + * \warning Decryption with the piecewise API is discouraged, see the + * warning on \c mbedtls_chachapoly_init(). + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA + * if \p ctx or \p mac are NULL. + * \return #MBEDTLS_ERR_CHACHAPOLY_BAD_STATE + * if the operation has not been started or has been + * finished. + */ +int mbedtls_chachapoly_finish( mbedtls_chachapoly_context *ctx, + unsigned char mac[16] ); + +/** + * \brief This function performs a complete ChaCha20-Poly1305 + * authenticated encryption with the previously-set key. + * + * \note Before using this function, you must set the key with + * \c mbedtls_chachapoly_setkey(). + * + * \warning You must never use the same nonce twice with the same key. + * This would void any confidentiality and authenticity + * guarantees for the messages encrypted with the same nonce + * and key. + * + * \param ctx The ChaCha20-Poly1305 context to use (holds the key). + * \param length The length (in bytes) of the data to encrypt or decrypt. + * \param nonce The 96-bit (12 bytes) nonce/IV to use. + * \param aad The buffer containing the additional authenticated data (AAD). + * This pointer can be NULL if aad_len == 0. + * \param aad_len The length (in bytes) of the AAD data to process. + * \param input The buffer containing the data to encrypt or decrypt. + * This pointer can be NULL if ilen == 0. + * \param output The buffer to where the encrypted or decrypted data is written. + * This pointer can be NULL if ilen == 0. + * \param tag The buffer to where the computed 128-bit (16 bytes) MAC is written. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA + * if one or more of the required parameters are NULL. + */ +int mbedtls_chachapoly_encrypt_and_tag( mbedtls_chachapoly_context *ctx, + size_t length, + const unsigned char nonce[12], + const unsigned char *aad, + size_t aad_len, + const unsigned char *input, + unsigned char *output, + unsigned char tag[16] ); + +/** + * \brief This function performs a complete ChaCha20-Poly1305 + * authenticated decryption with the previously-set key. + * + * \note Before using this function, you must set the key with + * \c mbedtls_chachapoly_setkey(). + * + * \param ctx The ChaCha20-Poly1305 context to use (holds the key). + * \param length The length (in bytes) of the data to decrypt. + * \param nonce The 96-bit (12 bytes) nonce/IV to use. + * \param aad The buffer containing the additional authenticated data (AAD). + * This pointer can be NULL if aad_len == 0. + * \param aad_len The length (in bytes) of the AAD data to process. + * \param tag The buffer holding the authentication tag. + * \param input The buffer containing the data to decrypt. + * This pointer can be NULL if ilen == 0. + * \param output The buffer to where the decrypted data is written. + * This pointer can be NULL if ilen == 0. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA + * if one or more of the required parameters are NULL. + * \return #MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED + * if the data was not authentic. + */ +int mbedtls_chachapoly_auth_decrypt( mbedtls_chachapoly_context *ctx, + size_t length, + const unsigned char nonce[12], + const unsigned char *aad, + size_t aad_len, + const unsigned char tag[16], + const unsigned char *input, + unsigned char *output ); + +#if defined(MBEDTLS_SELF_TEST) +/** + * \brief The ChaCha20-Poly1305 checkup routine. + * + * \return \c 0 on success. + * \return \c 1 on failure. + */ +int mbedtls_chachapoly_self_test( int verbose ); +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_CHACHAPOLY_H */ diff --git a/thirdparty/mbedtls/include/mbedtls/check_config.h b/thirdparty/mbedtls/include/mbedtls/check_config.h index be80332963..9e6bb8a46a 100644 --- a/thirdparty/mbedtls/include/mbedtls/check_config.h +++ b/thirdparty/mbedtls/include/mbedtls/check_config.h @@ -4,7 +4,7 @@ * \brief Consistency checks for configuration options */ /* - * Copyright (C) 2006-2016, ARM Limited, All Rights Reserved + * Copyright (C) 2006-2018, ARM Limited, All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); you may @@ -87,6 +87,11 @@ #error "MBEDTLS_CMAC_C defined, but not all prerequisites" #endif +#if defined(MBEDTLS_NIST_KW_C) && \ + ( !defined(MBEDTLS_AES_C) || !defined(MBEDTLS_CIPHER_C) ) +#error "MBEDTLS_NIST_KW_C defined, but not all prerequisites" +#endif + #if defined(MBEDTLS_ECDH_C) && !defined(MBEDTLS_ECP_C) #error "MBEDTLS_ECDH_C defined, but not all prerequisites" #endif @@ -191,6 +196,10 @@ #error "MBEDTLS_HAVEGE_C defined, but not all prerequisites" #endif +#if defined(MBEDTLS_HKDF_C) && !defined(MBEDTLS_MD_C) +#error "MBEDTLS_HKDF_C defined, but not all prerequisites" +#endif + #if defined(MBEDTLS_HMAC_DRBG_C) && !defined(MBEDTLS_MD_C) #error "MBEDTLS_HMAC_DRBG_C defined, but not all prerequisites" #endif diff --git a/thirdparty/mbedtls/include/mbedtls/cipher.h b/thirdparty/mbedtls/include/mbedtls/cipher.h index d1f4efef8e..ea0ce983f1 100644 --- a/thirdparty/mbedtls/include/mbedtls/cipher.h +++ b/thirdparty/mbedtls/include/mbedtls/cipher.h @@ -1,7 +1,9 @@ /** * \file cipher.h * - * \brief The generic cipher wrapper. + * \brief This file contains an abstraction interface for use with the cipher + * primitives provided by the library. It provides a common interface to all of + * the available cipher operations. * * \author Adriaan de Jong <dejong@fox-it.com> */ @@ -35,7 +37,7 @@ #include <stddef.h> -#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CCM_C) +#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CCM_C) || defined(MBEDTLS_CHACHAPOLY_C) #define MBEDTLS_CIPHER_MODE_AEAD #endif @@ -43,7 +45,7 @@ #define MBEDTLS_CIPHER_MODE_WITH_PADDING #endif -#if defined(MBEDTLS_ARC4_C) +#if defined(MBEDTLS_ARC4_C) || defined(MBEDTLS_CIPHER_NULL_CIPHER) #define MBEDTLS_CIPHER_MODE_STREAM #endif @@ -69,93 +71,122 @@ extern "C" { #endif /** - * \brief An enumeration of supported ciphers. + * \brief Supported cipher types. * - * \warning ARC4 and DES are considered weak ciphers and their use - * constitutes a security risk. We recommend considering stronger + * \warning RC4 and DES are considered weak ciphers and their use + * constitutes a security risk. Arm recommends considering stronger * ciphers instead. */ typedef enum { - MBEDTLS_CIPHER_ID_NONE = 0, - MBEDTLS_CIPHER_ID_NULL, - MBEDTLS_CIPHER_ID_AES, - MBEDTLS_CIPHER_ID_DES, - MBEDTLS_CIPHER_ID_3DES, - MBEDTLS_CIPHER_ID_CAMELLIA, - MBEDTLS_CIPHER_ID_BLOWFISH, - MBEDTLS_CIPHER_ID_ARC4, + MBEDTLS_CIPHER_ID_NONE = 0, /**< Placeholder to mark the end of cipher ID lists. */ + MBEDTLS_CIPHER_ID_NULL, /**< The identity cipher, treated as a stream cipher. */ + MBEDTLS_CIPHER_ID_AES, /**< The AES cipher. */ + MBEDTLS_CIPHER_ID_DES, /**< The DES cipher. */ + MBEDTLS_CIPHER_ID_3DES, /**< The Triple DES cipher. */ + MBEDTLS_CIPHER_ID_CAMELLIA, /**< The Camellia cipher. */ + MBEDTLS_CIPHER_ID_BLOWFISH, /**< The Blowfish cipher. */ + MBEDTLS_CIPHER_ID_ARC4, /**< The RC4 cipher. */ + MBEDTLS_CIPHER_ID_ARIA, /**< The Aria cipher. */ + MBEDTLS_CIPHER_ID_CHACHA20, /**< The ChaCha20 cipher. */ } mbedtls_cipher_id_t; /** - * \brief An enumeration of supported (cipher, mode) pairs. + * \brief Supported {cipher type, cipher mode} pairs. * - * \warning ARC4 and DES are considered weak ciphers and their use - * constitutes a security risk. We recommend considering stronger + * \warning RC4 and DES are considered weak ciphers and their use + * constitutes a security risk. Arm recommends considering stronger * ciphers instead. */ typedef enum { - MBEDTLS_CIPHER_NONE = 0, - MBEDTLS_CIPHER_NULL, - MBEDTLS_CIPHER_AES_128_ECB, - MBEDTLS_CIPHER_AES_192_ECB, - MBEDTLS_CIPHER_AES_256_ECB, - MBEDTLS_CIPHER_AES_128_CBC, - MBEDTLS_CIPHER_AES_192_CBC, - MBEDTLS_CIPHER_AES_256_CBC, - MBEDTLS_CIPHER_AES_128_CFB128, - MBEDTLS_CIPHER_AES_192_CFB128, - MBEDTLS_CIPHER_AES_256_CFB128, - MBEDTLS_CIPHER_AES_128_CTR, - MBEDTLS_CIPHER_AES_192_CTR, - MBEDTLS_CIPHER_AES_256_CTR, - MBEDTLS_CIPHER_AES_128_GCM, - MBEDTLS_CIPHER_AES_192_GCM, - MBEDTLS_CIPHER_AES_256_GCM, - MBEDTLS_CIPHER_CAMELLIA_128_ECB, - MBEDTLS_CIPHER_CAMELLIA_192_ECB, - MBEDTLS_CIPHER_CAMELLIA_256_ECB, - MBEDTLS_CIPHER_CAMELLIA_128_CBC, - MBEDTLS_CIPHER_CAMELLIA_192_CBC, - MBEDTLS_CIPHER_CAMELLIA_256_CBC, - MBEDTLS_CIPHER_CAMELLIA_128_CFB128, - MBEDTLS_CIPHER_CAMELLIA_192_CFB128, - MBEDTLS_CIPHER_CAMELLIA_256_CFB128, - MBEDTLS_CIPHER_CAMELLIA_128_CTR, - MBEDTLS_CIPHER_CAMELLIA_192_CTR, - MBEDTLS_CIPHER_CAMELLIA_256_CTR, - MBEDTLS_CIPHER_CAMELLIA_128_GCM, - MBEDTLS_CIPHER_CAMELLIA_192_GCM, - MBEDTLS_CIPHER_CAMELLIA_256_GCM, - MBEDTLS_CIPHER_DES_ECB, - MBEDTLS_CIPHER_DES_CBC, - MBEDTLS_CIPHER_DES_EDE_ECB, - MBEDTLS_CIPHER_DES_EDE_CBC, - MBEDTLS_CIPHER_DES_EDE3_ECB, - MBEDTLS_CIPHER_DES_EDE3_CBC, - MBEDTLS_CIPHER_BLOWFISH_ECB, - MBEDTLS_CIPHER_BLOWFISH_CBC, - MBEDTLS_CIPHER_BLOWFISH_CFB64, - MBEDTLS_CIPHER_BLOWFISH_CTR, - MBEDTLS_CIPHER_ARC4_128, - MBEDTLS_CIPHER_AES_128_CCM, - MBEDTLS_CIPHER_AES_192_CCM, - MBEDTLS_CIPHER_AES_256_CCM, - MBEDTLS_CIPHER_CAMELLIA_128_CCM, - MBEDTLS_CIPHER_CAMELLIA_192_CCM, - MBEDTLS_CIPHER_CAMELLIA_256_CCM, + MBEDTLS_CIPHER_NONE = 0, /**< Placeholder to mark the end of cipher-pair lists. */ + MBEDTLS_CIPHER_NULL, /**< The identity stream cipher. */ + MBEDTLS_CIPHER_AES_128_ECB, /**< AES cipher with 128-bit ECB mode. */ + MBEDTLS_CIPHER_AES_192_ECB, /**< AES cipher with 192-bit ECB mode. */ + MBEDTLS_CIPHER_AES_256_ECB, /**< AES cipher with 256-bit ECB mode. */ + MBEDTLS_CIPHER_AES_128_CBC, /**< AES cipher with 128-bit CBC mode. */ + MBEDTLS_CIPHER_AES_192_CBC, /**< AES cipher with 192-bit CBC mode. */ + MBEDTLS_CIPHER_AES_256_CBC, /**< AES cipher with 256-bit CBC mode. */ + MBEDTLS_CIPHER_AES_128_CFB128, /**< AES cipher with 128-bit CFB128 mode. */ + MBEDTLS_CIPHER_AES_192_CFB128, /**< AES cipher with 192-bit CFB128 mode. */ + MBEDTLS_CIPHER_AES_256_CFB128, /**< AES cipher with 256-bit CFB128 mode. */ + MBEDTLS_CIPHER_AES_128_CTR, /**< AES cipher with 128-bit CTR mode. */ + MBEDTLS_CIPHER_AES_192_CTR, /**< AES cipher with 192-bit CTR mode. */ + MBEDTLS_CIPHER_AES_256_CTR, /**< AES cipher with 256-bit CTR mode. */ + MBEDTLS_CIPHER_AES_128_GCM, /**< AES cipher with 128-bit GCM mode. */ + MBEDTLS_CIPHER_AES_192_GCM, /**< AES cipher with 192-bit GCM mode. */ + MBEDTLS_CIPHER_AES_256_GCM, /**< AES cipher with 256-bit GCM mode. */ + MBEDTLS_CIPHER_CAMELLIA_128_ECB, /**< Camellia cipher with 128-bit ECB mode. */ + MBEDTLS_CIPHER_CAMELLIA_192_ECB, /**< Camellia cipher with 192-bit ECB mode. */ + MBEDTLS_CIPHER_CAMELLIA_256_ECB, /**< Camellia cipher with 256-bit ECB mode. */ + MBEDTLS_CIPHER_CAMELLIA_128_CBC, /**< Camellia cipher with 128-bit CBC mode. */ + MBEDTLS_CIPHER_CAMELLIA_192_CBC, /**< Camellia cipher with 192-bit CBC mode. */ + MBEDTLS_CIPHER_CAMELLIA_256_CBC, /**< Camellia cipher with 256-bit CBC mode. */ + MBEDTLS_CIPHER_CAMELLIA_128_CFB128, /**< Camellia cipher with 128-bit CFB128 mode. */ + MBEDTLS_CIPHER_CAMELLIA_192_CFB128, /**< Camellia cipher with 192-bit CFB128 mode. */ + MBEDTLS_CIPHER_CAMELLIA_256_CFB128, /**< Camellia cipher with 256-bit CFB128 mode. */ + MBEDTLS_CIPHER_CAMELLIA_128_CTR, /**< Camellia cipher with 128-bit CTR mode. */ + MBEDTLS_CIPHER_CAMELLIA_192_CTR, /**< Camellia cipher with 192-bit CTR mode. */ + MBEDTLS_CIPHER_CAMELLIA_256_CTR, /**< Camellia cipher with 256-bit CTR mode. */ + MBEDTLS_CIPHER_CAMELLIA_128_GCM, /**< Camellia cipher with 128-bit GCM mode. */ + MBEDTLS_CIPHER_CAMELLIA_192_GCM, /**< Camellia cipher with 192-bit GCM mode. */ + MBEDTLS_CIPHER_CAMELLIA_256_GCM, /**< Camellia cipher with 256-bit GCM mode. */ + MBEDTLS_CIPHER_DES_ECB, /**< DES cipher with ECB mode. */ + MBEDTLS_CIPHER_DES_CBC, /**< DES cipher with CBC mode. */ + MBEDTLS_CIPHER_DES_EDE_ECB, /**< DES cipher with EDE ECB mode. */ + MBEDTLS_CIPHER_DES_EDE_CBC, /**< DES cipher with EDE CBC mode. */ + MBEDTLS_CIPHER_DES_EDE3_ECB, /**< DES cipher with EDE3 ECB mode. */ + MBEDTLS_CIPHER_DES_EDE3_CBC, /**< DES cipher with EDE3 CBC mode. */ + MBEDTLS_CIPHER_BLOWFISH_ECB, /**< Blowfish cipher with ECB mode. */ + MBEDTLS_CIPHER_BLOWFISH_CBC, /**< Blowfish cipher with CBC mode. */ + MBEDTLS_CIPHER_BLOWFISH_CFB64, /**< Blowfish cipher with CFB64 mode. */ + MBEDTLS_CIPHER_BLOWFISH_CTR, /**< Blowfish cipher with CTR mode. */ + MBEDTLS_CIPHER_ARC4_128, /**< RC4 cipher with 128-bit mode. */ + MBEDTLS_CIPHER_AES_128_CCM, /**< AES cipher with 128-bit CCM mode. */ + MBEDTLS_CIPHER_AES_192_CCM, /**< AES cipher with 192-bit CCM mode. */ + MBEDTLS_CIPHER_AES_256_CCM, /**< AES cipher with 256-bit CCM mode. */ + MBEDTLS_CIPHER_CAMELLIA_128_CCM, /**< Camellia cipher with 128-bit CCM mode. */ + MBEDTLS_CIPHER_CAMELLIA_192_CCM, /**< Camellia cipher with 192-bit CCM mode. */ + MBEDTLS_CIPHER_CAMELLIA_256_CCM, /**< Camellia cipher with 256-bit CCM mode. */ + MBEDTLS_CIPHER_ARIA_128_ECB, /**< Aria cipher with 128-bit key and ECB mode. */ + MBEDTLS_CIPHER_ARIA_192_ECB, /**< Aria cipher with 192-bit key and ECB mode. */ + MBEDTLS_CIPHER_ARIA_256_ECB, /**< Aria cipher with 256-bit key and ECB mode. */ + MBEDTLS_CIPHER_ARIA_128_CBC, /**< Aria cipher with 128-bit key and CBC mode. */ + MBEDTLS_CIPHER_ARIA_192_CBC, /**< Aria cipher with 192-bit key and CBC mode. */ + MBEDTLS_CIPHER_ARIA_256_CBC, /**< Aria cipher with 256-bit key and CBC mode. */ + MBEDTLS_CIPHER_ARIA_128_CFB128, /**< Aria cipher with 128-bit key and CFB-128 mode. */ + MBEDTLS_CIPHER_ARIA_192_CFB128, /**< Aria cipher with 192-bit key and CFB-128 mode. */ + MBEDTLS_CIPHER_ARIA_256_CFB128, /**< Aria cipher with 256-bit key and CFB-128 mode. */ + MBEDTLS_CIPHER_ARIA_128_CTR, /**< Aria cipher with 128-bit key and CTR mode. */ + MBEDTLS_CIPHER_ARIA_192_CTR, /**< Aria cipher with 192-bit key and CTR mode. */ + MBEDTLS_CIPHER_ARIA_256_CTR, /**< Aria cipher with 256-bit key and CTR mode. */ + MBEDTLS_CIPHER_ARIA_128_GCM, /**< Aria cipher with 128-bit key and GCM mode. */ + MBEDTLS_CIPHER_ARIA_192_GCM, /**< Aria cipher with 192-bit key and GCM mode. */ + MBEDTLS_CIPHER_ARIA_256_GCM, /**< Aria cipher with 256-bit key and GCM mode. */ + MBEDTLS_CIPHER_ARIA_128_CCM, /**< Aria cipher with 128-bit key and CCM mode. */ + MBEDTLS_CIPHER_ARIA_192_CCM, /**< Aria cipher with 192-bit key and CCM mode. */ + MBEDTLS_CIPHER_ARIA_256_CCM, /**< Aria cipher with 256-bit key and CCM mode. */ + MBEDTLS_CIPHER_AES_128_OFB, /**< AES 128-bit cipher in OFB mode. */ + MBEDTLS_CIPHER_AES_192_OFB, /**< AES 192-bit cipher in OFB mode. */ + MBEDTLS_CIPHER_AES_256_OFB, /**< AES 256-bit cipher in OFB mode. */ + MBEDTLS_CIPHER_AES_128_XTS, /**< AES 128-bit cipher in XTS block mode. */ + MBEDTLS_CIPHER_AES_256_XTS, /**< AES 256-bit cipher in XTS block mode. */ + MBEDTLS_CIPHER_CHACHA20, /**< ChaCha20 stream cipher. */ + MBEDTLS_CIPHER_CHACHA20_POLY1305, /**< ChaCha20-Poly1305 AEAD cipher. */ } mbedtls_cipher_type_t; /** Supported cipher modes. */ typedef enum { - MBEDTLS_MODE_NONE = 0, - MBEDTLS_MODE_ECB, - MBEDTLS_MODE_CBC, - MBEDTLS_MODE_CFB, - MBEDTLS_MODE_OFB, /* Unused! */ - MBEDTLS_MODE_CTR, - MBEDTLS_MODE_GCM, - MBEDTLS_MODE_STREAM, - MBEDTLS_MODE_CCM, + MBEDTLS_MODE_NONE = 0, /**< None. */ + MBEDTLS_MODE_ECB, /**< The ECB cipher mode. */ + MBEDTLS_MODE_CBC, /**< The CBC cipher mode. */ + MBEDTLS_MODE_CFB, /**< The CFB cipher mode. */ + MBEDTLS_MODE_OFB, /**< The OFB cipher mode. */ + MBEDTLS_MODE_CTR, /**< The CTR cipher mode. */ + MBEDTLS_MODE_GCM, /**< The GCM cipher mode. */ + MBEDTLS_MODE_STREAM, /**< The stream cipher mode. */ + MBEDTLS_MODE_CCM, /**< The CCM cipher mode. */ + MBEDTLS_MODE_XTS, /**< The XTS cipher mode. */ + MBEDTLS_MODE_CHACHAPOLY, /**< The ChaCha-Poly cipher mode. */ } mbedtls_cipher_mode_t; /** Supported cipher padding types. */ @@ -163,8 +194,8 @@ typedef enum { MBEDTLS_PADDING_PKCS7 = 0, /**< PKCS7 padding (default). */ MBEDTLS_PADDING_ONE_AND_ZEROS, /**< ISO/IEC 7816-4 padding. */ MBEDTLS_PADDING_ZEROS_AND_LEN, /**< ANSI X.923 padding. */ - MBEDTLS_PADDING_ZEROS, /**< zero padding (not reversible). */ - MBEDTLS_PADDING_NONE, /**< never pad (full blocks only). */ + MBEDTLS_PADDING_ZEROS, /**< Zero padding (not reversible). */ + MBEDTLS_PADDING_NONE, /**< Never pad (full blocks only). */ } mbedtls_cipher_padding_t; /** Type of operation. */ @@ -228,7 +259,10 @@ typedef struct { */ unsigned int iv_size; - /** Flags to set. For example, if the cipher supports variable IV sizes or variable key sizes. */ + /** Bitflag comprised of MBEDTLS_CIPHER_VARIABLE_IV_LEN and + * MBEDTLS_CIPHER_VARIABLE_KEY_LEN indicating whether the + * cipher supports variable IV or variable key sizes, respectively. + */ int flags; /** The block size, in Bytes. */ @@ -268,7 +302,8 @@ typedef struct { /** Number of Bytes that have not been processed yet. */ size_t unprocessed_len; - /** Current IV or NONCE_COUNTER for CTR-mode. */ + /** Current IV or NONCE_COUNTER for CTR-mode, data unit (or sector) number + * for XTS-mode. */ unsigned char iv[MBEDTLS_MAX_IV_LENGTH]; /** IV size in Bytes, for ciphers with variable-length IVs. */ @@ -299,7 +334,8 @@ const int *mbedtls_cipher_list( void ); * \param cipher_name Name of the cipher to search for. * * \return The cipher information structure associated with the - * given \p cipher_name, or NULL if not found. + * given \p cipher_name. + * \return NULL if the associated cipher information is not found. */ const mbedtls_cipher_info_t *mbedtls_cipher_info_from_string( const char *cipher_name ); @@ -310,7 +346,8 @@ const mbedtls_cipher_info_t *mbedtls_cipher_info_from_string( const char *cipher * \param cipher_type Type of the cipher to search for. * * \return The cipher information structure associated with the - * given \p cipher_type, or NULL if not found. + * given \p cipher_type. + * \return NULL if the associated cipher information is not found. */ const mbedtls_cipher_info_t *mbedtls_cipher_info_from_type( const mbedtls_cipher_type_t cipher_type ); @@ -325,7 +362,8 @@ const mbedtls_cipher_info_t *mbedtls_cipher_info_from_type( const mbedtls_cipher * \param mode The cipher mode. For example, #MBEDTLS_MODE_CBC. * * \return The cipher information structure associated with the - * given \p cipher_id, or NULL if not found. + * given \p cipher_id. + * \return NULL if the associated cipher information is not found. */ const mbedtls_cipher_info_t *mbedtls_cipher_info_from_values( const mbedtls_cipher_id_t cipher_id, int key_bitlen, @@ -352,10 +390,11 @@ void mbedtls_cipher_free( mbedtls_cipher_context_t *ctx ); * \param ctx The context to initialize. May not be NULL. * \param cipher_info The cipher to use. * - * \return \c 0 on success, - * #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on parameter failure, - * #MBEDTLS_ERR_CIPHER_ALLOC_FAILED if allocation of the - * cipher-specific context failed. + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on + * parameter-verification failure. + * \return #MBEDTLS_ERR_CIPHER_ALLOC_FAILED if allocation of the + * cipher-specific context fails. * * \internal Currently, the function also clears the structure. * In future versions, the caller will be required to call @@ -368,8 +407,8 @@ int mbedtls_cipher_setup( mbedtls_cipher_context_t *ctx, const mbedtls_cipher_in * * \param ctx The context of the cipher. Must be initialized. * - * \return The size of the blocks of the cipher, or zero if \p ctx - * has not been initialized. + * \return The size of the blocks of the cipher. + * \return 0 if \p ctx has not been initialized. */ static inline unsigned int mbedtls_cipher_get_block_size( const mbedtls_cipher_context_t *ctx ) { @@ -385,8 +424,8 @@ static inline unsigned int mbedtls_cipher_get_block_size( const mbedtls_cipher_c * * \param ctx The context of the cipher. Must be initialized. * - * \return The mode of operation, or #MBEDTLS_MODE_NONE if - * \p ctx has not been initialized. + * \return The mode of operation. + * \return #MBEDTLS_MODE_NONE if \p ctx has not been initialized. */ static inline mbedtls_cipher_mode_t mbedtls_cipher_get_cipher_mode( const mbedtls_cipher_context_t *ctx ) { @@ -402,9 +441,9 @@ static inline mbedtls_cipher_mode_t mbedtls_cipher_get_cipher_mode( const mbedtl * * \param ctx The context of the cipher. Must be initialized. * - * \return <ul><li>If no IV has been set: the recommended IV size. - * 0 for ciphers not using IV or nonce.</li> - * <li>If IV has already been set: the actual size.</li></ul> + * \return The recommended IV size if no IV has been set. + * \return \c 0 for ciphers not using an IV or a nonce. + * \return The actual size if an IV has been set. */ static inline int mbedtls_cipher_get_iv_size( const mbedtls_cipher_context_t *ctx ) { @@ -422,8 +461,8 @@ static inline int mbedtls_cipher_get_iv_size( const mbedtls_cipher_context_t *ct * * \param ctx The context of the cipher. Must be initialized. * - * \return The type of the cipher, or #MBEDTLS_CIPHER_NONE if - * \p ctx has not been initialized. + * \return The type of the cipher. + * \return #MBEDTLS_CIPHER_NONE if \p ctx has not been initialized. */ static inline mbedtls_cipher_type_t mbedtls_cipher_get_type( const mbedtls_cipher_context_t *ctx ) { @@ -439,8 +478,8 @@ static inline mbedtls_cipher_type_t mbedtls_cipher_get_type( const mbedtls_ciphe * * \param ctx The context of the cipher. Must be initialized. * - * \return The name of the cipher, or NULL if \p ctx has not - * been not initialized. + * \return The name of the cipher. + * \return NULL if \p ctx has not been not initialized. */ static inline const char *mbedtls_cipher_get_name( const mbedtls_cipher_context_t *ctx ) { @@ -455,8 +494,8 @@ static inline const char *mbedtls_cipher_get_name( const mbedtls_cipher_context_ * * \param ctx The context of the cipher. Must be initialized. * - * \return The key length of the cipher in bits, or - * #MBEDTLS_KEY_LENGTH_NONE if ctx \p has not been + * \return The key length of the cipher in bits. + * \return #MBEDTLS_KEY_LENGTH_NONE if ctx \p has not been * initialized. */ static inline int mbedtls_cipher_get_key_bitlen( const mbedtls_cipher_context_t *ctx ) @@ -472,9 +511,8 @@ static inline int mbedtls_cipher_get_key_bitlen( const mbedtls_cipher_context_t * * \param ctx The context of the cipher. Must be initialized. * - * \return The type of operation: #MBEDTLS_ENCRYPT or - * #MBEDTLS_DECRYPT, or #MBEDTLS_OPERATION_NONE if \p ctx - * has not been initialized. + * \return The type of operation: #MBEDTLS_ENCRYPT or #MBEDTLS_DECRYPT. + * \return #MBEDTLS_OPERATION_NONE if \p ctx has not been initialized. */ static inline mbedtls_operation_t mbedtls_cipher_get_operation( const mbedtls_cipher_context_t *ctx ) { @@ -495,9 +533,10 @@ static inline mbedtls_operation_t mbedtls_cipher_get_operation( const mbedtls_ci * \param operation The operation that the key will be used for: * #MBEDTLS_ENCRYPT or #MBEDTLS_DECRYPT. * - * \returns \c 0 on success, #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA if - * parameter verification fails, or a cipher-specific - * error code. + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on + * parameter-verification failure. + * \return A cipher-specific error code on failure. */ int mbedtls_cipher_setkey( mbedtls_cipher_context_t *ctx, const unsigned char *key, int key_bitlen, const mbedtls_operation_t operation ); @@ -512,9 +551,10 @@ int mbedtls_cipher_setkey( mbedtls_cipher_context_t *ctx, const unsigned char *k * \param ctx The generic cipher context. * \param mode The padding mode. * - * \returns \c 0 on success, #MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE - * if the selected padding mode is not supported, or - * #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA if the cipher mode + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE + * if the selected padding mode is not supported. + * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA if the cipher mode * does not support padding. */ int mbedtls_cipher_set_padding_mode( mbedtls_cipher_context_t *ctx, mbedtls_cipher_padding_t mode ); @@ -524,15 +564,17 @@ int mbedtls_cipher_set_padding_mode( mbedtls_cipher_context_t *ctx, mbedtls_ciph * \brief This function sets the initialization vector (IV) * or nonce. * + * \note Some ciphers do not use IVs nor nonce. For these + * ciphers, this function has no effect. + * * \param ctx The generic cipher context. * \param iv The IV to use, or NONCE_COUNTER for CTR-mode ciphers. * \param iv_len The IV length for ciphers with variable-size IV. * This parameter is discarded by ciphers with fixed-size IV. * - * \returns \c 0 on success, or #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA - * - * \note Some ciphers do not use IVs nor nonce. For these - * ciphers, this function has no effect. + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on + * parameter-verification failure. */ int mbedtls_cipher_set_iv( mbedtls_cipher_context_t *ctx, const unsigned char *iv, size_t iv_len ); @@ -542,26 +584,28 @@ int mbedtls_cipher_set_iv( mbedtls_cipher_context_t *ctx, * * \param ctx The generic cipher context. * - * \returns \c 0 on success, #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA - * if parameter verification fails. + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on + * parameter-verification failure. */ int mbedtls_cipher_reset( mbedtls_cipher_context_t *ctx ); -#if defined(MBEDTLS_GCM_C) +#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CHACHAPOLY_C) /** * \brief This function adds additional data for AEAD ciphers. - * Only supported with GCM. Must be called - * exactly once, after mbedtls_cipher_reset(). + * Currently supported with GCM and ChaCha20+Poly1305. + * Must be called exactly once, after mbedtls_cipher_reset(). * * \param ctx The generic cipher context. * \param ad The additional data to use. * \param ad_len the Length of \p ad. * - * \return \c 0 on success, or a specific error code on failure. + * \return \c 0 on success. + * \return A specific error code on failure. */ int mbedtls_cipher_update_ad( mbedtls_cipher_context_t *ctx, const unsigned char *ad, size_t ad_len ); -#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_GCM_C || MBEDTLS_CHACHAPOLY_C */ /** * \brief The generic cipher update function. It encrypts or @@ -573,6 +617,11 @@ int mbedtls_cipher_update_ad( mbedtls_cipher_context_t *ctx, * Exception: For MBEDTLS_MODE_ECB, expects a single block * in size. For example, 16 Bytes for AES. * + * \note If the underlying cipher is used in GCM mode, all calls + * to this function, except for the last one before + * mbedtls_cipher_finish(), must have \p ilen as a + * multiple of the block size of the cipher. + * * \param ctx The generic cipher context. * \param input The buffer holding the input data. * \param ilen The length of the input data. @@ -582,16 +631,12 @@ int mbedtls_cipher_update_ad( mbedtls_cipher_context_t *ctx, * \param olen The length of the output data, to be updated with the * actual number of Bytes written. * - * \returns \c 0 on success, #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA if - * parameter verification fails, - * #MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE on an - * unsupported mode for a cipher, or a cipher-specific - * error code. - * - * \note If the underlying cipher is GCM, all calls to this - * function, except the last one before - * mbedtls_cipher_finish(). Must have \p ilen as a - * multiple of the block_size. + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on + * parameter-verification failure. + * \return #MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE on an + * unsupported mode for a cipher. + * \return A cipher-specific error code on failure. */ int mbedtls_cipher_update( mbedtls_cipher_context_t *ctx, const unsigned char *input, size_t ilen, unsigned char *output, size_t *olen ); @@ -606,46 +651,49 @@ int mbedtls_cipher_update( mbedtls_cipher_context_t *ctx, const unsigned char *i * \param output The buffer to write data to. Needs block_size available. * \param olen The length of the data written to the \p output buffer. * - * \returns \c 0 on success, #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA if - * parameter verification fails, - * #MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED if decryption - * expected a full block but was not provided one, - * #MBEDTLS_ERR_CIPHER_INVALID_PADDING on invalid padding - * while decrypting, or a cipher-specific error code - * on failure for any other reason. + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on + * parameter-verification failure. + * \return #MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED on decryption + * expecting a full block but not receiving one. + * \return #MBEDTLS_ERR_CIPHER_INVALID_PADDING on invalid padding + * while decrypting. + * \return A cipher-specific error code on failure. */ int mbedtls_cipher_finish( mbedtls_cipher_context_t *ctx, unsigned char *output, size_t *olen ); -#if defined(MBEDTLS_GCM_C) +#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CHACHAPOLY_C) /** * \brief This function writes a tag for AEAD ciphers. - * Only supported with GCM. + * Currently supported with GCM and ChaCha20+Poly1305. * Must be called after mbedtls_cipher_finish(). * * \param ctx The generic cipher context. * \param tag The buffer to write the tag to. * \param tag_len The length of the tag to write. * - * \return \c 0 on success, or a specific error code on failure. + * \return \c 0 on success. + * \return A specific error code on failure. */ int mbedtls_cipher_write_tag( mbedtls_cipher_context_t *ctx, unsigned char *tag, size_t tag_len ); /** * \brief This function checks the tag for AEAD ciphers. - * Only supported with GCM. + * Currently supported with GCM and ChaCha20+Poly1305. * Must be called after mbedtls_cipher_finish(). * * \param ctx The generic cipher context. * \param tag The buffer holding the tag. * \param tag_len The length of the tag to check. * - * \return \c 0 on success, or a specific error code on failure. + * \return \c 0 on success. + * \return A specific error code on failure. */ int mbedtls_cipher_check_tag( mbedtls_cipher_context_t *ctx, const unsigned char *tag, size_t tag_len ); -#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_GCM_C || MBEDTLS_CHACHAPOLY_C */ /** * \brief The generic all-in-one encryption/decryption function, @@ -667,13 +715,14 @@ int mbedtls_cipher_check_tag( mbedtls_cipher_context_t *ctx, * \note Some ciphers do not use IVs nor nonce. For these * ciphers, use \p iv = NULL and \p iv_len = 0. * - * \returns \c 0 on success, or - * #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA, or - * #MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED if decryption - * expected a full block but was not provided one, or - * #MBEDTLS_ERR_CIPHER_INVALID_PADDING on invalid padding - * while decrypting, or a cipher-specific error code on - * failure for any other reason. + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on + * parameter-verification failure. + * \return #MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED on decryption + * expecting a full block but not receiving one. + * \return #MBEDTLS_ERR_CIPHER_INVALID_PADDING on invalid padding + * while decrypting. + * \return A cipher-specific error code on failure. */ int mbedtls_cipher_crypt( mbedtls_cipher_context_t *ctx, const unsigned char *iv, size_t iv_len, @@ -699,9 +748,10 @@ int mbedtls_cipher_crypt( mbedtls_cipher_context_t *ctx, * \param tag The buffer for the authentication tag. * \param tag_len The desired length of the authentication tag. * - * \returns \c 0 on success, or - * #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA, or - * a cipher-specific error code. + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on + * parameter-verification failure. + * \return A cipher-specific error code on failure. */ int mbedtls_cipher_auth_encrypt( mbedtls_cipher_context_t *ctx, const unsigned char *iv, size_t iv_len, @@ -713,6 +763,10 @@ int mbedtls_cipher_auth_encrypt( mbedtls_cipher_context_t *ctx, /** * \brief The generic autenticated decryption (AEAD) function. * + * \note If the data is not authentic, then the output buffer + * is zeroed out to prevent the unauthentic plaintext being + * used, making this interface safer. + * * \param ctx The generic cipher context. * \param iv The IV to use, or NONCE_COUNTER for CTR-mode ciphers. * \param iv_len The IV length for ciphers with variable-size IV. @@ -728,14 +782,11 @@ int mbedtls_cipher_auth_encrypt( mbedtls_cipher_context_t *ctx, * \param tag The buffer holding the authentication tag. * \param tag_len The length of the authentication tag. * - * \returns \c 0 on success, or - * #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA, or - * #MBEDTLS_ERR_CIPHER_AUTH_FAILED if data is not authentic, - * or a cipher-specific error code on failure for any other reason. - * - * \note If the data is not authentic, then the output buffer - * is zeroed out to prevent the unauthentic plaintext being - * used, making this interface safer. + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on + * parameter-verification failure. + * \return #MBEDTLS_ERR_CIPHER_AUTH_FAILED if data is not authentic. + * \return A cipher-specific error code on failure. */ int mbedtls_cipher_auth_decrypt( mbedtls_cipher_context_t *ctx, const unsigned char *iv, size_t iv_len, diff --git a/thirdparty/mbedtls/include/mbedtls/cipher_internal.h b/thirdparty/mbedtls/include/mbedtls/cipher_internal.h index 969ff9ccb8..c6def0bef7 100644 --- a/thirdparty/mbedtls/include/mbedtls/cipher_internal.h +++ b/thirdparty/mbedtls/include/mbedtls/cipher_internal.h @@ -64,6 +64,14 @@ struct mbedtls_cipher_base_t unsigned char *output ); #endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + /** Encrypt using OFB (Full length) */ + int (*ofb_func)( void *ctx, size_t length, size_t *iv_off, + unsigned char *iv, + const unsigned char *input, + unsigned char *output ); +#endif + #if defined(MBEDTLS_CIPHER_MODE_CTR) /** Encrypt using CTR */ int (*ctr_func)( void *ctx, size_t length, size_t *nc_off, @@ -71,6 +79,13 @@ struct mbedtls_cipher_base_t const unsigned char *input, unsigned char *output ); #endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + /** Encrypt or decrypt using XTS. */ + int (*xts_func)( void *ctx, mbedtls_operation_t mode, size_t length, + const unsigned char data_unit[16], + const unsigned char *input, unsigned char *output ); +#endif + #if defined(MBEDTLS_CIPHER_MODE_STREAM) /** Encrypt using STREAM */ int (*stream_func)( void *ctx, size_t length, diff --git a/thirdparty/mbedtls/include/mbedtls/cmac.h b/thirdparty/mbedtls/include/mbedtls/cmac.h index 628c9daba2..a4fd552565 100644 --- a/thirdparty/mbedtls/include/mbedtls/cmac.h +++ b/thirdparty/mbedtls/include/mbedtls/cmac.h @@ -1,8 +1,10 @@ /** * \file cmac.h * - * \brief The Cipher-based Message Authentication Code (CMAC) Mode for - * Authentication. + * \brief This file contains CMAC definitions and functions. + * + * The Cipher-based Message Authentication Code (CMAC) Mode for + * Authentication is defined in <em>RFC-4493: The AES-CMAC Algorithm</em>. */ /* * Copyright (C) 2015-2018, Arm Limited (or its affiliates), All Rights Reserved @@ -26,7 +28,7 @@ #ifndef MBEDTLS_CMAC_H #define MBEDTLS_CMAC_H -#include "mbedtls/cipher.h" +#include "cipher.h" #ifdef __cplusplus extern "C" { @@ -38,9 +40,9 @@ extern "C" { #define MBEDTLS_DES3_BLOCK_SIZE 8 #if defined(MBEDTLS_AES_C) -#define MBEDTLS_CIPHER_BLKSIZE_MAX 16 /* The longest block used by CMAC is that of AES. */ +#define MBEDTLS_CIPHER_BLKSIZE_MAX 16 /**< The longest block used by CMAC is that of AES. */ #else -#define MBEDTLS_CIPHER_BLKSIZE_MAX 8 /* The longest block used by CMAC is that of 3DES. */ +#define MBEDTLS_CIPHER_BLKSIZE_MAX 8 /**< The longest block used by CMAC is that of 3DES. */ #endif #if !defined(MBEDTLS_CMAC_ALT) @@ -61,22 +63,25 @@ struct mbedtls_cmac_context_t size_t unprocessed_len; }; +#else /* !MBEDTLS_CMAC_ALT */ +#include "cmac_alt.h" +#endif /* !MBEDTLS_CMAC_ALT */ + /** * \brief This function sets the CMAC key, and prepares to authenticate * the input data. * Must be called with an initialized cipher context. * * \param ctx The cipher context used for the CMAC operation, initialized - * as one of the following types:<ul> - * <li>MBEDTLS_CIPHER_AES_128_ECB</li> - * <li>MBEDTLS_CIPHER_AES_192_ECB</li> - * <li>MBEDTLS_CIPHER_AES_256_ECB</li> - * <li>MBEDTLS_CIPHER_DES_EDE3_ECB</li></ul> + * as one of the following types: MBEDTLS_CIPHER_AES_128_ECB, + * MBEDTLS_CIPHER_AES_192_ECB, MBEDTLS_CIPHER_AES_256_ECB, + * or MBEDTLS_CIPHER_DES_EDE3_ECB. * \param key The CMAC key. * \param keybits The length of the CMAC key in bits. * Must be supported by the cipher. * - * \return \c 0 on success, or a cipher-specific error code. + * \return \c 0 on success. + * \return A cipher-specific error code on failure. */ int mbedtls_cipher_cmac_starts( mbedtls_cipher_context_t *ctx, const unsigned char *key, size_t keybits ); @@ -93,8 +98,9 @@ int mbedtls_cipher_cmac_starts( mbedtls_cipher_context_t *ctx, * \param input The buffer holding the input data. * \param ilen The length of the input data. * - * \returns \c 0 on success, or #MBEDTLS_ERR_MD_BAD_INPUT_DATA - * if parameter verification fails. + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA + * if parameter verification fails. */ int mbedtls_cipher_cmac_update( mbedtls_cipher_context_t *ctx, const unsigned char *input, size_t ilen ); @@ -110,7 +116,8 @@ int mbedtls_cipher_cmac_update( mbedtls_cipher_context_t *ctx, * \param ctx The cipher context used for the CMAC operation. * \param output The output buffer for the CMAC checksum result. * - * \returns \c 0 on success, or #MBEDTLS_ERR_MD_BAD_INPUT_DATA + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA * if parameter verification fails. */ int mbedtls_cipher_cmac_finish( mbedtls_cipher_context_t *ctx, @@ -126,7 +133,8 @@ int mbedtls_cipher_cmac_finish( mbedtls_cipher_context_t *ctx, * * \param ctx The cipher context used for the CMAC operation. * - * \returns \c 0 on success, or #MBEDTLS_ERR_MD_BAD_INPUT_DATA + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA * if parameter verification fails. */ int mbedtls_cipher_cmac_reset( mbedtls_cipher_context_t *ctx ); @@ -149,7 +157,8 @@ int mbedtls_cipher_cmac_reset( mbedtls_cipher_context_t *ctx ); * \param ilen The length of the input data. * \param output The buffer for the generic CMAC result. * - * \returns \c 0 on success, or #MBEDTLS_ERR_MD_BAD_INPUT_DATA + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA * if parameter verification fails. */ int mbedtls_cipher_cmac( const mbedtls_cipher_info_t *cipher_info, @@ -180,23 +189,12 @@ int mbedtls_aes_cmac_prf_128( const unsigned char *key, size_t key_len, unsigned char output[16] ); #endif /* MBEDTLS_AES_C */ -#ifdef __cplusplus -} -#endif - -#else /* !MBEDTLS_CMAC_ALT */ -#include "cmac_alt.h" -#endif /* !MBEDTLS_CMAC_ALT */ - -#ifdef __cplusplus -extern "C" { -#endif - #if defined(MBEDTLS_SELF_TEST) && ( defined(MBEDTLS_AES_C) || defined(MBEDTLS_DES_C) ) /** * \brief The CMAC checkup routine. * - * \return \c 0 on success, or \c 1 on failure. + * \return \c 0 on success. + * \return \c 1 on failure. */ int mbedtls_cmac_self_test( int verbose ); #endif /* MBEDTLS_SELF_TEST && ( MBEDTLS_AES_C || MBEDTLS_DES_C ) */ diff --git a/thirdparty/mbedtls/include/mbedtls/compat-1.3.h b/thirdparty/mbedtls/include/mbedtls/compat-1.3.h index 600a0f154c..213b691403 100644 --- a/thirdparty/mbedtls/include/mbedtls/compat-1.3.h +++ b/thirdparty/mbedtls/include/mbedtls/compat-1.3.h @@ -1378,7 +1378,8 @@ #define SSL_ANTI_REPLAY_ENABLED MBEDTLS_SSL_ANTI_REPLAY_ENABLED #define SSL_ARC4_DISABLED MBEDTLS_SSL_ARC4_DISABLED #define SSL_ARC4_ENABLED MBEDTLS_SSL_ARC4_ENABLED -#define SSL_BUFFER_LEN MBEDTLS_SSL_BUFFER_LEN +#define SSL_BUFFER_LEN ( ( ( MBEDTLS_SSL_IN_BUFFER_LEN ) < ( MBEDTLS_SSL_OUT_BUFFER_LEN ) ) \ + ? ( MBEDTLS_SSL_IN_BUFFER_LEN ) : ( MBEDTLS_SSL_OUT_BUFFER_LEN ) ) #define SSL_CACHE_DEFAULT_MAX_ENTRIES MBEDTLS_SSL_CACHE_DEFAULT_MAX_ENTRIES #define SSL_CACHE_DEFAULT_TIMEOUT MBEDTLS_SSL_CACHE_DEFAULT_TIMEOUT #define SSL_CBC_RECORD_SPLITTING_DISABLED MBEDTLS_SSL_CBC_RECORD_SPLITTING_DISABLED diff --git a/thirdparty/mbedtls/include/mbedtls/config.h b/thirdparty/mbedtls/include/mbedtls/config.h index b5905ef9d0..70820be56f 100644 --- a/thirdparty/mbedtls/include/mbedtls/config.h +++ b/thirdparty/mbedtls/include/mbedtls/config.h @@ -8,7 +8,7 @@ * memory footprint. */ /* - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Copyright (C) 2006-2018, ARM Limited, All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); you may @@ -48,10 +48,14 @@ * Requires support for asm() in compiler. * * Used in: + * library/aria.c * library/timing.c - * library/padlock.c * include/mbedtls/bn_mul.h * + * Required by: + * MBEDTLS_AESNI_C + * MBEDTLS_PADLOCK_C + * * Comment to disable the use of assembly code. */ #define MBEDTLS_HAVE_ASM @@ -85,6 +89,28 @@ //#define MBEDTLS_NO_UDBL_DIVISION /** + * \def MBEDTLS_NO_64BIT_MULTIPLICATION + * + * The platform lacks support for 32x32 -> 64-bit multiplication. + * + * Used in: + * library/poly1305.c + * + * Some parts of the library may use multiplication of two unsigned 32-bit + * operands with a 64-bit result in order to speed up computations. On some + * platforms, this is not available in hardware and has to be implemented in + * software, usually in a library provided by the toolchain. + * + * Sometimes it is not desirable to have to link to that library. This option + * removes the dependency of that library on platforms that lack a hardware + * 64-bit multiplier by embedding a software implementation in Mbed TLS. + * + * Note that depending on the compiler, this may decrease performance compared + * to using the library function provided by the toolchain. + */ +//#define MBEDTLS_NO_64BIT_MULTIPLICATION + +/** * \def MBEDTLS_HAVE_SSE2 * * CPU supports SSE2 instruction set. @@ -271,23 +297,29 @@ */ //#define MBEDTLS_AES_ALT //#define MBEDTLS_ARC4_ALT +//#define MBEDTLS_ARIA_ALT //#define MBEDTLS_BLOWFISH_ALT //#define MBEDTLS_CAMELLIA_ALT //#define MBEDTLS_CCM_ALT +//#define MBEDTLS_CHACHA20_ALT +//#define MBEDTLS_CHACHAPOLY_ALT //#define MBEDTLS_CMAC_ALT //#define MBEDTLS_DES_ALT //#define MBEDTLS_DHM_ALT //#define MBEDTLS_ECJPAKE_ALT //#define MBEDTLS_GCM_ALT +//#define MBEDTLS_NIST_KW_ALT //#define MBEDTLS_MD2_ALT //#define MBEDTLS_MD4_ALT //#define MBEDTLS_MD5_ALT +//#define MBEDTLS_POLY1305_ALT //#define MBEDTLS_RIPEMD160_ALT //#define MBEDTLS_RSA_ALT //#define MBEDTLS_SHA1_ALT //#define MBEDTLS_SHA256_ALT //#define MBEDTLS_SHA512_ALT //#define MBEDTLS_XTEA_ALT + /* * When replacing the elliptic curve module, pleace consider, that it is * implemented with two .c files: @@ -440,13 +472,46 @@ /** * \def MBEDTLS_AES_ROM_TABLES * - * Store the AES tables in ROM. + * Use precomputed AES tables stored in ROM. + * + * Uncomment this macro to use precomputed AES tables stored in ROM. + * Comment this macro to generate AES tables in RAM at runtime. + * + * Tradeoff: Using precomputed ROM tables reduces RAM usage by ~8kb + * (or ~2kb if \c MBEDTLS_AES_FEWER_TABLES is used) and reduces the + * initialization time before the first AES operation can be performed. + * It comes at the cost of additional ~8kb ROM use (resp. ~2kb if \c + * MBEDTLS_AES_FEWER_TABLES below is used), and potentially degraded + * performance if ROM access is slower than RAM access. + * + * This option is independent of \c MBEDTLS_AES_FEWER_TABLES. * - * Uncomment this macro to store the AES tables in ROM. */ //#define MBEDTLS_AES_ROM_TABLES /** + * \def MBEDTLS_AES_FEWER_TABLES + * + * Use less ROM/RAM for AES tables. + * + * Uncommenting this macro omits 75% of the AES tables from + * ROM / RAM (depending on the value of \c MBEDTLS_AES_ROM_TABLES) + * by computing their values on the fly during operations + * (the tables are entry-wise rotations of one another). + * + * Tradeoff: Uncommenting this reduces the RAM / ROM footprint + * by ~6kb but at the cost of more arithmetic operations during + * runtime. Specifically, one has to compare 4 accesses within + * different tables to 4 accesses with additional arithmetic + * operations within the same table. The performance gain/loss + * depends on the system and memory details. + * + * This option is independent of \c MBEDTLS_AES_ROM_TABLES. + * + */ +//#define MBEDTLS_AES_FEWER_TABLES + +/** * \def MBEDTLS_CAMELLIA_SMALL_MEMORY * * Use less ROM for the Camellia implementation (saves about 768 bytes). @@ -477,6 +542,20 @@ #define MBEDTLS_CIPHER_MODE_CTR /** + * \def MBEDTLS_CIPHER_MODE_OFB + * + * Enable Output Feedback mode (OFB) for symmetric ciphers. + */ +#define MBEDTLS_CIPHER_MODE_OFB + +/** + * \def MBEDTLS_CIPHER_MODE_XTS + * + * Enable Xor-encrypt-xor with ciphertext stealing mode (XTS) for AES. + */ +#define MBEDTLS_CIPHER_MODE_XTS + +/** * \def MBEDTLS_CIPHER_NULL_CIPHER * * Enable NULL cipher. @@ -576,6 +655,7 @@ #define MBEDTLS_ECP_DP_BP384R1_ENABLED #define MBEDTLS_ECP_DP_BP512R1_ENABLED #define MBEDTLS_ECP_DP_CURVE25519_ENABLED +#define MBEDTLS_ECP_DP_CURVE448_ENABLED /** * \def MBEDTLS_ECP_NIST_OPTIM @@ -1095,6 +1175,17 @@ #define MBEDTLS_SSL_ALL_ALERT_MESSAGES /** + * \def MBEDTLS_SSL_ASYNC_PRIVATE + * + * Enable asynchronous external private key operations in SSL. This allows + * you to configure an SSL connection to call an external cryptographic + * module to perform private key operations instead of performing the + * operation inside the library. + * + */ +//#define MBEDTLS_SSL_ASYNC_PRIVATE + +/** * \def MBEDTLS_SSL_DEBUG_ALL * * Enable the debug messages in SSL module for all issues. @@ -1583,7 +1674,7 @@ * Enable the AES block cipher. * * Module: library/aes.c - * Caller: library/ssl_tls.c + * Caller: library/cipher.c * library/pem.c * library/ctr_drbg.c * @@ -1658,7 +1749,7 @@ * Enable the ARCFOUR stream cipher. * * Module: library/arc4.c - * Caller: library/ssl_tls.c + * Caller: library/cipher.c * * This module enables the following ciphersuites (if other requisites are * enabled as well): @@ -1752,7 +1843,7 @@ * Enable the Camellia block cipher. * * Module: library/camellia.c - * Caller: library/ssl_tls.c + * Caller: library/cipher.c * * This module enables the following ciphersuites (if other requisites are * enabled as well): @@ -1802,6 +1893,58 @@ #define MBEDTLS_CAMELLIA_C /** + * \def MBEDTLS_ARIA_C + * + * Enable the ARIA block cipher. + * + * Module: library/aria.c + * Caller: library/cipher.c + * + * This module enables the following ciphersuites (if other requisites are + * enabled as well): + * + * MBEDTLS_TLS_RSA_WITH_ARIA_128_CBC_SHA256 + * MBEDTLS_TLS_RSA_WITH_ARIA_256_CBC_SHA384 + * MBEDTLS_TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_256_CBC_SHA384 + * MBEDTLS_TLS_RSA_WITH_ARIA_128_GCM_SHA256 + * MBEDTLS_TLS_RSA_WITH_ARIA_256_GCM_SHA384 + * MBEDTLS_TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_256_GCM_SHA384 + * MBEDTLS_TLS_PSK_WITH_ARIA_128_CBC_SHA256 + * MBEDTLS_TLS_PSK_WITH_ARIA_256_CBC_SHA384 + * MBEDTLS_TLS_DHE_PSK_WITH_ARIA_128_CBC_SHA256 + * MBEDTLS_TLS_DHE_PSK_WITH_ARIA_256_CBC_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_ARIA_128_CBC_SHA256 + * MBEDTLS_TLS_RSA_PSK_WITH_ARIA_256_CBC_SHA384 + * MBEDTLS_TLS_PSK_WITH_ARIA_128_GCM_SHA256 + * MBEDTLS_TLS_PSK_WITH_ARIA_256_GCM_SHA384 + * MBEDTLS_TLS_DHE_PSK_WITH_ARIA_128_GCM_SHA256 + * MBEDTLS_TLS_DHE_PSK_WITH_ARIA_256_GCM_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256 + * MBEDTLS_TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_PSK_WITH_ARIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384 + */ +//#define MBEDTLS_ARIA_C + +/** * \def MBEDTLS_CCM_C * * Enable the Counter with CBC-MAC (CCM) mode for 128-bit block cipher. @@ -1828,6 +1971,26 @@ #define MBEDTLS_CERTS_C /** + * \def MBEDTLS_CHACHA20_C + * + * Enable the ChaCha20 stream cipher. + * + * Module: library/chacha20.c + */ +#define MBEDTLS_CHACHA20_C + +/** + * \def MBEDTLS_CHACHAPOLY_C + * + * Enable the ChaCha20-Poly1305 AEAD algorithm. + * + * Module: library/chachapoly.c + * + * This module requires: MBEDTLS_CHACHA20_C, MBEDTLS_POLY1305_C + */ +#define MBEDTLS_CHACHAPOLY_C + +/** * \def MBEDTLS_CIPHER_C * * Enable the generic cipher layer. @@ -1887,7 +2050,7 @@ * * Module: library/des.c * Caller: library/pem.c - * library/ssl_tls.c + * library/cipher.c * * This module enables the following ciphersuites (if other requisites are * enabled as well): @@ -2058,6 +2221,21 @@ //#define MBEDTLS_HAVEGE_C /** + * \def MBEDTLS_HKDF_C + * + * Enable the HKDF algorithm (RFC 5869). + * + * Module: library/hkdf.c + * Caller: + * + * Requires: MBEDTLS_MD_C + * + * This module adds support for the Hashed Message Authentication Code + * (HMAC)-based key derivation function (HKDF). + */ +#define MBEDTLS_HKDF_C + +/** * \def MBEDTLS_HMAC_DRBG_C * * Enable the HMAC_DRBG random generator. @@ -2072,6 +2250,19 @@ #define MBEDTLS_HMAC_DRBG_C /** + * \def MBEDTLS_NIST_KW_C + * + * Enable the Key Wrapping mode for 128-bit block ciphers, + * as defined in NIST SP 800-38F. Only KW and KWP modes + * are supported. At the moment, only AES is approved by NIST. + * + * Module: library/nist_kw.c + * + * Requires: MBEDTLS_AES_C and MBEDTLS_CIPHER_C + */ +//#define MBEDTLS_NIST_KW_C + +/** * \def MBEDTLS_MD_C * * Enable the generic message digest layer. @@ -2355,6 +2546,16 @@ #define MBEDTLS_PLATFORM_C /** + * \def MBEDTLS_POLY1305_C + * + * Enable the Poly1305 MAC algorithm. + * + * Module: library/poly1305.c + * Caller: library/chachapoly.c + */ +#define MBEDTLS_POLY1305_C + +/** * \def MBEDTLS_RIPEMD160_C * * Enable the RIPEMD-160 hash algorithm. @@ -2764,7 +2965,51 @@ //#define MBEDTLS_SSL_CACHE_DEFAULT_MAX_ENTRIES 50 /**< Maximum entries in cache */ /* SSL options */ -//#define MBEDTLS_SSL_MAX_CONTENT_LEN 16384 /**< Maxium fragment length in bytes, determines the size of each of the two internal I/O buffers */ + +/** \def MBEDTLS_SSL_MAX_CONTENT_LEN + * + * Maximum fragment length in bytes. + * + * Determines the size of both the incoming and outgoing TLS I/O buffers. + * + * Uncommenting MBEDTLS_SSL_IN_CONTENT_LEN and/or MBEDTLS_SSL_OUT_CONTENT_LEN + * will override this length by setting maximum incoming and/or outgoing + * fragment length, respectively. + */ +//#define MBEDTLS_SSL_MAX_CONTENT_LEN 16384 + +/** \def MBEDTLS_SSL_IN_CONTENT_LEN + * + * Maximum incoming fragment length in bytes. + * + * Uncomment to set the size of the inward TLS buffer independently of the + * outward buffer. + */ +//#define MBEDTLS_SSL_IN_CONTENT_LEN 16384 + +/** \def MBEDTLS_SSL_OUT_CONTENT_LEN + * + * Maximum outgoing fragment length in bytes. + * + * Uncomment to set the size of the outward TLS buffer independently of the + * inward buffer. + * + * It is possible to save RAM by setting a smaller outward buffer, while keeping + * the default inward 16384 byte buffer to conform to the TLS specification. + * + * The minimum required outward buffer size is determined by the handshake + * protocol's usage. Handshaking will fail if the outward buffer is too small. + * The specific size requirement depends on the configured ciphers and any + * certificate data which is sent during the handshake. + * + * For absolute minimum RAM usage, it's best to enable + * MBEDTLS_SSL_MAX_FRAGMENT_LENGTH and reduce MBEDTLS_SSL_MAX_CONTENT_LEN. This + * reduces both incoming and outgoing buffer sizes. However this is only + * guaranteed if the other end of the connection also supports the TLS + * max_fragment_len extension. Otherwise the connection may fail. + */ +//#define MBEDTLS_SSL_OUT_CONTENT_LEN 16384 + //#define MBEDTLS_SSL_DEFAULT_TICKET_LIFETIME 86400 /**< Lifetime of session tickets (if enabled) */ //#define MBEDTLS_PSK_MAX_LEN 32 /**< Max size of TLS pre-shared keys, in bytes (default 256 bits) */ //#define MBEDTLS_SSL_COOKIE_TIMEOUT 60 /**< Default expiration delay of DTLS cookies, in seconds if HAVE_TIME, or in number of cookies issued */ @@ -2818,10 +3063,30 @@ */ #define MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_KEY_EXCHANGE +/** + * Uncomment the macro to let mbed TLS use your alternate implementation of + * mbedtls_platform_zeroize(). This replaces the default implementation in + * platform_util.c. + * + * mbedtls_platform_zeroize() is a widely used function across the library to + * zero a block of memory. The implementation is expected to be secure in the + * sense that it has been written to prevent the compiler from removing calls + * to mbedtls_platform_zeroize() as part of redundant code elimination + * optimizations. However, it is difficult to guarantee that calls to + * mbedtls_platform_zeroize() will not be optimized by the compiler as older + * versions of the C language standards do not provide a secure implementation + * of memset(). Therefore, MBEDTLS_PLATFORM_ZEROIZE_ALT enables users to + * configure their own implementation of mbedtls_platform_zeroize(), for + * example by using directives specific to their compiler, features from newer + * C standards (e.g using memset_s() in C11) or calling a secure memset() from + * their system (e.g explicit_bzero() in BSD). + */ +//#define MBEDTLS_PLATFORM_ZEROIZE_ALT + /* \} name SECTION: Customisation configuration options */ /* Target and application specific configurations */ -//#define YOTTA_CFG_MBEDTLS_TARGET_CONFIG_FILE "mbedtls/target_config.h" +//#define YOTTA_CFG_MBEDTLS_TARGET_CONFIG_FILE "target_config.h" #if defined(TARGET_LIKE_MBED) && defined(YOTTA_CFG_MBEDTLS_TARGET_CONFIG_FILE) #include YOTTA_CFG_MBEDTLS_TARGET_CONFIG_FILE diff --git a/thirdparty/mbedtls/include/mbedtls/ctr_drbg.h b/thirdparty/mbedtls/include/mbedtls/ctr_drbg.h index 121575a51b..3835d7299b 100644 --- a/thirdparty/mbedtls/include/mbedtls/ctr_drbg.h +++ b/thirdparty/mbedtls/include/mbedtls/ctr_drbg.h @@ -1,10 +1,15 @@ /** * \file ctr_drbg.h * - * \brief CTR_DRBG is based on AES-256, as defined in <em>NIST SP 800-90A: - * Recommendation for Random Number Generation Using Deterministic - * Random Bit Generators</em>. + * \brief This file contains CTR_DRBG definitions and functions. * + * CTR_DRBG is a standardized way of building a PRNG from a block-cipher + * in counter mode operation, as defined in <em>NIST SP 800-90A: + * Recommendation for Random Number Generation Using Deterministic Random + * Bit Generators</em>. + * + * The Mbed TLS implementation of CTR_DRBG uses AES-256 as the underlying + * block cipher. */ /* * Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved @@ -31,7 +36,7 @@ #include "aes.h" #if defined(MBEDTLS_THREADING_C) -#include "mbedtls/threading.h" +#include "threading.h" #endif #define MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED -0x0034 /**< The entropy source failed. */ @@ -156,8 +161,8 @@ void mbedtls_ctr_drbg_init( mbedtls_ctr_drbg_context *ctx ); identifiers. Can be NULL. * \param len The length of the personalization data. * - * \return \c 0 on success, or - * #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED on failure. + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED on failure. */ int mbedtls_ctr_drbg_seed( mbedtls_ctr_drbg_context *ctx, int (*f_entropy)(void *, unsigned char *, size_t), @@ -216,22 +221,24 @@ void mbedtls_ctr_drbg_set_reseed_interval( mbedtls_ctr_drbg_context *ctx, * \param additional Additional data to add to the state. Can be NULL. * \param len The length of the additional data. * - * \return \c 0 on success, or - * #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED on failure. + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED on failure. */ int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context *ctx, const unsigned char *additional, size_t len ); /** - * \brief This function updates the state of the CTR_DRBG context. + * \brief This function updates the state of the CTR_DRBG context. * - * \param ctx The CTR_DRBG context. - * \param additional The data to update the state with. - * \param add_len Length of \p additional data. + * \note If \p add_len is greater than + * #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT, only the first + * #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT Bytes are used. + * The remaining Bytes are silently discarded. + * + * \param ctx The CTR_DRBG context. + * \param additional The data to update the state with. + * \param add_len Length of \p additional data. * - * \note If \p add_len is greater than #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT, - * only the first #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT Bytes are used. - * The remaining Bytes are silently discarded. */ void mbedtls_ctr_drbg_update( mbedtls_ctr_drbg_context *ctx, const unsigned char *additional, size_t add_len ); @@ -249,8 +256,8 @@ void mbedtls_ctr_drbg_update( mbedtls_ctr_drbg_context *ctx, * \param additional Additional data to update. Can be NULL. * \param add_len The length of the additional data. * - * \return \c 0 on success, or - * #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED or + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED or * #MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG on failure. */ int mbedtls_ctr_drbg_random_with_add( void *p_rng, @@ -267,8 +274,8 @@ int mbedtls_ctr_drbg_random_with_add( void *p_rng, * \param output The buffer to fill. * \param output_len The length of the buffer. * - * \return \c 0 on success, or - * #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED or + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED or * #MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG on failure. */ int mbedtls_ctr_drbg_random( void *p_rng, @@ -281,9 +288,9 @@ int mbedtls_ctr_drbg_random( void *p_rng, * \param ctx The CTR_DRBG context. * \param path The name of the file. * - * \return \c 0 on success, - * #MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR on file error, or - * #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED on + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR on file error. + * \return #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED on * failure. */ int mbedtls_ctr_drbg_write_seed_file( mbedtls_ctr_drbg_context *ctx, const char *path ); @@ -295,9 +302,9 @@ int mbedtls_ctr_drbg_write_seed_file( mbedtls_ctr_drbg_context *ctx, const char * \param ctx The CTR_DRBG context. * \param path The name of the file. * - * \return \c 0 on success, - * #MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR on file error, - * #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED or + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR on file error. + * \return #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED or * #MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG on failure. */ int mbedtls_ctr_drbg_update_seed_file( mbedtls_ctr_drbg_context *ctx, const char *path ); @@ -306,7 +313,8 @@ int mbedtls_ctr_drbg_update_seed_file( mbedtls_ctr_drbg_context *ctx, const char /** * \brief The CTR_DRBG checkup routine. * - * \return \c 0 on success, or \c 1 on failure. + * \return \c 0 on success. + * \return \c 1 on failure. */ int mbedtls_ctr_drbg_self_test( int verbose ); diff --git a/thirdparty/mbedtls/include/mbedtls/des.h b/thirdparty/mbedtls/include/mbedtls/des.h index 5a1a636522..6eb7d03bae 100644 --- a/thirdparty/mbedtls/include/mbedtls/des.h +++ b/thirdparty/mbedtls/include/mbedtls/des.h @@ -46,14 +46,14 @@ #define MBEDTLS_DES_KEY_SIZE 8 -#if !defined(MBEDTLS_DES_ALT) -// Regular implementation -// - #ifdef __cplusplus extern "C" { #endif +#if !defined(MBEDTLS_DES_ALT) +// Regular implementation +// + /** * \brief DES context structure * @@ -76,6 +76,10 @@ typedef struct } mbedtls_des3_context; +#else /* MBEDTLS_DES_ALT */ +#include "des_alt.h" +#endif /* MBEDTLS_DES_ALT */ + /** * \brief Initialize DES context * @@ -331,17 +335,6 @@ int mbedtls_des3_crypt_cbc( mbedtls_des3_context *ctx, */ void mbedtls_des_setkey( uint32_t SK[32], const unsigned char key[MBEDTLS_DES_KEY_SIZE] ); -#ifdef __cplusplus -} -#endif - -#else /* MBEDTLS_DES_ALT */ -#include "des_alt.h" -#endif /* MBEDTLS_DES_ALT */ - -#ifdef __cplusplus -extern "C" { -#endif /** * \brief Checkup routine diff --git a/thirdparty/mbedtls/include/mbedtls/dhm.h b/thirdparty/mbedtls/include/mbedtls/dhm.h index 00fafd8d16..75317a8e6d 100644 --- a/thirdparty/mbedtls/include/mbedtls/dhm.h +++ b/thirdparty/mbedtls/include/mbedtls/dhm.h @@ -1,7 +1,13 @@ /** * \file dhm.h * - * \brief Diffie-Hellman-Merkle key exchange. + * \brief This file contains Diffie-Hellman-Merkle (DHM) key exchange + * definitions and functions. + * + * Diffie-Hellman-Merkle (DHM) key exchange is defined in + * <em>RFC-2631: Diffie-Hellman Key Agreement Method</em> and + * <em>Public-Key Cryptography Standards (PKCS) #3: Diffie + * Hellman Key Agreement Standard</em>. * * <em>RFC-3526: More Modular Exponential (MODP) Diffie-Hellman groups for * Internet Key Exchange (IKE)</em> defines a number of standardized @@ -65,7 +71,6 @@ #include MBEDTLS_CONFIG_FILE #endif #include "bignum.h" -#if !defined(MBEDTLS_DHM_ALT) /* * DHM Error codes @@ -86,6 +91,8 @@ extern "C" { #endif +#if !defined(MBEDTLS_DHM_ALT) + /** * \brief The DHM context structure. */ @@ -105,6 +112,10 @@ typedef struct } mbedtls_dhm_context; +#else /* MBEDTLS_DHM_ALT */ +#include "dhm_alt.h" +#endif /* MBEDTLS_DHM_ALT */ + /** * \brief This function initializes the DHM context. * @@ -125,8 +136,8 @@ void mbedtls_dhm_init( mbedtls_dhm_context *ctx ); * failures. * \param end The end of the input buffer. * - * \return \c 0 on success, or an \c MBEDTLS_ERR_DHM_XXX error code - * on failure. + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_DHM_XXX error code on failure. */ int mbedtls_dhm_read_params( mbedtls_dhm_context *ctx, unsigned char **p, @@ -136,13 +147,6 @@ int mbedtls_dhm_read_params( mbedtls_dhm_context *ctx, * \brief This function sets up and writes the ServerKeyExchange * parameters. * - * \param ctx The DHM context. - * \param x_size The private value size in Bytes. - * \param olen The number of characters written. - * \param output The destination buffer. - * \param f_rng The RNG function. - * \param p_rng The RNG parameter. - * * \note The destination buffer must be large enough to hold * the reduced binary presentation of the modulus, the generator * and the public key, each wrapped with a 2-byte length field. @@ -155,8 +159,15 @@ int mbedtls_dhm_read_params( mbedtls_dhm_context *ctx, * mbedtls_dhm_set_group() below in conjunction with * mbedtls_mpi_read_binary() and mbedtls_mpi_read_string(). * - * \return \c 0 on success, or an \c MBEDTLS_ERR_DHM_XXX error code - * on failure. + * \param ctx The DHM context. + * \param x_size The private key size in Bytes. + * \param olen The number of characters written. + * \param output The destination buffer. + * \param f_rng The RNG function. + * \param p_rng The RNG context. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_DHM_XXX error code on failure. */ int mbedtls_dhm_make_params( mbedtls_dhm_context *ctx, int x_size, unsigned char *output, size_t *olen, @@ -164,54 +175,54 @@ int mbedtls_dhm_make_params( mbedtls_dhm_context *ctx, int x_size, void *p_rng ); /** - * \brief Set prime modulus and generator + * \brief This function sets the prime modulus and generator. * - * \param ctx The DHM context. - * \param P The MPI holding DHM prime modulus. - * \param G The MPI holding DHM generator. + * \note This function can be used to set \p P, \p G + * in preparation for mbedtls_dhm_make_params(). * - * \note This function can be used to set P, G - * in preparation for \c mbedtls_dhm_make_params. + * \param ctx The DHM context. + * \param P The MPI holding the DHM prime modulus. + * \param G The MPI holding the DHM generator. * - * \return \c 0 if successful, or an \c MBEDTLS_ERR_DHM_XXX error code - * on failure. + * \return \c 0 if successful. + * \return An \c MBEDTLS_ERR_DHM_XXX error code on failure. */ int mbedtls_dhm_set_group( mbedtls_dhm_context *ctx, const mbedtls_mpi *P, const mbedtls_mpi *G ); /** - * \brief This function imports the public value G^Y of the peer. + * \brief This function imports the public value of the peer, G^Y. * * \param ctx The DHM context. - * \param input The input buffer. + * \param input The input buffer containing the G^Y value of the peer. * \param ilen The size of the input buffer. * - * \return \c 0 on success, or an \c MBEDTLS_ERR_DHM_XXX error code - * on failure. + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_DHM_XXX error code on failure. */ int mbedtls_dhm_read_public( mbedtls_dhm_context *ctx, const unsigned char *input, size_t ilen ); /** - * \brief This function creates its own private value \c X and + * \brief This function creates its own private key, \c X, and * exports \c G^X. * + * \note The destination buffer is always fully written + * so as to contain a big-endian representation of G^X mod P. + * If it is larger than ctx->len, it is padded accordingly + * with zero-bytes at the beginning. + * * \param ctx The DHM context. - * \param x_size The private value size in Bytes. + * \param x_size The private key size in Bytes. * \param output The destination buffer. * \param olen The length of the destination buffer. Must be at least - equal to ctx->len (the size of \c P). + * equal to ctx->len (the size of \c P). * \param f_rng The RNG function. - * \param p_rng The RNG parameter. + * \param p_rng The RNG context. * - * \note The destination buffer will always be fully written - * so as to contain a big-endian presentation of G^X mod P. - * If it is larger than ctx->len, it will accordingly be - * padded with zero-bytes in the beginning. - * - * \return \c 0 on success, or an \c MBEDTLS_ERR_DHM_XXX error code - * on failure. + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_DHM_XXX error code on failure. */ int mbedtls_dhm_make_public( mbedtls_dhm_context *ctx, int x_size, unsigned char *output, size_t olen, @@ -222,22 +233,22 @@ int mbedtls_dhm_make_public( mbedtls_dhm_context *ctx, int x_size, * \brief This function derives and exports the shared secret * \c (G^Y)^X mod \c P. * + * \note If \p f_rng is not NULL, it is used to blind the input as + * a countermeasure against timing attacks. Blinding is used + * only if our private key \c X is re-used, and not used + * otherwise. We recommend always passing a non-NULL + * \p f_rng argument. + * * \param ctx The DHM context. * \param output The destination buffer. * \param output_size The size of the destination buffer. Must be at least - * the size of ctx->len. + * the size of ctx->len (the size of \c P). * \param olen On exit, holds the actual number of Bytes written. * \param f_rng The RNG function, for blinding purposes. - * \param p_rng The RNG parameter. + * \param p_rng The RNG context. * - * \return \c 0 on success, or an \c MBEDTLS_ERR_DHM_XXX error code - * on failure. - * - * \note If non-NULL, \p f_rng is used to blind the input as - * a countermeasure against timing attacks. Blinding is used - * only if our secret value \p X is re-used and omitted - * otherwise. Therefore, we recommend always passing a - * non-NULL \p f_rng argument. + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_DHM_XXX error code on failure. */ int mbedtls_dhm_calc_secret( mbedtls_dhm_context *ctx, unsigned char *output, size_t output_size, size_t *olen, @@ -245,7 +256,7 @@ int mbedtls_dhm_calc_secret( mbedtls_dhm_context *ctx, void *p_rng ); /** - * \brief This function frees and clears the components of a DHM key. + * \brief This function frees and clears the components of a DHM context. * * \param ctx The DHM context to free and clear. */ @@ -261,8 +272,9 @@ void mbedtls_dhm_free( mbedtls_dhm_context *ctx ); * \param dhminlen The size of the buffer, including the terminating null * Byte for PEM data. * - * \return \c 0 on success, or a specific DHM or PEM error code - * on failure. + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_DHM_XXX or \c MBEDTLS_ERR_PEM_XXX error code + * error code on failure. */ int mbedtls_dhm_parse_dhm( mbedtls_dhm_context *dhm, const unsigned char *dhmin, size_t dhminlen ); @@ -275,29 +287,19 @@ int mbedtls_dhm_parse_dhm( mbedtls_dhm_context *dhm, const unsigned char *dhmin, * \param dhm The DHM context to load the parameters to. * \param path The filename to read the DHM parameters from. * - * \return \c 0 on success, or a specific DHM or PEM error code - * on failure. + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_DHM_XXX or \c MBEDTLS_ERR_PEM_XXX error code + * error code on failure. */ int mbedtls_dhm_parse_dhmfile( mbedtls_dhm_context *dhm, const char *path ); #endif /* MBEDTLS_FS_IO */ #endif /* MBEDTLS_ASN1_PARSE_C */ -#ifdef __cplusplus -} -#endif - -#else /* MBEDTLS_DHM_ALT */ -#include "dhm_alt.h" -#endif /* MBEDTLS_DHM_ALT */ - -#ifdef __cplusplus -extern "C" { -#endif - /** * \brief The DMH checkup routine. * - * \return \c 0 on success, or \c 1 on failure. + * \return \c 0 on success. + * \return \c 1 on failure. */ int mbedtls_dhm_self_test( int verbose ); diff --git a/thirdparty/mbedtls/include/mbedtls/ecdh.h b/thirdparty/mbedtls/include/mbedtls/ecdh.h index 99cfde00d0..5fdf55a88a 100644 --- a/thirdparty/mbedtls/include/mbedtls/ecdh.h +++ b/thirdparty/mbedtls/include/mbedtls/ecdh.h @@ -1,10 +1,11 @@ /** * \file ecdh.h * - * \brief The Elliptic Curve Diffie-Hellman (ECDH) protocol APIs. + * \brief This file contains ECDH definitions and functions. * - * ECDH is an anonymous key agreement protocol allowing two parties to - * establish a shared secret over an insecure channel. Each party must have an + * The Elliptic Curve Diffie-Hellman (ECDH) protocol is an anonymous + * key agreement protocol allowing two parties to establish a shared + * secret over an insecure channel. Each party must have an * elliptic-curve public–private key pair. * * For more information, see <em>NIST SP 800-56A Rev. 2: Recommendation for @@ -40,14 +41,12 @@ extern "C" { #endif /** - * Defines the source of the imported EC key: - * <ul><li>Our key.</li> - * <li>The key of the peer.</li></ul> + * Defines the source of the imported EC key. */ typedef enum { - MBEDTLS_ECDH_OURS, - MBEDTLS_ECDH_THEIRS, + MBEDTLS_ECDH_OURS, /**< Our key. */ + MBEDTLS_ECDH_THEIRS, /**< The key of the peer. */ } mbedtls_ecdh_side; /** @@ -75,16 +74,18 @@ mbedtls_ecdh_context; * implemented during the ECDH key exchange. The second core * computation is performed by mbedtls_ecdh_compute_shared(). * + * \see ecp.h + * * \param grp The ECP group. * \param d The destination MPI (private key). * \param Q The destination point (public key). * \param f_rng The RNG function. - * \param p_rng The RNG parameter. + * \param p_rng The RNG context. * - * \return \c 0 on success, or an \c MBEDTLS_ERR_ECP_XXX or + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_ECP_XXX or * \c MBEDTLS_MPI_XXX error code on failure. * - * \see ecp.h */ int mbedtls_ecdh_gen_public( mbedtls_ecp_group *grp, mbedtls_mpi *d, mbedtls_ecp_point *Q, int (*f_rng)(void *, unsigned char *, size_t), @@ -97,21 +98,22 @@ int mbedtls_ecdh_gen_public( mbedtls_ecp_group *grp, mbedtls_mpi *d, mbedtls_ecp * implemented during the ECDH key exchange. The first core * computation is performed by mbedtls_ecdh_gen_public(). * + * \see ecp.h + * + * \note If \p f_rng is not NULL, it is used to implement + * countermeasures against side-channel attacks. + * For more information, see mbedtls_ecp_mul(). + * * \param grp The ECP group. * \param z The destination MPI (shared secret). * \param Q The public key from another party. * \param d Our secret exponent (private key). * \param f_rng The RNG function. - * \param p_rng The RNG parameter. + * \param p_rng The RNG context. * - * \return \c 0 on success, or an \c MBEDTLS_ERR_ECP_XXX or + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_ECP_XXX or * \c MBEDTLS_MPI_XXX error code on failure. - * - * \see ecp.h - * - * \note If \p f_rng is not NULL, it is used to implement - * countermeasures against potential elaborate timing - * attacks. For more information, see mbedtls_ecp_mul(). */ int mbedtls_ecdh_compute_shared( mbedtls_ecp_group *grp, mbedtls_mpi *z, const mbedtls_ecp_point *Q, const mbedtls_mpi *d, @@ -139,21 +141,21 @@ void mbedtls_ecdh_free( mbedtls_ecdh_context *ctx ); * This is the first function used by a TLS server for ECDHE * ciphersuites. * + * \note This function assumes that the ECP group (grp) of the + * \p ctx context has already been properly set, + * for example, using mbedtls_ecp_group_load(). + * + * \see ecp.h + * * \param ctx The ECDH context. * \param olen The number of characters written. * \param buf The destination buffer. * \param blen The length of the destination buffer. * \param f_rng The RNG function. - * \param p_rng The RNG parameter. + * \param p_rng The RNG context. * - * \note This function assumes that the ECP group (grp) of the - * \p ctx context has already been properly set, - * for example, using mbedtls_ecp_group_load(). - * - * \return \c 0 on success, or an \c MBEDTLS_ERR_ECP_XXX error code - * on failure. - * - * \see ecp.h + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_ECP_XXX error code on failure. */ int mbedtls_ecdh_make_params( mbedtls_ecdh_context *ctx, size_t *olen, unsigned char *buf, size_t blen, @@ -167,14 +169,15 @@ int mbedtls_ecdh_make_params( mbedtls_ecdh_context *ctx, size_t *olen, * This is the first function used by a TLS client for ECDHE * ciphersuites. * + * \see ecp.h + * * \param ctx The ECDH context. * \param buf The pointer to the start of the input buffer. * \param end The address for one Byte past the end of the buffer. * - * \return \c 0 on success, or an \c MBEDTLS_ERR_ECP_XXX error code - * on failure. + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_ECP_XXX error code on failure. * - * \see ecp.h */ int mbedtls_ecdh_read_params( mbedtls_ecdh_context *ctx, const unsigned char **buf, const unsigned char *end ); @@ -186,16 +189,16 @@ int mbedtls_ecdh_read_params( mbedtls_ecdh_context *ctx, * ServerKeyEchange for static ECDH, and imports ECDH * parameters from the EC key information of a certificate. * + * \see ecp.h + * * \param ctx The ECDH context to set up. * \param key The EC key to use. - * \param side Defines the source of the key: - * <ul><li>1: Our key.</li> - <li>0: The key of the peer.</li></ul> + * \param side Defines the source of the key: 1: Our key, or + * 0: The key of the peer. * - * \return \c 0 on success, or an \c MBEDTLS_ERR_ECP_XXX error code - * on failure. + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_ECP_XXX error code on failure. * - * \see ecp.h */ int mbedtls_ecdh_get_params( mbedtls_ecdh_context *ctx, const mbedtls_ecp_keypair *key, mbedtls_ecdh_side side ); @@ -207,17 +210,17 @@ int mbedtls_ecdh_get_params( mbedtls_ecdh_context *ctx, const mbedtls_ecp_keypai * This is the second function used by a TLS client for ECDH(E) * ciphersuites. * + * \see ecp.h + * * \param ctx The ECDH context. * \param olen The number of Bytes written. * \param buf The destination buffer. * \param blen The size of the destination buffer. * \param f_rng The RNG function. - * \param p_rng The RNG parameter. - * - * \return \c 0 on success, or an \c MBEDTLS_ERR_ECP_XXX error code - * on failure. + * \param p_rng The RNG context. * - * \see ecp.h + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_ECP_XXX error code on failure. */ int mbedtls_ecdh_make_public( mbedtls_ecdh_context *ctx, size_t *olen, unsigned char *buf, size_t blen, @@ -231,14 +234,14 @@ int mbedtls_ecdh_make_public( mbedtls_ecdh_context *ctx, size_t *olen, * This is the second function used by a TLS server for ECDH(E) * ciphersuites. * + * \see ecp.h + * * \param ctx The ECDH context. * \param buf The start of the input buffer. * \param blen The length of the input buffer. * - * \return \c 0 on success, or an \c MBEDTLS_ERR_ECP_XXX error code - * on failure. - * - * \see ecp.h + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_ECP_XXX error code on failure. */ int mbedtls_ecdh_read_public( mbedtls_ecdh_context *ctx, const unsigned char *buf, size_t blen ); @@ -249,21 +252,21 @@ int mbedtls_ecdh_read_public( mbedtls_ecdh_context *ctx, * This is the last function used by both TLS client * and servers. * + * \note If \p f_rng is not NULL, it is used to implement + * countermeasures against side-channel attacks. + * For more information, see mbedtls_ecp_mul(). + * + * \see ecp.h + * * \param ctx The ECDH context. * \param olen The number of Bytes written. * \param buf The destination buffer. * \param blen The length of the destination buffer. * \param f_rng The RNG function. - * \param p_rng The RNG parameter. - * - * \return \c 0 on success, or an \c MBEDTLS_ERR_ECP_XXX error code - * on failure. + * \param p_rng The RNG context. * - * \see ecp.h - * - * \note If \p f_rng is not NULL, it is used to implement - * countermeasures against potential elaborate timing - * attacks. For more information, see mbedtls_ecp_mul(). + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_ECP_XXX error code on failure. */ int mbedtls_ecdh_calc_secret( mbedtls_ecdh_context *ctx, size_t *olen, unsigned char *buf, size_t blen, diff --git a/thirdparty/mbedtls/include/mbedtls/ecdsa.h b/thirdparty/mbedtls/include/mbedtls/ecdsa.h index aa23d67f99..ce1a03d791 100644 --- a/thirdparty/mbedtls/include/mbedtls/ecdsa.h +++ b/thirdparty/mbedtls/include/mbedtls/ecdsa.h @@ -1,9 +1,10 @@ /** * \file ecdsa.h * - * \brief The Elliptic Curve Digital Signature Algorithm (ECDSA). + * \brief This file contains ECDSA definitions and functions. * - * ECDSA is defined in <em>Standards for Efficient Cryptography Group (SECG): + * The Elliptic Curve Digital Signature Algorithm (ECDSA) is defined in + * <em>Standards for Efficient Cryptography Group (SECG): * SEC1 Elliptic Curve Cryptography</em>. * The use of ECDSA for TLS is defined in <em>RFC-4492: Elliptic Curve * Cryptography (ECC) Cipher Suites for Transport Layer Security (TLS)</em>. @@ -69,6 +70,14 @@ extern "C" { * * \note The deterministic version is usually preferred. * + * \note If the bitlength of the message hash is larger than the + * bitlength of the group order, then the hash is truncated + * as defined in <em>Standards for Efficient Cryptography Group + * (SECG): SEC1 Elliptic Curve Cryptography</em>, section + * 4.1.3, step 5. + * + * \see ecp.h + * * \param grp The ECP group. * \param r The first output integer. * \param s The second output integer. @@ -76,18 +85,11 @@ extern "C" { * \param buf The message hash. * \param blen The length of \p buf. * \param f_rng The RNG function. - * \param p_rng The RNG parameter. + * \param p_rng The RNG context. * - * \note If the bitlength of the message hash is larger than the - * bitlength of the group order, then the hash is truncated - * as defined in <em>Standards for Efficient Cryptography Group - * (SECG): SEC1 Elliptic Curve Cryptography</em>, section - * 4.1.3, step 5. - * - * \return \c 0 on success, or an \c MBEDTLS_ERR_ECP_XXX + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_ECP_XXX * or \c MBEDTLS_MPI_XXX error code on failure. - * - * \see ecp.h */ int mbedtls_ecdsa_sign( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s, const mbedtls_mpi *d, const unsigned char *buf, size_t blen, @@ -97,10 +99,19 @@ int mbedtls_ecdsa_sign( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s, /** * \brief This function computes the ECDSA signature of a * previously-hashed message, deterministic version. + * * For more information, see <em>RFC-6979: Deterministic * Usage of the Digital Signature Algorithm (DSA) and Elliptic * Curve Digital Signature Algorithm (ECDSA)</em>. * + * \note If the bitlength of the message hash is larger than the + * bitlength of the group order, then the hash is truncated as + * defined in <em>Standards for Efficient Cryptography Group + * (SECG): SEC1 Elliptic Curve Cryptography</em>, section + * 4.1.3, step 5. + * + * \see ecp.h + * * \param grp The ECP group. * \param r The first output integer. * \param s The second output integer. @@ -109,17 +120,9 @@ int mbedtls_ecdsa_sign( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s, * \param blen The length of \p buf. * \param md_alg The MD algorithm used to hash the message. * - * \note If the bitlength of the message hash is larger than the - * bitlength of the group order, then the hash is truncated as - * defined in <em>Standards for Efficient Cryptography Group - * (SECG): SEC1 Elliptic Curve Cryptography</em>, section - * 4.1.3, step 5. - * - * \return \c 0 on success, - * or an \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_MPI_XXX + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_MPI_XXX * error code on failure. - * - * \see ecp.h */ int mbedtls_ecdsa_sign_det( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s, const mbedtls_mpi *d, const unsigned char *buf, size_t blen, @@ -130,6 +133,14 @@ int mbedtls_ecdsa_sign_det( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi * \brief This function verifies the ECDSA signature of a * previously-hashed message. * + * \note If the bitlength of the message hash is larger than the + * bitlength of the group order, then the hash is truncated as + * defined in <em>Standards for Efficient Cryptography Group + * (SECG): SEC1 Elliptic Curve Cryptography</em>, section + * 4.1.4, step 3. + * + * \see ecp.h + * * \param grp The ECP group. * \param buf The message hash. * \param blen The length of \p buf. @@ -137,18 +148,11 @@ int mbedtls_ecdsa_sign_det( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi * \param r The first integer of the signature. * \param s The second integer of the signature. * - * \note If the bitlength of the message hash is larger than the - * bitlength of the group order, then the hash is truncated as - * defined in <em>Standards for Efficient Cryptography Group - * (SECG): SEC1 Elliptic Curve Cryptography</em>, section - * 4.1.4, step 3. - * - * \return \c 0 on success, - * #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if signature is invalid, - * or an \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_MPI_XXX + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if the signature + * is invalid. + * \return An \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_MPI_XXX * error code on failure for any other reason. - * - * \see ecp.h */ int mbedtls_ecdsa_verify( mbedtls_ecp_group *grp, const unsigned char *buf, size_t blen, @@ -169,15 +173,6 @@ int mbedtls_ecdsa_verify( mbedtls_ecp_group *grp, * of the Digital Signature Algorithm (DSA) and Elliptic * Curve Digital Signature Algorithm (ECDSA)</em>. * - * \param ctx The ECDSA context. - * \param md_alg The message digest that was used to hash the message. - * \param hash The message hash. - * \param hlen The length of the hash. - * \param sig The buffer that holds the signature. - * \param slen The length of the signature written. - * \param f_rng The RNG function. - * \param p_rng The RNG parameter. - * * \note The \p sig buffer must be at least twice as large as the * size of the curve used, plus 9. For example, 73 Bytes if * a 256-bit curve is used. A buffer length of @@ -189,11 +184,20 @@ int mbedtls_ecdsa_verify( mbedtls_ecp_group *grp, * (SECG): SEC1 Elliptic Curve Cryptography</em>, section * 4.1.3, step 5. * - * \return \c 0 on success, - * or an \c MBEDTLS_ERR_ECP_XXX, \c MBEDTLS_ERR_MPI_XXX or - * \c MBEDTLS_ERR_ASN1_XXX error code on failure. - * * \see ecp.h + * + * \param ctx The ECDSA context. + * \param md_alg The message digest that was used to hash the message. + * \param hash The message hash. + * \param hlen The length of the hash. + * \param sig The buffer that holds the signature. + * \param slen The length of the signature written. + * \param f_rng The RNG function. + * \param p_rng The RNG context. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_ECP_XXX, \c MBEDTLS_ERR_MPI_XXX or + * \c MBEDTLS_ERR_ASN1_XXX error code on failure. */ int mbedtls_ecdsa_write_signature( mbedtls_ecdsa_context *ctx, mbedtls_md_type_t md_alg, const unsigned char *hash, size_t hlen, @@ -209,26 +213,17 @@ int mbedtls_ecdsa_write_signature( mbedtls_ecdsa_context *ctx, mbedtls_md_type_t #define MBEDTLS_DEPRECATED #endif /** - * \brief This function computes an ECDSA signature and writes it to a buffer, - * serialized as defined in <em>RFC-4492: Elliptic Curve Cryptography - * (ECC) Cipher Suites for Transport Layer Security (TLS)</em>. + * \brief This function computes an ECDSA signature and writes + * it to a buffer, serialized as defined in <em>RFC-4492: + * Elliptic Curve Cryptography (ECC) Cipher Suites for + * Transport Layer Security (TLS)</em>. * - * The deterministic version is defined in <em>RFC-6979: - * Deterministic Usage of the Digital Signature Algorithm (DSA) and - * Elliptic Curve Digital Signature Algorithm (ECDSA)</em>. + * The deterministic version is defined in <em>RFC-6979: + * Deterministic Usage of the Digital Signature Algorithm (DSA) + * and Elliptic Curve Digital Signature Algorithm (ECDSA)</em>. * * \warning It is not thread-safe to use the same context in * multiple threads. - - * - * \deprecated Superseded by mbedtls_ecdsa_write_signature() in 2.0.0 - * - * \param ctx The ECDSA context. - * \param hash The Message hash. - * \param hlen The length of the hash. - * \param sig The buffer that holds the signature. - * \param slen The length of the signature written. - * \param md_alg The MD algorithm used to hash the message. * * \note The \p sig buffer must be at least twice as large as the * size of the curve used, plus 9. For example, 73 Bytes if a @@ -241,11 +236,21 @@ int mbedtls_ecdsa_write_signature( mbedtls_ecdsa_context *ctx, mbedtls_md_type_t * (SECG): SEC1 Elliptic Curve Cryptography</em>, section * 4.1.3, step 5. * - * \return \c 0 on success, - * or an \c MBEDTLS_ERR_ECP_XXX, \c MBEDTLS_ERR_MPI_XXX or - * \c MBEDTLS_ERR_ASN1_XXX error code on failure. - * * \see ecp.h + * + * \deprecated Superseded by mbedtls_ecdsa_write_signature() in + * Mbed TLS version 2.0 and later. + * + * \param ctx The ECDSA context. + * \param hash The message hash. + * \param hlen The length of the hash. + * \param sig The buffer that holds the signature. + * \param slen The length of the signature written. + * \param md_alg The MD algorithm used to hash the message. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_ECP_XXX, \c MBEDTLS_ERR_MPI_XXX or + * \c MBEDTLS_ERR_ASN1_XXX error code on failure. */ int mbedtls_ecdsa_write_signature_det( mbedtls_ecdsa_context *ctx, const unsigned char *hash, size_t hlen, @@ -258,26 +263,26 @@ int mbedtls_ecdsa_write_signature_det( mbedtls_ecdsa_context *ctx, /** * \brief This function reads and verifies an ECDSA signature. * - * \param ctx The ECDSA context. - * \param hash The message hash. - * \param hlen The size of the hash. - * \param sig The signature to read and verify. - * \param slen The size of \p sig. - * * \note If the bitlength of the message hash is larger than the * bitlength of the group order, then the hash is truncated as * defined in <em>Standards for Efficient Cryptography Group * (SECG): SEC1 Elliptic Curve Cryptography</em>, section * 4.1.4, step 3. * - * \return \c 0 on success, - * #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if signature is invalid, - * #MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH if the signature is - * valid but its actual length is less than \p siglen, - * or an \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_ERR_MPI_XXX - * error code on failure for any other reason. - * * \see ecp.h + * + * \param ctx The ECDSA context. + * \param hash The message hash. + * \param hlen The size of the hash. + * \param sig The signature to read and verify. + * \param slen The size of \p sig. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if signature is invalid. + * \return #MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH if there is a valid + * signature in \p sig, but its length is less than \p siglen. + * \return An \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_ERR_MPI_XXX + * error code on failure for any other reason. */ int mbedtls_ecdsa_read_signature( mbedtls_ecdsa_context *ctx, const unsigned char *hash, size_t hlen, @@ -286,16 +291,16 @@ int mbedtls_ecdsa_read_signature( mbedtls_ecdsa_context *ctx, /** * \brief This function generates an ECDSA keypair on the given curve. * + * \see ecp.h + * * \param ctx The ECDSA context to store the keypair in. * \param gid The elliptic curve to use. One of the various * \c MBEDTLS_ECP_DP_XXX macros depending on configuration. * \param f_rng The RNG function. - * \param p_rng The RNG parameter. - * - * \return \c 0 on success, or an \c MBEDTLS_ERR_ECP_XXX code on - * failure. + * \param p_rng The RNG context. * - * \see ecp.h + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_ECP_XXX code on failure. */ int mbedtls_ecdsa_genkey( mbedtls_ecdsa_context *ctx, mbedtls_ecp_group_id gid, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); @@ -303,13 +308,13 @@ int mbedtls_ecdsa_genkey( mbedtls_ecdsa_context *ctx, mbedtls_ecp_group_id gid, /** * \brief This function sets an ECDSA context from an EC key pair. * + * \see ecp.h + * * \param ctx The ECDSA context to set. * \param key The EC key to use. * - * \return \c 0 on success, or an \c MBEDTLS_ERR_ECP_XXX code on - * failure. - * - * \see ecp.h + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_ECP_XXX code on failure. */ int mbedtls_ecdsa_from_keypair( mbedtls_ecdsa_context *ctx, const mbedtls_ecp_keypair *key ); diff --git a/thirdparty/mbedtls/include/mbedtls/ecjpake.h b/thirdparty/mbedtls/include/mbedtls/ecjpake.h index d86e8207f1..cc2b316f5e 100644 --- a/thirdparty/mbedtls/include/mbedtls/ecjpake.h +++ b/thirdparty/mbedtls/include/mbedtls/ecjpake.h @@ -44,8 +44,6 @@ #include "ecp.h" #include "md.h" -#if !defined(MBEDTLS_ECJPAKE_ALT) - #ifdef __cplusplus extern "C" { #endif @@ -58,6 +56,7 @@ typedef enum { MBEDTLS_ECJPAKE_SERVER, /**< Server */ } mbedtls_ecjpake_role; +#if !defined(MBEDTLS_ECJPAKE_ALT) /** * EC J-PAKE context structure. * @@ -88,6 +87,10 @@ typedef struct mbedtls_mpi s; /**< Pre-shared secret (passphrase) */ } mbedtls_ecjpake_context; +#else /* MBEDTLS_ECJPAKE_ALT */ +#include "ecjpake_alt.h" +#endif /* MBEDTLS_ECJPAKE_ALT */ + /** * \brief Initialize a context * (just makes it ready for setup() or free()). @@ -225,20 +228,10 @@ int mbedtls_ecjpake_derive_secret( mbedtls_ecjpake_context *ctx, */ void mbedtls_ecjpake_free( mbedtls_ecjpake_context *ctx ); -#ifdef __cplusplus -} -#endif -#else /* MBEDTLS_ECJPAKE_ALT */ -#include "ecjpake_alt.h" -#endif /* MBEDTLS_ECJPAKE_ALT */ #if defined(MBEDTLS_SELF_TEST) -#ifdef __cplusplus -extern "C" { -#endif - /** * \brief Checkup routine * @@ -246,10 +239,11 @@ extern "C" { */ int mbedtls_ecjpake_self_test( int verbose ); +#endif /* MBEDTLS_SELF_TEST */ + #ifdef __cplusplus } #endif -#endif /* MBEDTLS_SELF_TEST */ #endif /* ecjpake.h */ diff --git a/thirdparty/mbedtls/include/mbedtls/ecp.h b/thirdparty/mbedtls/include/mbedtls/ecp.h index b00ba4da87..3a407986dd 100644 --- a/thirdparty/mbedtls/include/mbedtls/ecp.h +++ b/thirdparty/mbedtls/include/mbedtls/ecp.h @@ -1,10 +1,21 @@ /** * \file ecp.h * - * \brief Elliptic curves over GF(p) + * \brief This file provides an API for Elliptic Curves over GF(P) (ECP). + * + * The use of ECP in cryptography and TLS is defined in + * <em>Standards for Efficient Cryptography Group (SECG): SEC1 + * Elliptic Curve Cryptography</em> and + * <em>RFC-4492: Elliptic Curve Cryptography (ECC) Cipher Suites + * for Transport Layer Security (TLS)</em>. + * + * <em>RFC-2409: The Internet Key Exchange (IKE)</em> defines ECP + * group types. + * */ + /* - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); you may @@ -19,8 +30,9 @@ * See the License for the specific language governing permissions and * limitations under the License. * - * This file is part of mbed TLS (https://tls.mbed.org) + * This file is part of Mbed TLS (https://tls.mbed.org) */ + #ifndef MBEDTLS_ECP_H #define MBEDTLS_ECP_H @@ -31,160 +43,157 @@ */ #define MBEDTLS_ERR_ECP_BAD_INPUT_DATA -0x4F80 /**< Bad input parameters to function. */ #define MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL -0x4F00 /**< The buffer is too small to write to. */ -#define MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE -0x4E80 /**< Requested curve not available. */ +#define MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE -0x4E80 /**< The requested feature is not available, for example, the requested curve is not supported. */ #define MBEDTLS_ERR_ECP_VERIFY_FAILED -0x4E00 /**< The signature is not valid. */ #define MBEDTLS_ERR_ECP_ALLOC_FAILED -0x4D80 /**< Memory allocation failed. */ -#define MBEDTLS_ERR_ECP_RANDOM_FAILED -0x4D00 /**< Generation of random value, such as (ephemeral) key, failed. */ +#define MBEDTLS_ERR_ECP_RANDOM_FAILED -0x4D00 /**< Generation of random value, such as ephemeral key, failed. */ #define MBEDTLS_ERR_ECP_INVALID_KEY -0x4C80 /**< Invalid private or public key. */ -#define MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH -0x4C00 /**< Signature is valid but shorter than the user-supplied length. */ -#define MBEDTLS_ERR_ECP_HW_ACCEL_FAILED -0x4B80 /**< ECP hardware accelerator failed. */ - -#if !defined(MBEDTLS_ECP_ALT) -/* - * default mbed TLS elliptic curve arithmetic implementation - * - * (in case MBEDTLS_ECP_ALT is defined then the developer has to provide an - * alternative implementation for the whole module and it will replace this - * one.) - */ +#define MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH -0x4C00 /**< The buffer contains a valid signature followed by more data. */ +#define MBEDTLS_ERR_ECP_HW_ACCEL_FAILED -0x4B80 /**< The ECP hardware accelerator failed. */ #ifdef __cplusplus extern "C" { #endif /** - * Domain parameters (curve, subgroup and generator) identifiers. + * Domain-parameter identifiers: curve, subgroup, and generator. * - * Only curves over prime fields are supported. + * \note Only curves over prime fields are supported. * * \warning This library does not support validation of arbitrary domain - * parameters. Therefore, only well-known domain parameters from trusted + * parameters. Therefore, only standardized domain parameters from trusted * sources should be used. See mbedtls_ecp_group_load(). */ typedef enum { - MBEDTLS_ECP_DP_NONE = 0, - MBEDTLS_ECP_DP_SECP192R1, /*!< 192-bits NIST curve */ - MBEDTLS_ECP_DP_SECP224R1, /*!< 224-bits NIST curve */ - MBEDTLS_ECP_DP_SECP256R1, /*!< 256-bits NIST curve */ - MBEDTLS_ECP_DP_SECP384R1, /*!< 384-bits NIST curve */ - MBEDTLS_ECP_DP_SECP521R1, /*!< 521-bits NIST curve */ - MBEDTLS_ECP_DP_BP256R1, /*!< 256-bits Brainpool curve */ - MBEDTLS_ECP_DP_BP384R1, /*!< 384-bits Brainpool curve */ - MBEDTLS_ECP_DP_BP512R1, /*!< 512-bits Brainpool curve */ - MBEDTLS_ECP_DP_CURVE25519, /*!< Curve25519 */ - MBEDTLS_ECP_DP_SECP192K1, /*!< 192-bits "Koblitz" curve */ - MBEDTLS_ECP_DP_SECP224K1, /*!< 224-bits "Koblitz" curve */ - MBEDTLS_ECP_DP_SECP256K1, /*!< 256-bits "Koblitz" curve */ + MBEDTLS_ECP_DP_NONE = 0, /*!< Curve not defined. */ + MBEDTLS_ECP_DP_SECP192R1, /*!< Domain parameters for the 192-bit curve defined by FIPS 186-4 and SEC1. */ + MBEDTLS_ECP_DP_SECP224R1, /*!< Domain parameters for the 224-bit curve defined by FIPS 186-4 and SEC1. */ + MBEDTLS_ECP_DP_SECP256R1, /*!< Domain parameters for the 256-bit curve defined by FIPS 186-4 and SEC1. */ + MBEDTLS_ECP_DP_SECP384R1, /*!< Domain parameters for the 384-bit curve defined by FIPS 186-4 and SEC1. */ + MBEDTLS_ECP_DP_SECP521R1, /*!< Domain parameters for the 521-bit curve defined by FIPS 186-4 and SEC1. */ + MBEDTLS_ECP_DP_BP256R1, /*!< Domain parameters for 256-bit Brainpool curve. */ + MBEDTLS_ECP_DP_BP384R1, /*!< Domain parameters for 384-bit Brainpool curve. */ + MBEDTLS_ECP_DP_BP512R1, /*!< Domain parameters for 512-bit Brainpool curve. */ + MBEDTLS_ECP_DP_CURVE25519, /*!< Domain parameters for Curve25519. */ + MBEDTLS_ECP_DP_SECP192K1, /*!< Domain parameters for 192-bit "Koblitz" curve. */ + MBEDTLS_ECP_DP_SECP224K1, /*!< Domain parameters for 224-bit "Koblitz" curve. */ + MBEDTLS_ECP_DP_SECP256K1, /*!< Domain parameters for 256-bit "Koblitz" curve. */ + MBEDTLS_ECP_DP_CURVE448, /*!< Domain parameters for Curve448. */ } mbedtls_ecp_group_id; /** - * Number of supported curves (plus one for NONE). + * The number of supported curves, plus one for #MBEDTLS_ECP_DP_NONE. * - * (Montgomery curves excluded for now.) + * \note Montgomery curves are currently excluded. */ #define MBEDTLS_ECP_DP_MAX 12 /** - * Curve information for use by other modules + * Curve information, for use by other modules. */ typedef struct { - mbedtls_ecp_group_id grp_id; /*!< Internal identifier */ - uint16_t tls_id; /*!< TLS NamedCurve identifier */ - uint16_t bit_size; /*!< Curve size in bits */ - const char *name; /*!< Human-friendly name */ + mbedtls_ecp_group_id grp_id; /*!< An internal identifier. */ + uint16_t tls_id; /*!< The TLS NamedCurve identifier. */ + uint16_t bit_size; /*!< The curve size in bits. */ + const char *name; /*!< A human-friendly name. */ } mbedtls_ecp_curve_info; /** - * \brief ECP point structure (jacobian coordinates) + * \brief The ECP point structure, in Jacobian coordinates. * * \note All functions expect and return points satisfying - * the following condition: Z == 0 or Z == 1. (Other - * values of Z are used by internal functions only.) - * The point is zero, or "at infinity", if Z == 0. - * Otherwise, X and Y are its standard (affine) coordinates. + * the following condition: <code>Z == 0</code> or + * <code>Z == 1</code>. Other values of \p Z are + * used only by internal functions. + * The point is zero, or "at infinity", if <code>Z == 0</code>. + * Otherwise, \p X and \p Y are its standard (affine) + * coordinates. */ typedef struct { - mbedtls_mpi X; /*!< the point's X coordinate */ - mbedtls_mpi Y; /*!< the point's Y coordinate */ - mbedtls_mpi Z; /*!< the point's Z coordinate */ + mbedtls_mpi X; /*!< The X coordinate of the ECP point. */ + mbedtls_mpi Y; /*!< The Y coordinate of the ECP point. */ + mbedtls_mpi Z; /*!< The Z coordinate of the ECP point. */ } mbedtls_ecp_point; -/** - * \brief ECP group structure - * - * We consider two types of curves equations: - * 1. Short Weierstrass y^2 = x^3 + A x + B mod P (SEC1 + RFC 4492) - * 2. Montgomery, y^2 = x^3 + A x^2 + x mod P (Curve25519 + draft) - * In both cases, a generator G for a prime-order subgroup is fixed. In the - * short weierstrass, this subgroup is actually the whole curve, and its - * cardinal is denoted by N. - * - * In the case of Short Weierstrass curves, our code requires that N is an odd - * prime. (Use odd in mbedtls_ecp_mul() and prime in mbedtls_ecdsa_sign() for blinding.) - * - * In the case of Montgomery curves, we don't store A but (A + 2) / 4 which is - * the quantity actually used in the formulas. Also, nbits is not the size of N - * but the required size for private keys. +#if !defined(MBEDTLS_ECP_ALT) +/* + * default mbed TLS elliptic curve arithmetic implementation * - * If modp is NULL, reduction modulo P is done using a generic algorithm. - * Otherwise, it must point to a function that takes an mbedtls_mpi in the range - * 0..2^(2*pbits)-1 and transforms it in-place in an integer of little more - * than pbits, so that the integer may be efficiently brought in the 0..P-1 - * range by a few additions or substractions. It must return 0 on success and - * non-zero on failure. + * (in case MBEDTLS_ECP_ALT is defined then the developer has to provide an + * alternative implementation for the whole module and it will replace this + * one.) */ -typedef struct -{ - mbedtls_ecp_group_id id; /*!< internal group identifier */ - mbedtls_mpi P; /*!< prime modulus of the base field */ - mbedtls_mpi A; /*!< 1. A in the equation, or 2. (A + 2) / 4 */ - mbedtls_mpi B; /*!< 1. B in the equation, or 2. unused */ - mbedtls_ecp_point G; /*!< generator of the (sub)group used */ - mbedtls_mpi N; /*!< 1. the order of G, or 2. unused */ - size_t pbits; /*!< number of bits in P */ - size_t nbits; /*!< number of bits in 1. P, or 2. private keys */ - unsigned int h; /*!< internal: 1 if the constants are static */ - int (*modp)(mbedtls_mpi *); /*!< function for fast reduction mod P */ - int (*t_pre)(mbedtls_ecp_point *, void *); /*!< unused */ - int (*t_post)(mbedtls_ecp_point *, void *); /*!< unused */ - void *t_data; /*!< unused */ - mbedtls_ecp_point *T; /*!< pre-computed points for ecp_mul_comb() */ - size_t T_size; /*!< number for pre-computed points */ -} -mbedtls_ecp_group; /** - * \brief ECP key pair structure + * \brief The ECP group structure. + * + * We consider two types of curve equations: + * <ul><li>Short Weierstrass: <code>y^2 = x^3 + A x + B mod P</code> + * (SEC1 + RFC-4492)</li> + * <li>Montgomery: <code>y^2 = x^3 + A x^2 + x mod P</code> (Curve25519, + * Curve448)</li></ul> + * In both cases, the generator (\p G) for a prime-order subgroup is fixed. * - * A generic key pair that could be used for ECDSA, fixed ECDH, etc. + * For Short Weierstrass, this subgroup is the whole curve, and its + * cardinality is denoted by \p N. Our code requires that \p N is an + * odd prime as mbedtls_ecp_mul() requires an odd number, and + * mbedtls_ecdsa_sign() requires that it is prime for blinding purposes. + * + * For Montgomery curves, we do not store \p A, but <code>(A + 2) / 4</code>, + * which is the quantity used in the formulas. Additionally, \p nbits is + * not the size of \p N but the required size for private keys. + * + * If \p modp is NULL, reduction modulo \p P is done using a generic algorithm. + * Otherwise, \p modp must point to a function that takes an \p mbedtls_mpi in the + * range of <code>0..2^(2*pbits)-1</code>, and transforms it in-place to an integer + * which is congruent mod \p P to the given MPI, and is close enough to \p pbits + * in size, so that it may be efficiently brought in the 0..P-1 range by a few + * additions or subtractions. Therefore, it is only an approximative modular + * reduction. It must return 0 on success and non-zero on failure. * - * \note Members purposefully in the same order as struc mbedtls_ecdsa_context. */ typedef struct { - mbedtls_ecp_group grp; /*!< Elliptic curve and base point */ - mbedtls_mpi d; /*!< our secret value */ - mbedtls_ecp_point Q; /*!< our public value */ + mbedtls_ecp_group_id id; /*!< An internal group identifier. */ + mbedtls_mpi P; /*!< The prime modulus of the base field. */ + mbedtls_mpi A; /*!< For Short Weierstrass: \p A in the equation. For + Montgomery curves: <code>(A + 2) / 4</code>. */ + mbedtls_mpi B; /*!< For Short Weierstrass: \p B in the equation. + For Montgomery curves: unused. */ + mbedtls_ecp_point G; /*!< The generator of the subgroup used. */ + mbedtls_mpi N; /*!< The order of \p G. */ + size_t pbits; /*!< The number of bits in \p P.*/ + size_t nbits; /*!< For Short Weierstrass: The number of bits in \p P. + For Montgomery curves: the number of bits in the + private keys. */ + unsigned int h; /*!< \internal 1 if the constants are static. */ + int (*modp)(mbedtls_mpi *); /*!< The function for fast pseudo-reduction + mod \p P (see above).*/ + int (*t_pre)(mbedtls_ecp_point *, void *); /*!< Unused. */ + int (*t_post)(mbedtls_ecp_point *, void *); /*!< Unused. */ + void *t_data; /*!< Unused. */ + mbedtls_ecp_point *T; /*!< Pre-computed points for ecp_mul_comb(). */ + size_t T_size; /*!< The number of pre-computed points. */ } -mbedtls_ecp_keypair; +mbedtls_ecp_group; /** * \name SECTION: Module settings * * The configuration options you can set for this module are in this section. - * Either change them in config.h or define them on the compiler command line. + * Either change them in config.h, or define them using the compiler command line. * \{ */ #if !defined(MBEDTLS_ECP_MAX_BITS) /** - * Maximum size of the groups (that is, of N and P) + * The maximum size of the groups, that is, of \c N and \c P. */ -#define MBEDTLS_ECP_MAX_BITS 521 /**< Maximum bit size of groups */ +#define MBEDTLS_ECP_MAX_BITS 521 /**< The maximum size of groups, in bits. */ #endif #define MBEDTLS_ECP_MAX_BYTES ( ( MBEDTLS_ECP_MAX_BITS + 7 ) / 8 ) @@ -207,11 +216,10 @@ mbedtls_ecp_keypair; * 521 145 141 135 120 97 * 384 214 209 198 177 146 * 256 320 320 303 262 226 - * 224 475 475 453 398 342 * 192 640 640 633 587 476 */ -#define MBEDTLS_ECP_WINDOW_SIZE 6 /**< Maximum window size used */ +#define MBEDTLS_ECP_WINDOW_SIZE 6 /**< The maximum window size used. */ #endif /* MBEDTLS_ECP_WINDOW_SIZE */ #if !defined(MBEDTLS_ECP_FIXED_POINT_OPTIM) @@ -226,33 +234,55 @@ mbedtls_ecp_keypair; * * Change this value to 0 to reduce peak memory usage. */ -#define MBEDTLS_ECP_FIXED_POINT_OPTIM 1 /**< Enable fixed-point speed-up */ +#define MBEDTLS_ECP_FIXED_POINT_OPTIM 1 /**< Enable fixed-point speed-up. */ #endif /* MBEDTLS_ECP_FIXED_POINT_OPTIM */ /* \} name SECTION: Module settings */ +#else /* MBEDTLS_ECP_ALT */ +#include "ecp_alt.h" +#endif /* MBEDTLS_ECP_ALT */ + +/** + * \brief The ECP key-pair structure. + * + * A generic key-pair that may be used for ECDSA and fixed ECDH, for example. + * + * \note Members are deliberately in the same order as in the + * ::mbedtls_ecdsa_context structure. + */ +typedef struct +{ + mbedtls_ecp_group grp; /*!< Elliptic curve and base point */ + mbedtls_mpi d; /*!< our secret value */ + mbedtls_ecp_point Q; /*!< our public value */ +} +mbedtls_ecp_keypair; + /* * Point formats, from RFC 4492's enum ECPointFormat */ -#define MBEDTLS_ECP_PF_UNCOMPRESSED 0 /**< Uncompressed point format */ -#define MBEDTLS_ECP_PF_COMPRESSED 1 /**< Compressed point format */ +#define MBEDTLS_ECP_PF_UNCOMPRESSED 0 /**< Uncompressed point format. */ +#define MBEDTLS_ECP_PF_COMPRESSED 1 /**< Compressed point format. */ /* * Some other constants from RFC 4492 */ -#define MBEDTLS_ECP_TLS_NAMED_CURVE 3 /**< ECCurveType's named_curve */ +#define MBEDTLS_ECP_TLS_NAMED_CURVE 3 /**< The named_curve of ECCurveType. */ /** - * \brief Get the list of supported curves in order of preferrence - * (full information) + * \brief This function retrieves the information defined in + * mbedtls_ecp_curve_info() for all supported curves in order + * of preference. * - * \return A statically allocated array, the last entry is 0. + * \return A statically allocated array. The last entry is 0. */ const mbedtls_ecp_curve_info *mbedtls_ecp_curve_list( void ); /** - * \brief Get the list of supported curves in order of preferrence - * (grp_id only) + * \brief This function retrieves the list of internal group + * identifiers of all supported curves in the order of + * preference. * * \return A statically allocated array, * terminated with MBEDTLS_ECP_DP_NONE. @@ -260,357 +290,400 @@ const mbedtls_ecp_curve_info *mbedtls_ecp_curve_list( void ); const mbedtls_ecp_group_id *mbedtls_ecp_grp_id_list( void ); /** - * \brief Get curve information from an internal group identifier + * \brief This function retrieves curve information from an internal + * group identifier. * - * \param grp_id A MBEDTLS_ECP_DP_XXX value + * \param grp_id An \c MBEDTLS_ECP_DP_XXX value. * - * \return The associated curve information or NULL + * \return The associated curve information on success. + * \return NULL on failure. */ const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_grp_id( mbedtls_ecp_group_id grp_id ); /** - * \brief Get curve information from a TLS NamedCurve value + * \brief This function retrieves curve information from a TLS + * NamedCurve value. * - * \param tls_id A MBEDTLS_ECP_DP_XXX value + * \param tls_id An \c MBEDTLS_ECP_DP_XXX value. * - * \return The associated curve information or NULL + * \return The associated curve information on success. + * \return NULL on failure. */ const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_tls_id( uint16_t tls_id ); /** - * \brief Get curve information from a human-readable name + * \brief This function retrieves curve information from a + * human-readable name. * - * \param name The name + * \param name The human-readable name. * - * \return The associated curve information or NULL + * \return The associated curve information on success. + * \return NULL on failure. */ const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_name( const char *name ); /** - * \brief Initialize a point (as zero) + * \brief This function initializes a point as zero. + * + * \param pt The point to initialize. */ void mbedtls_ecp_point_init( mbedtls_ecp_point *pt ); /** - * \brief Initialize a group (to something meaningless) + * \brief This function initializes an ECP group context + * without loading any domain parameters. + * + * \note After this function is called, domain parameters + * for various ECP groups can be loaded through the + * mbedtls_ecp_load() or mbedtls_ecp_tls_read_group() + * functions. */ void mbedtls_ecp_group_init( mbedtls_ecp_group *grp ); /** - * \brief Initialize a key pair (as an invalid one) + * \brief This function initializes a key pair as an invalid one. + * + * \param key The key pair to initialize. */ void mbedtls_ecp_keypair_init( mbedtls_ecp_keypair *key ); /** - * \brief Free the components of a point + * \brief This function frees the components of a point. + * + * \param pt The point to free. */ void mbedtls_ecp_point_free( mbedtls_ecp_point *pt ); /** - * \brief Free the components of an ECP group + * \brief This function frees the components of an ECP group. + * \param grp The group to free. */ void mbedtls_ecp_group_free( mbedtls_ecp_group *grp ); /** - * \brief Free the components of a key pair + * \brief This function frees the components of a key pair. + * \param key The key pair to free. */ void mbedtls_ecp_keypair_free( mbedtls_ecp_keypair *key ); /** - * \brief Copy the contents of point Q into P + * \brief This function copies the contents of point \p Q into + * point \p P. * - * \param P Destination point - * \param Q Source point + * \param P The destination point. + * \param Q The source point. * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory-allocation failure. */ int mbedtls_ecp_copy( mbedtls_ecp_point *P, const mbedtls_ecp_point *Q ); /** - * \brief Copy the contents of a group object + * \brief This function copies the contents of group \p src into + * group \p dst. * - * \param dst Destination group - * \param src Source group + * \param dst The destination group. + * \param src The source group. * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory-allocation failure. */ int mbedtls_ecp_group_copy( mbedtls_ecp_group *dst, const mbedtls_ecp_group *src ); /** - * \brief Set a point to zero + * \brief This function sets a point to zero. * - * \param pt Destination point + * \param pt The point to set. * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory-allocation failure. */ int mbedtls_ecp_set_zero( mbedtls_ecp_point *pt ); /** - * \brief Tell if a point is zero + * \brief This function checks if a point is zero. * - * \param pt Point to test + * \param pt The point to test. * - * \return 1 if point is zero, 0 otherwise + * \return \c 1 if the point is zero. + * \return \c 0 if the point is non-zero. */ int mbedtls_ecp_is_zero( mbedtls_ecp_point *pt ); /** - * \brief Compare two points + * \brief This function compares two points. * - * \note This assumes the points are normalized. Otherwise, + * \note This assumes that the points are normalized. Otherwise, * they may compare as "not equal" even if they are. * - * \param P First point to compare - * \param Q Second point to compare + * \param P The first point to compare. + * \param Q The second point to compare. * - * \return 0 if the points are equal, - * MBEDTLS_ERR_ECP_BAD_INPUT_DATA otherwise + * \return \c 0 if the points are equal. + * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if the points are not equal. */ int mbedtls_ecp_point_cmp( const mbedtls_ecp_point *P, const mbedtls_ecp_point *Q ); /** - * \brief Import a non-zero point from two ASCII strings + * \brief This function imports a non-zero point from two ASCII + * strings. * - * \param P Destination point - * \param radix Input numeric base - * \param x First affine coordinate as a null-terminated string - * \param y Second affine coordinate as a null-terminated string + * \param P The destination point. + * \param radix The numeric base of the input. + * \param x The first affine coordinate, as a null-terminated string. + * \param y The second affine coordinate, as a null-terminated string. * - * \return 0 if successful, or a MBEDTLS_ERR_MPI_XXX error code + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_MPI_XXX error code on failure. */ int mbedtls_ecp_point_read_string( mbedtls_ecp_point *P, int radix, const char *x, const char *y ); /** - * \brief Export a point into unsigned binary data + * \brief This function exports a point into unsigned binary data. * - * \param grp Group to which the point should belong - * \param P Point to export - * \param format Point format, should be a MBEDTLS_ECP_PF_XXX macro - * \param olen Length of the actual output - * \param buf Output buffer - * \param buflen Length of the output buffer + * \param grp The group to which the point should belong. + * \param P The point to export. + * \param format The point format. Should be an \c MBEDTLS_ECP_PF_XXX macro. + * \param olen The length of the output. + * \param buf The output buffer. + * \param buflen The length of the output buffer. * - * \return 0 if successful, - * or MBEDTLS_ERR_ECP_BAD_INPUT_DATA - * or MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA + * or #MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL on failure. */ int mbedtls_ecp_point_write_binary( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *P, int format, size_t *olen, unsigned char *buf, size_t buflen ); /** - * \brief Import a point from unsigned binary data + * \brief This function imports a point from unsigned binary data. * - * \param grp Group to which the point should belong - * \param P Point to import - * \param buf Input buffer - * \param ilen Actual length of input + * \note This function does not check that the point actually + * belongs to the given group, see mbedtls_ecp_check_pubkey() + * for that. * - * \return 0 if successful, - * MBEDTLS_ERR_ECP_BAD_INPUT_DATA if input is invalid, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed, - * MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE if the point format + * \param grp The group to which the point should belong. + * \param P The point to import. + * \param buf The input buffer. + * \param ilen The length of the input. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if input is invalid. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory-allocation failure. + * \return #MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE if the point format * is not implemented. * - * \note This function does NOT check that the point actually - * belongs to the given group, see mbedtls_ecp_check_pubkey() for - * that. */ int mbedtls_ecp_point_read_binary( const mbedtls_ecp_group *grp, mbedtls_ecp_point *P, const unsigned char *buf, size_t ilen ); /** - * \brief Import a point from a TLS ECPoint record + * \brief This function imports a point from a TLS ECPoint record. * - * \param grp ECP group used - * \param pt Destination point - * \param buf $(Start of input buffer) - * \param len Buffer length + * \note On function return, \p buf is updated to point to immediately + * after the ECPoint record. * - * \note buf is updated to point right after the ECPoint on exit + * \param grp The ECP group used. + * \param pt The destination point. + * \param buf The address of the pointer to the start of the input buffer. + * \param len The length of the buffer. * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_XXX if initialization failed - * MBEDTLS_ERR_ECP_BAD_INPUT_DATA if input is invalid + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_MPI_XXX error code on initialization failure. + * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if input is invalid. */ int mbedtls_ecp_tls_read_point( const mbedtls_ecp_group *grp, mbedtls_ecp_point *pt, const unsigned char **buf, size_t len ); /** - * \brief Export a point as a TLS ECPoint record + * \brief This function exports a point as a TLS ECPoint record. * - * \param grp ECP group used - * \param pt Point to export - * \param format Export format - * \param olen length of data written - * \param buf Buffer to write to - * \param blen Buffer length + * \param grp The ECP group used. + * \param pt The point format to export to. The point format is an + * \c MBEDTLS_ECP_PF_XXX constant. + * \param format The export format. + * \param olen The length of the data written. + * \param buf The buffer to write to. + * \param blen The length of the buffer. * - * \return 0 if successful, - * or MBEDTLS_ERR_ECP_BAD_INPUT_DATA - * or MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA or + * #MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL on failure. */ int mbedtls_ecp_tls_write_point( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt, int format, size_t *olen, unsigned char *buf, size_t blen ); /** - * \brief Set a group using well-known domain parameters + * \brief This function sets a group using standardized domain parameters. * - * \param grp Destination group - * \param id Index in the list of well-known domain parameters + * \note The index should be a value of the NamedCurve enum, + * as defined in <em>RFC-4492: Elliptic Curve Cryptography + * (ECC) Cipher Suites for Transport Layer Security (TLS)</em>, + * usually in the form of an \c MBEDTLS_ECP_DP_XXX macro. * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_XXX if initialization failed - * MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE for unkownn groups + * \param grp The destination group. + * \param id The identifier of the domain parameter set to load. * - * \note Index should be a value of RFC 4492's enum NamedCurve, - * usually in the form of a MBEDTLS_ECP_DP_XXX macro. + * \return \c 0 on success, + * \return An \c MBEDTLS_ERR_MPI_XXX error code on initialization failure. + * \return #MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE for unkownn groups. + */ int mbedtls_ecp_group_load( mbedtls_ecp_group *grp, mbedtls_ecp_group_id id ); /** - * \brief Set a group from a TLS ECParameters record + * \brief This function sets a group from a TLS ECParameters record. * - * \param grp Destination group - * \param buf &(Start of input buffer) - * \param len Buffer length + * \note \p buf is updated to point right after the ECParameters record + * on exit. * - * \note buf is updated to point right after ECParameters on exit + * \param grp The destination group. + * \param buf The address of the pointer to the start of the input buffer. + * \param len The length of the buffer. * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_XXX if initialization failed - * MBEDTLS_ERR_ECP_BAD_INPUT_DATA if input is invalid + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_MPI_XXX error code on initialization failure. + * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if input is invalid. */ int mbedtls_ecp_tls_read_group( mbedtls_ecp_group *grp, const unsigned char **buf, size_t len ); /** - * \brief Write the TLS ECParameters record for a group + * \brief This function writes the TLS ECParameters record for a group. * - * \param grp ECP group used - * \param olen Number of bytes actually written - * \param buf Buffer to write to - * \param blen Buffer length + * \param grp The ECP group used. + * \param olen The number of Bytes written. + * \param buf The buffer to write to. + * \param blen The length of the buffer. * - * \return 0 if successful, - * or MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL on failure. */ int mbedtls_ecp_tls_write_group( const mbedtls_ecp_group *grp, size_t *olen, unsigned char *buf, size_t blen ); /** - * \brief Multiplication by an integer: R = m * P - * (Not thread-safe to use same group in multiple threads) + * \brief This function performs multiplication of a point by + * an integer: \p R = \p m * \p P. * - * \note In order to prevent timing attacks, this function - * executes the exact same sequence of (base field) - * operations for any valid m. It avoids any if-branch or - * array index depending on the value of m. + * It is not thread-safe to use same group in multiple threads. * - * \note If f_rng is not NULL, it is used to randomize intermediate - * results in order to prevent potential timing attacks - * targeting these results. It is recommended to always - * provide a non-NULL f_rng (the overhead is negligible). + * \note To prevent timing attacks, this function + * executes the exact same sequence of base-field + * operations for any valid \p m. It avoids any if-branch or + * array index depending on the value of \p m. * - * \param grp ECP group - * \param R Destination point - * \param m Integer by which to multiply - * \param P Point to multiply - * \param f_rng RNG function (see notes) - * \param p_rng RNG parameter + * \note If \p f_rng is not NULL, it is used to randomize + * intermediate results to prevent potential timing attacks + * targeting these results. We recommend always providing + * a non-NULL \p f_rng. The overhead is negligible. * - * \return 0 if successful, - * MBEDTLS_ERR_ECP_INVALID_KEY if m is not a valid privkey - * or P is not a valid pubkey, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + * \param grp The ECP group. + * \param R The destination point. + * \param m The integer by which to multiply. + * \param P The point to multiply. + * \param f_rng The RNG function. + * \param p_rng The RNG context. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_INVALID_KEY if \p m is not a valid private + * key, or \p P is not a valid public key. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory-allocation failure. */ int mbedtls_ecp_mul( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, const mbedtls_mpi *m, const mbedtls_ecp_point *P, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); /** - * \brief Multiplication and addition of two points by integers: - * R = m * P + n * Q - * (Not thread-safe to use same group in multiple threads) + * \brief This function performs multiplication and addition of two + * points by integers: \p R = \p m * \p P + \p n * \p Q + * + * It is not thread-safe to use same group in multiple threads. * - * \note In contrast to mbedtls_ecp_mul(), this function does not guarantee - * a constant execution flow and timing. + * \note In contrast to mbedtls_ecp_mul(), this function does not + * guarantee a constant execution flow and timing. * - * \param grp ECP group - * \param R Destination point - * \param m Integer by which to multiply P - * \param P Point to multiply by m - * \param n Integer by which to multiply Q - * \param Q Point to be multiplied by n + * \param grp The ECP group. + * \param R The destination point. + * \param m The integer by which to multiply \p P. + * \param P The point to multiply by \p m. + * \param n The integer by which to multiply \p Q. + * \param Q The point to be multiplied by \p n. * - * \return 0 if successful, - * MBEDTLS_ERR_ECP_INVALID_KEY if m or n is not a valid privkey - * or P or Q is not a valid pubkey, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_INVALID_KEY if \p m or \p n are not + * valid private keys, or \p P or \p Q are not valid public + * keys. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory-allocation failure. */ int mbedtls_ecp_muladd( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, const mbedtls_mpi *m, const mbedtls_ecp_point *P, const mbedtls_mpi *n, const mbedtls_ecp_point *Q ); /** - * \brief Check that a point is a valid public key on this curve + * \brief This function checks that a point is a valid public key + * on this curve. * - * \param grp Curve/group the point should belong to - * \param pt Point to check + * It only checks that the point is non-zero, has + * valid coordinates and lies on the curve. It does not verify + * that it is indeed a multiple of \p G. This additional + * check is computationally more expensive, is not required + * by standards, and should not be necessary if the group + * used has a small cofactor. In particular, it is useless for + * the NIST groups which all have a cofactor of 1. * - * \return 0 if point is a valid public key, - * MBEDTLS_ERR_ECP_INVALID_KEY otherwise. + * \note This function uses bare components rather than an + * ::mbedtls_ecp_keypair structure, to ease use with other + * structures, such as ::mbedtls_ecdh_context or + * ::mbedtls_ecdsa_context. * - * \note This function only checks the point is non-zero, has valid - * coordinates and lies on the curve, but not that it is - * indeed a multiple of G. This is additional check is more - * expensive, isn't required by standards, and shouldn't be - * necessary if the group used has a small cofactor. In - * particular, it is useless for the NIST groups which all - * have a cofactor of 1. + * \param grp The curve the point should lie on. + * \param pt The point to check. * - * \note Uses bare components rather than an mbedtls_ecp_keypair structure - * in order to ease use with other structures such as - * mbedtls_ecdh_context of mbedtls_ecdsa_context. + * \return \c 0 if the point is a valid public key. + * \return #MBEDTLS_ERR_ECP_INVALID_KEY on failure. */ int mbedtls_ecp_check_pubkey( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt ); /** - * \brief Check that an mbedtls_mpi is a valid private key for this curve + * \brief This function checks that an \p mbedtls_mpi is a valid private + * key for this curve. * - * \param grp Group used - * \param d Integer to check + * \note This function uses bare components rather than an + * ::mbedtls_ecp_keypair structure to ease use with other + * structures, such as ::mbedtls_ecdh_context or + * ::mbedtls_ecdsa_context. * - * \return 0 if point is a valid private key, - * MBEDTLS_ERR_ECP_INVALID_KEY otherwise. + * \param grp The group used. + * \param d The integer to check. * - * \note Uses bare components rather than an mbedtls_ecp_keypair structure - * in order to ease use with other structures such as - * mbedtls_ecdh_context of mbedtls_ecdsa_context. + * \return \c 0 if the point is a valid private key. + * \return #MBEDTLS_ERR_ECP_INVALID_KEY on failure. */ int mbedtls_ecp_check_privkey( const mbedtls_ecp_group *grp, const mbedtls_mpi *d ); /** - * \brief Generate a keypair with configurable base point + * \brief This function generates a keypair with a configurable base + * point. * - * \param grp ECP group - * \param G Chosen base point - * \param d Destination MPI (secret part) - * \param Q Destination point (public part) - * \param f_rng RNG function - * \param p_rng RNG parameter + * \note This function uses bare components rather than an + * ::mbedtls_ecp_keypair structure to ease use with other + * structures, such as ::mbedtls_ecdh_context or + * ::mbedtls_ecdsa_context. * - * \return 0 if successful, - * or a MBEDTLS_ERR_ECP_XXX or MBEDTLS_MPI_XXX error code + * \param grp The ECP group. + * \param G The chosen base point. + * \param d The destination MPI (secret part). + * \param Q The destination point (public part). + * \param f_rng The RNG function. + * \param p_rng The RNG context. * - * \note Uses bare components rather than an mbedtls_ecp_keypair structure - * in order to ease use with other structures such as - * mbedtls_ecdh_context of mbedtls_ecdsa_context. + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_MPI_XXX error code + * on failure. */ int mbedtls_ecp_gen_keypair_base( mbedtls_ecp_group *grp, const mbedtls_ecp_point *G, @@ -619,57 +692,66 @@ int mbedtls_ecp_gen_keypair_base( mbedtls_ecp_group *grp, void *p_rng ); /** - * \brief Generate a keypair + * \brief This function generates an ECP keypair. * - * \param grp ECP group - * \param d Destination MPI (secret part) - * \param Q Destination point (public part) - * \param f_rng RNG function - * \param p_rng RNG parameter + * \note This function uses bare components rather than an + * ::mbedtls_ecp_keypair structure to ease use with other + * structures, such as ::mbedtls_ecdh_context or + * ::mbedtls_ecdsa_context. * - * \return 0 if successful, - * or a MBEDTLS_ERR_ECP_XXX or MBEDTLS_MPI_XXX error code + * \param grp The ECP group. + * \param d The destination MPI (secret part). + * \param Q The destination point (public part). + * \param f_rng The RNG function. + * \param p_rng The RNG context. * - * \note Uses bare components rather than an mbedtls_ecp_keypair structure - * in order to ease use with other structures such as - * mbedtls_ecdh_context of mbedtls_ecdsa_context. + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_MPI_XXX error code + * on failure. */ int mbedtls_ecp_gen_keypair( mbedtls_ecp_group *grp, mbedtls_mpi *d, mbedtls_ecp_point *Q, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); /** - * \brief Generate a keypair + * \brief This function generates an ECP key. * - * \param grp_id ECP group identifier - * \param key Destination keypair - * \param f_rng RNG function - * \param p_rng RNG parameter + * \param grp_id The ECP group identifier. + * \param key The destination key. + * \param f_rng The RNG function. + * \param p_rng The RNG context. * - * \return 0 if successful, - * or a MBEDTLS_ERR_ECP_XXX or MBEDTLS_MPI_XXX error code + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_MPI_XXX error code + * on failure. */ int mbedtls_ecp_gen_key( mbedtls_ecp_group_id grp_id, mbedtls_ecp_keypair *key, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); /** - * \brief Check a public-private key pair + * \brief This function checks that the keypair objects + * \p pub and \p prv have the same group and the + * same public point, and that the private key in + * \p prv is consistent with the public key. * - * \param pub Keypair structure holding a public key - * \param prv Keypair structure holding a private (plus public) key + * \param pub The keypair structure holding the public key. + * If it contains a private key, that part is ignored. + * \param prv The keypair structure holding the full keypair. * - * \return 0 if successful (keys are valid and match), or - * MBEDTLS_ERR_ECP_BAD_INPUT_DATA, or - * a MBEDTLS_ERR_ECP_XXX or MBEDTLS_ERR_MPI_XXX code. + * \return \c 0 on success, meaning that the keys are valid and match. + * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if the keys are invalid or do not match. + * \return An \c MBEDTLS_ERR_ECP_XXX or an \c MBEDTLS_ERR_MPI_XXX + * error code on calculation failure. */ int mbedtls_ecp_check_pub_priv( const mbedtls_ecp_keypair *pub, const mbedtls_ecp_keypair *prv ); #if defined(MBEDTLS_SELF_TEST) /** - * \brief Checkup routine + * \brief The ECP checkup routine. * - * \return 0 if successful, or 1 if a test failed + * \return \c 0 on success. + * \return \c 1 on failure. */ int mbedtls_ecp_self_test( int verbose ); @@ -679,8 +761,4 @@ int mbedtls_ecp_self_test( int verbose ); } #endif -#else /* MBEDTLS_ECP_ALT */ -#include "ecp_alt.h" -#endif /* MBEDTLS_ECP_ALT */ - #endif /* ecp.h */ diff --git a/thirdparty/mbedtls/include/mbedtls/ecp_internal.h b/thirdparty/mbedtls/include/mbedtls/ecp_internal.h index 8a6d517ed0..18040697ad 100644 --- a/thirdparty/mbedtls/include/mbedtls/ecp_internal.h +++ b/thirdparty/mbedtls/include/mbedtls/ecp_internal.h @@ -48,7 +48,7 @@ * [6] Digital Signature Standard (DSS), FIPS 186-4. * <http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf> * - * [7] Elliptic Curve Cryptography (ECC) Cipher Suites for Transport Layer + * [7] Elliptic Curve Cryptography (ECC) Cipher Suites for Transport Layer * Security (TLS), RFC 4492. * <https://tools.ietf.org/search/rfc4492> * diff --git a/thirdparty/mbedtls/include/mbedtls/entropy.h b/thirdparty/mbedtls/include/mbedtls/entropy.h index fcb4d02557..a5cb05a584 100644 --- a/thirdparty/mbedtls/include/mbedtls/entropy.h +++ b/thirdparty/mbedtls/include/mbedtls/entropy.h @@ -166,7 +166,7 @@ void mbedtls_entropy_free( mbedtls_entropy_context *ctx ); * \param threshold Minimum required from source before entropy is released * ( with mbedtls_entropy_func() ) (in bytes) * \param strong MBEDTLS_ENTROPY_SOURCE_STRONG or - * MBEDTSL_ENTROPY_SOURCE_WEAK. + * MBEDTLS_ENTROPY_SOURCE_WEAK. * At least one strong source needs to be added. * Weaker sources (such as the cycle counter) can be used as * a complement. diff --git a/thirdparty/mbedtls/include/mbedtls/error.h b/thirdparty/mbedtls/include/mbedtls/error.h index 8b4d3a8755..6b82d4fbbe 100644 --- a/thirdparty/mbedtls/include/mbedtls/error.h +++ b/thirdparty/mbedtls/include/mbedtls/error.h @@ -4,7 +4,7 @@ * \brief Error to string translation */ /* - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Copyright (C) 2006-2018, ARM Limited, All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); you may @@ -53,7 +53,7 @@ * GCM 3 0x0012-0x0014 0x0013-0x0013 * BLOWFISH 3 0x0016-0x0018 0x0017-0x0017 * THREADING 3 0x001A-0x001E - * AES 4 0x0020-0x0022 0x0023-0x0025 + * AES 5 0x0020-0x0022 0x0021-0x0025 * CAMELLIA 3 0x0024-0x0026 0x0027-0x0027 * XTEA 2 0x0028-0x0028 0x0029-0x0029 * BASE64 2 0x002A-0x002C @@ -62,7 +62,8 @@ * DES 2 0x0032-0x0032 0x0033-0x0033 * CTR_DBRG 4 0x0034-0x003A * ENTROPY 3 0x003C-0x0040 0x003D-0x003F - * NET 11 0x0042-0x0052 0x0043-0x0045 + * NET 13 0x0042-0x0052 0x0043-0x0049 + * ARIA 4 0x0058-0x005E * ASN1 7 0x0060-0x006C * CMAC 1 0x007A-0x007A * PBKDF2 1 0x007C-0x007C @@ -76,6 +77,9 @@ * SHA1 1 0x0035-0x0035 * SHA256 1 0x0037-0x0037 * SHA512 1 0x0039-0x0039 + * CHACHA20 3 0x0051-0x0055 + * POLY1305 3 0x0057-0x005B + * CHACHAPOLY 2 0x0054-0x0056 * * High-level module nr (3 bits - 0x0...-0x7...) * Name ID Nr of Errors @@ -88,8 +92,9 @@ * RSA 4 11 * ECP 4 9 (Started from top) * MD 5 5 + * HKDF 5 1 (Started from top) * CIPHER 6 8 - * SSL 6 17 (Started from top) + * SSL 6 22 (Started from top) * SSL 7 31 * * Module dependent error code (5 bits 0x.00.-0x.F8.) diff --git a/thirdparty/mbedtls/include/mbedtls/gcm.h b/thirdparty/mbedtls/include/mbedtls/gcm.h index 1e5a507a26..87535ab957 100644 --- a/thirdparty/mbedtls/include/mbedtls/gcm.h +++ b/thirdparty/mbedtls/include/mbedtls/gcm.h @@ -1,9 +1,11 @@ /** * \file gcm.h * - * \brief Galois/Counter Mode (GCM) for 128-bit block ciphers, as defined - * in <em>D. McGrew, J. Viega, The Galois/Counter Mode of Operation - * (GCM), Natl. Inst. Stand. Technol.</em> + * \brief This file contains GCM definitions and functions. + * + * The Galois/Counter Mode (GCM) for 128-bit block ciphers is defined + * in <em>D. McGrew, J. Viega, The Galois/Counter Mode of Operation + * (GCM), Natl. Inst. Stand. Technol.</em> * * For more information on GCM, see <em>NIST SP 800-38D: Recommendation for * Block Cipher Modes of Operation: Galois/Counter Mode (GCM) and GMAC</em>. @@ -42,12 +44,12 @@ #define MBEDTLS_ERR_GCM_HW_ACCEL_FAILED -0x0013 /**< GCM hardware accelerator failed. */ #define MBEDTLS_ERR_GCM_BAD_INPUT -0x0014 /**< Bad input parameters to function. */ -#if !defined(MBEDTLS_GCM_ALT) - #ifdef __cplusplus extern "C" { #endif +#if !defined(MBEDTLS_GCM_ALT) + /** * \brief The GCM context structure. */ @@ -66,6 +68,10 @@ typedef struct { } mbedtls_gcm_context; +#else /* !MBEDTLS_GCM_ALT */ +#include "gcm_alt.h" +#endif /* !MBEDTLS_GCM_ALT */ + /** * \brief This function initializes the specified GCM context, * to make references valid, and prepares the context @@ -91,7 +97,8 @@ void mbedtls_gcm_init( mbedtls_gcm_context *ctx ); * <li>192 bits</li> * <li>256 bits</li></ul> * - * \return \c 0 on success, or a cipher specific error code. + * \return \c 0 on success. + * \return A cipher-specific error code on failure. */ int mbedtls_gcm_setkey( mbedtls_gcm_context *ctx, mbedtls_cipher_id_t cipher, @@ -101,25 +108,46 @@ int mbedtls_gcm_setkey( mbedtls_gcm_context *ctx, /** * \brief This function performs GCM encryption or decryption of a buffer. * - * \note For encryption, the output buffer can be the same as the input buffer. - * For decryption, the output buffer cannot be the same as input buffer. - * If the buffers overlap, the output buffer must trail at least 8 Bytes - * behind the input buffer. + * \note For encryption, the output buffer can be the same as the + * input buffer. For decryption, the output buffer cannot be + * the same as input buffer. If the buffers overlap, the output + * buffer must trail at least 8 Bytes behind the input buffer. + * + * \warning When this function performs a decryption, it outputs the + * authentication tag and does not verify that the data is + * authentic. You should use this function to perform encryption + * only. For decryption, use mbedtls_gcm_auth_decrypt() instead. * * \param ctx The GCM context to use for encryption or decryption. - * \param mode The operation to perform: #MBEDTLS_GCM_ENCRYPT or - * #MBEDTLS_GCM_DECRYPT. - * \param length The length of the input data. This must be a multiple of 16 except in the last call before mbedtls_gcm_finish(). + * \param mode The operation to perform: + * - #MBEDTLS_GCM_ENCRYPT to perform authenticated encryption. + * The ciphertext is written to \p output and the + * authentication tag is written to \p tag. + * - #MBEDTLS_GCM_DECRYPT to perform decryption. + * The plaintext is written to \p output and the + * authentication tag is written to \p tag. + * Note that this mode is not recommended, because it does + * not verify the authenticity of the data. For this reason, + * you should use mbedtls_gcm_auth_decrypt() instead of + * calling this function in decryption mode. + * \param length The length of the input data, which is equal to the length + * of the output data. * \param iv The initialization vector. * \param iv_len The length of the IV. * \param add The buffer holding the additional data. * \param add_len The length of the additional data. - * \param input The buffer holding the input data. - * \param output The buffer for holding the output data. + * \param input The buffer holding the input data. Its size is \b length. + * \param output The buffer for holding the output data. It must have room + * for \b length bytes. * \param tag_len The length of the tag to generate. * \param tag The buffer for holding the tag. * - * \return \c 0 on success. + * \return \c 0 if the encryption or decryption was performed + * successfully. Note that in #MBEDTLS_GCM_DECRYPT mode, + * this does not indicate that the data is authentic. + * \return #MBEDTLS_ERR_GCM_BAD_INPUT if the lengths are not valid. + * \return #MBEDTLS_ERR_GCM_HW_ACCEL_FAILED or a cipher-specific + * error code if the encryption or decryption failed. */ int mbedtls_gcm_crypt_and_tag( mbedtls_gcm_context *ctx, int mode, @@ -137,23 +165,28 @@ int mbedtls_gcm_crypt_and_tag( mbedtls_gcm_context *ctx, * \brief This function performs a GCM authenticated decryption of a * buffer. * - * \note For decryption, the output buffer cannot be the same as input buffer. - * If the buffers overlap, the output buffer must trail at least 8 Bytes - * behind the input buffer. + * \note For decryption, the output buffer cannot be the same as + * input buffer. If the buffers overlap, the output buffer + * must trail at least 8 Bytes behind the input buffer. * * \param ctx The GCM context. - * \param length The length of the input data. This must be a multiple of 16 except in the last call before mbedtls_gcm_finish(). + * \param length The length of the ciphertext to decrypt, which is also + * the length of the decrypted plaintext. * \param iv The initialization vector. * \param iv_len The length of the IV. * \param add The buffer holding the additional data. * \param add_len The length of the additional data. - * \param tag The buffer holding the tag. - * \param tag_len The length of the tag. - * \param input The buffer holding the input data. - * \param output The buffer for holding the output data. + * \param tag The buffer holding the tag to verify. + * \param tag_len The length of the tag to verify. + * \param input The buffer holding the ciphertext. Its size is \b length. + * \param output The buffer for holding the decrypted plaintext. It must + * have room for \b length bytes. * - * \return 0 if successful and authenticated, or - * #MBEDTLS_ERR_GCM_AUTH_FAILED if tag does not match. + * \return \c 0 if successful and authenticated. + * \return #MBEDTLS_ERR_GCM_AUTH_FAILED if the tag does not match. + * \return #MBEDTLS_ERR_GCM_BAD_INPUT if the lengths are not valid. + * \return #MBEDTLS_ERR_GCM_HW_ACCEL_FAILED or a cipher-specific + * error code if the decryption failed. */ int mbedtls_gcm_auth_decrypt( mbedtls_gcm_context *ctx, size_t length, @@ -175,10 +208,12 @@ int mbedtls_gcm_auth_decrypt( mbedtls_gcm_context *ctx, * #MBEDTLS_GCM_DECRYPT. * \param iv The initialization vector. * \param iv_len The length of the IV. - * \param add The buffer holding the additional data, or NULL if \p add_len is 0. - * \param add_len The length of the additional data. If 0, \p add is NULL. + * \param add The buffer holding the additional data, or NULL + * if \p add_len is 0. + * \param add_len The length of the additional data. If 0, + * \p add is NULL. * - * \return \c 0 on success. + * \return \c 0 on success. */ int mbedtls_gcm_starts( mbedtls_gcm_context *ctx, int mode, @@ -195,16 +230,18 @@ int mbedtls_gcm_starts( mbedtls_gcm_context *ctx, * Bytes. Only the last call before calling * mbedtls_gcm_finish() can be less than 16 Bytes. * - * \note For decryption, the output buffer cannot be the same as input buffer. - * If the buffers overlap, the output buffer must trail at least 8 Bytes - * behind the input buffer. + * \note For decryption, the output buffer cannot be the same as + * input buffer. If the buffers overlap, the output buffer + * must trail at least 8 Bytes behind the input buffer. * * \param ctx The GCM context. - * \param length The length of the input data. This must be a multiple of 16 except in the last call before mbedtls_gcm_finish(). + * \param length The length of the input data. This must be a multiple of + * 16 except in the last call before mbedtls_gcm_finish(). * \param input The buffer holding the input data. * \param output The buffer for holding the output data. * - * \return \c 0 on success, or #MBEDTLS_ERR_GCM_BAD_INPUT on failure. + * \return \c 0 on success. + * \return #MBEDTLS_ERR_GCM_BAD_INPUT on failure. */ int mbedtls_gcm_update( mbedtls_gcm_context *ctx, size_t length, @@ -222,7 +259,8 @@ int mbedtls_gcm_update( mbedtls_gcm_context *ctx, * \param tag The buffer for holding the tag. * \param tag_len The length of the tag to generate. Must be at least four. * - * \return \c 0 on success, or #MBEDTLS_ERR_GCM_BAD_INPUT on failure. + * \return \c 0 on success. + * \return #MBEDTLS_ERR_GCM_BAD_INPUT on failure. */ int mbedtls_gcm_finish( mbedtls_gcm_context *ctx, unsigned char *tag, @@ -236,22 +274,11 @@ int mbedtls_gcm_finish( mbedtls_gcm_context *ctx, */ void mbedtls_gcm_free( mbedtls_gcm_context *ctx ); -#ifdef __cplusplus -} -#endif - -#else /* !MBEDTLS_GCM_ALT */ -#include "gcm_alt.h" -#endif /* !MBEDTLS_GCM_ALT */ - -#ifdef __cplusplus -extern "C" { -#endif - /** * \brief The GCM checkup routine. * - * \return \c 0 on success, or \c 1 on failure. + * \return \c 0 on success. + * \return \c 1 on failure. */ int mbedtls_gcm_self_test( int verbose ); diff --git a/thirdparty/mbedtls/include/mbedtls/hkdf.h b/thirdparty/mbedtls/include/mbedtls/hkdf.h new file mode 100644 index 0000000000..6833e7272e --- /dev/null +++ b/thirdparty/mbedtls/include/mbedtls/hkdf.h @@ -0,0 +1,125 @@ +/** + * \file hkdf.h + * + * \brief This file contains the HKDF interface. + * + * The HMAC-based Extract-and-Expand Key Derivation Function (HKDF) is + * specified by RFC 5869. + */ +/* + * Copyright (C) 2016-2018, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +#ifndef MBEDTLS_HKDF_H +#define MBEDTLS_HKDF_H + +#include "md.h" + +/** + * \name HKDF Error codes + * \{ + */ +#define MBEDTLS_ERR_HKDF_BAD_INPUT_DATA -0x5F80 /**< Bad input parameters to function. */ +/* \} name */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief This is the HMAC-based Extract-and-Expand Key Derivation Function + * (HKDF). + * + * \param md A hash function; md.size denotes the length of the hash + * function output in bytes. + * \param salt An optional salt value (a non-secret random value); + * if the salt is not provided, a string of all zeros of + * md.size length is used as the salt. + * \param salt_len The length in bytes of the optional \p salt. + * \param ikm The input keying material. + * \param ikm_len The length in bytes of \p ikm. + * \param info An optional context and application specific information + * string. This can be a zero-length string. + * \param info_len The length of \p info in bytes. + * \param okm The output keying material of \p okm_len bytes. + * \param okm_len The length of the output keying material in bytes. This + * must be less than or equal to 255 * md.size bytes. + * + * \return 0 on success. + * \return #MBEDTLS_ERR_HKDF_BAD_INPUT_DATA when the parameters are invalid. + * \return An MBEDTLS_ERR_MD_* error for errors returned from the underlying + * MD layer. + */ +int mbedtls_hkdf( const mbedtls_md_info_t *md, const unsigned char *salt, + size_t salt_len, const unsigned char *ikm, size_t ikm_len, + const unsigned char *info, size_t info_len, + unsigned char *okm, size_t okm_len ); + +/** + * \brief Take the input keying material \p ikm and extract from it a + * fixed-length pseudorandom key \p prk. + * + * \param md A hash function; md.size denotes the length of the + * hash function output in bytes. + * \param salt An optional salt value (a non-secret random value); + * if the salt is not provided, a string of all zeros + * of md.size length is used as the salt. + * \param salt_len The length in bytes of the optional \p salt. + * \param ikm The input keying material. + * \param ikm_len The length in bytes of \p ikm. + * \param[out] prk A pseudorandom key of at least md.size bytes. + * + * \return 0 on success. + * \return #MBEDTLS_ERR_HKDF_BAD_INPUT_DATA when the parameters are invalid. + * \return An MBEDTLS_ERR_MD_* error for errors returned from the underlying + * MD layer. + */ +int mbedtls_hkdf_extract( const mbedtls_md_info_t *md, + const unsigned char *salt, size_t salt_len, + const unsigned char *ikm, size_t ikm_len, + unsigned char *prk ); + +/** + * \brief Expand the supplied \p prk into several additional pseudorandom + * keys, which is the output of the HKDF. + * + * \param md A hash function; md.size denotes the length of the hash + * function output in bytes. + * \param prk A pseudorandom key of at least md.size bytes. \p prk is usually, + * the output from the HKDF extract step. + * \param prk_len The length in bytes of \p prk. + * \param info An optional context and application specific information + * string. This can be a zero-length string. + * \param info_len The length of \p info in bytes. + * \param okm The output keying material of \p okm_len bytes. + * \param okm_len The length of the output keying material in bytes. This + * must be less than or equal to 255 * md.size bytes. + * + * \return 0 on success. + * \return #MBEDTLS_ERR_HKDF_BAD_INPUT_DATA when the parameters are invalid. + * \return An MBEDTLS_ERR_MD_* error for errors returned from the underlying + * MD layer. + */ +int mbedtls_hkdf_expand( const mbedtls_md_info_t *md, const unsigned char *prk, + size_t prk_len, const unsigned char *info, + size_t info_len, unsigned char *okm, size_t okm_len ); + +#ifdef __cplusplus +} +#endif + +#endif /* hkdf.h */ diff --git a/thirdparty/mbedtls/include/mbedtls/hmac_drbg.h b/thirdparty/mbedtls/include/mbedtls/hmac_drbg.h index e0821cf788..2608de8595 100644 --- a/thirdparty/mbedtls/include/mbedtls/hmac_drbg.h +++ b/thirdparty/mbedtls/include/mbedtls/hmac_drbg.h @@ -27,7 +27,7 @@ #include "md.h" #if defined(MBEDTLS_THREADING_C) -#include "mbedtls/threading.h" +#include "threading.h" #endif /* diff --git a/thirdparty/mbedtls/include/mbedtls/md.h b/thirdparty/mbedtls/include/mbedtls/md.h index 06538c3827..6b6f5c53dd 100644 --- a/thirdparty/mbedtls/include/mbedtls/md.h +++ b/thirdparty/mbedtls/include/mbedtls/md.h @@ -1,7 +1,7 @@ /** * \file md.h * - * \brief The generic message-digest wrapper. + * \brief This file contains the generic message-digest wrapper. * * \author Adriaan de Jong <dejong@fox-it.com> */ @@ -46,7 +46,7 @@ extern "C" { #endif /** - * \brief Enumeration of supported message digests + * \brief Supported message digests. * * \warning MD2, MD4, MD5 and SHA-1 are considered weak message digests and * their use constitutes a security risk. We recommend considering @@ -54,16 +54,16 @@ extern "C" { * */ typedef enum { - MBEDTLS_MD_NONE=0, - MBEDTLS_MD_MD2, - MBEDTLS_MD_MD4, - MBEDTLS_MD_MD5, - MBEDTLS_MD_SHA1, - MBEDTLS_MD_SHA224, - MBEDTLS_MD_SHA256, - MBEDTLS_MD_SHA384, - MBEDTLS_MD_SHA512, - MBEDTLS_MD_RIPEMD160, + MBEDTLS_MD_NONE=0, /**< None. */ + MBEDTLS_MD_MD2, /**< The MD2 message digest. */ + MBEDTLS_MD_MD4, /**< The MD4 message digest. */ + MBEDTLS_MD_MD5, /**< The MD5 message digest. */ + MBEDTLS_MD_SHA1, /**< The SHA-1 message digest. */ + MBEDTLS_MD_SHA224, /**< The SHA-224 message digest. */ + MBEDTLS_MD_SHA256, /**< The SHA-256 message digest. */ + MBEDTLS_MD_SHA384, /**< The SHA-384 message digest. */ + MBEDTLS_MD_SHA512, /**< The SHA-512 message digest. */ + MBEDTLS_MD_RIPEMD160, /**< The RIPEMD-160 message digest. */ } mbedtls_md_type_t; #if defined(MBEDTLS_SHA512_C) @@ -108,8 +108,8 @@ const int *mbedtls_md_list( void ); * * \param md_name The name of the digest to search for. * - * \return The message-digest information associated with \p md_name, - * or NULL if not found. + * \return The message-digest information associated with \p md_name. + * \return NULL if the associated message-digest information is not found. */ const mbedtls_md_info_t *mbedtls_md_info_from_string( const char *md_name ); @@ -119,8 +119,8 @@ const mbedtls_md_info_t *mbedtls_md_info_from_string( const char *md_name ); * * \param md_type The type of digest to search for. * - * \return The message-digest information associated with \p md_type, - * or NULL if not found. + * \return The message-digest information associated with \p md_type. + * \return NULL if the associated message-digest information is not found. */ const mbedtls_md_info_t *mbedtls_md_info_from_type( mbedtls_md_type_t md_type ); @@ -168,9 +168,10 @@ void mbedtls_md_free( mbedtls_md_context_t *ctx ); * \param md_info The information structure of the message-digest algorithm * to use. * - * \returns \c 0 on success, - * #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter failure, - * #MBEDTLS_ERR_MD_ALLOC_FAILED memory allocation failure. + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification + * failure. + * \return #MBEDTLS_ERR_MD_ALLOC_FAILED on memory-allocation failure. */ int mbedtls_md_init_ctx( mbedtls_md_context_t *ctx, const mbedtls_md_info_t *md_info ) MBEDTLS_DEPRECATED; #undef MBEDTLS_DEPRECATED @@ -187,12 +188,13 @@ int mbedtls_md_init_ctx( mbedtls_md_context_t *ctx, const mbedtls_md_info_t *md_ * \param ctx The context to set up. * \param md_info The information structure of the message-digest algorithm * to use. - * \param hmac <ul><li>0: HMAC is not used. Saves some memory.</li> - * <li>non-zero: HMAC is used with this context.</li></ul> + * \param hmac Defines if HMAC is used. 0: HMAC is not used (saves some memory), + * or non-zero: HMAC is used with this context. * - * \returns \c 0 on success, - * #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter failure, or - * #MBEDTLS_ERR_MD_ALLOC_FAILED on memory allocation failure. + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification + * failure. + * \return #MBEDTLS_ERR_MD_ALLOC_FAILED on memory-allocation failure. */ int mbedtls_md_setup( mbedtls_md_context_t *ctx, const mbedtls_md_info_t *md_info, int hmac ); @@ -212,8 +214,8 @@ int mbedtls_md_setup( mbedtls_md_context_t *ctx, const mbedtls_md_info_t *md_inf * \param dst The destination context. * \param src The context to be cloned. * - * \return \c 0 on success, - * #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter failure. + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification failure. */ int mbedtls_md_clone( mbedtls_md_context_t *dst, const mbedtls_md_context_t *src ); @@ -260,8 +262,9 @@ const char *mbedtls_md_get_name( const mbedtls_md_info_t *md_info ); * * \param ctx The generic message-digest context. * - * \returns \c 0 on success, #MBEDTLS_ERR_MD_BAD_INPUT_DATA if - * parameter verification fails. + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification + * failure. */ int mbedtls_md_starts( mbedtls_md_context_t *ctx ); @@ -277,8 +280,9 @@ int mbedtls_md_starts( mbedtls_md_context_t *ctx ); * \param input The buffer holding the input data. * \param ilen The length of the input data. * - * \returns \c 0 on success, #MBEDTLS_ERR_MD_BAD_INPUT_DATA if - * parameter verification fails. + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification + * failure. */ int mbedtls_md_update( mbedtls_md_context_t *ctx, const unsigned char *input, size_t ilen ); @@ -296,8 +300,9 @@ int mbedtls_md_update( mbedtls_md_context_t *ctx, const unsigned char *input, si * \param ctx The generic message-digest context. * \param output The buffer for the generic message-digest checksum result. * - * \returns \c 0 on success, or #MBEDTLS_ERR_MD_BAD_INPUT_DATA if - * parameter verification fails. + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification + * failure. */ int mbedtls_md_finish( mbedtls_md_context_t *ctx, unsigned char *output ); @@ -315,8 +320,9 @@ int mbedtls_md_finish( mbedtls_md_context_t *ctx, unsigned char *output ); * \param ilen The length of the input data. * \param output The generic message-digest checksum result. * - * \returns \c 0 on success, or #MBEDTLS_ERR_MD_BAD_INPUT_DATA if - * parameter verification fails. + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification + * failure. */ int mbedtls_md( const mbedtls_md_info_t *md_info, const unsigned char *input, size_t ilen, unsigned char *output ); @@ -334,9 +340,10 @@ int mbedtls_md( const mbedtls_md_info_t *md_info, const unsigned char *input, si * \param path The input file name. * \param output The generic message-digest checksum result. * - * \return \c 0 on success, - * #MBEDTLS_ERR_MD_FILE_IO_ERROR if file input failed, or - * #MBEDTLS_ERR_MD_BAD_INPUT_DATA if \p md_info was NULL. + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_FILE_IO_ERROR on an I/O error accessing + * the file pointed by \p path. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA if \p md_info was NULL. */ int mbedtls_md_file( const mbedtls_md_info_t *md_info, const char *path, unsigned char *output ); @@ -356,8 +363,9 @@ int mbedtls_md_file( const mbedtls_md_info_t *md_info, const char *path, * \param key The HMAC secret key. * \param keylen The length of the HMAC key in Bytes. * - * \returns \c 0 on success, or #MBEDTLS_ERR_MD_BAD_INPUT_DATA if - * parameter verification fails. + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification + * failure. */ int mbedtls_md_hmac_starts( mbedtls_md_context_t *ctx, const unsigned char *key, size_t keylen ); @@ -377,8 +385,9 @@ int mbedtls_md_hmac_starts( mbedtls_md_context_t *ctx, const unsigned char *key, * \param input The buffer holding the input data. * \param ilen The length of the input data. * - * \returns \c 0 on success, or #MBEDTLS_ERR_MD_BAD_INPUT_DATA if - * parameter verification fails. + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification + * failure. */ int mbedtls_md_hmac_update( mbedtls_md_context_t *ctx, const unsigned char *input, size_t ilen ); @@ -397,8 +406,9 @@ int mbedtls_md_hmac_update( mbedtls_md_context_t *ctx, const unsigned char *inpu * context. * \param output The generic HMAC checksum result. * - * \returns \c 0 on success, or #MBEDTLS_ERR_MD_BAD_INPUT_DATA if - * parameter verification fails. + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification + * failure. */ int mbedtls_md_hmac_finish( mbedtls_md_context_t *ctx, unsigned char *output); @@ -413,8 +423,9 @@ int mbedtls_md_hmac_finish( mbedtls_md_context_t *ctx, unsigned char *output); * \param ctx The message digest context containing an embedded HMAC * context. * - * \returns \c 0 on success, or #MBEDTLS_ERR_MD_BAD_INPUT_DATA if - * parameter verification fails. + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification + * failure. */ int mbedtls_md_hmac_reset( mbedtls_md_context_t *ctx ); @@ -436,8 +447,9 @@ int mbedtls_md_hmac_reset( mbedtls_md_context_t *ctx ); * \param ilen The length of the input data. * \param output The generic HMAC result. * - * \returns \c 0 on success, or #MBEDTLS_ERR_MD_BAD_INPUT_DATA if - * parameter verification fails. + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification + * failure. */ int mbedtls_md_hmac( const mbedtls_md_info_t *md_info, const unsigned char *key, size_t keylen, const unsigned char *input, size_t ilen, diff --git a/thirdparty/mbedtls/include/mbedtls/md2.h b/thirdparty/mbedtls/include/mbedtls/md2.h index 0fd8b5afcc..08e75b247b 100644 --- a/thirdparty/mbedtls/include/mbedtls/md2.h +++ b/thirdparty/mbedtls/include/mbedtls/md2.h @@ -39,14 +39,14 @@ #define MBEDTLS_ERR_MD2_HW_ACCEL_FAILED -0x002B /**< MD2 hardware accelerator failed */ -#if !defined(MBEDTLS_MD2_ALT) -// Regular implementation -// - #ifdef __cplusplus extern "C" { #endif +#if !defined(MBEDTLS_MD2_ALT) +// Regular implementation +// + /** * \brief MD2 context structure * @@ -64,6 +64,10 @@ typedef struct } mbedtls_md2_context; +#else /* MBEDTLS_MD2_ALT */ +#include "md2_alt.h" +#endif /* MBEDTLS_MD2_ALT */ + /** * \brief Initialize MD2 context * @@ -235,18 +239,6 @@ MBEDTLS_DEPRECATED void mbedtls_md2_process( mbedtls_md2_context *ctx ); #undef MBEDTLS_DEPRECATED #endif /* !MBEDTLS_DEPRECATED_REMOVED */ -#ifdef __cplusplus -} -#endif - -#else /* MBEDTLS_MD2_ALT */ -#include "md2_alt.h" -#endif /* MBEDTLS_MD2_ALT */ - -#ifdef __cplusplus -extern "C" { -#endif - /** * \brief Output = MD2( input buffer ) * diff --git a/thirdparty/mbedtls/include/mbedtls/md4.h b/thirdparty/mbedtls/include/mbedtls/md4.h index 23fa95e46a..8ee4e5cabf 100644 --- a/thirdparty/mbedtls/include/mbedtls/md4.h +++ b/thirdparty/mbedtls/include/mbedtls/md4.h @@ -40,14 +40,14 @@ #define MBEDTLS_ERR_MD4_HW_ACCEL_FAILED -0x002D /**< MD4 hardware accelerator failed */ -#if !defined(MBEDTLS_MD4_ALT) -// Regular implementation -// - #ifdef __cplusplus extern "C" { #endif +#if !defined(MBEDTLS_MD4_ALT) +// Regular implementation +// + /** * \brief MD4 context structure * @@ -64,6 +64,10 @@ typedef struct } mbedtls_md4_context; +#else /* MBEDTLS_MD4_ALT */ +#include "md4_alt.h" +#endif /* MBEDTLS_MD4_ALT */ + /** * \brief Initialize MD4 context * @@ -238,18 +242,6 @@ MBEDTLS_DEPRECATED void mbedtls_md4_process( mbedtls_md4_context *ctx, #undef MBEDTLS_DEPRECATED #endif /* !MBEDTLS_DEPRECATED_REMOVED */ -#ifdef __cplusplus -} -#endif - -#else /* MBEDTLS_MD4_ALT */ -#include "md4_alt.h" -#endif /* MBEDTLS_MD4_ALT */ - -#ifdef __cplusplus -extern "C" { -#endif - /** * \brief Output = MD4( input buffer ) * diff --git a/thirdparty/mbedtls/include/mbedtls/md5.h b/thirdparty/mbedtls/include/mbedtls/md5.h index 06ea4c5d44..43ead4b747 100644 --- a/thirdparty/mbedtls/include/mbedtls/md5.h +++ b/thirdparty/mbedtls/include/mbedtls/md5.h @@ -39,14 +39,14 @@ #define MBEDTLS_ERR_MD5_HW_ACCEL_FAILED -0x002F /**< MD5 hardware accelerator failed */ -#if !defined(MBEDTLS_MD5_ALT) -// Regular implementation -// - #ifdef __cplusplus extern "C" { #endif +#if !defined(MBEDTLS_MD5_ALT) +// Regular implementation +// + /** * \brief MD5 context structure * @@ -63,6 +63,10 @@ typedef struct } mbedtls_md5_context; +#else /* MBEDTLS_MD5_ALT */ +#include "md5_alt.h" +#endif /* MBEDTLS_MD5_ALT */ + /** * \brief Initialize MD5 context * @@ -238,18 +242,6 @@ MBEDTLS_DEPRECATED void mbedtls_md5_process( mbedtls_md5_context *ctx, #undef MBEDTLS_DEPRECATED #endif /* !MBEDTLS_DEPRECATED_REMOVED */ -#ifdef __cplusplus -} -#endif - -#else /* MBEDTLS_MD5_ALT */ -#include "md5_alt.h" -#endif /* MBEDTLS_MD5_ALT */ - -#ifdef __cplusplus -extern "C" { -#endif - /** * \brief Output = MD5( input buffer ) * diff --git a/thirdparty/mbedtls/include/mbedtls/net.h b/thirdparty/mbedtls/include/mbedtls/net.h index 28ae8217c0..6c13b53fb9 100644 --- a/thirdparty/mbedtls/include/mbedtls/net.h +++ b/thirdparty/mbedtls/include/mbedtls/net.h @@ -1,7 +1,7 @@ /** * \file net.h * - * \brief Deprecated header file that includes mbedtls/net_sockets.h + * \brief Deprecated header file that includes net_sockets.h * * \deprecated Superseded by mbedtls/net_sockets.h */ @@ -25,7 +25,7 @@ */ #if !defined(MBEDTLS_DEPRECATED_REMOVED) -#include "mbedtls/net_sockets.h" +#include "net_sockets.h" #if defined(MBEDTLS_DEPRECATED_WARNING) #warning "Deprecated header file: Superseded by mbedtls/net_sockets.h" #endif /* MBEDTLS_DEPRECATED_WARNING */ diff --git a/thirdparty/mbedtls/include/mbedtls/net_sockets.h b/thirdparty/mbedtls/include/mbedtls/net_sockets.h index 54e612cc5e..9f07eeb4d3 100644 --- a/thirdparty/mbedtls/include/mbedtls/net_sockets.h +++ b/thirdparty/mbedtls/include/mbedtls/net_sockets.h @@ -1,7 +1,23 @@ /** * \file net_sockets.h * - * \brief Network communication functions + * \brief Network sockets abstraction layer to integrate Mbed TLS into a + * BSD-style sockets API. + * + * The network sockets module provides an example integration of the + * Mbed TLS library into a BSD sockets implementation. The module is + * intended to be an example of how Mbed TLS can be integrated into a + * networking stack, as well as to be Mbed TLS's network integration + * for its supported platforms. + * + * The module is intended only to be used with the Mbed TLS library and + * is not intended to be used by third party application software + * directly. + * + * The supported platforms are as follows: + * * Microsoft Windows and Windows CE + * * POSIX/Unix platforms including Linux, OS X + * */ /* * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved @@ -46,12 +62,17 @@ #define MBEDTLS_ERR_NET_UNKNOWN_HOST -0x0052 /**< Failed to get an IP address for the given hostname. */ #define MBEDTLS_ERR_NET_BUFFER_TOO_SMALL -0x0043 /**< Buffer is too small to hold the data. */ #define MBEDTLS_ERR_NET_INVALID_CONTEXT -0x0045 /**< The context is invalid, eg because it was free()ed. */ +#define MBEDTLS_ERR_NET_POLL_FAILED -0x0047 /**< Polling the net context failed. */ +#define MBEDTLS_ERR_NET_BAD_INPUT_DATA -0x0049 /**< Input invalid. */ #define MBEDTLS_NET_LISTEN_BACKLOG 10 /**< The backlog that listen() should use. */ #define MBEDTLS_NET_PROTO_TCP 0 /**< The TCP transport protocol */ #define MBEDTLS_NET_PROTO_UDP 1 /**< The UDP transport protocol */ +#define MBEDTLS_NET_POLL_READ 1 /**< Used in \c mbedtls_net_poll to check for pending data */ +#define MBEDTLS_NET_POLL_WRITE 2 /**< Used in \c mbedtls_net_poll to check if write possible */ + #ifdef __cplusplus extern "C" { #endif @@ -118,9 +139,10 @@ int mbedtls_net_bind( mbedtls_net_context *ctx, const char *bind_ip, const char * * \param bind_ctx Relevant socket * \param client_ctx Will contain the connected client socket - * \param client_ip Will contain the client IP address + * \param client_ip Will contain the client IP address, can be NULL * \param buf_size Size of the client_ip buffer - * \param ip_len Will receive the size of the client IP written + * \param ip_len Will receive the size of the client IP written, + * can be NULL if client_ip is null * * \return 0 if successful, or * MBEDTLS_ERR_NET_ACCEPT_FAILED, or @@ -133,6 +155,29 @@ int mbedtls_net_accept( mbedtls_net_context *bind_ctx, void *client_ip, size_t buf_size, size_t *ip_len ); /** + * \brief Check and wait for the context to be ready for read/write + * + * \param ctx Socket to check + * \param rw Bitflag composed of MBEDTLS_NET_POLL_READ and + * MBEDTLS_NET_POLL_WRITE specifying the events + * to wait for: + * - If MBEDTLS_NET_POLL_READ is set, the function + * will return as soon as the net context is available + * for reading. + * - If MBEDTLS_NET_POLL_WRITE is set, the function + * will return as soon as the net context is available + * for writing. + * \param timeout Maximal amount of time to wait before returning, + * in milliseconds. If \c timeout is zero, the + * function returns immediately. If \c timeout is + * -1u, the function blocks potentially indefinitely. + * + * \return Bitmask composed of MBEDTLS_NET_POLL_READ/WRITE + * on success or timeout, or a negative return code otherwise. + */ +int mbedtls_net_poll( mbedtls_net_context *ctx, uint32_t rw, uint32_t timeout ); + +/** * \brief Set the socket blocking * * \param ctx Socket to set diff --git a/thirdparty/mbedtls/include/mbedtls/nist_kw.h b/thirdparty/mbedtls/include/mbedtls/nist_kw.h new file mode 100644 index 0000000000..5a0f656a8f --- /dev/null +++ b/thirdparty/mbedtls/include/mbedtls/nist_kw.h @@ -0,0 +1,178 @@ +/** + * \file nist_kw.h + * + * \brief This file provides an API for key wrapping (KW) and key wrapping with + * padding (KWP) as defined in NIST SP 800-38F. + * https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-38F.pdf + * + * Key wrapping specifies a deterministic authenticated-encryption mode + * of operation, according to <em>NIST SP 800-38F: Recommendation for + * Block Cipher Modes of Operation: Methods for Key Wrapping</em>. Its + * purpose is to protect cryptographic keys. + * + * Its equivalent is RFC 3394 for KW, and RFC 5649 for KWP. + * https://tools.ietf.org/html/rfc3394 + * https://tools.ietf.org/html/rfc5649 + * + */ +/* + * Copyright (C) 2018, Arm Limited (or its affiliates), All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of Mbed TLS (https://tls.mbed.org) + */ + +#ifndef MBEDTLS_NIST_KW_H +#define MBEDTLS_NIST_KW_H + +#include "cipher.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum +{ + MBEDTLS_KW_MODE_KW = 0, + MBEDTLS_KW_MODE_KWP = 1 +} mbedtls_nist_kw_mode_t; + +#if !defined(MBEDTLS_NIST_KW_ALT) +// Regular implementation +// + +/** + * \brief The key wrapping context-type definition. The key wrapping context is passed + * to the APIs called. + * + * \note The definition of this type may change in future library versions. + * Don't make any assumptions on this context! + */ +typedef struct { + mbedtls_cipher_context_t cipher_ctx; /*!< The cipher context used. */ +} mbedtls_nist_kw_context; + +#else /* MBEDTLS_NIST_key wrapping_ALT */ +#include "nist_kw_alt.h" +#endif /* MBEDTLS_NIST_KW_ALT */ + +/** + * \brief This function initializes the specified key wrapping context + * to make references valid and prepare the context + * for mbedtls_nist_kw_setkey() or mbedtls_nist_kw_free(). + * + * \param ctx The key wrapping context to initialize. + * + */ +void mbedtls_nist_kw_init( mbedtls_nist_kw_context *ctx ); + +/** + * \brief This function initializes the key wrapping context set in the + * \p ctx parameter and sets the encryption key. + * + * \param ctx The key wrapping context. + * \param cipher The 128-bit block cipher to use. Only AES is supported. + * \param key The Key Encryption Key (KEK). + * \param keybits The KEK size in bits. This must be acceptable by the cipher. + * \param is_wrap Specify whether the operation within the context is wrapping or unwrapping + * + * \return \c 0 on success. + * \return \c MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA for any invalid input. + * \return \c MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE for 128-bit block ciphers + * which are not supported. + * \return cipher-specific error code on failure of the underlying cipher. + */ +int mbedtls_nist_kw_setkey( mbedtls_nist_kw_context *ctx, + mbedtls_cipher_id_t cipher, + const unsigned char *key, + unsigned int keybits, + const int is_wrap ); + +/** + * \brief This function releases and clears the specified key wrapping context + * and underlying cipher sub-context. + * + * \param ctx The key wrapping context to clear. + */ +void mbedtls_nist_kw_free( mbedtls_nist_kw_context *ctx ); + +/** + * \brief This function encrypts a buffer using key wrapping. + * + * \param ctx The key wrapping context to use for encryption. + * \param mode The key wrapping mode to use (MBEDTLS_KW_MODE_KW or MBEDTLS_KW_MODE_KWP) + * \param input The buffer holding the input data. + * \param in_len The length of the input data in Bytes. + * The input uses units of 8 Bytes called semiblocks. + * <ul><li>For KW mode: a multiple of 8 bytes between 16 and 2^57-8 inclusive. </li> + * <li>For KWP mode: any length between 1 and 2^32-1 inclusive.</li></ul> + * \param[out] output The buffer holding the output data. + * <ul><li>For KW mode: Must be at least 8 bytes larger than \p in_len.</li> + * <li>For KWP mode: Must be at least 8 bytes larger rounded up to a multiple of + * 8 bytes for KWP (15 bytes at most).</li></ul> + * \param[out] out_len The number of bytes written to the output buffer. \c 0 on failure. + * \param[in] out_size The capacity of the output buffer. + * + * \return \c 0 on success. + * \return \c MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA for invalid input length. + * \return cipher-specific error code on failure of the underlying cipher. + */ +int mbedtls_nist_kw_wrap( mbedtls_nist_kw_context *ctx, mbedtls_nist_kw_mode_t mode, + const unsigned char *input, size_t in_len, + unsigned char *output, size_t* out_len, size_t out_size ); + +/** + * \brief This function decrypts a buffer using key wrapping. + * + * \param ctx The key wrapping context to use for decryption. + * \param mode The key wrapping mode to use (MBEDTLS_KW_MODE_KW or MBEDTLS_KW_MODE_KWP) + * \param input The buffer holding the input data. + * \param in_len The length of the input data in Bytes. + * The input uses units of 8 Bytes called semiblocks. + * The input must be a multiple of semiblocks. + * <ul><li>For KW mode: a multiple of 8 bytes between 24 and 2^57 inclusive. </li> + * <li>For KWP mode: a multiple of 8 bytes between 16 and 2^32 inclusive.</li></ul> + * \param[out] output The buffer holding the output data. + * The output buffer's minimal length is 8 bytes shorter than \p in_len. + * \param[out] out_len The number of bytes written to the output buffer. \c 0 on failure. + * For KWP mode, the length could be up to 15 bytes shorter than \p in_len, + * depending on how much padding was added to the data. + * \param[in] out_size The capacity of the output buffer. + * + * \return \c 0 on success. + * \return \c MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA for invalid input length. + * \return \c MBEDTLS_ERR_CIPHER_AUTH_FAILED for verification failure of the ciphertext. + * \return cipher-specific error code on failure of the underlying cipher. + */ +int mbedtls_nist_kw_unwrap( mbedtls_nist_kw_context *ctx, mbedtls_nist_kw_mode_t mode, + const unsigned char *input, size_t in_len, + unsigned char *output, size_t* out_len, size_t out_size); + + +#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C) +/** + * \brief The key wrapping checkup routine. + * + * \return \c 0 on success. + * \return \c 1 on failure. + */ +int mbedtls_nist_kw_self_test( int verbose ); +#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */ + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_NIST_KW_H */ diff --git a/thirdparty/mbedtls/include/mbedtls/oid.h b/thirdparty/mbedtls/include/mbedtls/oid.h index 408645ece7..f82554844c 100644 --- a/thirdparty/mbedtls/include/mbedtls/oid.h +++ b/thirdparty/mbedtls/include/mbedtls/oid.h @@ -97,6 +97,8 @@ /* ISO arc for standard certificate and CRL extensions */ #define MBEDTLS_OID_ID_CE MBEDTLS_OID_ISO_CCITT_DS "\x1D" /**< id-ce OBJECT IDENTIFIER ::= {joint-iso-ccitt(2) ds(5) 29} */ +#define MBEDTLS_OID_NIST_ALG MBEDTLS_OID_GOV "\x03\x04" /** { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistAlgorithm(4) */ + /** * Private Internet Extensions * { iso(1) identified-organization(3) dod(6) internet(1) @@ -219,12 +221,12 @@ #define MBEDTLS_OID_DIGEST_ALG_MD4 MBEDTLS_OID_RSA_COMPANY "\x02\x04" /**< id-mbedtls_md4 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 4 } */ #define MBEDTLS_OID_DIGEST_ALG_MD5 MBEDTLS_OID_RSA_COMPANY "\x02\x05" /**< id-mbedtls_md5 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 5 } */ #define MBEDTLS_OID_DIGEST_ALG_SHA1 MBEDTLS_OID_ISO_IDENTIFIED_ORG MBEDTLS_OID_OIW_SECSIG_SHA1 /**< id-mbedtls_sha1 OBJECT IDENTIFIER ::= { iso(1) identified-organization(3) oiw(14) secsig(3) algorithms(2) 26 } */ -#define MBEDTLS_OID_DIGEST_ALG_SHA224 MBEDTLS_OID_GOV "\x03\x04\x02\x04" /**< id-sha224 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 4 } */ -#define MBEDTLS_OID_DIGEST_ALG_SHA256 MBEDTLS_OID_GOV "\x03\x04\x02\x01" /**< id-mbedtls_sha256 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 1 } */ +#define MBEDTLS_OID_DIGEST_ALG_SHA224 MBEDTLS_OID_NIST_ALG "\x02\x04" /**< id-sha224 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 4 } */ +#define MBEDTLS_OID_DIGEST_ALG_SHA256 MBEDTLS_OID_NIST_ALG "\x02\x01" /**< id-mbedtls_sha256 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 1 } */ -#define MBEDTLS_OID_DIGEST_ALG_SHA384 MBEDTLS_OID_GOV "\x03\x04\x02\x02" /**< id-sha384 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 2 } */ +#define MBEDTLS_OID_DIGEST_ALG_SHA384 MBEDTLS_OID_NIST_ALG "\x02\x02" /**< id-sha384 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 2 } */ -#define MBEDTLS_OID_DIGEST_ALG_SHA512 MBEDTLS_OID_GOV "\x03\x04\x02\x03" /**< id-mbedtls_sha512 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 3 } */ +#define MBEDTLS_OID_DIGEST_ALG_SHA512 MBEDTLS_OID_NIST_ALG "\x02\x03" /**< id-mbedtls_sha512 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 3 } */ #define MBEDTLS_OID_HMAC_SHA1 MBEDTLS_OID_RSA_COMPANY "\x02\x07" /**< id-hmacWithSHA1 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 7 } */ @@ -241,8 +243,21 @@ */ #define MBEDTLS_OID_DES_CBC MBEDTLS_OID_ISO_IDENTIFIED_ORG MBEDTLS_OID_OIW_SECSIG_ALG "\x07" /**< desCBC OBJECT IDENTIFIER ::= { iso(1) identified-organization(3) oiw(14) secsig(3) algorithms(2) 7 } */ #define MBEDTLS_OID_DES_EDE3_CBC MBEDTLS_OID_RSA_COMPANY "\x03\x07" /**< des-ede3-cbc OBJECT IDENTIFIER ::= { iso(1) member-body(2) -- us(840) rsadsi(113549) encryptionAlgorithm(3) 7 } */ +#define MBEDTLS_OID_AES MBEDTLS_OID_NIST_ALG "\x01" /** aes OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistAlgorithm(4) 1 } */ /* + * Key Wrapping algorithms + */ +/* + * RFC 5649 + */ +#define MBEDTLS_OID_AES128_KW MBEDTLS_OID_AES "\x05" /** id-aes128-wrap OBJECT IDENTIFIER ::= { aes 5 } */ +#define MBEDTLS_OID_AES128_KWP MBEDTLS_OID_AES "\x08" /** id-aes128-wrap-pad OBJECT IDENTIFIER ::= { aes 8 } */ +#define MBEDTLS_OID_AES192_KW MBEDTLS_OID_AES "\x19" /** id-aes192-wrap OBJECT IDENTIFIER ::= { aes 25 } */ +#define MBEDTLS_OID_AES192_KWP MBEDTLS_OID_AES "\x1c" /** id-aes192-wrap-pad OBJECT IDENTIFIER ::= { aes 28 } */ +#define MBEDTLS_OID_AES256_KW MBEDTLS_OID_AES "\x2d" /** id-aes256-wrap OBJECT IDENTIFIER ::= { aes 45 } */ +#define MBEDTLS_OID_AES256_KWP MBEDTLS_OID_AES "\x30" /** id-aes256-wrap-pad OBJECT IDENTIFIER ::= { aes 48 } */ +/* * PKCS#5 OIDs */ #define MBEDTLS_OID_PKCS5_PBKDF2 MBEDTLS_OID_PKCS5 "\x0c" /**< id-PBKDF2 OBJECT IDENTIFIER ::= {pkcs-5 12} */ diff --git a/thirdparty/mbedtls/include/mbedtls/pk.h b/thirdparty/mbedtls/include/mbedtls/pk.h index 1059bdaa5b..ee06b2fd20 100644 --- a/thirdparty/mbedtls/include/mbedtls/pk.h +++ b/thirdparty/mbedtls/include/mbedtls/pk.h @@ -63,7 +63,7 @@ #define MBEDTLS_ERR_PK_INVALID_ALG -0x3A80 /**< The algorithm tag or value is invalid. */ #define MBEDTLS_ERR_PK_UNKNOWN_NAMED_CURVE -0x3A00 /**< Elliptic curve is unsupported (only NIST curves are supported). */ #define MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE -0x3980 /**< Unavailable feature, e.g. RSA disabled for RSA key. */ -#define MBEDTLS_ERR_PK_SIG_LEN_MISMATCH -0x3900 /**< The signature is valid but its length is less than expected. */ +#define MBEDTLS_ERR_PK_SIG_LEN_MISMATCH -0x3900 /**< The buffer contains a valid signature followed by more data. */ #define MBEDTLS_ERR_PK_HW_ACCEL_FAILED -0x3880 /**< PK hardware accelerator failed. */ #ifdef __cplusplus @@ -269,8 +269,8 @@ int mbedtls_pk_can_do( const mbedtls_pk_context *ctx, mbedtls_pk_type_t type ); * \param sig_len Signature length * * \return 0 on success (signature is valid), - * MBEDTLS_ERR_PK_SIG_LEN_MISMATCH if the signature is - * valid but its actual length is less than sig_len, + * #MBEDTLS_ERR_PK_SIG_LEN_MISMATCH if there is a valid + * signature in sig but its length is less than \p siglen, * or a specific error code. * * \note For RSA keys, the default padding type is PKCS#1 v1.5. @@ -300,10 +300,10 @@ int mbedtls_pk_verify( mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, * \param sig_len Signature length * * \return 0 on success (signature is valid), - * MBEDTLS_ERR_PK_TYPE_MISMATCH if the PK context can't be + * #MBEDTLS_ERR_PK_TYPE_MISMATCH if the PK context can't be * used for this type of signatures, - * MBEDTLS_ERR_PK_SIG_LEN_MISMATCH if the signature is - * valid but its actual length is less than sig_len, + * #MBEDTLS_ERR_PK_SIG_LEN_MISMATCH if there is a valid + * signature in sig but its length is less than \p siglen, * or a specific error code. * * \note If hash_len is 0, then the length associated with md_alg diff --git a/thirdparty/mbedtls/include/mbedtls/platform.h b/thirdparty/mbedtls/include/mbedtls/platform.h index ed10775848..624cc642ac 100644 --- a/thirdparty/mbedtls/include/mbedtls/platform.h +++ b/thirdparty/mbedtls/include/mbedtls/platform.h @@ -1,7 +1,16 @@ /** * \file platform.h * - * \brief The Mbed TLS platform abstraction layer. + * \brief This file contains the definitions and functions of the + * Mbed TLS platform abstraction layer. + * + * The platform abstraction layer removes the need for the library + * to directly link to standard C library functions or operating + * system services, making the library easier to port and embed. + * Application developers and users of the library can provide their own + * implementations of these functions, or implementations specific to + * their platform, which can be statically linked to the library or + * dynamically configured at runtime. */ /* * Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved @@ -31,7 +40,7 @@ #endif #if defined(MBEDTLS_HAVE_TIME) -#include "mbedtls/platform_time.h" +#include "platform_time.h" #endif #ifdef __cplusplus @@ -102,7 +111,7 @@ extern "C" { /* \} name SECTION: Module settings */ /* - * The function pointers for calloc and free + * The function pointers for calloc and free. */ #if defined(MBEDTLS_PLATFORM_MEMORY) #if defined(MBEDTLS_PLATFORM_FREE_MACRO) && \ @@ -112,11 +121,12 @@ extern "C" { #else /* For size_t */ #include <stddef.h> -extern void * (*mbedtls_calloc)( size_t n, size_t size ); -extern void (*mbedtls_free)( void *ptr ); +extern void *mbedtls_calloc( size_t n, size_t size ); +extern void mbedtls_free( void *ptr ); /** - * \brief This function allows configuring custom memory-management functions. + * \brief This function dynamically sets the memory-management + * functions used by the library, during runtime. * * \param calloc_func The \c calloc function implementation. * \param free_func The \c free function implementation. @@ -140,7 +150,9 @@ int mbedtls_platform_set_calloc_free( void * (*calloc_func)( size_t, size_t ), extern int (*mbedtls_fprintf)( FILE *stream, const char *format, ... ); /** - * \brief This function allows configuring a custom \p fprintf function pointer. + * \brief This function dynamically configures the fprintf + * function that is called when the + * mbedtls_fprintf() function is invoked by the library. * * \param fprintf_func The \c fprintf function implementation. * @@ -163,8 +175,9 @@ int mbedtls_platform_set_fprintf( int (*fprintf_func)( FILE *stream, const char extern int (*mbedtls_printf)( const char *format, ... ); /** - * \brief This function allows configuring a custom \c printf function - * pointer. + * \brief This function dynamically configures the snprintf + * function that is called when the mbedtls_snprintf() + * function is invoked by the library. * * \param printf_func The \c printf function implementation. * @@ -197,12 +210,12 @@ int mbedtls_platform_win32_snprintf( char *s, size_t n, const char *fmt, ... ); extern int (*mbedtls_snprintf)( char * s, size_t n, const char * format, ... ); /** - * \brief This function allows configuring a custom \c snprintf function - * pointer. + * \brief This function allows configuring a custom + * \c snprintf function pointer. * * \param snprintf_func The \c snprintf function implementation. * - * \return \c 0 on success. + * \return \c 0 on success. */ int mbedtls_platform_set_snprintf( int (*snprintf_func)( char * s, size_t n, const char * format, ... ) ); @@ -210,7 +223,7 @@ int mbedtls_platform_set_snprintf( int (*snprintf_func)( char * s, size_t n, #if defined(MBEDTLS_PLATFORM_SNPRINTF_MACRO) #define mbedtls_snprintf MBEDTLS_PLATFORM_SNPRINTF_MACRO #else -#define mbedtls_snprintf snprintf +#define mbedtls_snprintf MBEDTLS_PLATFORM_STD_SNPRINTF #endif /* MBEDTLS_PLATFORM_SNPRINTF_MACRO */ #endif /* MBEDTLS_PLATFORM_SNPRINTF_ALT */ @@ -221,12 +234,13 @@ int mbedtls_platform_set_snprintf( int (*snprintf_func)( char * s, size_t n, extern void (*mbedtls_exit)( int status ); /** - * \brief This function allows configuring a custom \c exit function - * pointer. + * \brief This function dynamically configures the exit + * function that is called when the mbedtls_exit() + * function is invoked by the library. * * \param exit_func The \c exit function implementation. * - * \return \c 0 on success. + * \return \c 0 on success. */ int mbedtls_platform_set_exit( void (*exit_func)( int status ) ); #else @@ -302,7 +316,7 @@ int mbedtls_platform_set_nv_seed( * setup or teardown operations. */ typedef struct { - char dummy; /**< Placeholder member, as empty structs are not portable. */ + char dummy; /**< A placeholder member, as empty structs are not portable. */ } mbedtls_platform_context; @@ -311,33 +325,34 @@ mbedtls_platform_context; #endif /* !MBEDTLS_PLATFORM_SETUP_TEARDOWN_ALT */ /** - * \brief This function performs any platform initialization operations. - * - * \param ctx The Mbed TLS context. + * \brief This function performs any platform-specific initialization + * operations. * - * \return \c 0 on success. + * \note This function should be called before any other library functions. * - * \note This function is intended to allow platform-specific initialization, - * and should be called before any other library functions. Its - * implementation is platform-specific, and unless + * Its implementation is platform-specific, and unless * platform-specific code is provided, it does nothing. * - * Its use and whether it is necessary to call it is dependent on the - * platform. + * \note The usage and necessity of this function is dependent on the platform. + * + * \param ctx The platform context. + * + * \return \c 0 on success. */ int mbedtls_platform_setup( mbedtls_platform_context *ctx ); /** * \brief This function performs any platform teardown operations. * - * \param ctx The Mbed TLS context. - * * \note This function should be called after every other Mbed TLS module * has been correctly freed using the appropriate free function. + * * Its implementation is platform-specific, and unless * platform-specific code is provided, it does nothing. * - * Its use and whether it is necessary to call it is dependent on the - * platform. + * \note The usage and necessity of this function is dependent on the platform. + * + * \param ctx The platform context. + * */ void mbedtls_platform_teardown( mbedtls_platform_context *ctx ); diff --git a/thirdparty/mbedtls/include/mbedtls/platform_util.h b/thirdparty/mbedtls/include/mbedtls/platform_util.h new file mode 100644 index 0000000000..84f0732eeb --- /dev/null +++ b/thirdparty/mbedtls/include/mbedtls/platform_util.h @@ -0,0 +1,62 @@ +/** + * \file platform_util.h + * + * \brief Common and shared functions used by multiple modules in the Mbed TLS + * library. + */ +/* + * Copyright (C) 2018, Arm Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of Mbed TLS (https://tls.mbed.org) + */ +#ifndef MBEDTLS_PLATFORM_UTIL_H +#define MBEDTLS_PLATFORM_UTIL_H + +#include <stddef.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Securely zeroize a buffer + * + * The function is meant to wipe the data contained in a buffer so + * that it can no longer be recovered even if the program memory + * is later compromised. Call this function on sensitive data + * stored on the stack before returning from a function, and on + * sensitive data stored on the heap before freeing the heap + * object. + * + * It is extremely difficult to guarantee that calls to + * mbedtls_platform_zeroize() are not removed by aggressive + * compiler optimizations in a portable way. For this reason, Mbed + * TLS provides the configuration option + * MBEDTLS_PLATFORM_ZEROIZE_ALT, which allows users to configure + * mbedtls_platform_zeroize() to use a suitable implementation for + * their platform and needs + * + * \param buf Buffer to be zeroized + * \param len Length of the buffer in bytes + * + */ +void mbedtls_platform_zeroize( void *buf, size_t len ); + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_PLATFORM_UTIL_H */ diff --git a/thirdparty/mbedtls/include/mbedtls/poly1305.h b/thirdparty/mbedtls/include/mbedtls/poly1305.h new file mode 100644 index 0000000000..54b50abc25 --- /dev/null +++ b/thirdparty/mbedtls/include/mbedtls/poly1305.h @@ -0,0 +1,181 @@ +/** + * \file poly1305.h + * + * \brief This file contains Poly1305 definitions and functions. + * + * Poly1305 is a one-time message authenticator that can be used to + * authenticate messages. Poly1305-AES was created by Daniel + * Bernstein https://cr.yp.to/mac/poly1305-20050329.pdf The generic + * Poly1305 algorithm (not tied to AES) was also standardized in RFC + * 7539. + * + * \author Daniel King <damaki.gh@gmail.com> + */ + +/* Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of Mbed TLS (https://tls.mbed.org) + */ + +#ifndef MBEDTLS_POLY1305_H +#define MBEDTLS_POLY1305_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include <stdint.h> +#include <stddef.h> + +#define MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA -0x0057 /**< Invalid input parameter(s). */ +#define MBEDTLS_ERR_POLY1305_FEATURE_UNAVAILABLE -0x0059 /**< Feature not available. For example, s part of the API is not implemented. */ +#define MBEDTLS_ERR_POLY1305_HW_ACCEL_FAILED -0x005B /**< Poly1305 hardware accelerator failed. */ + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(MBEDTLS_POLY1305_ALT) + +typedef struct +{ + uint32_t r[4]; /** The value for 'r' (low 128 bits of the key). */ + uint32_t s[4]; /** The value for 's' (high 128 bits of the key). */ + uint32_t acc[5]; /** The accumulator number. */ + uint8_t queue[16]; /** The current partial block of data. */ + size_t queue_len; /** The number of bytes stored in 'queue'. */ +} +mbedtls_poly1305_context; + +#else /* MBEDTLS_POLY1305_ALT */ +#include "poly1305_alt.h" +#endif /* MBEDTLS_POLY1305_ALT */ + +/** + * \brief This function initializes the specified Poly1305 context. + * + * It must be the first API called before using + * the context. + * + * It is usually followed by a call to + * \c mbedtls_poly1305_starts(), then one or more calls to + * \c mbedtls_poly1305_update(), then one call to + * \c mbedtls_poly1305_finish(), then finally + * \c mbedtls_poly1305_free(). + * + * \param ctx The Poly1305 context to initialize. + */ +void mbedtls_poly1305_init( mbedtls_poly1305_context *ctx ); + +/** + * \brief This function releases and clears the specified Poly1305 context. + * + * \param ctx The Poly1305 context to clear. + */ +void mbedtls_poly1305_free( mbedtls_poly1305_context *ctx ); + +/** + * \brief This function sets the one-time authentication key. + * + * \warning The key must be unique and unpredictable for each + * invocation of Poly1305. + * + * \param ctx The Poly1305 context to which the key should be bound. + * \param key The buffer containing the 256-bit key. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA + * if ctx or key are NULL. + */ +int mbedtls_poly1305_starts( mbedtls_poly1305_context *ctx, + const unsigned char key[32] ); + +/** + * \brief This functions feeds an input buffer into an ongoing + * Poly1305 computation. + * + * It is called between \c mbedtls_cipher_poly1305_starts() and + * \c mbedtls_cipher_poly1305_finish(). + * It can be called repeatedly to process a stream of data. + * + * \param ctx The Poly1305 context to use for the Poly1305 operation. + * \param ilen The length of the input data (in bytes). Any value is accepted. + * \param input The buffer holding the input data. + * This pointer can be NULL if ilen == 0. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA + * if ctx or input are NULL. + */ +int mbedtls_poly1305_update( mbedtls_poly1305_context *ctx, + const unsigned char *input, + size_t ilen ); + +/** + * \brief This function generates the Poly1305 Message + * Authentication Code (MAC). + * + * \param ctx The Poly1305 context to use for the Poly1305 operation. + * \param mac The buffer to where the MAC is written. Must be big enough + * to hold the 16-byte MAC. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA + * if ctx or mac are NULL. + */ +int mbedtls_poly1305_finish( mbedtls_poly1305_context *ctx, + unsigned char mac[16] ); + +/** + * \brief This function calculates the Poly1305 MAC of the input + * buffer with the provided key. + * + * \warning The key must be unique and unpredictable for each + * invocation of Poly1305. + * + * \param key The buffer containing the 256-bit key. + * \param ilen The length of the input data (in bytes). Any value is accepted. + * \param input The buffer holding the input data. + * This pointer can be NULL if ilen == 0. + * \param mac The buffer to where the MAC is written. Must be big enough + * to hold the 16-byte MAC. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA + * if key, input, or mac are NULL. + */ +int mbedtls_poly1305_mac( const unsigned char key[32], + const unsigned char *input, + size_t ilen, + unsigned char mac[16] ); + +#if defined(MBEDTLS_SELF_TEST) +/** + * \brief The Poly1305 checkup routine. + * + * \return \c 0 on success. + * \return \c 1 on failure. + */ +int mbedtls_poly1305_self_test( int verbose ); +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_POLY1305_H */ diff --git a/thirdparty/mbedtls/include/mbedtls/ripemd160.h b/thirdparty/mbedtls/include/mbedtls/ripemd160.h index 3a8b50a621..a0dac0c360 100644 --- a/thirdparty/mbedtls/include/mbedtls/ripemd160.h +++ b/thirdparty/mbedtls/include/mbedtls/ripemd160.h @@ -35,14 +35,14 @@ #define MBEDTLS_ERR_RIPEMD160_HW_ACCEL_FAILED -0x0031 /**< RIPEMD160 hardware accelerator failed */ -#if !defined(MBEDTLS_RIPEMD160_ALT) -// Regular implementation -// - #ifdef __cplusplus extern "C" { #endif +#if !defined(MBEDTLS_RIPEMD160_ALT) +// Regular implementation +// + /** * \brief RIPEMD-160 context structure */ @@ -54,6 +54,10 @@ typedef struct } mbedtls_ripemd160_context; +#else /* MBEDTLS_RIPEMD160_ALT */ +#include "ripemd160.h" +#endif /* MBEDTLS_RIPEMD160_ALT */ + /** * \brief Initialize RIPEMD-160 context * @@ -178,18 +182,6 @@ MBEDTLS_DEPRECATED void mbedtls_ripemd160_process( #undef MBEDTLS_DEPRECATED #endif /* !MBEDTLS_DEPRECATED_REMOVED */ -#ifdef __cplusplus -} -#endif - -#else /* MBEDTLS_RIPEMD160_ALT */ -#include "ripemd160_alt.h" -#endif /* MBEDTLS_RIPEMD160_ALT */ - -#ifdef __cplusplus -extern "C" { -#endif - /** * \brief Output = RIPEMD-160( input buffer ) * diff --git a/thirdparty/mbedtls/include/mbedtls/rsa.h b/thirdparty/mbedtls/include/mbedtls/rsa.h index 5548f3c127..19eb2ee74c 100644 --- a/thirdparty/mbedtls/include/mbedtls/rsa.h +++ b/thirdparty/mbedtls/include/mbedtls/rsa.h @@ -1,11 +1,12 @@ /** * \file rsa.h * - * \brief The RSA public-key cryptosystem. + * \brief This file provides an API for the RSA public-key cryptosystem. * - * For more information, see <em>Public-Key Cryptography Standards (PKCS) - * #1 v1.5: RSA Encryption</em> and <em>Public-Key Cryptography Standards - * (PKCS) #1 v2.1: RSA Cryptography Specifications</em>. + * The RSA public-key cryptosystem is defined in <em>Public-Key + * Cryptography Standards (PKCS) #1 v1.5: RSA Encryption</em> + * and <em>Public-Key Cryptography Standards (PKCS) #1 v2.1: + * RSA Cryptography Specifications</em>. * */ /* @@ -63,8 +64,8 @@ #define MBEDTLS_RSA_PUBLIC 0 /**< Request private key operation. */ #define MBEDTLS_RSA_PRIVATE 1 /**< Request public key operation. */ -#define MBEDTLS_RSA_PKCS_V15 0 /**< Use PKCS-1 v1.5 encoding. */ -#define MBEDTLS_RSA_PKCS_V21 1 /**< Use PKCS-1 v2.1 encoding. */ +#define MBEDTLS_RSA_PKCS_V15 0 /**< Use PKCS#1 v1.5 encoding. */ +#define MBEDTLS_RSA_PKCS_V21 1 /**< Use PKCS#1 v2.1 encoding. */ #define MBEDTLS_RSA_SIGN 1 /**< Identifier for RSA signature operations. */ #define MBEDTLS_RSA_CRYPT 2 /**< Identifier for RSA encryption and decryption operations. */ @@ -76,14 +77,14 @@ * eg for alternative (PKCS#11) RSA implemenations in the PK layers. */ -#if !defined(MBEDTLS_RSA_ALT) -// Regular implementation -// - #ifdef __cplusplus extern "C" { #endif +#if !defined(MBEDTLS_RSA_ALT) +// Regular implementation +// + /** * \brief The RSA context structure. * @@ -96,24 +97,24 @@ typedef struct int ver; /*!< Always 0.*/ size_t len; /*!< The size of \p N in Bytes. */ - mbedtls_mpi N; /*!< The public modulus. */ - mbedtls_mpi E; /*!< The public exponent. */ + mbedtls_mpi N; /*!< The public modulus. */ + mbedtls_mpi E; /*!< The public exponent. */ - mbedtls_mpi D; /*!< The private exponent. */ - mbedtls_mpi P; /*!< The first prime factor. */ - mbedtls_mpi Q; /*!< The second prime factor. */ + mbedtls_mpi D; /*!< The private exponent. */ + mbedtls_mpi P; /*!< The first prime factor. */ + mbedtls_mpi Q; /*!< The second prime factor. */ - mbedtls_mpi DP; /*!< \p D % (P - 1) */ - mbedtls_mpi DQ; /*!< \p D % (Q - 1) */ - mbedtls_mpi QP; /*!< 1 / (Q % P) */ + mbedtls_mpi DP; /*!< <code>D % (P - 1)</code>. */ + mbedtls_mpi DQ; /*!< <code>D % (Q - 1)</code>. */ + mbedtls_mpi QP; /*!< <code>1 / (Q % P)</code>. */ - mbedtls_mpi RN; /*!< cached R^2 mod \p N */ + mbedtls_mpi RN; /*!< cached <code>R^2 mod N</code>. */ - mbedtls_mpi RP; /*!< cached R^2 mod \p P */ - mbedtls_mpi RQ; /*!< cached R^2 mod \p Q */ + mbedtls_mpi RP; /*!< cached <code>R^2 mod P</code>. */ + mbedtls_mpi RQ; /*!< cached <code>R^2 mod Q</code>. */ - mbedtls_mpi Vi; /*!< The cached blinding value. */ - mbedtls_mpi Vf; /*!< The cached un-blinding value. */ + mbedtls_mpi Vi; /*!< The cached blinding value. */ + mbedtls_mpi Vf; /*!< The cached un-blinding value. */ int padding; /*!< Selects padding mode: #MBEDTLS_RSA_PKCS_V15 for 1.5 padding and @@ -128,18 +129,16 @@ typedef struct } mbedtls_rsa_context; +#else /* MBEDTLS_RSA_ALT */ +#include "rsa_alt.h" +#endif /* MBEDTLS_RSA_ALT */ + /** * \brief This function initializes an RSA context. * * \note Set padding to #MBEDTLS_RSA_PKCS_V21 for the RSAES-OAEP * encryption scheme and the RSASSA-PSS signature scheme. * - * \param ctx The RSA context to initialize. - * \param padding Selects padding mode: #MBEDTLS_RSA_PKCS_V15 or - * #MBEDTLS_RSA_PKCS_V21. - * \param hash_id The hash identifier of #mbedtls_md_type_t type, if - * \p padding is #MBEDTLS_RSA_PKCS_V21. - * * \note The \p hash_id parameter is ignored when using * #MBEDTLS_RSA_PKCS_V15 padding. * @@ -153,6 +152,12 @@ mbedtls_rsa_context; * encryption. For PSS signatures, it is always used for * making signatures, but can be overriden for verifying them. * If set to #MBEDTLS_MD_NONE, it is always overriden. + * + * \param ctx The RSA context to initialize. + * \param padding Selects padding mode: #MBEDTLS_RSA_PKCS_V15 or + * #MBEDTLS_RSA_PKCS_V21. + * \param hash_id The hash identifier of #mbedtls_md_type_t type, if + * \p padding is #MBEDTLS_RSA_PKCS_V21. */ void mbedtls_rsa_init( mbedtls_rsa_context *ctx, int padding, @@ -162,13 +167,6 @@ void mbedtls_rsa_init( mbedtls_rsa_context *ctx, * \brief This function imports a set of core parameters into an * RSA context. * - * \param ctx The initialized RSA context to store the parameters in. - * \param N The RSA modulus, or NULL. - * \param P The first prime factor of \p N, or NULL. - * \param Q The second prime factor of \p N, or NULL. - * \param D The private exponent, or NULL. - * \param E The public exponent, or NULL. - * * \note This function can be called multiple times for successive * imports, if the parameters are not simultaneously present. * @@ -184,7 +182,15 @@ void mbedtls_rsa_init( mbedtls_rsa_context *ctx, * \note The imported parameters are copied and need not be preserved * for the lifetime of the RSA context being set up. * - * \return \c 0 on success, or a non-zero error code on failure. + * \param ctx The initialized RSA context to store the parameters in. + * \param N The RSA modulus, or NULL. + * \param P The first prime factor of \p N, or NULL. + * \param Q The second prime factor of \p N, or NULL. + * \param D The private exponent, or NULL. + * \param E The public exponent, or NULL. + * + * \return \c 0 on success. + * \return A non-zero error code on failure. */ int mbedtls_rsa_import( mbedtls_rsa_context *ctx, const mbedtls_mpi *N, @@ -195,18 +201,6 @@ int mbedtls_rsa_import( mbedtls_rsa_context *ctx, * \brief This function imports core RSA parameters, in raw big-endian * binary format, into an RSA context. * - * \param ctx The initialized RSA context to store the parameters in. - * \param N The RSA modulus, or NULL. - * \param N_len The Byte length of \p N, ignored if \p N == NULL. - * \param P The first prime factor of \p N, or NULL. - * \param P_len The Byte length of \p P, ignored if \p P == NULL. - * \param Q The second prime factor of \p N, or NULL. - * \param Q_len The Byte length of \p Q, ignored if \p Q == NULL. - * \param D The private exponent, or NULL. - * \param D_len The Byte length of \p D, ignored if \p D == NULL. - * \param E The public exponent, or NULL. - * \param E_len The Byte length of \p E, ignored if \p E == NULL. - * * \note This function can be called multiple times for successive * imports, if the parameters are not simultaneously present. * @@ -222,7 +216,20 @@ int mbedtls_rsa_import( mbedtls_rsa_context *ctx, * \note The imported parameters are copied and need not be preserved * for the lifetime of the RSA context being set up. * - * \return \c 0 on success, or a non-zero error code on failure. + * \param ctx The initialized RSA context to store the parameters in. + * \param N The RSA modulus, or NULL. + * \param N_len The Byte length of \p N, ignored if \p N == NULL. + * \param P The first prime factor of \p N, or NULL. + * \param P_len The Byte length of \p P, ignored if \p P == NULL. + * \param Q The second prime factor of \p N, or NULL. + * \param Q_len The Byte length of \p Q, ignored if \p Q == NULL. + * \param D The private exponent, or NULL. + * \param D_len The Byte length of \p D, ignored if \p D == NULL. + * \param E The public exponent, or NULL. + * \param E_len The Byte length of \p E, ignored if \p E == NULL. + * + * \return \c 0 on success. + * \return A non-zero error code on failure. */ int mbedtls_rsa_import_raw( mbedtls_rsa_context *ctx, unsigned char const *N, size_t N_len, @@ -250,17 +257,18 @@ int mbedtls_rsa_import_raw( mbedtls_rsa_context *ctx, * the RSA context can be used for RSA operations without * the risk of failure or crash. * - * \param ctx The initialized RSA context holding imported parameters. - * - * \return \c 0 on success, or #MBEDTLS_ERR_RSA_BAD_INPUT_DATA if the - * attempted derivations failed. - * * \warning This function need not perform consistency checks * for the imported parameters. In particular, parameters that * are not needed by the implementation might be silently * discarded and left unchecked. To check the consistency * of the key material, see mbedtls_rsa_check_privkey(). * + * \param ctx The initialized RSA context holding imported parameters. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_RSA_BAD_INPUT_DATA if the attempted derivations + * failed. + * */ int mbedtls_rsa_complete( mbedtls_rsa_context *ctx ); @@ -292,11 +300,11 @@ int mbedtls_rsa_complete( mbedtls_rsa_context *ctx ); * \param D The MPI to hold the private exponent, or NULL. * \param E The MPI to hold the public exponent, or NULL. * - * \return \c 0 on success, - * #MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION if exporting the + * \return \c 0 on success. + * \return #MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION if exporting the * requested parameters cannot be done due to missing - * functionality or because of security policies, - * or a non-zero return code on any other failure. + * functionality or because of security policies. + * \return A non-zero return code on any other failure. * */ int mbedtls_rsa_export( const mbedtls_rsa_context *ctx, @@ -324,6 +332,9 @@ int mbedtls_rsa_export( const mbedtls_rsa_context *ctx, * If the function fails due to an unsupported operation, * the RSA context stays intact and remains usable. * + * \note The length parameters are ignored if the corresponding + * buffer pointers are NULL. + * * \param ctx The initialized RSA context. * \param N The Byte array to store the RSA modulus, or NULL. * \param N_len The size of the buffer for the modulus. @@ -331,21 +342,18 @@ int mbedtls_rsa_export( const mbedtls_rsa_context *ctx, * NULL. * \param P_len The size of the buffer for the first prime factor. * \param Q The Byte array to hold the second prime factor of \p N, or - NULL. + * NULL. * \param Q_len The size of the buffer for the second prime factor. * \param D The Byte array to hold the private exponent, or NULL. * \param D_len The size of the buffer for the private exponent. * \param E The Byte array to hold the public exponent, or NULL. * \param E_len The size of the buffer for the public exponent. * - * \note The length fields are ignored if the corresponding - * buffer pointers are NULL. - * - * \return \c 0 on success, - * #MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION if exporting the + * \return \c 0 on success. + * \return #MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION if exporting the * requested parameters cannot be done due to missing - * functionality or because of security policies, - * or a non-zero return code on any other failure. + * functionality or because of security policies. + * \return A non-zero return code on any other failure. */ int mbedtls_rsa_export_raw( const mbedtls_rsa_context *ctx, unsigned char *N, size_t N_len, @@ -357,16 +365,17 @@ int mbedtls_rsa_export_raw( const mbedtls_rsa_context *ctx, /** * \brief This function exports CRT parameters of a private RSA key. * + * \note Alternative RSA implementations not using CRT-parameters + * internally can implement this function based on + * mbedtls_rsa_deduce_opt(). + * * \param ctx The initialized RSA context. * \param DP The MPI to hold D modulo P-1, or NULL. * \param DQ The MPI to hold D modulo Q-1, or NULL. * \param QP The MPI to hold modular inverse of Q modulo P, or NULL. * - * \return \c 0 on success, non-zero error code otherwise. - * - * \note Alternative RSA implementations not using CRT-parameters - * internally can implement this function based on - * mbedtls_rsa_deduce_opt(). + * \return \c 0 on success. + * \return A non-zero error code on failure. * */ int mbedtls_rsa_export_crt( const mbedtls_rsa_context *ctx, @@ -397,17 +406,17 @@ size_t mbedtls_rsa_get_len( const mbedtls_rsa_context *ctx ); /** * \brief This function generates an RSA keypair. * + * \note mbedtls_rsa_init() must be called before this function, + * to set up the RSA context. + * * \param ctx The RSA context used to hold the key. * \param f_rng The RNG function. - * \param p_rng The RNG parameter. + * \param p_rng The RNG context. * \param nbits The size of the public key in bits. * \param exponent The public exponent. For example, 65537. * - * \note mbedtls_rsa_init() must be called before this function, - * to set up the RSA context. - * - * \return \c 0 on success, or an \c MBEDTLS_ERR_RSA_XXX error code - on failure. + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. */ int mbedtls_rsa_gen_key( mbedtls_rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), @@ -424,8 +433,8 @@ int mbedtls_rsa_gen_key( mbedtls_rsa_context *ctx, * * \param ctx The RSA context to check. * - * \return \c 0 on success, or an \c MBEDTLS_ERR_RSA_XXX error code - * on failure. + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. * */ int mbedtls_rsa_check_pubkey( const mbedtls_rsa_context *ctx ); @@ -434,11 +443,6 @@ int mbedtls_rsa_check_pubkey( const mbedtls_rsa_context *ctx ); * \brief This function checks if a context contains an RSA private key * and perform basic consistency checks. * - * \param ctx The RSA context to check. - * - * \return \c 0 on success, or an \c MBEDTLS_ERR_RSA_XXX error code on - * failure. - * * \note The consistency checks performed by this function not only * ensure that mbedtls_rsa_private() can be called successfully * on the given context, but that the various parameters are @@ -465,6 +469,11 @@ int mbedtls_rsa_check_pubkey( const mbedtls_rsa_context *ctx ); * user to ensure the trustworthiness of the source of his RSA * parameters, which goes beyond what is effectively checkable * by the library.</li></ul> + * + * \param ctx The RSA context to check. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. */ int mbedtls_rsa_check_privkey( const mbedtls_rsa_context *ctx ); @@ -476,8 +485,8 @@ int mbedtls_rsa_check_privkey( const mbedtls_rsa_context *ctx ); * \param pub The RSA context holding the public key. * \param prv The RSA context holding the private key. * - * \return \c 0 on success, or an \c MBEDTLS_ERR_RSA_XXX error code - * on failure. + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. */ int mbedtls_rsa_check_pub_priv( const mbedtls_rsa_context *pub, const mbedtls_rsa_context *prv ); @@ -485,13 +494,6 @@ int mbedtls_rsa_check_pub_priv( const mbedtls_rsa_context *pub, /** * \brief This function performs an RSA public key operation. * - * \param ctx The RSA context. - * \param input The input buffer. - * \param output The output buffer. - * - * \return \c 0 on success, or an \c MBEDTLS_ERR_RSA_XXX error code - * on failure. - * * \note This function does not handle message padding. * * \note Make sure to set \p input[0] = 0 or ensure that @@ -499,6 +501,13 @@ int mbedtls_rsa_check_pub_priv( const mbedtls_rsa_context *pub, * * \note The input and output buffers must be large * enough. For example, 128 Bytes if RSA-1024 is used. + * + * \param ctx The RSA context. + * \param input The input buffer. + * \param output The output buffer. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. */ int mbedtls_rsa_public( mbedtls_rsa_context *ctx, const unsigned char *input, @@ -507,15 +516,6 @@ int mbedtls_rsa_public( mbedtls_rsa_context *ctx, /** * \brief This function performs an RSA private key operation. * - * \param ctx The RSA context. - * \param f_rng The RNG function. Needed for blinding. - * \param p_rng The RNG parameter. - * \param input The input buffer. - * \param output The output buffer. - * - * \return \c 0 on success, or an \c MBEDTLS_ERR_RSA_XXX error code - * on failure. - * * \note The input and output buffers must be large * enough. For example, 128 Bytes if RSA-1024 is used. * @@ -530,6 +530,15 @@ int mbedtls_rsa_public( mbedtls_rsa_context *ctx, * Future versions of the library may enforce the presence * of a PRNG. * + * \param ctx The RSA context. + * \param f_rng The RNG function. Needed for blinding. + * \param p_rng The RNG context. + * \param input The input buffer. + * \param output The output buffer. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. + * */ int mbedtls_rsa_private( mbedtls_rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), @@ -544,15 +553,8 @@ int mbedtls_rsa_private( mbedtls_rsa_context *ctx, * It is the generic wrapper for performing a PKCS#1 encryption * operation using the \p mode from the context. * - * - * \param ctx The RSA context. - * \param f_rng The RNG function. Needed for padding, PKCS#1 v2.1 - * encoding, and #MBEDTLS_RSA_PRIVATE. - * \param p_rng The RNG parameter. - * \param mode #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE. - * \param ilen The length of the plaintext. - * \param input The buffer holding the data to encrypt. - * \param output The buffer used to hold the ciphertext. + * \note The input and output buffers must be as large as the size + * of \p ctx->N. For example, 128 Bytes if RSA-1024 is used. * * \deprecated It is deprecated and discouraged to call this function * in #MBEDTLS_RSA_PRIVATE mode. Future versions of the library @@ -563,11 +565,17 @@ int mbedtls_rsa_private( mbedtls_rsa_context *ctx, * mode being set to #MBEDTLS_RSA_PRIVATE and might instead * return #MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION. * - * \return \c 0 on success, or an \c MBEDTLS_ERR_RSA_XXX error code - * on failure. + * \param ctx The RSA context. + * \param f_rng The RNG function. Needed for padding, PKCS#1 v2.1 + * encoding, and #MBEDTLS_RSA_PRIVATE. + * \param p_rng The RNG context. + * \param mode #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE. + * \param ilen The length of the plaintext. + * \param input The buffer holding the data to encrypt. + * \param output The buffer used to hold the ciphertext. * - * \note The input and output buffers must be as large as the size - * of \p ctx->N. For example, 128 Bytes if RSA-1024 is used. + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. */ int mbedtls_rsa_pkcs1_encrypt( mbedtls_rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), @@ -580,14 +588,8 @@ int mbedtls_rsa_pkcs1_encrypt( mbedtls_rsa_context *ctx, * \brief This function performs a PKCS#1 v1.5 encryption operation * (RSAES-PKCS1-v1_5-ENCRYPT). * - * \param ctx The RSA context. - * \param f_rng The RNG function. Needed for padding and - * #MBEDTLS_RSA_PRIVATE. - * \param p_rng The RNG parameter. - * \param mode #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE. - * \param ilen The length of the plaintext. - * \param input The buffer holding the data to encrypt. - * \param output The buffer used to hold the ciphertext. + * \note The output buffer must be as large as the size + * of \p ctx->N. For example, 128 Bytes if RSA-1024 is used. * * \deprecated It is deprecated and discouraged to call this function * in #MBEDTLS_RSA_PRIVATE mode. Future versions of the library @@ -598,11 +600,17 @@ int mbedtls_rsa_pkcs1_encrypt( mbedtls_rsa_context *ctx, * mode being set to #MBEDTLS_RSA_PRIVATE and might instead * return #MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION. * - * \return \c 0 on success, or an \c MBEDTLS_ERR_RSA_XXX error code - * on failure. + * \param ctx The RSA context. + * \param f_rng The RNG function. Needed for padding and + * #MBEDTLS_RSA_PRIVATE. + * \param p_rng The RNG context. + * \param mode #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE. + * \param ilen The length of the plaintext. + * \param input The buffer holding the data to encrypt. + * \param output The buffer used to hold the ciphertext. * - * \note The output buffer must be as large as the size - * of \p ctx->N. For example, 128 Bytes if RSA-1024 is used. + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. */ int mbedtls_rsa_rsaes_pkcs1_v15_encrypt( mbedtls_rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), @@ -615,10 +623,22 @@ int mbedtls_rsa_rsaes_pkcs1_v15_encrypt( mbedtls_rsa_context *ctx, * \brief This function performs a PKCS#1 v2.1 OAEP encryption * operation (RSAES-OAEP-ENCRYPT). * + * \note The output buffer must be as large as the size + * of ctx->N. For example, 128 Bytes if RSA-1024 is used. + * + * \deprecated It is deprecated and discouraged to call this function + * in #MBEDTLS_RSA_PRIVATE mode. Future versions of the library + * are likely to remove the \p mode argument and have it + * implicitly set to #MBEDTLS_RSA_PUBLIC. + * + * \note Alternative implementations of RSA need not support + * mode being set to #MBEDTLS_RSA_PRIVATE and might instead + * return #MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION. + * * \param ctx The RSA context. * \param f_rng The RNG function. Needed for padding and PKCS#1 v2.1 * encoding and #MBEDTLS_RSA_PRIVATE. - * \param p_rng The RNG parameter. + * \param p_rng The RNG context. * \param mode #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE. * \param label The buffer holding the custom label to use. * \param label_len The length of the label. @@ -626,20 +646,8 @@ int mbedtls_rsa_rsaes_pkcs1_v15_encrypt( mbedtls_rsa_context *ctx, * \param input The buffer holding the data to encrypt. * \param output The buffer used to hold the ciphertext. * - * \deprecated It is deprecated and discouraged to call this function - * in #MBEDTLS_RSA_PRIVATE mode. Future versions of the library - * are likely to remove the \p mode argument and have it - * implicitly set to #MBEDTLS_RSA_PUBLIC. - * - * \note Alternative implementations of RSA need not support - * mode being set to #MBEDTLS_RSA_PRIVATE and might instead - * return #MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION. - * - * \return \c 0 on success, or an \c MBEDTLS_ERR_RSA_XXX error code - * on failure. - * - * \note The output buffer must be as large as the size - * of ctx->N. For example, 128 Bytes if RSA-1024 is used. + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. */ int mbedtls_rsa_rsaes_oaep_encrypt( mbedtls_rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), @@ -657,14 +665,15 @@ int mbedtls_rsa_rsaes_oaep_encrypt( mbedtls_rsa_context *ctx, * It is the generic wrapper for performing a PKCS#1 decryption * operation using the \p mode from the context. * - * \param ctx The RSA context. - * \param f_rng The RNG function. Only needed for #MBEDTLS_RSA_PRIVATE. - * \param p_rng The RNG parameter. - * \param mode #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE. - * \param olen The length of the plaintext. - * \param input The buffer holding the encrypted data. - * \param output The buffer used to hold the plaintext. - * \param output_max_len The maximum length of the output buffer. + * \note The output buffer length \c output_max_len should be + * as large as the size \p ctx->len of \p ctx->N (for example, + * 128 Bytes if RSA-1024 is used) to be able to hold an + * arbitrary decrypted message. If it is not large enough to + * hold the decryption of the particular ciphertext provided, + * the function returns \c MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE. + * + * \note The input buffer must be as large as the size + * of \p ctx->N. For example, 128 Bytes if RSA-1024 is used. * * \deprecated It is deprecated and discouraged to call this function * in #MBEDTLS_RSA_PUBLIC mode. Future versions of the library @@ -675,18 +684,17 @@ int mbedtls_rsa_rsaes_oaep_encrypt( mbedtls_rsa_context *ctx, * mode being set to #MBEDTLS_RSA_PUBLIC and might instead * return #MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION. * - * \return \c 0 on success, or an \c MBEDTLS_ERR_RSA_XXX error code - * on failure. - * - * \note The output buffer length \c output_max_len should be - * as large as the size \p ctx->len of \p ctx->N (for example, - * 128 Bytes if RSA-1024 is used) to be able to hold an - * arbitrary decrypted message. If it is not large enough to - * hold the decryption of the particular ciphertext provided, - * the function returns \c MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE. + * \param ctx The RSA context. + * \param f_rng The RNG function. Only needed for #MBEDTLS_RSA_PRIVATE. + * \param p_rng The RNG context. + * \param mode #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE. + * \param olen The length of the plaintext. + * \param input The buffer holding the encrypted data. + * \param output The buffer used to hold the plaintext. + * \param output_max_len The maximum length of the output buffer. * - * \note The input buffer must be as large as the size - * of \p ctx->N. For example, 128 Bytes if RSA-1024 is used. + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. */ int mbedtls_rsa_pkcs1_decrypt( mbedtls_rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), @@ -700,14 +708,15 @@ int mbedtls_rsa_pkcs1_decrypt( mbedtls_rsa_context *ctx, * \brief This function performs a PKCS#1 v1.5 decryption * operation (RSAES-PKCS1-v1_5-DECRYPT). * - * \param ctx The RSA context. - * \param f_rng The RNG function. Only needed for #MBEDTLS_RSA_PRIVATE. - * \param p_rng The RNG parameter. - * \param mode #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE. - * \param olen The length of the plaintext. - * \param input The buffer holding the encrypted data. - * \param output The buffer to hold the plaintext. - * \param output_max_len The maximum length of the output buffer. + * \note The output buffer length \c output_max_len should be + * as large as the size \p ctx->len of \p ctx->N, for example, + * 128 Bytes if RSA-1024 is used, to be able to hold an + * arbitrary decrypted message. If it is not large enough to + * hold the decryption of the particular ciphertext provided, + * the function returns #MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE. + * + * \note The input buffer must be as large as the size + * of \p ctx->N. For example, 128 Bytes if RSA-1024 is used. * * \deprecated It is deprecated and discouraged to call this function * in #MBEDTLS_RSA_PUBLIC mode. Future versions of the library @@ -718,18 +727,18 @@ int mbedtls_rsa_pkcs1_decrypt( mbedtls_rsa_context *ctx, * mode being set to #MBEDTLS_RSA_PUBLIC and might instead * return #MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION. * - * \return \c 0 on success, or an \c MBEDTLS_ERR_RSA_XXX error code - * on failure. + * \param ctx The RSA context. + * \param f_rng The RNG function. Only needed for #MBEDTLS_RSA_PRIVATE. + * \param p_rng The RNG context. + * \param mode #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE. + * \param olen The length of the plaintext. + * \param input The buffer holding the encrypted data. + * \param output The buffer to hold the plaintext. + * \param output_max_len The maximum length of the output buffer. * - * \note The output buffer length \c output_max_len should be - * as large as the size \p ctx->len of \p ctx->N, for example, - * 128 Bytes if RSA-1024 is used, to be able to hold an - * arbitrary decrypted message. If it is not large enough to - * hold the decryption of the particular ciphertext provided, - * the function returns #MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE. + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. * - * \note The input buffer must be as large as the size - * of \p ctx->N. For example, 128 Bytes if RSA-1024 is used. */ int mbedtls_rsa_rsaes_pkcs1_v15_decrypt( mbedtls_rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), @@ -740,12 +749,32 @@ int mbedtls_rsa_rsaes_pkcs1_v15_decrypt( mbedtls_rsa_context *ctx, size_t output_max_len ); /** - * \brief This function performs a PKCS#1 v2.1 OAEP decryption - * operation (RSAES-OAEP-DECRYPT). + * \brief This function performs a PKCS#1 v2.1 OAEP decryption + * operation (RSAES-OAEP-DECRYPT). + * + * \note The output buffer length \c output_max_len should be + * as large as the size \p ctx->len of \p ctx->N, for + * example, 128 Bytes if RSA-1024 is used, to be able to + * hold an arbitrary decrypted message. If it is not + * large enough to hold the decryption of the particular + * ciphertext provided, the function returns + * #MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE. + * + * \note The input buffer must be as large as the size + * of \p ctx->N. For example, 128 Bytes if RSA-1024 is used. + * + * \deprecated It is deprecated and discouraged to call this function + * in #MBEDTLS_RSA_PUBLIC mode. Future versions of the library + * are likely to remove the \p mode argument and have it + * implicitly set to #MBEDTLS_RSA_PRIVATE. + * + * \note Alternative implementations of RSA need not support + * mode being set to #MBEDTLS_RSA_PUBLIC and might instead + * return #MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION. * * \param ctx The RSA context. * \param f_rng The RNG function. Only needed for #MBEDTLS_RSA_PRIVATE. - * \param p_rng The RNG parameter. + * \param p_rng The RNG context. * \param mode #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE. * \param label The buffer holding the custom label to use. * \param label_len The length of the label. @@ -754,28 +783,8 @@ int mbedtls_rsa_rsaes_pkcs1_v15_decrypt( mbedtls_rsa_context *ctx, * \param output The buffer to hold the plaintext. * \param output_max_len The maximum length of the output buffer. * - * \deprecated It is deprecated and discouraged to call this function - * in #MBEDTLS_RSA_PUBLIC mode. Future versions of the library - * are likely to remove the \p mode argument and have it - * implicitly set to #MBEDTLS_RSA_PRIVATE. - * - * \note Alternative implementations of RSA need not support - * mode being set to #MBEDTLS_RSA_PUBLIC and might instead - * return #MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION. - * - * \return \c 0 on success, or an \c MBEDTLS_ERR_RSA_XXX error code - * on failure. - * - * \note The output buffer length \c output_max_len should be - * as large as the size \p ctx->len of \p ctx->N, for - * example, 128 Bytes if RSA-1024 is used, to be able to - * hold an arbitrary decrypted message. If it is not - * large enough to hold the decryption of the particular - * ciphertext provided, the function returns - * #MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE. - * - * \note The input buffer must be as large as the size - * of \p ctx->N. For example, 128 Bytes if RSA-1024 is used. + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. */ int mbedtls_rsa_rsaes_oaep_decrypt( mbedtls_rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), @@ -794,16 +803,12 @@ int mbedtls_rsa_rsaes_oaep_decrypt( mbedtls_rsa_context *ctx, * It is the generic wrapper for performing a PKCS#1 * signature using the \p mode from the context. * - * \param ctx The RSA context. - * \param f_rng The RNG function. Needed for PKCS#1 v2.1 encoding and for - * #MBEDTLS_RSA_PRIVATE. - * \param p_rng The RNG parameter. - * \param mode #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE. - * \param md_alg The message-digest algorithm used to hash the original data. - * Use #MBEDTLS_MD_NONE for signing raw data. - * \param hashlen The length of the message digest. Only used if \p md_alg is #MBEDTLS_MD_NONE. - * \param hash The buffer holding the message digest. - * \param sig The buffer to hold the ciphertext. + * \note The \p sig buffer must be as large as the size + * of \p ctx->N. For example, 128 Bytes if RSA-1024 is used. + * + * \note For PKCS#1 v2.1 encoding, see comments on + * mbedtls_rsa_rsassa_pss_sign() for details on + * \p md_alg and \p hash_id. * * \deprecated It is deprecated and discouraged to call this function * in #MBEDTLS_RSA_PUBLIC mode. Future versions of the library @@ -814,15 +819,19 @@ int mbedtls_rsa_rsaes_oaep_decrypt( mbedtls_rsa_context *ctx, * mode being set to #MBEDTLS_RSA_PUBLIC and might instead * return #MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION. * - * \return \c 0 if the signing operation was successful, - * or an \c MBEDTLS_ERR_RSA_XXX error code on failure. - * - * \note The \p sig buffer must be as large as the size - * of \p ctx->N. For example, 128 Bytes if RSA-1024 is used. + * \param ctx The RSA context. + * \param f_rng The RNG function. Needed for PKCS#1 v2.1 encoding and for + * #MBEDTLS_RSA_PRIVATE. + * \param p_rng The RNG context. + * \param mode #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE. + * \param md_alg The message-digest algorithm used to hash the original data. + * Use #MBEDTLS_MD_NONE for signing raw data. + * \param hashlen The length of the message digest. Only used if \p md_alg is #MBEDTLS_MD_NONE. + * \param hash The buffer holding the message digest. + * \param sig The buffer to hold the ciphertext. * - * \note For PKCS#1 v2.1 encoding, see comments on - * mbedtls_rsa_rsassa_pss_sign() for details on - * \p md_alg and \p hash_id. + * \return \c 0 if the signing operation was successful. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. */ int mbedtls_rsa_pkcs1_sign( mbedtls_rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), @@ -837,15 +846,8 @@ int mbedtls_rsa_pkcs1_sign( mbedtls_rsa_context *ctx, * \brief This function performs a PKCS#1 v1.5 signature * operation (RSASSA-PKCS1-v1_5-SIGN). * - * \param ctx The RSA context. - * \param f_rng The RNG function. Only needed for #MBEDTLS_RSA_PRIVATE. - * \param p_rng The RNG parameter. - * \param mode #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE. - * \param md_alg The message-digest algorithm used to hash the original data. - * Use #MBEDTLS_MD_NONE for signing raw data. - * \param hashlen The length of the message digest. Only used if \p md_alg is #MBEDTLS_MD_NONE. - * \param hash The buffer holding the message digest. - * \param sig The buffer to hold the ciphertext. + * \note The \p sig buffer must be as large as the size + * of \p ctx->N. For example, 128 Bytes if RSA-1024 is used. * * \deprecated It is deprecated and discouraged to call this function * in #MBEDTLS_RSA_PUBLIC mode. Future versions of the library @@ -856,12 +858,18 @@ int mbedtls_rsa_pkcs1_sign( mbedtls_rsa_context *ctx, * mode being set to #MBEDTLS_RSA_PUBLIC and might instead * return #MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION. * - * \return \c 0 if the signing operation was successful, - * or an \c MBEDTLS_ERR_RSA_XXX error code - * on failure. + * \param ctx The RSA context. + * \param f_rng The RNG function. Only needed for #MBEDTLS_RSA_PRIVATE. + * \param p_rng The RNG context. + * \param mode #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE. + * \param md_alg The message-digest algorithm used to hash the original data. + * Use #MBEDTLS_MD_NONE for signing raw data. + * \param hashlen The length of the message digest. Only used if \p md_alg is #MBEDTLS_MD_NONE. + * \param hash The buffer holding the message digest. + * \param sig The buffer to hold the ciphertext. * - * \note The \p sig buffer must be as large as the size - * of \p ctx->N. For example, 128 Bytes if RSA-1024 is used. + * \return \c 0 if the signing operation was successful. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. */ int mbedtls_rsa_rsassa_pkcs1_v15_sign( mbedtls_rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), @@ -876,16 +884,15 @@ int mbedtls_rsa_rsassa_pkcs1_v15_sign( mbedtls_rsa_context *ctx, * \brief This function performs a PKCS#1 v2.1 PSS signature * operation (RSASSA-PSS-SIGN). * - * \param ctx The RSA context. - * \param f_rng The RNG function. Needed for PKCS#1 v2.1 encoding and for - * #MBEDTLS_RSA_PRIVATE. - * \param p_rng The RNG parameter. - * \param mode #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE. - * \param md_alg The message-digest algorithm used to hash the original data. - * Use #MBEDTLS_MD_NONE for signing raw data. - * \param hashlen The length of the message digest. Only used if \p md_alg is #MBEDTLS_MD_NONE. - * \param hash The buffer holding the message digest. - * \param sig The buffer to hold the ciphertext. + * \note The \p sig buffer must be as large as the size + * of \p ctx->N. For example, 128 Bytes if RSA-1024 is used. + * + * \note The \p hash_id in the RSA context is the one used for the + * encoding. \p md_alg in the function call is the type of hash + * that is encoded. According to <em>RFC-3447: Public-Key + * Cryptography Standards (PKCS) #1 v2.1: RSA Cryptography + * Specifications</em> it is advised to keep both hashes the + * same. * * \deprecated It is deprecated and discouraged to call this function * in #MBEDTLS_RSA_PUBLIC mode. Future versions of the library @@ -896,19 +903,19 @@ int mbedtls_rsa_rsassa_pkcs1_v15_sign( mbedtls_rsa_context *ctx, * mode being set to #MBEDTLS_RSA_PUBLIC and might instead * return #MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION. * - * \return \c 0 if the signing operation was successful, - * or an \c MBEDTLS_ERR_RSA_XXX error code - * on failure. - * - * \note The \p sig buffer must be as large as the size - * of \p ctx->N. For example, 128 Bytes if RSA-1024 is used. + * \param ctx The RSA context. + * \param f_rng The RNG function. Needed for PKCS#1 v2.1 encoding and for + * #MBEDTLS_RSA_PRIVATE. + * \param p_rng The RNG context. + * \param mode #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE. + * \param md_alg The message-digest algorithm used to hash the original data. + * Use #MBEDTLS_MD_NONE for signing raw data. + * \param hashlen The length of the message digest. Only used if \p md_alg is #MBEDTLS_MD_NONE. + * \param hash The buffer holding the message digest. + * \param sig The buffer to hold the ciphertext. * - * \note The \p hash_id in the RSA context is the one used for the - * encoding. \p md_alg in the function call is the type of hash - * that is encoded. According to <em>RFC-3447: Public-Key - * Cryptography Standards (PKCS) #1 v2.1: RSA Cryptography - * Specifications</em> it is advised to keep both hashes the - * same. + * \return \c 0 if the signing operation was successful. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. */ int mbedtls_rsa_rsassa_pss_sign( mbedtls_rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), @@ -926,15 +933,12 @@ int mbedtls_rsa_rsassa_pss_sign( mbedtls_rsa_context *ctx, * This is the generic wrapper for performing a PKCS#1 * verification using the mode from the context. * - * \param ctx The RSA public key context. - * \param f_rng The RNG function. Only needed for #MBEDTLS_RSA_PRIVATE. - * \param p_rng The RNG parameter. - * \param mode #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE. - * \param md_alg The message-digest algorithm used to hash the original data. - * Use #MBEDTLS_MD_NONE for signing raw data. - * \param hashlen The length of the message digest. Only used if \p md_alg is #MBEDTLS_MD_NONE. - * \param hash The buffer holding the message digest. - * \param sig The buffer holding the ciphertext. + * \note The \p sig buffer must be as large as the size + * of \p ctx->N. For example, 128 Bytes if RSA-1024 is used. + * + * \note For PKCS#1 v2.1 encoding, see comments on + * mbedtls_rsa_rsassa_pss_verify() about \p md_alg and + * \p hash_id. * * \deprecated It is deprecated and discouraged to call this function * in #MBEDTLS_RSA_PRIVATE mode. Future versions of the library @@ -945,16 +949,18 @@ int mbedtls_rsa_rsassa_pss_sign( mbedtls_rsa_context *ctx, * mode being set to #MBEDTLS_RSA_PRIVATE and might instead * return #MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION. * - * \return \c 0 if the verify operation was successful, - * or an \c MBEDTLS_ERR_RSA_XXX error code - * on failure. - * - * \note The \p sig buffer must be as large as the size - * of \p ctx->N. For example, 128 Bytes if RSA-1024 is used. + * \param ctx The RSA public key context. + * \param f_rng The RNG function. Only needed for #MBEDTLS_RSA_PRIVATE. + * \param p_rng The RNG context. + * \param mode #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE. + * \param md_alg The message-digest algorithm used to hash the original data. + * Use #MBEDTLS_MD_NONE for signing raw data. + * \param hashlen The length of the message digest. Only used if \p md_alg is #MBEDTLS_MD_NONE. + * \param hash The buffer holding the message digest. + * \param sig The buffer holding the ciphertext. * - * \note For PKCS#1 v2.1 encoding, see comments on - * mbedtls_rsa_rsassa_pss_verify() about \p md_alg and - * \p hash_id. + * \return \c 0 if the verify operation was successful. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. */ int mbedtls_rsa_pkcs1_verify( mbedtls_rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), @@ -969,15 +975,8 @@ int mbedtls_rsa_pkcs1_verify( mbedtls_rsa_context *ctx, * \brief This function performs a PKCS#1 v1.5 verification * operation (RSASSA-PKCS1-v1_5-VERIFY). * - * \param ctx The RSA public key context. - * \param f_rng The RNG function. Only needed for #MBEDTLS_RSA_PRIVATE. - * \param p_rng The RNG parameter. - * \param mode #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE. - * \param md_alg The message-digest algorithm used to hash the original data. - * Use #MBEDTLS_MD_NONE for signing raw data. - * \param hashlen The length of the message digest. Only used if \p md_alg is #MBEDTLS_MD_NONE. - * \param hash The buffer holding the message digest. - * \param sig The buffer holding the ciphertext. + * \note The \p sig buffer must be as large as the size + * of \p ctx->N. For example, 128 Bytes if RSA-1024 is used. * * \deprecated It is deprecated and discouraged to call this function * in #MBEDTLS_RSA_PRIVATE mode. Future versions of the library @@ -988,12 +987,18 @@ int mbedtls_rsa_pkcs1_verify( mbedtls_rsa_context *ctx, * mode being set to #MBEDTLS_RSA_PRIVATE and might instead * return #MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION. * - * \return \c 0 if the verify operation was successful, - * or an \c MBEDTLS_ERR_RSA_XXX error code - * on failure. + * \param ctx The RSA public key context. + * \param f_rng The RNG function. Only needed for #MBEDTLS_RSA_PRIVATE. + * \param p_rng The RNG context. + * \param mode #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE. + * \param md_alg The message-digest algorithm used to hash the original data. + * Use #MBEDTLS_MD_NONE for signing raw data. + * \param hashlen The length of the message digest. Only used if \p md_alg is #MBEDTLS_MD_NONE. + * \param hash The buffer holding the message digest. + * \param sig The buffer holding the ciphertext. * - * \note The \p sig buffer must be as large as the size - * of \p ctx->N. For example, 128 Bytes if RSA-1024 is used. + * \return \c 0 if the verify operation was successful. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. */ int mbedtls_rsa_rsassa_pkcs1_v15_verify( mbedtls_rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), @@ -1011,15 +1016,16 @@ int mbedtls_rsa_rsassa_pkcs1_v15_verify( mbedtls_rsa_context *ctx, * The hash function for the MGF mask generating function * is that specified in the RSA context. * - * \param ctx The RSA public key context. - * \param f_rng The RNG function. Only needed for #MBEDTLS_RSA_PRIVATE. - * \param p_rng The RNG parameter. - * \param mode #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE. - * \param md_alg The message-digest algorithm used to hash the original data. - * Use #MBEDTLS_MD_NONE for signing raw data. - * \param hashlen The length of the message digest. Only used if \p md_alg is #MBEDTLS_MD_NONE. - * \param hash The buffer holding the message digest. - * \param sig The buffer holding the ciphertext. + * \note The \p sig buffer must be as large as the size + * of \p ctx->N. For example, 128 Bytes if RSA-1024 is used. + * + * \note The \p hash_id in the RSA context is the one used for the + * verification. \p md_alg in the function call is the type of + * hash that is verified. According to <em>RFC-3447: Public-Key + * Cryptography Standards (PKCS) #1 v2.1: RSA Cryptography + * Specifications</em> it is advised to keep both hashes the + * same. If \p hash_id in the RSA context is unset, + * the \p md_alg from the function call is used. * * \deprecated It is deprecated and discouraged to call this function * in #MBEDTLS_RSA_PRIVATE mode. Future versions of the library @@ -1030,20 +1036,18 @@ int mbedtls_rsa_rsassa_pkcs1_v15_verify( mbedtls_rsa_context *ctx, * mode being set to #MBEDTLS_RSA_PRIVATE and might instead * return #MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION. * - * \return \c 0 if the verify operation was successful, - * or an \c MBEDTLS_ERR_RSA_XXX error code - * on failure. - * - * \note The \p sig buffer must be as large as the size - * of \p ctx->N. For example, 128 Bytes if RSA-1024 is used. + * \param ctx The RSA public key context. + * \param f_rng The RNG function. Only needed for #MBEDTLS_RSA_PRIVATE. + * \param p_rng The RNG context. + * \param mode #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE. + * \param md_alg The message-digest algorithm used to hash the original data. + * Use #MBEDTLS_MD_NONE for signing raw data. + * \param hashlen The length of the message digest. Only used if \p md_alg is #MBEDTLS_MD_NONE. + * \param hash The buffer holding the message digest. + * \param sig The buffer holding the ciphertext. * - * \note The \p hash_id in the RSA context is the one used for the - * verification. \p md_alg in the function call is the type of - * hash that is verified. According to <em>RFC-3447: Public-Key - * Cryptography Standards (PKCS) #1 v2.1: RSA Cryptography - * Specifications</em> it is advised to keep both hashes the - * same. If \p hash_id in the RSA context is unset, - * the \p md_alg from the function call is used. + * \return \c 0 if the verify operation was successful. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. */ int mbedtls_rsa_rsassa_pss_verify( mbedtls_rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), @@ -1061,27 +1065,27 @@ int mbedtls_rsa_rsassa_pss_verify( mbedtls_rsa_context *ctx, * The hash function for the MGF mask generating function * is that specified in \p mgf1_hash_id. * + * \note The \p sig buffer must be as large as the size + * of \p ctx->N. For example, 128 Bytes if RSA-1024 is used. + * + * \note The \p hash_id in the RSA context is ignored. + * * \param ctx The RSA public key context. * \param f_rng The RNG function. Only needed for #MBEDTLS_RSA_PRIVATE. - * \param p_rng The RNG parameter. + * \param p_rng The RNG context. * \param mode #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE. * \param md_alg The message-digest algorithm used to hash the original data. * Use #MBEDTLS_MD_NONE for signing raw data. - * \param hashlen The length of the message digest. Only used if \p md_alg is #MBEDTLS_MD_NONE. + * \param hashlen The length of the message digest. Only used if \p md_alg is + * #MBEDTLS_MD_NONE. * \param hash The buffer holding the message digest. - * \param mgf1_hash_id The message digest used for mask generation. - * \param expected_salt_len The length of the salt used in padding. Use - * #MBEDTLS_RSA_SALT_LEN_ANY to accept any salt length. + * \param mgf1_hash_id The message digest used for mask generation. + * \param expected_salt_len The length of the salt used in padding. Use + * #MBEDTLS_RSA_SALT_LEN_ANY to accept any salt length. * \param sig The buffer holding the ciphertext. * - * \return \c 0 if the verify operation was successful, - * or an \c MBEDTLS_ERR_RSA_XXX error code - * on failure. - * - * \note The \p sig buffer must be as large as the size - * of \p ctx->N. For example, 128 Bytes if RSA-1024 is used. - * - * \note The \p hash_id in the RSA context is ignored. + * \return \c 0 if the verify operation was successful. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. */ int mbedtls_rsa_rsassa_pss_verify_ext( mbedtls_rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), @@ -1100,8 +1104,8 @@ int mbedtls_rsa_rsassa_pss_verify_ext( mbedtls_rsa_context *ctx, * \param dst The destination context. * \param src The source context. * - * \return \c 0 on success, - * #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory allocation failure. + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory allocation failure. */ int mbedtls_rsa_copy( mbedtls_rsa_context *dst, const mbedtls_rsa_context *src ); @@ -1112,22 +1116,11 @@ int mbedtls_rsa_copy( mbedtls_rsa_context *dst, const mbedtls_rsa_context *src ) */ void mbedtls_rsa_free( mbedtls_rsa_context *ctx ); -#ifdef __cplusplus -} -#endif - -#else /* MBEDTLS_RSA_ALT */ -#include "rsa_alt.h" -#endif /* MBEDTLS_RSA_ALT */ - -#ifdef __cplusplus -extern "C" { -#endif - /** * \brief The RSA checkup routine. * - * \return \c 0 on success, or \c 1 on failure. + * \return \c 0 on success. + * \return \c 1 on failure. */ int mbedtls_rsa_self_test( int verbose ); diff --git a/thirdparty/mbedtls/include/mbedtls/rsa_internal.h b/thirdparty/mbedtls/include/mbedtls/rsa_internal.h index bcb3c9401d..53abd3c5b0 100644 --- a/thirdparty/mbedtls/include/mbedtls/rsa_internal.h +++ b/thirdparty/mbedtls/include/mbedtls/rsa_internal.h @@ -2,6 +2,37 @@ * \file rsa_internal.h * * \brief Context-independent RSA helper functions + * + * This module declares some RSA-related helper functions useful when + * implementing the RSA interface. These functions are provided in a separate + * compilation unit in order to make it easy for designers of alternative RSA + * implementations to use them in their own code, as it is conceived that the + * functionality they provide will be necessary for most complete + * implementations. + * + * End-users of Mbed TLS who are not providing their own alternative RSA + * implementations should not use these functions directly, and should instead + * use only the functions declared in rsa.h. + * + * The interface provided by this module will be maintained through LTS (Long + * Term Support) branches of Mbed TLS, but may otherwise be subject to change, + * and must be considered an internal interface of the library. + * + * There are two classes of helper functions: + * + * (1) Parameter-generating helpers. These are: + * - mbedtls_rsa_deduce_primes + * - mbedtls_rsa_deduce_private_exponent + * - mbedtls_rsa_deduce_crt + * Each of these functions takes a set of core RSA parameters and + * generates some other, or CRT related parameters. + * + * (2) Parameter-checking helpers. These are: + * - mbedtls_rsa_validate_params + * - mbedtls_rsa_validate_crt + * They take a set of core or CRT related RSA parameters and check their + * validity. + * */ /* * Copyright (C) 2006-2017, ARM Limited, All Rights Reserved @@ -21,31 +52,6 @@ * * This file is part of mbed TLS (https://tls.mbed.org) * - * - * This file declares some RSA-related helper functions useful when - * implementing the RSA interface. They are public and provided in a - * separate compilation unit in order to make it easy for designers of - * alternative RSA implementations to use them in their code, as it is - * conceived that the functionality they provide will be necessary - * for most complete implementations. - * - * End-users of Mbed TLS not intending to re-implement the RSA functionality - * are not expected to get into the need of making use of these functions directly, - * but instead should be able to use the functions declared in rsa.h. - * - * There are two classes of helper functions: - * (1) Parameter-generating helpers. These are: - * - mbedtls_rsa_deduce_primes - * - mbedtls_rsa_deduce_private_exponent - * - mbedtls_rsa_deduce_crt - * Each of these functions takes a set of core RSA parameters - * and generates some other, or CRT related parameters. - * (2) Parameter-checking helpers. These are: - * - mbedtls_rsa_validate_params - * - mbedtls_rsa_validate_crt - * They take a set of core or CRT related RSA parameters - * and check their validity. - * */ #ifndef MBEDTLS_RSA_INTERNAL_H @@ -213,4 +219,8 @@ int mbedtls_rsa_validate_crt( const mbedtls_mpi *P, const mbedtls_mpi *Q, const mbedtls_mpi *D, const mbedtls_mpi *DP, const mbedtls_mpi *DQ, const mbedtls_mpi *QP ); +#ifdef __cplusplus +} +#endif + #endif /* rsa_internal.h */ diff --git a/thirdparty/mbedtls/include/mbedtls/sha1.h b/thirdparty/mbedtls/include/mbedtls/sha1.h index 05540cde12..65a124c94b 100644 --- a/thirdparty/mbedtls/include/mbedtls/sha1.h +++ b/thirdparty/mbedtls/include/mbedtls/sha1.h @@ -1,7 +1,10 @@ /** * \file sha1.h * - * \brief The SHA-1 cryptographic hash function. + * \brief This file contains SHA-1 definitions and functions. + * + * The Secure Hash Algorithm 1 (SHA-1) cryptographic hash function is defined in + * <em>FIPS 180-4: Secure Hash Standard (SHS)</em>. * * \warning SHA-1 is considered a weak message digest and its use constitutes * a security risk. We recommend considering stronger message @@ -39,14 +42,14 @@ #define MBEDTLS_ERR_SHA1_HW_ACCEL_FAILED -0x0035 /**< SHA-1 hardware accelerator failed */ -#if !defined(MBEDTLS_SHA1_ALT) -// Regular implementation -// - #ifdef __cplusplus extern "C" { #endif +#if !defined(MBEDTLS_SHA1_ALT) +// Regular implementation +// + /** * \brief The SHA-1 context structure. * @@ -63,40 +66,44 @@ typedef struct } mbedtls_sha1_context; +#else /* MBEDTLS_SHA1_ALT */ +#include "sha1_alt.h" +#endif /* MBEDTLS_SHA1_ALT */ + /** * \brief This function initializes a SHA-1 context. * - * \param ctx The SHA-1 context to initialize. - * * \warning SHA-1 is considered a weak message digest and its use * constitutes a security risk. We recommend considering * stronger message digests instead. * + * \param ctx The SHA-1 context to initialize. + * */ void mbedtls_sha1_init( mbedtls_sha1_context *ctx ); /** * \brief This function clears a SHA-1 context. * - * \param ctx The SHA-1 context to clear. - * * \warning SHA-1 is considered a weak message digest and its use * constitutes a security risk. We recommend considering * stronger message digests instead. * + * \param ctx The SHA-1 context to clear. + * */ void mbedtls_sha1_free( mbedtls_sha1_context *ctx ); /** * \brief This function clones the state of a SHA-1 context. * - * \param dst The destination context. - * \param src The context to clone. - * * \warning SHA-1 is considered a weak message digest and its use * constitutes a security risk. We recommend considering * stronger message digests instead. * + * \param dst The SHA-1 context to clone to. + * \param src The SHA-1 context to clone from. + * */ void mbedtls_sha1_clone( mbedtls_sha1_context *dst, const mbedtls_sha1_context *src ); @@ -104,14 +111,14 @@ void mbedtls_sha1_clone( mbedtls_sha1_context *dst, /** * \brief This function starts a SHA-1 checksum calculation. * - * \param ctx The context to initialize. - * - * \return \c 0 if successful - * * \warning SHA-1 is considered a weak message digest and its use * constitutes a security risk. We recommend considering * stronger message digests instead. * + * \param ctx The SHA-1 context to initialize. + * + * \return \c 0 on success. + * */ int mbedtls_sha1_starts_ret( mbedtls_sha1_context *ctx ); @@ -119,16 +126,15 @@ int mbedtls_sha1_starts_ret( mbedtls_sha1_context *ctx ); * \brief This function feeds an input buffer into an ongoing SHA-1 * checksum calculation. * - * \param ctx The SHA-1 context. - * \param input The buffer holding the input data. - * \param ilen The length of the input data. - * - * \return \c 0 if successful - * * \warning SHA-1 is considered a weak message digest and its use * constitutes a security risk. We recommend considering * stronger message digests instead. * + * \param ctx The SHA-1 context. + * \param input The buffer holding the input data. + * \param ilen The length of the input data. + * + * \return \c 0 on success. */ int mbedtls_sha1_update_ret( mbedtls_sha1_context *ctx, const unsigned char *input, @@ -138,31 +144,30 @@ int mbedtls_sha1_update_ret( mbedtls_sha1_context *ctx, * \brief This function finishes the SHA-1 operation, and writes * the result to the output buffer. * - * \param ctx The SHA-1 context. - * \param output The SHA-1 checksum result. - * - * \return \c 0 if successful - * * \warning SHA-1 is considered a weak message digest and its use * constitutes a security risk. We recommend considering * stronger message digests instead. * + * \param ctx The SHA-1 context. + * \param output The SHA-1 checksum result. + * + * \return \c 0 on success. */ int mbedtls_sha1_finish_ret( mbedtls_sha1_context *ctx, unsigned char output[20] ); /** - * \brief SHA-1 process data block (internal use only) - * - * \param ctx SHA-1 context - * \param data The data block being processed. - * - * \return \c 0 if successful + * \brief SHA-1 process data block (internal use only). * * \warning SHA-1 is considered a weak message digest and its use * constitutes a security risk. We recommend considering * stronger message digests instead. * + * \param ctx The SHA-1 context. + * \param data The data block being processed. + * + * \return \c 0 on success. + * */ int mbedtls_internal_sha1_process( mbedtls_sha1_context *ctx, const unsigned char data[64] ); @@ -174,65 +179,67 @@ int mbedtls_internal_sha1_process( mbedtls_sha1_context *ctx, #define MBEDTLS_DEPRECATED #endif /** - * \brief SHA-1 context setup - * - * \deprecated Superseded by mbedtls_sha1_starts_ret() in 2.7.0 - * - * \param ctx The SHA-1 context to be initialized. + * \brief This function starts a SHA-1 checksum calculation. * * \warning SHA-1 is considered a weak message digest and its use * constitutes a security risk. We recommend considering * stronger message digests instead. * + * \deprecated Superseded by mbedtls_sha1_starts_ret() in 2.7.0. + * + * \param ctx The SHA-1 context to initialize. + * */ MBEDTLS_DEPRECATED void mbedtls_sha1_starts( mbedtls_sha1_context *ctx ); /** - * \brief SHA-1 process buffer + * \brief This function feeds an input buffer into an ongoing SHA-1 + * checksum calculation. + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. * - * \deprecated Superseded by mbedtls_sha1_update_ret() in 2.7.0 + * \deprecated Superseded by mbedtls_sha1_update_ret() in 2.7.0. * * \param ctx The SHA-1 context. * \param input The buffer holding the input data. * \param ilen The length of the input data. * - * \warning SHA-1 is considered a weak message digest and its use - * constitutes a security risk. We recommend considering - * stronger message digests instead. - * */ MBEDTLS_DEPRECATED void mbedtls_sha1_update( mbedtls_sha1_context *ctx, const unsigned char *input, size_t ilen ); /** - * \brief SHA-1 final digest - * - * \deprecated Superseded by mbedtls_sha1_finish_ret() in 2.7.0 - * - * \param ctx The SHA-1 context. - * \param output The SHA-1 checksum result. + * \brief This function finishes the SHA-1 operation, and writes + * the result to the output buffer. * * \warning SHA-1 is considered a weak message digest and its use * constitutes a security risk. We recommend considering * stronger message digests instead. * + * \deprecated Superseded by mbedtls_sha1_finish_ret() in 2.7.0. + * + * \param ctx The SHA-1 context. + * \param output The SHA-1 checksum result. + * */ MBEDTLS_DEPRECATED void mbedtls_sha1_finish( mbedtls_sha1_context *ctx, unsigned char output[20] ); /** - * \brief SHA-1 process data block (internal use only) - * - * \deprecated Superseded by mbedtls_internal_sha1_process() in 2.7.0 - * - * \param ctx The SHA-1 context. - * \param data The data block being processed. + * \brief SHA-1 process data block (internal use only). * * \warning SHA-1 is considered a weak message digest and its use * constitutes a security risk. We recommend considering * stronger message digests instead. * + * \deprecated Superseded by mbedtls_internal_sha1_process() in 2.7.0. + * + * \param ctx The SHA-1 context. + * \param data The data block being processed. + * */ MBEDTLS_DEPRECATED void mbedtls_sha1_process( mbedtls_sha1_context *ctx, const unsigned char data[64] ); @@ -240,18 +247,6 @@ MBEDTLS_DEPRECATED void mbedtls_sha1_process( mbedtls_sha1_context *ctx, #undef MBEDTLS_DEPRECATED #endif /* !MBEDTLS_DEPRECATED_REMOVED */ -#ifdef __cplusplus -} -#endif - -#else /* MBEDTLS_SHA1_ALT */ -#include "sha1_alt.h" -#endif /* MBEDTLS_SHA1_ALT */ - -#ifdef __cplusplus -extern "C" { -#endif - /** * \brief This function calculates the SHA-1 checksum of a buffer. * @@ -261,15 +256,15 @@ extern "C" { * The SHA-1 result is calculated as * output = SHA-1(input buffer). * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * * \param input The buffer holding the input data. * \param ilen The length of the input data. * \param output The SHA-1 checksum result. * - * \return \c 0 if successful - * - * \warning SHA-1 is considered a weak message digest and its use - * constitutes a security risk. We recommend considering - * stronger message digests instead. + * \return \c 0 on success. * */ int mbedtls_sha1_ret( const unsigned char *input, @@ -283,18 +278,24 @@ int mbedtls_sha1_ret( const unsigned char *input, #define MBEDTLS_DEPRECATED #endif /** - * \brief Output = SHA-1( input buffer ) + * \brief This function calculates the SHA-1 checksum of a buffer. * - * \deprecated Superseded by mbedtls_sha1_ret() in 2.7.0 + * The function allocates the context, performs the + * calculation, and frees the context. * - * \param input The buffer holding the input data. - * \param ilen The length of the input data. - * \param output The SHA-1 checksum result. + * The SHA-1 result is calculated as + * output = SHA-1(input buffer). * * \warning SHA-1 is considered a weak message digest and its use * constitutes a security risk. We recommend considering * stronger message digests instead. * + * \deprecated Superseded by mbedtls_sha1_ret() in 2.7.0 + * + * \param input The buffer holding the input data. + * \param ilen The length of the input data. + * \param output The SHA-1 checksum result. + * */ MBEDTLS_DEPRECATED void mbedtls_sha1( const unsigned char *input, size_t ilen, @@ -306,12 +307,13 @@ MBEDTLS_DEPRECATED void mbedtls_sha1( const unsigned char *input, /** * \brief The SHA-1 checkup routine. * - * \return \c 0 on success, or \c 1 on failure. - * * \warning SHA-1 is considered a weak message digest and its use * constitutes a security risk. We recommend considering * stronger message digests instead. * + * \return \c 0 on success. + * \return \c 1 on failure. + * */ int mbedtls_sha1_self_test( int verbose ); diff --git a/thirdparty/mbedtls/include/mbedtls/sha256.h b/thirdparty/mbedtls/include/mbedtls/sha256.h index ffb16c277a..adf31a82ed 100644 --- a/thirdparty/mbedtls/include/mbedtls/sha256.h +++ b/thirdparty/mbedtls/include/mbedtls/sha256.h @@ -1,7 +1,10 @@ /** * \file sha256.h * - * \brief The SHA-224 and SHA-256 cryptographic hash function. + * \brief This file contains SHA-224 and SHA-256 definitions and functions. + * + * The Secure Hash Algorithms 224 and 256 (SHA-224 and SHA-256) cryptographic + * hash functions are defined in <em>FIPS 180-4: Secure Hash Standard (SHS)</em>. */ /* * Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved @@ -35,14 +38,14 @@ #define MBEDTLS_ERR_SHA256_HW_ACCEL_FAILED -0x0037 /**< SHA-256 hardware accelerator failed */ -#if !defined(MBEDTLS_SHA256_ALT) -// Regular implementation -// - #ifdef __cplusplus extern "C" { #endif +#if !defined(MBEDTLS_SHA256_ALT) +// Regular implementation +// + /** * \brief The SHA-256 context structure. * @@ -55,12 +58,15 @@ typedef struct uint32_t total[2]; /*!< The number of Bytes processed. */ uint32_t state[8]; /*!< The intermediate digest state. */ unsigned char buffer[64]; /*!< The data block being processed. */ - int is224; /*!< Determines which function to use. - <ul><li>0: Use SHA-256.</li> - <li>1: Use SHA-224.</li></ul> */ + int is224; /*!< Determines which function to use: + 0: Use SHA-256, or 1: Use SHA-224. */ } mbedtls_sha256_context; +#else /* MBEDTLS_SHA256_ALT */ +#include "sha256_alt.h" +#endif /* MBEDTLS_SHA256_ALT */ + /** * \brief This function initializes a SHA-256 context. * @@ -89,9 +95,8 @@ void mbedtls_sha256_clone( mbedtls_sha256_context *dst, * calculation. * * \param ctx The context to initialize. - * \param is224 Determines which function to use. - * <ul><li>0: Use SHA-256.</li> - * <li>1: Use SHA-224.</li></ul> + * \param is224 Determines which function to use: + * 0: Use SHA-256, or 1: Use SHA-224. * * \return \c 0 on success. */ @@ -101,9 +106,9 @@ int mbedtls_sha256_starts_ret( mbedtls_sha256_context *ctx, int is224 ); * \brief This function feeds an input buffer into an ongoing * SHA-256 checksum calculation. * - * \param ctx SHA-256 context - * \param input buffer holding the data - * \param ilen length of the input data + * \param ctx The SHA-256 context. + * \param input The buffer holding the data. + * \param ilen The length of the input data. * * \return \c 0 on success. */ @@ -143,14 +148,15 @@ int mbedtls_internal_sha256_process( mbedtls_sha256_context *ctx, #define MBEDTLS_DEPRECATED #endif /** - * \brief This function starts a SHA-256 checksum calculation. + * \brief This function starts a SHA-224 or SHA-256 checksum + * calculation. + * * * \deprecated Superseded by mbedtls_sha256_starts_ret() in 2.7.0. * - * \param ctx The SHA-256 context to initialize. - * \param is224 Determines which function to use. - * <ul><li>0: Use SHA-256.</li> - * <li>1: Use SHA-224.</li></ul> + * \param ctx The context to initialize. + * \param is224 Determines which function to use: + * 0: Use SHA-256, or 1: Use SHA-224. */ MBEDTLS_DEPRECATED void mbedtls_sha256_starts( mbedtls_sha256_context *ctx, int is224 ); @@ -176,7 +182,7 @@ MBEDTLS_DEPRECATED void mbedtls_sha256_update( mbedtls_sha256_context *ctx, * \deprecated Superseded by mbedtls_sha256_finish_ret() in 2.7.0. * * \param ctx The SHA-256 context. - * \param output The SHA-224or SHA-256 checksum result. + * \param output The SHA-224 or SHA-256 checksum result. */ MBEDTLS_DEPRECATED void mbedtls_sha256_finish( mbedtls_sha256_context *ctx, unsigned char output[32] ); @@ -196,17 +202,6 @@ MBEDTLS_DEPRECATED void mbedtls_sha256_process( mbedtls_sha256_context *ctx, #undef MBEDTLS_DEPRECATED #endif /* !MBEDTLS_DEPRECATED_REMOVED */ -#ifdef __cplusplus -} -#endif - -#else /* MBEDTLS_SHA256_ALT */ -#include "sha256_alt.h" -#endif /* MBEDTLS_SHA256_ALT */ - -#ifdef __cplusplus -extern "C" { -#endif /** * \brief This function calculates the SHA-224 or SHA-256 @@ -221,9 +216,8 @@ extern "C" { * \param input The buffer holding the input data. * \param ilen The length of the input data. * \param output The SHA-224 or SHA-256 checksum result. - * \param is224 Determines which function to use. - * <ul><li>0: Use SHA-256.</li> - * <li>1: Use SHA-224.</li></ul> + * \param is224 Determines which function to use: + * 0: Use SHA-256, or 1: Use SHA-224. */ int mbedtls_sha256_ret( const unsigned char *input, size_t ilen, @@ -252,9 +246,8 @@ int mbedtls_sha256_ret( const unsigned char *input, * \param input The buffer holding the data. * \param ilen The length of the input data. * \param output The SHA-224 or SHA-256 checksum result. - * \param is224 Determines which function to use. - * <ul><li>0: Use SHA-256.</li> - * <li>1: Use SHA-224.</li></ul> + * \param is224 Determines which function to use: + * 0: Use SHA-256, or 1: Use SHA-224. */ MBEDTLS_DEPRECATED void mbedtls_sha256( const unsigned char *input, size_t ilen, @@ -267,7 +260,8 @@ MBEDTLS_DEPRECATED void mbedtls_sha256( const unsigned char *input, /** * \brief The SHA-224 and SHA-256 checkup routine. * - * \return \c 0 on success, or \c 1 on failure. + * \return \c 0 on success. + * \return \c 1 on failure. */ int mbedtls_sha256_self_test( int verbose ); diff --git a/thirdparty/mbedtls/include/mbedtls/sha512.h b/thirdparty/mbedtls/include/mbedtls/sha512.h index 8404a2d599..5bb83f43bd 100644 --- a/thirdparty/mbedtls/include/mbedtls/sha512.h +++ b/thirdparty/mbedtls/include/mbedtls/sha512.h @@ -1,7 +1,9 @@ /** * \file sha512.h + * \brief This file contains SHA-384 and SHA-512 definitions and functions. * - * \brief The SHA-384 and SHA-512 cryptographic hash function. + * The Secure Hash Algorithms 384 and 512 (SHA-384 and SHA-512) cryptographic + * hash functions are defined in <em>FIPS 180-4: Secure Hash Standard (SHS)</em>. */ /* * Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved @@ -35,14 +37,14 @@ #define MBEDTLS_ERR_SHA512_HW_ACCEL_FAILED -0x0039 /**< SHA-512 hardware accelerator failed */ -#if !defined(MBEDTLS_SHA512_ALT) -// Regular implementation -// - #ifdef __cplusplus extern "C" { #endif +#if !defined(MBEDTLS_SHA512_ALT) +// Regular implementation +// + /** * \brief The SHA-512 context structure. * @@ -55,12 +57,15 @@ typedef struct uint64_t total[2]; /*!< The number of Bytes processed. */ uint64_t state[8]; /*!< The intermediate digest state. */ unsigned char buffer[128]; /*!< The data block being processed. */ - int is384; /*!< Determines which function to use. - * <ul><li>0: Use SHA-512.</li> - * <li>1: Use SHA-384.</li></ul> */ + int is384; /*!< Determines which function to use: + 0: Use SHA-512, or 1: Use SHA-384. */ } mbedtls_sha512_context; +#else /* MBEDTLS_SHA512_ALT */ +#include "sha512_alt.h" +#endif /* MBEDTLS_SHA512_ALT */ + /** * \brief This function initializes a SHA-512 context. * @@ -89,9 +94,8 @@ void mbedtls_sha512_clone( mbedtls_sha512_context *dst, * calculation. * * \param ctx The SHA-512 context to initialize. - * \param is384 Determines which function to use. - * <ul><li>0: Use SHA-512.</li> - * <li>1: Use SHA-384.</li></ul> + * \param is384 Determines which function to use: + * 0: Use SHA-512, or 1: Use SHA-384. * * \return \c 0 on success. */ @@ -148,9 +152,8 @@ int mbedtls_internal_sha512_process( mbedtls_sha512_context *ctx, * \deprecated Superseded by mbedtls_sha512_starts_ret() in 2.7.0 * * \param ctx The SHA-512 context to initialize. - * \param is384 Determines which function to use. - * <ul><li>0: Use SHA-512.</li> - * <li>1: Use SHA-384.</li></ul> + * \param is384 Determines which function to use: + * 0: Use SHA-512, or 1: Use SHA-384. */ MBEDTLS_DEPRECATED void mbedtls_sha512_starts( mbedtls_sha512_context *ctx, int is384 ); @@ -159,7 +162,7 @@ MBEDTLS_DEPRECATED void mbedtls_sha512_starts( mbedtls_sha512_context *ctx, * \brief This function feeds an input buffer into an ongoing * SHA-512 checksum calculation. * - * \deprecated Superseded by mbedtls_sha512_update_ret() in 2.7.0 + * \deprecated Superseded by mbedtls_sha512_update_ret() in 2.7.0. * * \param ctx The SHA-512 context. * \param input The buffer holding the data. @@ -173,7 +176,7 @@ MBEDTLS_DEPRECATED void mbedtls_sha512_update( mbedtls_sha512_context *ctx, * \brief This function finishes the SHA-512 operation, and writes * the result to the output buffer. * - * \deprecated Superseded by mbedtls_sha512_finish_ret() in 2.7.0 + * \deprecated Superseded by mbedtls_sha512_finish_ret() in 2.7.0. * * \param ctx The SHA-512 context. * \param output The SHA-384 or SHA-512 checksum result. @@ -186,7 +189,7 @@ MBEDTLS_DEPRECATED void mbedtls_sha512_finish( mbedtls_sha512_context *ctx, * the ongoing SHA-512 computation. This function is for * internal use only. * - * \deprecated Superseded by mbedtls_internal_sha512_process() in 2.7.0 + * \deprecated Superseded by mbedtls_internal_sha512_process() in 2.7.0. * * \param ctx The SHA-512 context. * \param data The buffer holding one block of data. @@ -198,18 +201,6 @@ MBEDTLS_DEPRECATED void mbedtls_sha512_process( #undef MBEDTLS_DEPRECATED #endif /* !MBEDTLS_DEPRECATED_REMOVED */ -#ifdef __cplusplus -} -#endif - -#else /* MBEDTLS_SHA512_ALT */ -#include "sha512_alt.h" -#endif /* MBEDTLS_SHA512_ALT */ - -#ifdef __cplusplus -extern "C" { -#endif - /** * \brief This function calculates the SHA-512 or SHA-384 * checksum of a buffer. @@ -223,9 +214,8 @@ extern "C" { * \param input The buffer holding the input data. * \param ilen The length of the input data. * \param output The SHA-384 or SHA-512 checksum result. - * \param is384 Determines which function to use. - * <ul><li>0: Use SHA-512.</li> - * <li>1: Use SHA-384.</li></ul> + * \param is384 Determines which function to use: + * 0: Use SHA-512, or 1: Use SHA-384. * * \return \c 0 on success. */ @@ -255,9 +245,8 @@ int mbedtls_sha512_ret( const unsigned char *input, * \param input The buffer holding the data. * \param ilen The length of the input data. * \param output The SHA-384 or SHA-512 checksum result. - * \param is384 Determines which function to use. - * <ul><li>0: Use SHA-512.</li> - * <li>1: Use SHA-384.</li></ul> + * \param is384 Determines which function to use: + * 0: Use SHA-512, or 1: Use SHA-384. */ MBEDTLS_DEPRECATED void mbedtls_sha512( const unsigned char *input, size_t ilen, @@ -269,7 +258,8 @@ MBEDTLS_DEPRECATED void mbedtls_sha512( const unsigned char *input, /** * \brief The SHA-384 or SHA-512 checkup routine. * - * \return \c 0 on success, or \c 1 on failure. + * \return \c 0 on success. + * \return \c 1 on failure. */ int mbedtls_sha512_self_test( int verbose ); diff --git a/thirdparty/mbedtls/include/mbedtls/ssl.h b/thirdparty/mbedtls/include/mbedtls/ssl.h index dffc162191..2d511a8ea1 100644 --- a/thirdparty/mbedtls/include/mbedtls/ssl.h +++ b/thirdparty/mbedtls/include/mbedtls/ssl.h @@ -62,7 +62,7 @@ #endif #if defined(MBEDTLS_HAVE_TIME) -#include "mbedtls/platform_time.h" +#include "platform_time.h" #endif /* @@ -112,13 +112,15 @@ #define MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED -0x6A80 /**< DTLS client must retry for hello verification */ #define MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL -0x6A00 /**< A buffer is too small to receive or write a message */ #define MBEDTLS_ERR_SSL_NO_USABLE_CIPHERSUITE -0x6980 /**< None of the common ciphersuites is usable (eg, no suitable certificate, see debug messages). */ -#define MBEDTLS_ERR_SSL_WANT_READ -0x6900 /**< Connection requires a read call. */ +#define MBEDTLS_ERR_SSL_WANT_READ -0x6900 /**< No data of requested type currently available on underlying transport. */ #define MBEDTLS_ERR_SSL_WANT_WRITE -0x6880 /**< Connection requires a write call. */ #define MBEDTLS_ERR_SSL_TIMEOUT -0x6800 /**< The operation timed out. */ #define MBEDTLS_ERR_SSL_CLIENT_RECONNECT -0x6780 /**< The client initiated a reconnect from the same port. */ #define MBEDTLS_ERR_SSL_UNEXPECTED_RECORD -0x6700 /**< Record header looks valid but is not expected. */ #define MBEDTLS_ERR_SSL_NON_FATAL -0x6680 /**< The alert message received indicates a non-fatal error. */ #define MBEDTLS_ERR_SSL_INVALID_VERIFY_HASH -0x6600 /**< Couldn't set the hash for verifying CertificateVerify */ +#define MBEDTLS_ERR_SSL_CONTINUE_PROCESSING -0x6580 /**< Internal-only message signaling that further message-processing should be done */ +#define MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS -0x6500 /**< The asynchronous operation is not completed yet. */ /* * Various constants @@ -218,7 +220,7 @@ #endif /* - * Maxium fragment length in bytes, + * Maximum fragment length in bytes, * determines the size of each of the two internal I/O buffers. * * Note: the RFC defines the default size of SSL / TLS messages. If you @@ -232,6 +234,14 @@ #define MBEDTLS_SSL_MAX_CONTENT_LEN 16384 /**< Size of the input / output buffer */ #endif +#if !defined(MBEDTLS_SSL_IN_CONTENT_LEN) +#define MBEDTLS_SSL_IN_CONTENT_LEN MBEDTLS_SSL_MAX_CONTENT_LEN +#endif + +#if !defined(MBEDTLS_SSL_OUT_CONTENT_LEN) +#define MBEDTLS_SSL_OUT_CONTENT_LEN MBEDTLS_SSL_MAX_CONTENT_LEN +#endif + /* \} name SECTION: Module settings */ /* @@ -535,7 +545,6 @@ typedef void mbedtls_ssl_set_timer_t( void * ctx, */ typedef int mbedtls_ssl_get_timer_t( void * ctx ); - /* Defined below */ typedef struct mbedtls_ssl_session mbedtls_ssl_session; typedef struct mbedtls_ssl_context mbedtls_ssl_context; @@ -552,6 +561,218 @@ typedef struct mbedtls_ssl_key_cert mbedtls_ssl_key_cert; typedef struct mbedtls_ssl_flight_item mbedtls_ssl_flight_item; #endif +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) +#if defined(MBEDTLS_X509_CRT_PARSE_C) +/** + * \brief Callback type: start external signature operation. + * + * This callback is called during an SSL handshake to start + * a signature decryption operation using an + * external processor. The parameter \p cert contains + * the public key; it is up to the callback function to + * determine how to access the associated private key. + * + * This function typically sends or enqueues a request, and + * does not wait for the operation to complete. This allows + * the handshake step to be non-blocking. + * + * The parameters \p ssl and \p cert are guaranteed to remain + * valid throughout the handshake. On the other hand, this + * function must save the contents of \p hash if the value + * is needed for later processing, because the \p hash buffer + * is no longer valid after this function returns. + * + * This function may call mbedtls_ssl_set_async_operation_data() + * to store an operation context for later retrieval + * by the resume or cancel callback. + * + * \note For RSA signatures, this function must produce output + * that is consistent with PKCS#1 v1.5 in the same way as + * mbedtls_rsa_pkcs1_sign(). Before the private key operation, + * apply the padding steps described in RFC 8017, section 9.2 + * "EMSA-PKCS1-v1_5" as follows. + * - If \p md_alg is #MBEDTLS_MD_NONE, apply the PKCS#1 v1.5 + * encoding, treating \p hash as the DigestInfo to be + * padded. In other words, apply EMSA-PKCS1-v1_5 starting + * from step 3, with `T = hash` and `tLen = hash_len`. + * - If `md_alg != MBEDTLS_MD_NONE`, apply the PKCS#1 v1.5 + * encoding, treating \p hash as the hash to be encoded and + * padded. In other words, apply EMSA-PKCS1-v1_5 starting + * from step 2, with `digestAlgorithm` obtained by calling + * mbedtls_oid_get_oid_by_md() on \p md_alg. + * + * \note For ECDSA signatures, the output format is the DER encoding + * `Ecdsa-Sig-Value` defined in + * [RFC 4492 section 5.4](https://tools.ietf.org/html/rfc4492#section-5.4). + * + * \param ssl The SSL connection instance. It should not be + * modified other than via + * mbedtls_ssl_set_async_operation_data(). + * \param cert Certificate containing the public key. + * In simple cases, this is one of the pointers passed to + * mbedtls_ssl_conf_own_cert() when configuring the SSL + * connection. However, if other callbacks are used, this + * property may not hold. For example, if an SNI callback + * is registered with mbedtls_ssl_conf_sni(), then + * this callback determines what certificate is used. + * \param md_alg Hash algorithm. + * \param hash Buffer containing the hash. This buffer is + * no longer valid when the function returns. + * \param hash_len Size of the \c hash buffer in bytes. + * + * \return 0 if the operation was started successfully and the SSL + * stack should call the resume callback immediately. + * \return #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS if the operation + * was started successfully and the SSL stack should return + * immediately without calling the resume callback yet. + * \return #MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH if the external + * processor does not support this key. The SSL stack will + * use the private key object instead. + * \return Any other error indicates a fatal failure and is + * propagated up the call chain. The callback should + * use \c MBEDTLS_ERR_PK_xxx error codes, and <b>must not</b> + * use \c MBEDTLS_ERR_SSL_xxx error codes except as + * directed in the documentation of this callback. + */ +typedef int mbedtls_ssl_async_sign_t( mbedtls_ssl_context *ssl, + mbedtls_x509_crt *cert, + mbedtls_md_type_t md_alg, + const unsigned char *hash, + size_t hash_len ); + +/** + * \brief Callback type: start external decryption operation. + * + * This callback is called during an SSL handshake to start + * an RSA decryption operation using an + * external processor. The parameter \p cert contains + * the public key; it is up to the callback function to + * determine how to access the associated private key. + * + * This function typically sends or enqueues a request, and + * does not wait for the operation to complete. This allows + * the handshake step to be non-blocking. + * + * The parameters \p ssl and \p cert are guaranteed to remain + * valid throughout the handshake. On the other hand, this + * function must save the contents of \p input if the value + * is needed for later processing, because the \p input buffer + * is no longer valid after this function returns. + * + * This function may call mbedtls_ssl_set_async_operation_data() + * to store an operation context for later retrieval + * by the resume or cancel callback. + * + * \warning RSA decryption as used in TLS is subject to a potential + * timing side channel attack first discovered by Bleichenbacher + * in 1998. This attack can be remotely exploitable + * in practice. To avoid this attack, you must ensure that + * if the callback performs an RSA decryption, the time it + * takes to execute and return the result does not depend + * on whether the RSA decryption succeeded or reported + * invalid padding. + * + * \param ssl The SSL connection instance. It should not be + * modified other than via + * mbedtls_ssl_set_async_operation_data(). + * \param cert Certificate containing the public key. + * In simple cases, this is one of the pointers passed to + * mbedtls_ssl_conf_own_cert() when configuring the SSL + * connection. However, if other callbacks are used, this + * property may not hold. For example, if an SNI callback + * is registered with mbedtls_ssl_conf_sni(), then + * this callback determines what certificate is used. + * \param input Buffer containing the input ciphertext. This buffer + * is no longer valid when the function returns. + * \param input_len Size of the \p input buffer in bytes. + * + * \return 0 if the operation was started successfully and the SSL + * stack should call the resume callback immediately. + * \return #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS if the operation + * was started successfully and the SSL stack should return + * immediately without calling the resume callback yet. + * \return #MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH if the external + * processor does not support this key. The SSL stack will + * use the private key object instead. + * \return Any other error indicates a fatal failure and is + * propagated up the call chain. The callback should + * use \c MBEDTLS_ERR_PK_xxx error codes, and <b>must not</b> + * use \c MBEDTLS_ERR_SSL_xxx error codes except as + * directed in the documentation of this callback. + */ +typedef int mbedtls_ssl_async_decrypt_t( mbedtls_ssl_context *ssl, + mbedtls_x509_crt *cert, + const unsigned char *input, + size_t input_len ); +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +/** + * \brief Callback type: resume external operation. + * + * This callback is called during an SSL handshake to resume + * an external operation started by the + * ::mbedtls_ssl_async_sign_t or + * ::mbedtls_ssl_async_decrypt_t callback. + * + * This function typically checks the status of a pending + * request or causes the request queue to make progress, and + * does not wait for the operation to complete. This allows + * the handshake step to be non-blocking. + * + * This function may call mbedtls_ssl_get_async_operation_data() + * to retrieve an operation context set by the start callback. + * It may call mbedtls_ssl_set_async_operation_data() to modify + * this context. + * + * Note that when this function returns a status other than + * #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS, it must free any + * resources associated with the operation. + * + * \param ssl The SSL connection instance. It should not be + * modified other than via + * mbedtls_ssl_set_async_operation_data(). + * \param output Buffer containing the output (signature or decrypted + * data) on success. + * \param output_len On success, number of bytes written to \p output. + * \param output_size Size of the \p output buffer in bytes. + * + * \return 0 if output of the operation is available in the + * \p output buffer. + * \return #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS if the operation + * is still in progress. Subsequent requests for progress + * on the SSL connection will call the resume callback + * again. + * \return Any other error means that the operation is aborted. + * The SSL handshake is aborted. The callback should + * use \c MBEDTLS_ERR_PK_xxx error codes, and <b>must not</b> + * use \c MBEDTLS_ERR_SSL_xxx error codes except as + * directed in the documentation of this callback. + */ +typedef int mbedtls_ssl_async_resume_t( mbedtls_ssl_context *ssl, + unsigned char *output, + size_t *output_len, + size_t output_size ); + +/** + * \brief Callback type: cancel external operation. + * + * This callback is called if an SSL connection is closed + * while an asynchronous operation is in progress. Note that + * this callback is not called if the + * ::mbedtls_ssl_async_resume_t callback has run and has + * returned a value other than + * #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS, since in that case + * the asynchronous operation has already completed. + * + * This function may call mbedtls_ssl_get_async_operation_data() + * to retrieve an operation context set by the start callback. + * + * \param ssl The SSL connection instance. It should not be + * modified. + */ +typedef void mbedtls_ssl_async_cancel_t( mbedtls_ssl_context *ssl ); +#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ + /* * This structure is used for storing current session data. */ @@ -668,6 +889,16 @@ struct mbedtls_ssl_config mbedtls_x509_crl *ca_crl; /*!< trusted CAs CRLs */ #endif /* MBEDTLS_X509_CRT_PARSE_C */ +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) +#if defined(MBEDTLS_X509_CRT_PARSE_C) + mbedtls_ssl_async_sign_t *f_async_sign_start; /*!< start asynchronous signature operation */ + mbedtls_ssl_async_decrypt_t *f_async_decrypt_start; /*!< start asynchronous decryption operation */ +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + mbedtls_ssl_async_resume_t *f_async_resume; /*!< resume asynchronous operation */ + mbedtls_ssl_async_cancel_t *f_async_cancel; /*!< cancel asynchronous operation */ + void *p_async_config_data; /*!< Configuration data set by mbedtls_ssl_conf_async_private_cb(). */ +#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ + #if defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) const int *sig_hashes; /*!< allowed signature hashes */ #endif @@ -682,10 +913,18 @@ struct mbedtls_ssl_config #endif #if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) - unsigned char *psk; /*!< pre-shared key */ - size_t psk_len; /*!< length of the pre-shared key */ - unsigned char *psk_identity; /*!< identity for PSK negotiation */ - size_t psk_identity_len;/*!< length of identity */ + unsigned char *psk; /*!< pre-shared key. This field should + only be set via + mbedtls_ssl_conf_psk() */ + size_t psk_len; /*!< length of the pre-shared key. This + field should only be set via + mbedtls_ssl_conf_psk() */ + unsigned char *psk_identity; /*!< identity for PSK negotiation. This + field should only be set via + mbedtls_ssl_conf_psk() */ + size_t psk_identity_len;/*!< length of identity. This field should + only be set via + mbedtls_ssl_conf_psk() */ #endif #if defined(MBEDTLS_SSL_ALPN) @@ -938,14 +1177,6 @@ extern int (*mbedtls_ssl_hw_record_finish)(mbedtls_ssl_context *ssl); #endif /* MBEDTLS_SSL_HW_RECORD_ACCEL */ /** - * \brief Returns the list of ciphersuites supported by the SSL/TLS module. - * - * \return a statically allocated array of ciphersuites, the last - * entry is 0. - */ -const int *mbedtls_ssl_list_ciphersuites( void ); - -/** * \brief Return the name of the ciphersuite associated with the * given ID * @@ -1306,6 +1537,85 @@ void mbedtls_ssl_conf_export_keys_cb( mbedtls_ssl_config *conf, void *p_export_keys ); #endif /* MBEDTLS_SSL_EXPORT_KEYS */ +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) +/** + * \brief Configure asynchronous private key operation callbacks. + * + * \param conf SSL configuration context + * \param f_async_sign Callback to start a signature operation. See + * the description of ::mbedtls_ssl_async_sign_t + * for more information. This may be \c NULL if the + * external processor does not support any signature + * operation; in this case the private key object + * associated with the certificate will be used. + * \param f_async_decrypt Callback to start a decryption operation. See + * the description of ::mbedtls_ssl_async_decrypt_t + * for more information. This may be \c NULL if the + * external processor does not support any decryption + * operation; in this case the private key object + * associated with the certificate will be used. + * \param f_async_resume Callback to resume an asynchronous operation. See + * the description of ::mbedtls_ssl_async_resume_t + * for more information. This may not be \c NULL unless + * \p f_async_sign and \p f_async_decrypt are both + * \c NULL. + * \param f_async_cancel Callback to cancel an asynchronous operation. See + * the description of ::mbedtls_ssl_async_cancel_t + * for more information. This may be \c NULL if + * no cleanup is needed. + * \param config_data A pointer to configuration data which can be + * retrieved with + * mbedtls_ssl_conf_get_async_config_data(). The + * library stores this value without dereferencing it. + */ +void mbedtls_ssl_conf_async_private_cb( mbedtls_ssl_config *conf, + mbedtls_ssl_async_sign_t *f_async_sign, + mbedtls_ssl_async_decrypt_t *f_async_decrypt, + mbedtls_ssl_async_resume_t *f_async_resume, + mbedtls_ssl_async_cancel_t *f_async_cancel, + void *config_data ); + +/** + * \brief Retrieve the configuration data set by + * mbedtls_ssl_conf_async_private_cb(). + * + * \param conf SSL configuration context + * \return The configuration data set by + * mbedtls_ssl_conf_async_private_cb(). + */ +void *mbedtls_ssl_conf_get_async_config_data( const mbedtls_ssl_config *conf ); + +/** + * \brief Retrieve the asynchronous operation user context. + * + * \note This function may only be called while a handshake + * is in progress. + * + * \param ssl The SSL context to access. + * + * \return The asynchronous operation user context that was last + * set during the current handshake. If + * mbedtls_ssl_set_async_operation_data() has not yet been + * called during the current handshake, this function returns + * \c NULL. + */ +void *mbedtls_ssl_get_async_operation_data( const mbedtls_ssl_context *ssl ); + +/** + * \brief Retrieve the asynchronous operation user context. + * + * \note This function may only be called while a handshake + * is in progress. + * + * \param ssl The SSL context to access. + * \param ctx The new value of the asynchronous operation user context. + * Call mbedtls_ssl_get_async_operation_data() later during the + * same handshake to retrieve this value. + */ +void mbedtls_ssl_set_async_operation_data( mbedtls_ssl_context *ssl, + void *ctx ); +#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ + /** * \brief Callback type: generate a cookie * @@ -1601,6 +1911,10 @@ void mbedtls_ssl_conf_cert_profile( mbedtls_ssl_config *conf, /** * \brief Set the data required to verify peer certificate * + * \note See \c mbedtls_x509_crt_verify() for notes regarding the + * parameters ca_chain (maps to trust_ca for that function) + * and ca_crl. + * * \param conf SSL configuration * \param ca_chain trusted CA chain (meaning all fully trusted top-level CAs) * \param ca_crl trusted CA CRLs @@ -1841,21 +2155,21 @@ void mbedtls_ssl_conf_sig_hashes( mbedtls_ssl_config *conf, #if defined(MBEDTLS_X509_CRT_PARSE_C) /** - * \brief Set or reset the hostname to check against the received - * server certificate. It sets the ServerName TLS extension, + * \brief Set or reset the hostname to check against the received + * server certificate. It sets the ServerName TLS extension, * too, if that extension is enabled. (client-side only) * * \param ssl SSL context * \param hostname the server hostname, may be NULL to clear hostname - + * \note Maximum hostname length MBEDTLS_SSL_MAX_HOST_NAME_LEN. * - * \return 0 if successful, MBEDTLS_ERR_SSL_ALLOC_FAILED on - * allocation failure, MBEDTLS_ERR_SSL_BAD_INPUT_DATA on + * \return 0 if successful, MBEDTLS_ERR_SSL_ALLOC_FAILED on + * allocation failure, MBEDTLS_ERR_SSL_BAD_INPUT_DATA on * too long input hostname. * * Hostname set to the one provided on success (cleared - * when NULL). On allocation failure hostname is cleared. + * when NULL). On allocation failure hostname is cleared. * On too long input failure, old hostname is unchanged. */ int mbedtls_ssl_set_hostname( mbedtls_ssl_context *ssl, const char *hostname ); @@ -2112,7 +2426,8 @@ void mbedtls_ssl_conf_cert_req_ca_list( mbedtls_ssl_config *conf, #if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) /** * \brief Set the maximum fragment length to emit and/or negotiate - * (Default: MBEDTLS_SSL_MAX_CONTENT_LEN, usually 2^14 bytes) + * (Default: the smaller of MBEDTLS_SSL_IN_CONTENT_LEN and + * MBEDTLS_SSL_OUT_CONTENT_LEN, usually 2^14 bytes) * (Server: set maximum fragment length to emit, * usually negotiated by the client during handshake * (Client: set maximum fragment length to emit *and* @@ -2289,11 +2604,59 @@ void mbedtls_ssl_conf_renegotiation_period( mbedtls_ssl_config *conf, #endif /* MBEDTLS_SSL_RENEGOTIATION */ /** - * \brief Return the number of data bytes available to read + * \brief Check if there is data already read from the + * underlying transport but not yet processed. * * \param ssl SSL context * - * \return how many bytes are available in the read buffer + * \return 0 if nothing's pending, 1 otherwise. + * + * \note This is different in purpose and behaviour from + * \c mbedtls_ssl_get_bytes_avail in that it considers + * any kind of unprocessed data, not only unread + * application data. If \c mbedtls_ssl_get_bytes + * returns a non-zero value, this function will + * also signal pending data, but the converse does + * not hold. For example, in DTLS there might be + * further records waiting to be processed from + * the current underlying transport's datagram. + * + * \note If this function returns 1 (data pending), this + * does not imply that a subsequent call to + * \c mbedtls_ssl_read will provide any data; + * e.g., the unprocessed data might turn out + * to be an alert or a handshake message. + * + * \note This function is useful in the following situation: + * If the SSL/TLS module successfully returns from an + * operation - e.g. a handshake or an application record + * read - and you're awaiting incoming data next, you + * must not immediately idle on the underlying transport + * to have data ready, but you need to check the value + * of this function first. The reason is that the desired + * data might already be read but not yet processed. + * If, in contrast, a previous call to the SSL/TLS module + * returned MBEDTLS_ERR_SSL_WANT_READ, it is not necessary + * to call this function, as the latter error code entails + * that all internal data has been processed. + * + */ +int mbedtls_ssl_check_pending( const mbedtls_ssl_context *ssl ); + +/** + * \brief Return the number of application data bytes + * remaining to be read from the current record. + * + * \param ssl SSL context + * + * \return How many bytes are available in the application + * data record read buffer. + * + * \note When working over a datagram transport, this is + * useful to detect the current datagram's boundary + * in case \c mbedtls_ssl_read has written the maximal + * amount of data fitting into the input buffer. + * */ size_t mbedtls_ssl_get_bytes_avail( const mbedtls_ssl_context *ssl ); @@ -2383,7 +2746,6 @@ const mbedtls_x509_crt *mbedtls_ssl_get_peer_cert( const mbedtls_ssl_context *ss * \brief Save session in order to resume it later (client-side only) * Session data is copied to presented session structure. * - * \warning Currently, peer certificate is lost in the operation. * * \param ssl SSL context * \param session session context @@ -2391,7 +2753,18 @@ const mbedtls_x509_crt *mbedtls_ssl_get_peer_cert( const mbedtls_ssl_context *ss * \return 0 if successful, * MBEDTLS_ERR_SSL_ALLOC_FAILED if memory allocation failed, * MBEDTLS_ERR_SSL_BAD_INPUT_DATA if used server-side or - * arguments are otherwise invalid + * arguments are otherwise invalid. + * + * \note Only the server certificate is copied, and not the full chain, + * so you should not attempt to validate the certificate again + * by calling \c mbedtls_x509_crt_verify() on it. + * Instead, you should use the results from the verification + * in the original handshake by calling \c mbedtls_ssl_get_verify_result() + * after loading the session again into a new SSL context + * using \c mbedtls_ssl_set_session(). + * + * \note Once the session object is not needed anymore, you should + * free it by calling \c mbedtls_ssl_session_free(). * * \sa mbedtls_ssl_set_session() */ @@ -2408,11 +2781,25 @@ int mbedtls_ssl_get_session( const mbedtls_ssl_context *ssl, mbedtls_ssl_session * MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED (see below), or * a specific SSL error code. * + * If this function returns MBEDTLS_ERR_SSL_WANT_READ, the + * handshake is unfinished and no further data is available + * from the underlying transport. In this case, you must call + * the function again at some later stage. + * + * \note Remarks regarding event-driven DTLS: + * If the function returns MBEDTLS_ERR_SSL_WANT_READ, no datagram + * from the underlying transport layer is currently being processed, + * and it is safe to idle until the timer or the underlying transport + * signal a new event. This is not true for a successful handshake, + * in which case the datagram of the underlying transport that is + * currently being processed might or might not contain further + * DTLS records. + * * \note If this function returns something other than 0 or - * MBEDTLS_ERR_SSL_WANT_READ/WRITE, then the ssl context - * becomes unusable, and you should either free it or call - * \c mbedtls_ssl_session_reset() on it before re-using it for - * a new connection; the current connection must be closed. + * MBEDTLS_ERR_SSL_WANT_READ/WRITE, you must stop using + * the SSL context for reading or writing, and either free it or + * call \c mbedtls_ssl_session_reset() on it before re-using it + * for a new connection; the current connection must be closed. * * \note If DTLS is in use, then you may choose to handle * MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED specially for logging @@ -2429,10 +2816,10 @@ int mbedtls_ssl_handshake( mbedtls_ssl_context *ssl ); * call this function if state is MBEDTLS_SSL_HANDSHAKE_OVER. * * \note If this function returns something other than 0 or - * MBEDTLS_ERR_SSL_WANT_READ/WRITE, then the ssl context - * becomes unusable, and you should either free it or call - * \c mbedtls_ssl_session_reset() on it before re-using it for - * a new connection; the current connection must be closed. + * MBEDTLS_ERR_SSL_WANT_READ/WRITE, you must stop using + * the SSL context for reading or writing, and either free it or + * call \c mbedtls_ssl_session_reset() on it before re-using it + * for a new connection; the current connection must be closed. * * \param ssl SSL context * @@ -2456,10 +2843,10 @@ int mbedtls_ssl_handshake_step( mbedtls_ssl_context *ssl ); * value. * * \note If this function returns something other than 0 or - * MBEDTLS_ERR_SSL_WANT_READ/WRITE, then the ssl context - * becomes unusable, and you should either free it or call - * \c mbedtls_ssl_session_reset() on it before re-using it for - * a new connection; the current connection must be closed. + * MBEDTLS_ERR_SSL_WANT_READ/WRITE, you must stop using + * the SSL context for reading or writing, and either free it or + * call \c mbedtls_ssl_session_reset() on it before re-using it + * for a new connection; the current connection must be closed. */ int mbedtls_ssl_renegotiate( mbedtls_ssl_context *ssl ); #endif /* MBEDTLS_SSL_RENEGOTIATION */ @@ -2471,20 +2858,20 @@ int mbedtls_ssl_renegotiate( mbedtls_ssl_context *ssl ); * \param buf buffer that will hold the data * \param len maximum number of bytes to read * - * \return the number of bytes read, or - * 0 for EOF, or - * MBEDTLS_ERR_SSL_WANT_READ or MBEDTLS_ERR_SSL_WANT_WRITE, or - * MBEDTLS_ERR_SSL_CLIENT_RECONNECT (see below), or - * another negative error code. + * \return One of the following: + * - 0 if the read end of the underlying transport was closed, + * - the (positive) number of bytes read, or + * - a negative error code on failure. * - * \note If this function returns something other than a positive - * value or MBEDTLS_ERR_SSL_WANT_READ/WRITE or - * MBEDTLS_ERR_SSL_CLIENT_RECONNECT, then the ssl context - * becomes unusable, and you should either free it or call - * \c mbedtls_ssl_session_reset() on it before re-using it for - * a new connection; the current connection must be closed. + * If MBEDTLS_ERR_SSL_WANT_READ is returned, no application data + * is available from the underlying transport. In this case, + * the function needs to be called again at some later stage. * - * \note When this function return MBEDTLS_ERR_SSL_CLIENT_RECONNECT + * If MBEDTLS_ERR_SSL_WANT_WRITE is returned, a write is pending + * but the underlying transport isn't available for writing. In this + * case, the function needs to be called again at some later stage. + * + * When this function return MBEDTLS_ERR_SSL_CLIENT_RECONNECT * (which can only happen server-side), it means that a client * is initiating a new connection using the same source port. * You can either treat that as a connection close and wait @@ -2497,6 +2884,28 @@ int mbedtls_ssl_renegotiate( mbedtls_ssl_context *ssl ); * again. WARNING: not validating the identity of the client * again, or not transmitting the new identity to the * application layer, would allow authentication bypass! + * + * \note If this function returns something other than a positive value + * or MBEDTLS_ERR_SSL_WANT_READ/WRITE or MBEDTLS_ERR_SSL_CLIENT_RECONNECT, + * you must stop using the SSL context for reading or writing, + * and either free it or call \c mbedtls_ssl_session_reset() on it + * before re-using it for a new connection; the current connection + * must be closed. + * + * \note Remarks regarding event-driven DTLS: + * - If the function returns MBEDTLS_ERR_SSL_WANT_READ, no datagram + * from the underlying transport layer is currently being processed, + * and it is safe to idle until the timer or the underlying transport + * signal a new event. + * - This function may return MBEDTLS_ERR_SSL_WANT_READ even if data was + * initially available on the underlying transport, as this data may have + * been only e.g. duplicated messages or a renegotiation request. + * Therefore, you must be prepared to receive MBEDTLS_ERR_SSL_WANT_READ even + * when reacting to an incoming-data event from the underlying transport. + * - On success, the datagram of the underlying transport that is currently + * being processed may contain further DTLS records. You should call + * \c mbedtls_ssl_check_pending to check for remaining records. + * */ int mbedtls_ssl_read( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len ); @@ -2517,15 +2926,19 @@ int mbedtls_ssl_read( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len ) * or MBEDTLS_ERR_SSL_WANT_WRITE or MBEDTLS_ERR_SSL_WANT_READ, * or another negative error code. * - * \note If this function returns something other than a positive - * value or MBEDTLS_ERR_SSL_WANT_READ/WRITE, the ssl context - * becomes unusable, and you should either free it or call - * \c mbedtls_ssl_session_reset() on it before re-using it for - * a new connection; the current connection must be closed. + * \note If this function returns something other than 0, a positive + * value or MBEDTLS_ERR_SSL_WANT_READ/WRITE, you must stop + * using the SSL context for reading or writing, and either + * free it or call \c mbedtls_ssl_session_reset() on it before + * re-using it for a new connection; the current connection + * must be closed. * * \note When this function returns MBEDTLS_ERR_SSL_WANT_WRITE/READ, * it must be called later with the *same* arguments, - * until it returns a positive value. + * until it returns a value greater that or equal to 0. When + * the function returns MBEDTLS_ERR_SSL_WANT_WRITE there may be + * some partial data in the output buffer, however this is not + * yet sent. * * \note If the requested length is greater than the maximum * fragment length (either the built-in limit or the one set @@ -2534,6 +2947,9 @@ int mbedtls_ssl_read( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len ) * - with DTLS, MBEDTLS_ERR_SSL_BAD_INPUT_DATA is returned. * \c mbedtls_ssl_get_max_frag_len() may be used to query the * active maximum fragment length. + * + * \note Attempting to write 0 bytes will result in an empty TLS + * application record being sent. */ int mbedtls_ssl_write( mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len ); @@ -2548,10 +2964,10 @@ int mbedtls_ssl_write( mbedtls_ssl_context *ssl, const unsigned char *buf, size_ * \return 0 if successful, or a specific SSL error code. * * \note If this function returns something other than 0 or - * MBEDTLS_ERR_SSL_WANT_READ/WRITE, then the ssl context - * becomes unusable, and you should either free it or call - * \c mbedtls_ssl_session_reset() on it before re-using it for - * a new connection; the current connection must be closed. + * MBEDTLS_ERR_SSL_WANT_READ/WRITE, you must stop using + * the SSL context for reading or writing, and either free it or + * call \c mbedtls_ssl_session_reset() on it before re-using it + * for a new connection; the current connection must be closed. */ int mbedtls_ssl_send_alert_message( mbedtls_ssl_context *ssl, unsigned char level, @@ -2564,10 +2980,10 @@ int mbedtls_ssl_send_alert_message( mbedtls_ssl_context *ssl, * \return 0 if successful, or a specific SSL error code. * * \note If this function returns something other than 0 or - * MBEDTLS_ERR_SSL_WANT_READ/WRITE, then the ssl context - * becomes unusable, and you should either free it or call - * \c mbedtls_ssl_session_reset() on it before re-using it for - * a new connection; the current connection must be closed. + * MBEDTLS_ERR_SSL_WANT_READ/WRITE, you must stop using + * the SSL context for reading or writing, and either free it or + * call \c mbedtls_ssl_session_reset() on it before re-using it + * for a new connection; the current connection must be closed. */ int mbedtls_ssl_close_notify( mbedtls_ssl_context *ssl ); @@ -2626,6 +3042,9 @@ void mbedtls_ssl_session_init( mbedtls_ssl_session *session ); * \brief Free referenced items in an SSL session including the * peer certificate and clear memory * + * \note A session object can be freed even if the SSL context + * that was used to retrieve the session is still in use. + * * \param session SSL session */ void mbedtls_ssl_session_free( mbedtls_ssl_session *session ); diff --git a/thirdparty/mbedtls/include/mbedtls/ssl_ciphersuites.h b/thirdparty/mbedtls/include/mbedtls/ssl_ciphersuites.h index 545468a510..cda8b4835b 100644 --- a/thirdparty/mbedtls/include/mbedtls/ssl_ciphersuites.h +++ b/thirdparty/mbedtls/include/mbedtls/ssl_ciphersuites.h @@ -169,6 +169,45 @@ extern "C" { #define MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA256 0xC03A /**< Weak! No SSL3! */ #define MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA384 0xC03B /**< Weak! No SSL3! */ +#define MBEDTLS_TLS_RSA_WITH_ARIA_128_CBC_SHA256 0xC03C /**< TLS 1.2 */ +#define MBEDTLS_TLS_RSA_WITH_ARIA_256_CBC_SHA384 0xC03D /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256 0xC044 /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384 0xC045 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256 0xC048 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384 0xC049 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_128_CBC_SHA256 0xC04A /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_256_CBC_SHA384 0xC04B /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256 0xC04C /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384 0xC04D /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_128_CBC_SHA256 0xC04E /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_256_CBC_SHA384 0xC04F /**< TLS 1.2 */ +#define MBEDTLS_TLS_RSA_WITH_ARIA_128_GCM_SHA256 0xC050 /**< TLS 1.2 */ +#define MBEDTLS_TLS_RSA_WITH_ARIA_256_GCM_SHA384 0xC051 /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256 0xC052 /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384 0xC053 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256 0xC05C /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384 0xC05D /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256 0xC05E /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384 0xC05F /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256 0xC060 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384 0xC061 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_128_GCM_SHA256 0xC062 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_256_GCM_SHA384 0xC063 /**< TLS 1.2 */ +#define MBEDTLS_TLS_PSK_WITH_ARIA_128_CBC_SHA256 0xC064 /**< TLS 1.2 */ +#define MBEDTLS_TLS_PSK_WITH_ARIA_256_CBC_SHA384 0xC065 /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_PSK_WITH_ARIA_128_CBC_SHA256 0xC066 /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_PSK_WITH_ARIA_256_CBC_SHA384 0xC067 /**< TLS 1.2 */ +#define MBEDTLS_TLS_RSA_PSK_WITH_ARIA_128_CBC_SHA256 0xC068 /**< TLS 1.2 */ +#define MBEDTLS_TLS_RSA_PSK_WITH_ARIA_256_CBC_SHA384 0xC069 /**< TLS 1.2 */ +#define MBEDTLS_TLS_PSK_WITH_ARIA_128_GCM_SHA256 0xC06A /**< TLS 1.2 */ +#define MBEDTLS_TLS_PSK_WITH_ARIA_256_GCM_SHA384 0xC06B /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_PSK_WITH_ARIA_128_GCM_SHA256 0xC06C /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_PSK_WITH_ARIA_256_GCM_SHA384 0xC06D /**< TLS 1.2 */ +#define MBEDTLS_TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256 0xC06E /**< TLS 1.2 */ +#define MBEDTLS_TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384 0xC06F /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_PSK_WITH_ARIA_128_CBC_SHA256 0xC070 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384 0xC071 /**< TLS 1.2 */ + #define MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 0xC072 /**< Not in SSL3! */ #define MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 0xC073 /**< Not in SSL3! */ #define MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 0xC074 /**< Not in SSL3! */ @@ -232,6 +271,15 @@ extern "C" { #define MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8 0xC0FF /**< experimental */ +/* RFC 7905 */ +#define MBEDTLS_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 0xCCA8 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 0xCCA9 /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 0xCCAA /**< TLS 1.2 */ +#define MBEDTLS_TLS_PSK_WITH_CHACHA20_POLY1305_SHA256 0xCCAB /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256 0xCCAC /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256 0xCCAD /**< TLS 1.2 */ +#define MBEDTLS_TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256 0xCCAE /**< TLS 1.2 */ + /* Reminder: update mbedtls_ssl_premaster_secret when adding a new key exchange. * Reminder: update MBEDTLS_KEY_EXCHANGE__xxx below */ @@ -267,7 +315,7 @@ typedef enum { defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) #define MBEDTLS_KEY_EXCHANGE__CERT_REQ_ALLOWED__ENABLED #endif diff --git a/thirdparty/mbedtls/include/mbedtls/ssl_internal.h b/thirdparty/mbedtls/include/mbedtls/ssl_internal.h index 60b431a0f4..d214703d77 100644 --- a/thirdparty/mbedtls/include/mbedtls/ssl_internal.h +++ b/thirdparty/mbedtls/include/mbedtls/ssl_internal.h @@ -143,32 +143,73 @@ #define MBEDTLS_SSL_PADDING_ADD 0 #endif -#define MBEDTLS_SSL_PAYLOAD_LEN ( MBEDTLS_SSL_MAX_CONTENT_LEN \ - + MBEDTLS_SSL_COMPRESSION_ADD \ - + MBEDTLS_MAX_IV_LENGTH \ - + MBEDTLS_SSL_MAC_ADD \ - + MBEDTLS_SSL_PADDING_ADD \ - ) +#define MBEDTLS_SSL_PAYLOAD_OVERHEAD ( MBEDTLS_SSL_COMPRESSION_ADD + \ + MBEDTLS_MAX_IV_LENGTH + \ + MBEDTLS_SSL_MAC_ADD + \ + MBEDTLS_SSL_PADDING_ADD \ + ) + +#define MBEDTLS_SSL_IN_PAYLOAD_LEN ( MBEDTLS_SSL_PAYLOAD_OVERHEAD + \ + ( MBEDTLS_SSL_IN_CONTENT_LEN ) ) + +#define MBEDTLS_SSL_OUT_PAYLOAD_LEN ( MBEDTLS_SSL_PAYLOAD_OVERHEAD + \ + ( MBEDTLS_SSL_OUT_CONTENT_LEN ) ) + +/* Maximum length we can advertise as our max content length for + RFC 6066 max_fragment_length extension negotiation purposes + (the lesser of both sizes, if they are unequal.) + */ +#define MBEDTLS_TLS_EXT_ADV_CONTENT_LEN ( \ + (MBEDTLS_SSL_IN_CONTENT_LEN > MBEDTLS_SSL_OUT_CONTENT_LEN) \ + ? ( MBEDTLS_SSL_OUT_CONTENT_LEN ) \ + : ( MBEDTLS_SSL_IN_CONTENT_LEN ) \ + ) /* * Check that we obey the standard's message size bounds */ #if MBEDTLS_SSL_MAX_CONTENT_LEN > 16384 -#error Bad configuration - record content too large. +#error "Bad configuration - record content too large." +#endif + +#if MBEDTLS_SSL_IN_CONTENT_LEN > MBEDTLS_SSL_MAX_CONTENT_LEN +#error "Bad configuration - incoming record content should not be larger than MBEDTLS_SSL_MAX_CONTENT_LEN." +#endif + +#if MBEDTLS_SSL_OUT_CONTENT_LEN > MBEDTLS_SSL_MAX_CONTENT_LEN +#error "Bad configuration - outgoing record content should not be larger than MBEDTLS_SSL_MAX_CONTENT_LEN." +#endif + +#if MBEDTLS_SSL_IN_PAYLOAD_LEN > MBEDTLS_SSL_MAX_CONTENT_LEN + 2048 +#error "Bad configuration - incoming protected record payload too large." #endif -#if MBEDTLS_SSL_PAYLOAD_LEN > 16384 + 2048 -#error Bad configuration - protected record payload too large. +#if MBEDTLS_SSL_OUT_PAYLOAD_LEN > MBEDTLS_SSL_MAX_CONTENT_LEN + 2048 +#error "Bad configuration - outgoing protected record payload too large." #endif +/* Calculate buffer sizes */ + /* Note: Even though the TLS record header is only 5 bytes long, we're internally using 8 bytes to store the implicit sequence number. */ #define MBEDTLS_SSL_HEADER_LEN 13 -#define MBEDTLS_SSL_BUFFER_LEN \ - ( ( MBEDTLS_SSL_HEADER_LEN ) + ( MBEDTLS_SSL_PAYLOAD_LEN ) ) +#define MBEDTLS_SSL_IN_BUFFER_LEN \ + ( ( MBEDTLS_SSL_HEADER_LEN ) + ( MBEDTLS_SSL_IN_PAYLOAD_LEN ) ) + +#define MBEDTLS_SSL_OUT_BUFFER_LEN \ + ( ( MBEDTLS_SSL_HEADER_LEN ) + ( MBEDTLS_SSL_OUT_PAYLOAD_LEN ) ) + +#ifdef MBEDTLS_ZLIB_SUPPORT +/* Compression buffer holds both IN and OUT buffers, so should be size of the larger */ +#define MBEDTLS_SSL_COMPRESS_BUFFER_LEN ( \ + ( MBEDTLS_SSL_IN_BUFFER_LEN > MBEDTLS_SSL_OUT_BUFFER_LEN ) \ + ? MBEDTLS_SSL_IN_BUFFER_LEN \ + : MBEDTLS_SSL_OUT_BUFFER_LEN \ + ) +#endif /* * TLS extension flags (for extensions with outgoing ServerHello content @@ -243,6 +284,7 @@ struct mbedtls_ssl_handshake_params mbedtls_x509_crl *sni_ca_crl; /*!< trusted CAs CRLs from SNI */ #endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ #endif /* MBEDTLS_X509_CRT_PARSE_C */ + #if defined(MBEDTLS_SSL_PROTO_DTLS) unsigned int out_msg_seq; /*!< Outgoing handshake sequence number */ unsigned int in_msg_seq; /*!< Incoming handshake sequence number */ @@ -307,6 +349,19 @@ struct mbedtls_ssl_handshake_params #if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) int extended_ms; /*!< use Extended Master Secret? */ #endif + +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) + unsigned int async_in_progress : 1; /*!< an asynchronous operation is in progress */ +#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ + +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) + /** Asynchronous operation context. This field is meant for use by the + * asynchronous operation callbacks (mbedtls_ssl_config::f_async_sign_start, + * mbedtls_ssl_config::f_async_decrypt_start, + * mbedtls_ssl_config::f_async_resume, mbedtls_ssl_config::f_async_cancel). + * The library does not use it internally. */ + void *user_async_ctx; +#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ }; /* @@ -410,9 +465,9 @@ void mbedtls_ssl_transform_free( mbedtls_ssl_transform *transform ); * \brief Free referenced items in an SSL handshake context and clear * memory * - * \param handshake SSL handshake context + * \param ssl SSL context */ -void mbedtls_ssl_handshake_free( mbedtls_ssl_handshake_params *handshake ); +void mbedtls_ssl_handshake_free( mbedtls_ssl_context *ssl ); int mbedtls_ssl_handshake_client_step( mbedtls_ssl_context *ssl ); int mbedtls_ssl_handshake_server_step( mbedtls_ssl_context *ssl ); @@ -630,7 +685,13 @@ static inline int mbedtls_ssl_safer_memcmp( const void *a, const void *b, size_t volatile unsigned char diff = 0; for( i = 0; i < n; i++ ) - diff |= A[i] ^ B[i]; + { + /* Read volatile data in order before computing diff. + * This avoids IAR compiler warning: + * 'the order of volatile accesses is undefined ..' */ + unsigned char x = A[i], y = B[i]; + diff |= x ^ y; + } return( diff ); } @@ -646,9 +707,9 @@ int mbedtls_ssl_get_key_exchange_md_ssl_tls( mbedtls_ssl_context *ssl, #if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ defined(MBEDTLS_SSL_PROTO_TLS1_2) int mbedtls_ssl_get_key_exchange_md_tls1_2( mbedtls_ssl_context *ssl, - unsigned char *output, - unsigned char *data, size_t data_len, - mbedtls_md_type_t md_alg ); + unsigned char *hash, size_t *hashlen, + unsigned char *data, size_t data_len, + mbedtls_md_type_t md_alg ); #endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 || \ MBEDTLS_SSL_PROTO_TLS1_2 */ diff --git a/thirdparty/mbedtls/include/mbedtls/threading.h b/thirdparty/mbedtls/include/mbedtls/threading.h index 58e6db2f3a..c25daa5cdf 100644 --- a/thirdparty/mbedtls/include/mbedtls/threading.h +++ b/thirdparty/mbedtls/include/mbedtls/threading.h @@ -96,8 +96,9 @@ extern int (*mbedtls_mutex_unlock)( mbedtls_threading_mutex_t *mutex ); /* * Global mutexes */ +#if defined(MBEDTLS_FS_IO) extern mbedtls_threading_mutex_t mbedtls_threading_readdir_mutex; -extern mbedtls_threading_mutex_t mbedtls_threading_gmtime_mutex; +#endif #endif /* MBEDTLS_THREADING_C */ #ifdef __cplusplus diff --git a/thirdparty/mbedtls/include/mbedtls/timing.h b/thirdparty/mbedtls/include/mbedtls/timing.h index 2c497bf4eb..bbcb90688a 100644 --- a/thirdparty/mbedtls/include/mbedtls/timing.h +++ b/thirdparty/mbedtls/include/mbedtls/timing.h @@ -30,16 +30,16 @@ #include MBEDTLS_CONFIG_FILE #endif -#if !defined(MBEDTLS_TIMING_ALT) -// Regular implementation -// - #include <stdint.h> #ifdef __cplusplus extern "C" { #endif +#if !defined(MBEDTLS_TIMING_ALT) +// Regular implementation +// + /** * \brief timer structure */ @@ -58,6 +58,10 @@ typedef struct uint32_t fin_ms; } mbedtls_timing_delay_context; +#else /* MBEDTLS_TIMING_ALT */ +#include "timing_alt.h" +#endif /* MBEDTLS_TIMING_ALT */ + extern volatile int mbedtls_timing_alarmed; /** @@ -133,18 +137,6 @@ void mbedtls_timing_set_delay( void *data, uint32_t int_ms, uint32_t fin_ms ); */ int mbedtls_timing_get_delay( void *data ); -#ifdef __cplusplus -} -#endif - -#else /* MBEDTLS_TIMING_ALT */ -#include "timing_alt.h" -#endif /* MBEDTLS_TIMING_ALT */ - -#ifdef __cplusplus -extern "C" { -#endif - #if defined(MBEDTLS_SELF_TEST) /** * \brief Checkup routine diff --git a/thirdparty/mbedtls/include/mbedtls/version.h b/thirdparty/mbedtls/include/mbedtls/version.h index c3ee649f5c..eaf25d908c 100644 --- a/thirdparty/mbedtls/include/mbedtls/version.h +++ b/thirdparty/mbedtls/include/mbedtls/version.h @@ -39,7 +39,7 @@ * Major, Minor, Patchlevel */ #define MBEDTLS_VERSION_MAJOR 2 -#define MBEDTLS_VERSION_MINOR 8 +#define MBEDTLS_VERSION_MINOR 12 #define MBEDTLS_VERSION_PATCH 0 /** @@ -47,9 +47,9 @@ * MMNNPP00 * Major version | Minor version | Patch version */ -#define MBEDTLS_VERSION_NUMBER 0x02080000 -#define MBEDTLS_VERSION_STRING "2.8.0" -#define MBEDTLS_VERSION_STRING_FULL "mbed TLS 2.8.0" +#define MBEDTLS_VERSION_NUMBER 0x020C0000 +#define MBEDTLS_VERSION_STRING "2.12.0" +#define MBEDTLS_VERSION_STRING_FULL "mbed TLS 2.12.0" #if defined(MBEDTLS_VERSION_C) diff --git a/thirdparty/mbedtls/include/mbedtls/x509_crt.h b/thirdparty/mbedtls/include/mbedtls/x509_crt.h index 2dbb7ec964..ac23cffe84 100644 --- a/thirdparty/mbedtls/include/mbedtls/x509_crt.h +++ b/thirdparty/mbedtls/include/mbedtls/x509_crt.h @@ -287,8 +287,15 @@ int mbedtls_x509_crt_verify_info( char *buf, size_t size, const char *prefix, * used to sign the certificate, CRL verification is skipped * silently, that is *without* setting any flag. * + * \note The \c trust_ca list can contain two types of certificates: + * (1) those of trusted root CAs, so that certificates + * chaining up to those CAs will be trusted, and (2) + * self-signed end-entity certificates to be trusted (for + * specific peers you know) - in that case, the self-signed + * certificate doesn't need to have the CA bit set. + * * \param crt a certificate (chain) to be verified - * \param trust_ca the list of trusted CAs + * \param trust_ca the list of trusted CAs (see note above) * \param ca_crl the list of CRLs for trusted CAs (see note above) * \param cn expected Common Name (can be set to * NULL if the CN must not be verified) diff --git a/thirdparty/mbedtls/include/mbedtls/xtea.h b/thirdparty/mbedtls/include/mbedtls/xtea.h index 34ccee3c22..8df708a3a5 100644 --- a/thirdparty/mbedtls/include/mbedtls/xtea.h +++ b/thirdparty/mbedtls/include/mbedtls/xtea.h @@ -39,14 +39,14 @@ #define MBEDTLS_ERR_XTEA_INVALID_INPUT_LENGTH -0x0028 /**< The data input has an invalid length. */ #define MBEDTLS_ERR_XTEA_HW_ACCEL_FAILED -0x0029 /**< XTEA hardware accelerator failed. */ -#if !defined(MBEDTLS_XTEA_ALT) -// Regular implementation -// - #ifdef __cplusplus extern "C" { #endif +#if !defined(MBEDTLS_XTEA_ALT) +// Regular implementation +// + /** * \brief XTEA context structure */ @@ -56,6 +56,10 @@ typedef struct } mbedtls_xtea_context; +#else /* MBEDTLS_XTEA_ALT */ +#include "xtea_alt.h" +#endif /* MBEDTLS_XTEA_ALT */ + /** * \brief Initialize XTEA context * @@ -115,18 +119,6 @@ int mbedtls_xtea_crypt_cbc( mbedtls_xtea_context *ctx, unsigned char *output); #endif /* MBEDTLS_CIPHER_MODE_CBC */ -#ifdef __cplusplus -} -#endif - -#else /* MBEDTLS_XTEA_ALT */ -#include "xtea_alt.h" -#endif /* MBEDTLS_XTEA_ALT */ - -#ifdef __cplusplus -extern "C" { -#endif - /** * \brief Checkup routine * diff --git a/thirdparty/mbedtls/library/aes.c b/thirdparty/mbedtls/library/aes.c index 3d2eac82dd..5c939bba47 100644 --- a/thirdparty/mbedtls/library/aes.c +++ b/thirdparty/mbedtls/library/aes.c @@ -36,6 +36,7 @@ #include <string.h> #include "mbedtls/aes.h" +#include "mbedtls/platform_util.h" #if defined(MBEDTLS_PADLOCK_C) #include "mbedtls/padlock.h" #endif @@ -54,11 +55,6 @@ #if !defined(MBEDTLS_AES_ALT) -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize( void *v, size_t n ) { - volatile unsigned char *p = (unsigned char*)v; while( n-- ) *p++ = 0; -} - /* * 32-bit integer manipulation macros (little endian) */ @@ -201,6 +197,8 @@ static const unsigned char FSb[256] = static const uint32_t FT0[256] = { FT }; #undef V +#if !defined(MBEDTLS_AES_FEWER_TABLES) + #define V(a,b,c,d) 0x##b##c##d##a static const uint32_t FT1[256] = { FT }; #undef V @@ -213,6 +211,8 @@ static const uint32_t FT2[256] = { FT }; static const uint32_t FT3[256] = { FT }; #undef V +#endif /* !MBEDTLS_AES_FEWER_TABLES */ + #undef FT /* @@ -328,6 +328,8 @@ static const unsigned char RSb[256] = static const uint32_t RT0[256] = { RT }; #undef V +#if !defined(MBEDTLS_AES_FEWER_TABLES) + #define V(a,b,c,d) 0x##b##c##d##a static const uint32_t RT1[256] = { RT }; #undef V @@ -340,6 +342,8 @@ static const uint32_t RT2[256] = { RT }; static const uint32_t RT3[256] = { RT }; #undef V +#endif /* !MBEDTLS_AES_FEWER_TABLES */ + #undef RT /* @@ -359,18 +363,22 @@ static const uint32_t RCON[10] = */ static unsigned char FSb[256]; static uint32_t FT0[256]; +#if !defined(MBEDTLS_AES_FEWER_TABLES) static uint32_t FT1[256]; static uint32_t FT2[256]; static uint32_t FT3[256]; +#endif /* !MBEDTLS_AES_FEWER_TABLES */ /* * Reverse S-box & tables */ static unsigned char RSb[256]; static uint32_t RT0[256]; +#if !defined(MBEDTLS_AES_FEWER_TABLES) static uint32_t RT1[256]; static uint32_t RT2[256]; static uint32_t RT3[256]; +#endif /* !MBEDTLS_AES_FEWER_TABLES */ /* * Round constants @@ -445,9 +453,11 @@ static void aes_gen_tables( void ) ( (uint32_t) x << 16 ) ^ ( (uint32_t) z << 24 ); +#if !defined(MBEDTLS_AES_FEWER_TABLES) FT1[i] = ROTL8( FT0[i] ); FT2[i] = ROTL8( FT1[i] ); FT3[i] = ROTL8( FT2[i] ); +#endif /* !MBEDTLS_AES_FEWER_TABLES */ x = RSb[i]; @@ -456,14 +466,48 @@ static void aes_gen_tables( void ) ( (uint32_t) MUL( 0x0D, x ) << 16 ) ^ ( (uint32_t) MUL( 0x0B, x ) << 24 ); +#if !defined(MBEDTLS_AES_FEWER_TABLES) RT1[i] = ROTL8( RT0[i] ); RT2[i] = ROTL8( RT1[i] ); RT3[i] = ROTL8( RT2[i] ); +#endif /* !MBEDTLS_AES_FEWER_TABLES */ } } +#undef ROTL8 + #endif /* MBEDTLS_AES_ROM_TABLES */ +#if defined(MBEDTLS_AES_FEWER_TABLES) + +#define ROTL8(x) ( (uint32_t)( ( x ) << 8 ) + (uint32_t)( ( x ) >> 24 ) ) +#define ROTL16(x) ( (uint32_t)( ( x ) << 16 ) + (uint32_t)( ( x ) >> 16 ) ) +#define ROTL24(x) ( (uint32_t)( ( x ) << 24 ) + (uint32_t)( ( x ) >> 8 ) ) + +#define AES_RT0(idx) RT0[idx] +#define AES_RT1(idx) ROTL8( RT0[idx] ) +#define AES_RT2(idx) ROTL16( RT0[idx] ) +#define AES_RT3(idx) ROTL24( RT0[idx] ) + +#define AES_FT0(idx) FT0[idx] +#define AES_FT1(idx) ROTL8( FT0[idx] ) +#define AES_FT2(idx) ROTL16( FT0[idx] ) +#define AES_FT3(idx) ROTL24( FT0[idx] ) + +#else /* MBEDTLS_AES_FEWER_TABLES */ + +#define AES_RT0(idx) RT0[idx] +#define AES_RT1(idx) RT1[idx] +#define AES_RT2(idx) RT2[idx] +#define AES_RT3(idx) RT3[idx] + +#define AES_FT0(idx) FT0[idx] +#define AES_FT1(idx) FT1[idx] +#define AES_FT2(idx) FT2[idx] +#define AES_FT3(idx) FT3[idx] + +#endif /* MBEDTLS_AES_FEWER_TABLES */ + void mbedtls_aes_init( mbedtls_aes_context *ctx ) { memset( ctx, 0, sizeof( mbedtls_aes_context ) ); @@ -474,9 +518,23 @@ void mbedtls_aes_free( mbedtls_aes_context *ctx ) if( ctx == NULL ) return; - mbedtls_zeroize( ctx, sizeof( mbedtls_aes_context ) ); + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_aes_context ) ); } +#if defined(MBEDTLS_CIPHER_MODE_XTS) +void mbedtls_aes_xts_init( mbedtls_aes_xts_context *ctx ) +{ + mbedtls_aes_init( &ctx->crypt ); + mbedtls_aes_init( &ctx->tweak ); +} + +void mbedtls_aes_xts_free( mbedtls_aes_xts_context *ctx ) +{ + mbedtls_aes_free( &ctx->crypt ); + mbedtls_aes_free( &ctx->tweak ); +} +#endif /* MBEDTLS_CIPHER_MODE_XTS */ + /* * AES key schedule (encryption) */ @@ -641,10 +699,10 @@ int mbedtls_aes_setkey_dec( mbedtls_aes_context *ctx, const unsigned char *key, { for( j = 0; j < 4; j++, SK++ ) { - *RK++ = RT0[ FSb[ ( *SK ) & 0xFF ] ] ^ - RT1[ FSb[ ( *SK >> 8 ) & 0xFF ] ] ^ - RT2[ FSb[ ( *SK >> 16 ) & 0xFF ] ] ^ - RT3[ FSb[ ( *SK >> 24 ) & 0xFF ] ]; + *RK++ = AES_RT0( FSb[ ( *SK ) & 0xFF ] ) ^ + AES_RT1( FSb[ ( *SK >> 8 ) & 0xFF ] ) ^ + AES_RT2( FSb[ ( *SK >> 16 ) & 0xFF ] ) ^ + AES_RT3( FSb[ ( *SK >> 24 ) & 0xFF ] ); } } @@ -658,52 +716,124 @@ exit: return( ret ); } + +#if defined(MBEDTLS_CIPHER_MODE_XTS) +static int mbedtls_aes_xts_decode_keys( const unsigned char *key, + unsigned int keybits, + const unsigned char **key1, + unsigned int *key1bits, + const unsigned char **key2, + unsigned int *key2bits ) +{ + const unsigned int half_keybits = keybits / 2; + const unsigned int half_keybytes = half_keybits / 8; + + switch( keybits ) + { + case 256: break; + case 512: break; + default : return( MBEDTLS_ERR_AES_INVALID_KEY_LENGTH ); + } + + *key1bits = half_keybits; + *key2bits = half_keybits; + *key1 = &key[0]; + *key2 = &key[half_keybytes]; + + return 0; +} + +int mbedtls_aes_xts_setkey_enc( mbedtls_aes_xts_context *ctx, + const unsigned char *key, + unsigned int keybits) +{ + int ret; + const unsigned char *key1, *key2; + unsigned int key1bits, key2bits; + + ret = mbedtls_aes_xts_decode_keys( key, keybits, &key1, &key1bits, + &key2, &key2bits ); + if( ret != 0 ) + return( ret ); + + /* Set the tweak key. Always set tweak key for the encryption mode. */ + ret = mbedtls_aes_setkey_enc( &ctx->tweak, key2, key2bits ); + if( ret != 0 ) + return( ret ); + + /* Set crypt key for encryption. */ + return mbedtls_aes_setkey_enc( &ctx->crypt, key1, key1bits ); +} + +int mbedtls_aes_xts_setkey_dec( mbedtls_aes_xts_context *ctx, + const unsigned char *key, + unsigned int keybits) +{ + int ret; + const unsigned char *key1, *key2; + unsigned int key1bits, key2bits; + + ret = mbedtls_aes_xts_decode_keys( key, keybits, &key1, &key1bits, + &key2, &key2bits ); + if( ret != 0 ) + return( ret ); + + /* Set the tweak key. Always set tweak key for encryption. */ + ret = mbedtls_aes_setkey_enc( &ctx->tweak, key2, key2bits ); + if( ret != 0 ) + return( ret ); + + /* Set crypt key for decryption. */ + return mbedtls_aes_setkey_dec( &ctx->crypt, key1, key1bits ); +} +#endif /* MBEDTLS_CIPHER_MODE_XTS */ + #endif /* !MBEDTLS_AES_SETKEY_DEC_ALT */ -#define AES_FROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3) \ -{ \ - X0 = *RK++ ^ FT0[ ( Y0 ) & 0xFF ] ^ \ - FT1[ ( Y1 >> 8 ) & 0xFF ] ^ \ - FT2[ ( Y2 >> 16 ) & 0xFF ] ^ \ - FT3[ ( Y3 >> 24 ) & 0xFF ]; \ - \ - X1 = *RK++ ^ FT0[ ( Y1 ) & 0xFF ] ^ \ - FT1[ ( Y2 >> 8 ) & 0xFF ] ^ \ - FT2[ ( Y3 >> 16 ) & 0xFF ] ^ \ - FT3[ ( Y0 >> 24 ) & 0xFF ]; \ - \ - X2 = *RK++ ^ FT0[ ( Y2 ) & 0xFF ] ^ \ - FT1[ ( Y3 >> 8 ) & 0xFF ] ^ \ - FT2[ ( Y0 >> 16 ) & 0xFF ] ^ \ - FT3[ ( Y1 >> 24 ) & 0xFF ]; \ - \ - X3 = *RK++ ^ FT0[ ( Y3 ) & 0xFF ] ^ \ - FT1[ ( Y0 >> 8 ) & 0xFF ] ^ \ - FT2[ ( Y1 >> 16 ) & 0xFF ] ^ \ - FT3[ ( Y2 >> 24 ) & 0xFF ]; \ +#define AES_FROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3) \ +{ \ + X0 = *RK++ ^ AES_FT0( ( Y0 ) & 0xFF ) ^ \ + AES_FT1( ( Y1 >> 8 ) & 0xFF ) ^ \ + AES_FT2( ( Y2 >> 16 ) & 0xFF ) ^ \ + AES_FT3( ( Y3 >> 24 ) & 0xFF ); \ + \ + X1 = *RK++ ^ AES_FT0( ( Y1 ) & 0xFF ) ^ \ + AES_FT1( ( Y2 >> 8 ) & 0xFF ) ^ \ + AES_FT2( ( Y3 >> 16 ) & 0xFF ) ^ \ + AES_FT3( ( Y0 >> 24 ) & 0xFF ); \ + \ + X2 = *RK++ ^ AES_FT0( ( Y2 ) & 0xFF ) ^ \ + AES_FT1( ( Y3 >> 8 ) & 0xFF ) ^ \ + AES_FT2( ( Y0 >> 16 ) & 0xFF ) ^ \ + AES_FT3( ( Y1 >> 24 ) & 0xFF ); \ + \ + X3 = *RK++ ^ AES_FT0( ( Y3 ) & 0xFF ) ^ \ + AES_FT1( ( Y0 >> 8 ) & 0xFF ) ^ \ + AES_FT2( ( Y1 >> 16 ) & 0xFF ) ^ \ + AES_FT3( ( Y2 >> 24 ) & 0xFF ); \ } -#define AES_RROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3) \ -{ \ - X0 = *RK++ ^ RT0[ ( Y0 ) & 0xFF ] ^ \ - RT1[ ( Y3 >> 8 ) & 0xFF ] ^ \ - RT2[ ( Y2 >> 16 ) & 0xFF ] ^ \ - RT3[ ( Y1 >> 24 ) & 0xFF ]; \ - \ - X1 = *RK++ ^ RT0[ ( Y1 ) & 0xFF ] ^ \ - RT1[ ( Y0 >> 8 ) & 0xFF ] ^ \ - RT2[ ( Y3 >> 16 ) & 0xFF ] ^ \ - RT3[ ( Y2 >> 24 ) & 0xFF ]; \ - \ - X2 = *RK++ ^ RT0[ ( Y2 ) & 0xFF ] ^ \ - RT1[ ( Y1 >> 8 ) & 0xFF ] ^ \ - RT2[ ( Y0 >> 16 ) & 0xFF ] ^ \ - RT3[ ( Y3 >> 24 ) & 0xFF ]; \ - \ - X3 = *RK++ ^ RT0[ ( Y3 ) & 0xFF ] ^ \ - RT1[ ( Y2 >> 8 ) & 0xFF ] ^ \ - RT2[ ( Y1 >> 16 ) & 0xFF ] ^ \ - RT3[ ( Y0 >> 24 ) & 0xFF ]; \ +#define AES_RROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3) \ +{ \ + X0 = *RK++ ^ AES_RT0( ( Y0 ) & 0xFF ) ^ \ + AES_RT1( ( Y3 >> 8 ) & 0xFF ) ^ \ + AES_RT2( ( Y2 >> 16 ) & 0xFF ) ^ \ + AES_RT3( ( Y1 >> 24 ) & 0xFF ); \ + \ + X1 = *RK++ ^ AES_RT0( ( Y1 ) & 0xFF ) ^ \ + AES_RT1( ( Y0 >> 8 ) & 0xFF ) ^ \ + AES_RT2( ( Y3 >> 16 ) & 0xFF ) ^ \ + AES_RT3( ( Y2 >> 24 ) & 0xFF ); \ + \ + X2 = *RK++ ^ AES_RT0( ( Y2 ) & 0xFF ) ^ \ + AES_RT1( ( Y1 >> 8 ) & 0xFF ) ^ \ + AES_RT2( ( Y0 >> 16 ) & 0xFF ) ^ \ + AES_RT3( ( Y3 >> 24 ) & 0xFF ); \ + \ + X3 = *RK++ ^ AES_RT0( ( Y3 ) & 0xFF ) ^ \ + AES_RT1( ( Y2 >> 8 ) & 0xFF ) ^ \ + AES_RT2( ( Y1 >> 16 ) & 0xFF ) ^ \ + AES_RT3( ( Y0 >> 24 ) & 0xFF ); \ } /* @@ -939,6 +1069,165 @@ int mbedtls_aes_crypt_cbc( mbedtls_aes_context *ctx, } #endif /* MBEDTLS_CIPHER_MODE_CBC */ +#if defined(MBEDTLS_CIPHER_MODE_XTS) + +/* Endianess with 64 bits values */ +#ifndef GET_UINT64_LE +#define GET_UINT64_LE(n,b,i) \ +{ \ + (n) = ( (uint64_t) (b)[(i) + 7] << 56 ) \ + | ( (uint64_t) (b)[(i) + 6] << 48 ) \ + | ( (uint64_t) (b)[(i) + 5] << 40 ) \ + | ( (uint64_t) (b)[(i) + 4] << 32 ) \ + | ( (uint64_t) (b)[(i) + 3] << 24 ) \ + | ( (uint64_t) (b)[(i) + 2] << 16 ) \ + | ( (uint64_t) (b)[(i) + 1] << 8 ) \ + | ( (uint64_t) (b)[(i) ] ); \ +} +#endif + +#ifndef PUT_UINT64_LE +#define PUT_UINT64_LE(n,b,i) \ +{ \ + (b)[(i) + 7] = (unsigned char) ( (n) >> 56 ); \ + (b)[(i) + 6] = (unsigned char) ( (n) >> 48 ); \ + (b)[(i) + 5] = (unsigned char) ( (n) >> 40 ); \ + (b)[(i) + 4] = (unsigned char) ( (n) >> 32 ); \ + (b)[(i) + 3] = (unsigned char) ( (n) >> 24 ); \ + (b)[(i) + 2] = (unsigned char) ( (n) >> 16 ); \ + (b)[(i) + 1] = (unsigned char) ( (n) >> 8 ); \ + (b)[(i) ] = (unsigned char) ( (n) ); \ +} +#endif + +typedef unsigned char mbedtls_be128[16]; + +/* + * GF(2^128) multiplication function + * + * This function multiplies a field element by x in the polynomial field + * representation. It uses 64-bit word operations to gain speed but compensates + * for machine endianess and hence works correctly on both big and little + * endian machines. + */ +static void mbedtls_gf128mul_x_ble( unsigned char r[16], + const unsigned char x[16] ) +{ + uint64_t a, b, ra, rb; + + GET_UINT64_LE( a, x, 0 ); + GET_UINT64_LE( b, x, 8 ); + + ra = ( a << 1 ) ^ 0x0087 >> ( 8 - ( ( b >> 63 ) << 3 ) ); + rb = ( a >> 63 ) | ( b << 1 ); + + PUT_UINT64_LE( ra, r, 0 ); + PUT_UINT64_LE( rb, r, 8 ); +} + +/* + * AES-XTS buffer encryption/decryption + */ +int mbedtls_aes_crypt_xts( mbedtls_aes_xts_context *ctx, + int mode, + size_t length, + const unsigned char data_unit[16], + const unsigned char *input, + unsigned char *output ) +{ + int ret; + size_t blocks = length / 16; + size_t leftover = length % 16; + unsigned char tweak[16]; + unsigned char prev_tweak[16]; + unsigned char tmp[16]; + + /* Sectors must be at least 16 bytes. */ + if( length < 16 ) + return MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH; + + /* NIST SP 80-38E disallows data units larger than 2**20 blocks. */ + if( length > ( 1 << 20 ) * 16 ) + return MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH; + + /* Compute the tweak. */ + ret = mbedtls_aes_crypt_ecb( &ctx->tweak, MBEDTLS_AES_ENCRYPT, + data_unit, tweak ); + if( ret != 0 ) + return( ret ); + + while( blocks-- ) + { + size_t i; + + if( leftover && ( mode == MBEDTLS_AES_DECRYPT ) && blocks == 0 ) + { + /* We are on the last block in a decrypt operation that has + * leftover bytes, so we need to use the next tweak for this block, + * and this tweak for the lefover bytes. Save the current tweak for + * the leftovers and then update the current tweak for use on this, + * the last full block. */ + memcpy( prev_tweak, tweak, sizeof( tweak ) ); + mbedtls_gf128mul_x_ble( tweak, tweak ); + } + + for( i = 0; i < 16; i++ ) + tmp[i] = input[i] ^ tweak[i]; + + ret = mbedtls_aes_crypt_ecb( &ctx->crypt, mode, tmp, tmp ); + if( ret != 0 ) + return( ret ); + + for( i = 0; i < 16; i++ ) + output[i] = tmp[i] ^ tweak[i]; + + /* Update the tweak for the next block. */ + mbedtls_gf128mul_x_ble( tweak, tweak ); + + output += 16; + input += 16; + } + + if( leftover ) + { + /* If we are on the leftover bytes in a decrypt operation, we need to + * use the previous tweak for these bytes (as saved in prev_tweak). */ + unsigned char *t = mode == MBEDTLS_AES_DECRYPT ? prev_tweak : tweak; + + /* We are now on the final part of the data unit, which doesn't divide + * evenly by 16. It's time for ciphertext stealing. */ + size_t i; + unsigned char *prev_output = output - 16; + + /* Copy ciphertext bytes from the previous block to our output for each + * byte of cyphertext we won't steal. At the same time, copy the + * remainder of the input for this final round (since the loop bounds + * are the same). */ + for( i = 0; i < leftover; i++ ) + { + output[i] = prev_output[i]; + tmp[i] = input[i] ^ t[i]; + } + + /* Copy ciphertext bytes from the previous block for input in this + * round. */ + for( ; i < 16; i++ ) + tmp[i] = prev_output[i] ^ t[i]; + + ret = mbedtls_aes_crypt_ecb( &ctx->crypt, mode, tmp, tmp ); + if( ret != 0 ) + return ret; + + /* Write the result back to the previous block, overriding the previous + * output we copied. */ + for( i = 0; i < 16; i++ ) + prev_output[i] = tmp[i] ^ t[i]; + } + + return( 0 ); +} +#endif /* MBEDTLS_CIPHER_MODE_XTS */ + #if defined(MBEDTLS_CIPHER_MODE_CFB) /* * AES-CFB128 buffer encryption/decryption @@ -1017,7 +1306,41 @@ int mbedtls_aes_crypt_cfb8( mbedtls_aes_context *ctx, return( 0 ); } -#endif /*MBEDTLS_CIPHER_MODE_CFB */ +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_OFB) +/* + * AES-OFB (Output Feedback Mode) buffer encryption/decryption + */ +int mbedtls_aes_crypt_ofb( mbedtls_aes_context *ctx, + size_t length, + size_t *iv_off, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ) +{ + int ret = 0; + size_t n = *iv_off; + + while( length-- ) + { + if( n == 0 ) + { + ret = mbedtls_aes_crypt_ecb( ctx, MBEDTLS_AES_ENCRYPT, iv, iv ); + if( ret != 0 ) + goto exit; + } + *output++ = *input++ ^ iv[n]; + + n = ( n + 1 ) & 0x0F; + } + + *iv_off = n; + +exit: + return( ret ); +} +#endif /* MBEDTLS_CIPHER_MODE_OFB */ #if defined(MBEDTLS_CIPHER_MODE_CTR) /* @@ -1034,6 +1357,9 @@ int mbedtls_aes_crypt_ctr( mbedtls_aes_context *ctx, int c, i; size_t n = *nc_off; + if ( n > 0x0F ) + return( MBEDTLS_ERR_AES_BAD_INPUT_DATA ); + while( length-- ) { if( n == 0 ) { @@ -1171,6 +1497,72 @@ static const unsigned char aes_test_cfb128_ct[3][64] = }; #endif /* MBEDTLS_CIPHER_MODE_CFB */ +#if defined(MBEDTLS_CIPHER_MODE_OFB) +/* + * AES-OFB test vectors from: + * + * https://csrc.nist.gov/publications/detail/sp/800-38a/final + */ +static const unsigned char aes_test_ofb_key[3][32] = +{ + { 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6, + 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C }, + { 0x8E, 0x73, 0xB0, 0xF7, 0xDA, 0x0E, 0x64, 0x52, + 0xC8, 0x10, 0xF3, 0x2B, 0x80, 0x90, 0x79, 0xE5, + 0x62, 0xF8, 0xEA, 0xD2, 0x52, 0x2C, 0x6B, 0x7B }, + { 0x60, 0x3D, 0xEB, 0x10, 0x15, 0xCA, 0x71, 0xBE, + 0x2B, 0x73, 0xAE, 0xF0, 0x85, 0x7D, 0x77, 0x81, + 0x1F, 0x35, 0x2C, 0x07, 0x3B, 0x61, 0x08, 0xD7, + 0x2D, 0x98, 0x10, 0xA3, 0x09, 0x14, 0xDF, 0xF4 } +}; + +static const unsigned char aes_test_ofb_iv[16] = +{ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F +}; + +static const unsigned char aes_test_ofb_pt[64] = +{ + 0x6B, 0xC1, 0xBE, 0xE2, 0x2E, 0x40, 0x9F, 0x96, + 0xE9, 0x3D, 0x7E, 0x11, 0x73, 0x93, 0x17, 0x2A, + 0xAE, 0x2D, 0x8A, 0x57, 0x1E, 0x03, 0xAC, 0x9C, + 0x9E, 0xB7, 0x6F, 0xAC, 0x45, 0xAF, 0x8E, 0x51, + 0x30, 0xC8, 0x1C, 0x46, 0xA3, 0x5C, 0xE4, 0x11, + 0xE5, 0xFB, 0xC1, 0x19, 0x1A, 0x0A, 0x52, 0xEF, + 0xF6, 0x9F, 0x24, 0x45, 0xDF, 0x4F, 0x9B, 0x17, + 0xAD, 0x2B, 0x41, 0x7B, 0xE6, 0x6C, 0x37, 0x10 +}; + +static const unsigned char aes_test_ofb_ct[3][64] = +{ + { 0x3B, 0x3F, 0xD9, 0x2E, 0xB7, 0x2D, 0xAD, 0x20, + 0x33, 0x34, 0x49, 0xF8, 0xE8, 0x3C, 0xFB, 0x4A, + 0x77, 0x89, 0x50, 0x8d, 0x16, 0x91, 0x8f, 0x03, + 0xf5, 0x3c, 0x52, 0xda, 0xc5, 0x4e, 0xd8, 0x25, + 0x97, 0x40, 0x05, 0x1e, 0x9c, 0x5f, 0xec, 0xf6, + 0x43, 0x44, 0xf7, 0xa8, 0x22, 0x60, 0xed, 0xcc, + 0x30, 0x4c, 0x65, 0x28, 0xf6, 0x59, 0xc7, 0x78, + 0x66, 0xa5, 0x10, 0xd9, 0xc1, 0xd6, 0xae, 0x5e }, + { 0xCD, 0xC8, 0x0D, 0x6F, 0xDD, 0xF1, 0x8C, 0xAB, + 0x34, 0xC2, 0x59, 0x09, 0xC9, 0x9A, 0x41, 0x74, + 0xfc, 0xc2, 0x8b, 0x8d, 0x4c, 0x63, 0x83, 0x7c, + 0x09, 0xe8, 0x17, 0x00, 0xc1, 0x10, 0x04, 0x01, + 0x8d, 0x9a, 0x9a, 0xea, 0xc0, 0xf6, 0x59, 0x6f, + 0x55, 0x9c, 0x6d, 0x4d, 0xaf, 0x59, 0xa5, 0xf2, + 0x6d, 0x9f, 0x20, 0x08, 0x57, 0xca, 0x6c, 0x3e, + 0x9c, 0xac, 0x52, 0x4b, 0xd9, 0xac, 0xc9, 0x2a }, + { 0xDC, 0x7E, 0x84, 0xBF, 0xDA, 0x79, 0x16, 0x4B, + 0x7E, 0xCD, 0x84, 0x86, 0x98, 0x5D, 0x38, 0x60, + 0x4f, 0xeb, 0xdc, 0x67, 0x40, 0xd2, 0x0b, 0x3a, + 0xc8, 0x8f, 0x6a, 0xd8, 0x2a, 0x4f, 0xb0, 0x8d, + 0x71, 0xab, 0x47, 0xa0, 0x86, 0xe8, 0x6e, 0xed, + 0xf3, 0x9d, 0x1c, 0x5b, 0xba, 0x97, 0xc4, 0x08, + 0x01, 0x26, 0x14, 0x1d, 0x67, 0xf3, 0x7b, 0xe8, + 0x53, 0x8f, 0x5a, 0x8b, 0xe7, 0x40, 0xe4, 0x84 } +}; +#endif /* MBEDTLS_CIPHER_MODE_OFB */ + #if defined(MBEDTLS_CIPHER_MODE_CTR) /* * AES-CTR test vectors from: @@ -1234,6 +1626,74 @@ static const int aes_test_ctr_len[3] = { 16, 32, 36 }; #endif /* MBEDTLS_CIPHER_MODE_CTR */ +#if defined(MBEDTLS_CIPHER_MODE_XTS) +/* + * AES-XTS test vectors from: + * + * IEEE P1619/D16 Annex B + * https://web.archive.org/web/20150629024421/http://grouper.ieee.org/groups/1619/email/pdf00086.pdf + * (Archived from original at http://grouper.ieee.org/groups/1619/email/pdf00086.pdf) + */ +static const unsigned char aes_test_xts_key[][32] = +{ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, + 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22 }, + { 0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8, + 0xf7, 0xf6, 0xf5, 0xf4, 0xf3, 0xf2, 0xf1, 0xf0, + 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, + 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22 }, +}; + +static const unsigned char aes_test_xts_pt32[][32] = +{ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, + 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, + 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, + 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44 }, + { 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, + 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, + 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, + 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44 }, +}; + +static const unsigned char aes_test_xts_ct32[][32] = +{ + { 0x91, 0x7c, 0xf6, 0x9e, 0xbd, 0x68, 0xb2, 0xec, + 0x9b, 0x9f, 0xe9, 0xa3, 0xea, 0xdd, 0xa6, 0x92, + 0xcd, 0x43, 0xd2, 0xf5, 0x95, 0x98, 0xed, 0x85, + 0x8c, 0x02, 0xc2, 0x65, 0x2f, 0xbf, 0x92, 0x2e }, + { 0xc4, 0x54, 0x18, 0x5e, 0x6a, 0x16, 0x93, 0x6e, + 0x39, 0x33, 0x40, 0x38, 0xac, 0xef, 0x83, 0x8b, + 0xfb, 0x18, 0x6f, 0xff, 0x74, 0x80, 0xad, 0xc4, + 0x28, 0x93, 0x82, 0xec, 0xd6, 0xd3, 0x94, 0xf0 }, + { 0xaf, 0x85, 0x33, 0x6b, 0x59, 0x7a, 0xfc, 0x1a, + 0x90, 0x0b, 0x2e, 0xb2, 0x1e, 0xc9, 0x49, 0xd2, + 0x92, 0xdf, 0x4c, 0x04, 0x7e, 0x0b, 0x21, 0x53, + 0x21, 0x86, 0xa5, 0x97, 0x1a, 0x22, 0x7a, 0x89 }, +}; + +static const unsigned char aes_test_xts_data_unit[][16] = +{ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x33, 0x33, 0x33, 0x33, 0x33, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x33, 0x33, 0x33, 0x33, 0x33, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, +}; + +#endif /* MBEDTLS_CIPHER_MODE_XTS */ + /* * Checkup routine */ @@ -1250,11 +1710,14 @@ int mbedtls_aes_self_test( int verbose ) #if defined(MBEDTLS_CIPHER_MODE_CBC) unsigned char prv[16]; #endif -#if defined(MBEDTLS_CIPHER_MODE_CTR) || defined(MBEDTLS_CIPHER_MODE_CFB) +#if defined(MBEDTLS_CIPHER_MODE_CTR) || defined(MBEDTLS_CIPHER_MODE_CFB) || \ + defined(MBEDTLS_CIPHER_MODE_OFB) size_t offset; #endif -#if defined(MBEDTLS_CIPHER_MODE_CTR) +#if defined(MBEDTLS_CIPHER_MODE_CTR) || defined(MBEDTLS_CIPHER_MODE_XTS) int len; +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) unsigned char nonce_counter[16]; unsigned char stream_block[16]; #endif @@ -1462,6 +1925,69 @@ int mbedtls_aes_self_test( int verbose ) mbedtls_printf( "\n" ); #endif /* MBEDTLS_CIPHER_MODE_CFB */ +#if defined(MBEDTLS_CIPHER_MODE_OFB) + /* + * OFB mode + */ + for( i = 0; i < 6; i++ ) + { + u = i >> 1; + keybits = 128 + u * 64; + mode = i & 1; + + if( verbose != 0 ) + mbedtls_printf( " AES-OFB-%3d (%s): ", keybits, + ( mode == MBEDTLS_AES_DECRYPT ) ? "dec" : "enc" ); + + memcpy( iv, aes_test_ofb_iv, 16 ); + memcpy( key, aes_test_ofb_key[u], keybits / 8 ); + + offset = 0; + ret = mbedtls_aes_setkey_enc( &ctx, key, keybits ); + /* + * AES-192 is an optional feature that may be unavailable when + * there is an alternative underlying implementation i.e. when + * MBEDTLS_AES_ALT is defined. + */ + if( ret == MBEDTLS_ERR_AES_FEATURE_UNAVAILABLE && keybits == 192 ) + { + mbedtls_printf( "skipped\n" ); + continue; + } + else if( ret != 0 ) + { + goto exit; + } + + if( mode == MBEDTLS_AES_DECRYPT ) + { + memcpy( buf, aes_test_ofb_ct[u], 64 ); + aes_tests = aes_test_ofb_pt; + } + else + { + memcpy( buf, aes_test_ofb_pt, 64 ); + aes_tests = aes_test_ofb_ct[u]; + } + + ret = mbedtls_aes_crypt_ofb( &ctx, 64, &offset, iv, buf, buf ); + if( ret != 0 ) + goto exit; + + if( memcmp( buf, aes_tests, 64 ) != 0 ) + { + ret = 1; + goto exit; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); +#endif /* MBEDTLS_CIPHER_MODE_OFB */ + #if defined(MBEDTLS_CIPHER_MODE_CTR) /* * CTR mode @@ -1514,6 +2040,73 @@ int mbedtls_aes_self_test( int verbose ) mbedtls_printf( "\n" ); #endif /* MBEDTLS_CIPHER_MODE_CTR */ +#if defined(MBEDTLS_CIPHER_MODE_XTS) + { + static const int num_tests = + sizeof(aes_test_xts_key) / sizeof(*aes_test_xts_key); + mbedtls_aes_xts_context ctx_xts; + + /* + * XTS mode + */ + mbedtls_aes_xts_init( &ctx_xts ); + + for( i = 0; i < num_tests << 1; i++ ) + { + const unsigned char *data_unit; + u = i >> 1; + mode = i & 1; + + if( verbose != 0 ) + mbedtls_printf( " AES-XTS-128 (%s): ", + ( mode == MBEDTLS_AES_DECRYPT ) ? "dec" : "enc" ); + + memset( key, 0, sizeof( key ) ); + memcpy( key, aes_test_xts_key[u], 32 ); + data_unit = aes_test_xts_data_unit[u]; + + len = sizeof( *aes_test_xts_ct32 ); + + if( mode == MBEDTLS_AES_DECRYPT ) + { + ret = mbedtls_aes_xts_setkey_dec( &ctx_xts, key, 256 ); + if( ret != 0) + goto exit; + memcpy( buf, aes_test_xts_ct32[u], len ); + aes_tests = aes_test_xts_pt32[u]; + } + else + { + ret = mbedtls_aes_xts_setkey_enc( &ctx_xts, key, 256 ); + if( ret != 0) + goto exit; + memcpy( buf, aes_test_xts_pt32[u], len ); + aes_tests = aes_test_xts_ct32[u]; + } + + + ret = mbedtls_aes_crypt_xts( &ctx_xts, mode, len, data_unit, + buf, buf ); + if( ret != 0 ) + goto exit; + + if( memcmp( buf, aes_tests, len ) != 0 ) + { + ret = 1; + goto exit; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + mbedtls_aes_xts_free( &ctx_xts ); + } +#endif /* MBEDTLS_CIPHER_MODE_XTS */ + ret = 0; exit: diff --git a/thirdparty/mbedtls/library/aesni.c b/thirdparty/mbedtls/library/aesni.c index 1ca3c3ef5b..062708b047 100644 --- a/thirdparty/mbedtls/library/aesni.c +++ b/thirdparty/mbedtls/library/aesni.c @@ -32,6 +32,12 @@ #if defined(MBEDTLS_AESNI_C) +#if defined(__has_feature) +#if __has_feature(memory_sanitizer) +#warning "MBEDTLS_AESNI_C is known to cause spurious error reports with some memory sanitizers as they do not understand the assembly code." +#endif +#endif + #include "mbedtls/aesni.h" #include <string.h> diff --git a/thirdparty/mbedtls/library/arc4.c b/thirdparty/mbedtls/library/arc4.c index 05b33d3fdb..b8998ac6cd 100644 --- a/thirdparty/mbedtls/library/arc4.c +++ b/thirdparty/mbedtls/library/arc4.c @@ -33,6 +33,7 @@ #if defined(MBEDTLS_ARC4_C) #include "mbedtls/arc4.h" +#include "mbedtls/platform_util.h" #include <string.h> @@ -47,11 +48,6 @@ #if !defined(MBEDTLS_ARC4_ALT) -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize( void *v, size_t n ) { - volatile unsigned char *p = (unsigned char*)v; while( n-- ) *p++ = 0; -} - void mbedtls_arc4_init( mbedtls_arc4_context *ctx ) { memset( ctx, 0, sizeof( mbedtls_arc4_context ) ); @@ -62,7 +58,7 @@ void mbedtls_arc4_free( mbedtls_arc4_context *ctx ) if( ctx == NULL ) return; - mbedtls_zeroize( ctx, sizeof( mbedtls_arc4_context ) ); + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_arc4_context ) ); } /* diff --git a/thirdparty/mbedtls/library/aria.c b/thirdparty/mbedtls/library/aria.c new file mode 100644 index 0000000000..e9bcd6d135 --- /dev/null +++ b/thirdparty/mbedtls/library/aria.c @@ -0,0 +1,1028 @@ +/* + * ARIA implementation + * + * Copyright (C) 2006-2017, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +/* + * This implementation is based on the following standards: + * [1] http://210.104.33.10/ARIA/doc/ARIA-specification-e.pdf + * [2] https://tools.ietf.org/html/rfc5794 + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_ARIA_C) + +#include "mbedtls/aria.h" + +#include <string.h> + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include <stdio.h> +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +#if !defined(MBEDTLS_ARIA_ALT) + +#include "mbedtls/platform_util.h" + +#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ + !defined(inline) && !defined(__cplusplus) +#define inline __inline +#endif + +/* + * 32-bit integer manipulation macros (little endian) + */ +#ifndef GET_UINT32_LE +#define GET_UINT32_LE( n, b, i ) \ +{ \ + (n) = ( (uint32_t) (b)[(i) ] ) \ + | ( (uint32_t) (b)[(i) + 1] << 8 ) \ + | ( (uint32_t) (b)[(i) + 2] << 16 ) \ + | ( (uint32_t) (b)[(i) + 3] << 24 ); \ +} +#endif + +#ifndef PUT_UINT32_LE +#define PUT_UINT32_LE( n, b, i ) \ +{ \ + (b)[(i) ] = (unsigned char) ( ( (n) ) & 0xFF ); \ + (b)[(i) + 1] = (unsigned char) ( ( (n) >> 8 ) & 0xFF ); \ + (b)[(i) + 2] = (unsigned char) ( ( (n) >> 16 ) & 0xFF ); \ + (b)[(i) + 3] = (unsigned char) ( ( (n) >> 24 ) & 0xFF ); \ +} +#endif + +/* + * modify byte order: ( A B C D ) -> ( B A D C ), i.e. swap pairs of bytes + * + * This is submatrix P1 in [1] Appendix B.1 + * + * Common compilers fail to translate this to minimal number of instructions, + * so let's provide asm versions for common platforms with C fallback. + */ +#if defined(MBEDTLS_HAVE_ASM) +#if defined(__arm__) /* rev16 available from v6 up */ +/* armcc5 --gnu defines __GNUC__ but doesn't support GNU's extended asm */ +#if defined(__GNUC__) && \ + ( !defined(__ARMCC_VERSION) || __ARMCC_VERSION >= 6000000 ) && \ + __ARM_ARCH >= 6 +static inline uint32_t aria_p1( uint32_t x ) +{ + uint32_t r; + __asm( "rev16 %0, %1" : "=l" (r) : "l" (x) ); + return( r ); +} +#define ARIA_P1 aria_p1 +#elif defined(__ARMCC_VERSION) && __ARMCC_VERSION < 6000000 && \ + ( __TARGET_ARCH_ARM >= 6 || __TARGET_ARCH_THUMB >= 3 ) +static inline uint32_t aria_p1( uint32_t x ) +{ + uint32_t r; + __asm( "rev16 r, x" ); + return( r ); +} +#define ARIA_P1 aria_p1 +#endif +#endif /* arm */ +#if defined(__GNUC__) && \ + defined(__i386__) || defined(__amd64__) || defined( __x86_64__) +/* I couldn't find an Intel equivalent of rev16, so two instructions */ +#define ARIA_P1(x) ARIA_P2( ARIA_P3( x ) ) +#endif /* x86 gnuc */ +#endif /* MBEDTLS_HAVE_ASM && GNUC */ +#if !defined(ARIA_P1) +#define ARIA_P1(x) ((((x) >> 8) & 0x00FF00FF) ^ (((x) & 0x00FF00FF) << 8)) +#endif + +/* + * modify byte order: ( A B C D ) -> ( C D A B ), i.e. rotate by 16 bits + * + * This is submatrix P2 in [1] Appendix B.1 + * + * Common compilers will translate this to a single instruction. + */ +#define ARIA_P2(x) (((x) >> 16) ^ ((x) << 16)) + +/* + * modify byte order: ( A B C D ) -> ( D C B A ), i.e. change endianness + * + * This is submatrix P3 in [1] Appendix B.1 + * + * Some compilers fail to translate this to a single instruction, + * so let's provide asm versions for common platforms with C fallback. + */ +#if defined(MBEDTLS_HAVE_ASM) +#if defined(__arm__) /* rev available from v6 up */ +/* armcc5 --gnu defines __GNUC__ but doesn't support GNU's extended asm */ +#if defined(__GNUC__) && \ + ( !defined(__ARMCC_VERSION) || __ARMCC_VERSION >= 6000000 ) && \ + __ARM_ARCH >= 6 +static inline uint32_t aria_p3( uint32_t x ) +{ + uint32_t r; + __asm( "rev %0, %1" : "=l" (r) : "l" (x) ); + return( r ); +} +#define ARIA_P3 aria_p3 +#elif defined(__ARMCC_VERSION) && __ARMCC_VERSION < 6000000 && \ + ( __TARGET_ARCH_ARM >= 6 || __TARGET_ARCH_THUMB >= 3 ) +static inline uint32_t aria_p3( uint32_t x ) +{ + uint32_t r; + __asm( "rev r, x" ); + return( r ); +} +#define ARIA_P3 aria_p3 +#endif +#endif /* arm */ +#if defined(__GNUC__) && \ + defined(__i386__) || defined(__amd64__) || defined( __x86_64__) +static inline uint32_t aria_p3( uint32_t x ) +{ + __asm( "bswap %0" : "=r" (x) : "0" (x) ); + return( x ); +} +#define ARIA_P3 aria_p3 +#endif /* x86 gnuc */ +#endif /* MBEDTLS_HAVE_ASM && GNUC */ +#if !defined(ARIA_P3) +#define ARIA_P3(x) ARIA_P2( ARIA_P1 ( x ) ) +#endif + +/* + * ARIA Affine Transform + * (a, b, c, d) = state in/out + * + * If we denote the first byte of input by 0, ..., the last byte by f, + * then inputs are: a = 0123, b = 4567, c = 89ab, d = cdef. + * + * Reading [1] 2.4 or [2] 2.4.3 in columns and performing simple + * rearrangements on adjacent pairs, output is: + * + * a = 3210 + 4545 + 6767 + 88aa + 99bb + dccd + effe + * = 3210 + 4567 + 6745 + 89ab + 98ba + dcfe + efcd + * b = 0101 + 2323 + 5476 + 8998 + baab + eecc + ffdd + * = 0123 + 2301 + 5476 + 89ab + ba98 + efcd + fedc + * c = 0022 + 1133 + 4554 + 7667 + ab89 + dcdc + fefe + * = 0123 + 1032 + 4567 + 7654 + ab89 + dcfe + fedc + * d = 1001 + 2332 + 6644 + 7755 + 9898 + baba + cdef + * = 1032 + 2301 + 6745 + 7654 + 98ba + ba98 + cdef + * + * Note: another presentation of the A transform can be found as the first + * half of App. B.1 in [1] in terms of 4-byte operators P1, P2, P3 and P4. + * The implementation below uses only P1 and P2 as they are sufficient. + */ +static inline void aria_a( uint32_t *a, uint32_t *b, + uint32_t *c, uint32_t *d ) +{ + uint32_t ta, tb, tc; + ta = *b; // 4567 + *b = *a; // 0123 + *a = ARIA_P2( ta ); // 6745 + tb = ARIA_P2( *d ); // efcd + *d = ARIA_P1( *c ); // 98ba + *c = ARIA_P1( tb ); // fedc + ta ^= *d; // 4567+98ba + tc = ARIA_P2( *b ); // 2301 + ta = ARIA_P1( ta ) ^ tc ^ *c; // 2301+5476+89ab+fedc + tb ^= ARIA_P2( *d ); // ba98+efcd + tc ^= ARIA_P1( *a ); // 2301+7654 + *b ^= ta ^ tb; // 0123+2301+5476+89ab+ba98+efcd+fedc OUT + tb = ARIA_P2( tb ) ^ ta; // 2301+5476+89ab+98ba+cdef+fedc + *a ^= ARIA_P1( tb ); // 3210+4567+6745+89ab+98ba+dcfe+efcd OUT + ta = ARIA_P2( ta ); // 0123+7654+ab89+dcfe + *d ^= ARIA_P1( ta ) ^ tc; // 1032+2301+6745+7654+98ba+ba98+cdef OUT + tc = ARIA_P2( tc ); // 0123+5476 + *c ^= ARIA_P1( tc ) ^ ta; // 0123+1032+4567+7654+ab89+dcfe+fedc OUT +} + +/* + * ARIA Substitution Layer SL1 / SL2 + * (a, b, c, d) = state in/out + * (sa, sb, sc, sd) = 256 8-bit S-Boxes (see below) + * + * By passing sb1, sb2, is1, is2 as S-Boxes you get SL1 + * By passing is1, is2, sb1, sb2 as S-Boxes you get SL2 + */ +static inline void aria_sl( uint32_t *a, uint32_t *b, + uint32_t *c, uint32_t *d, + const uint8_t sa[256], const uint8_t sb[256], + const uint8_t sc[256], const uint8_t sd[256] ) +{ + *a = ( (uint32_t) sa[ *a & 0xFF] ) ^ + (((uint32_t) sb[(*a >> 8) & 0xFF]) << 8) ^ + (((uint32_t) sc[(*a >> 16) & 0xFF]) << 16) ^ + (((uint32_t) sd[ *a >> 24 ]) << 24); + *b = ( (uint32_t) sa[ *b & 0xFF] ) ^ + (((uint32_t) sb[(*b >> 8) & 0xFF]) << 8) ^ + (((uint32_t) sc[(*b >> 16) & 0xFF]) << 16) ^ + (((uint32_t) sd[ *b >> 24 ]) << 24); + *c = ( (uint32_t) sa[ *c & 0xFF] ) ^ + (((uint32_t) sb[(*c >> 8) & 0xFF]) << 8) ^ + (((uint32_t) sc[(*c >> 16) & 0xFF]) << 16) ^ + (((uint32_t) sd[ *c >> 24 ]) << 24); + *d = ( (uint32_t) sa[ *d & 0xFF] ) ^ + (((uint32_t) sb[(*d >> 8) & 0xFF]) << 8) ^ + (((uint32_t) sc[(*d >> 16) & 0xFF]) << 16) ^ + (((uint32_t) sd[ *d >> 24 ]) << 24); +} + +/* + * S-Boxes + */ +static const uint8_t aria_sb1[256] = +{ + 0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 0x30, 0x01, 0x67, 0x2B, + 0xFE, 0xD7, 0xAB, 0x76, 0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, + 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0, 0xB7, 0xFD, 0x93, 0x26, + 0x36, 0x3F, 0xF7, 0xCC, 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15, + 0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, 0x07, 0x12, 0x80, 0xE2, + 0xEB, 0x27, 0xB2, 0x75, 0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, + 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84, 0x53, 0xD1, 0x00, 0xED, + 0x20, 0xFC, 0xB1, 0x5B, 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF, + 0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, 0x45, 0xF9, 0x02, 0x7F, + 0x50, 0x3C, 0x9F, 0xA8, 0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, + 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2, 0xCD, 0x0C, 0x13, 0xEC, + 0x5F, 0x97, 0x44, 0x17, 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73, + 0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, 0x46, 0xEE, 0xB8, 0x14, + 0xDE, 0x5E, 0x0B, 0xDB, 0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, + 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79, 0xE7, 0xC8, 0x37, 0x6D, + 0x8D, 0xD5, 0x4E, 0xA9, 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08, + 0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, 0xE8, 0xDD, 0x74, 0x1F, + 0x4B, 0xBD, 0x8B, 0x8A, 0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, + 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E, 0xE1, 0xF8, 0x98, 0x11, + 0x69, 0xD9, 0x8E, 0x94, 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF, + 0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, 0x41, 0x99, 0x2D, 0x0F, + 0xB0, 0x54, 0xBB, 0x16 +}; + +static const uint8_t aria_sb2[256] = +{ + 0xE2, 0x4E, 0x54, 0xFC, 0x94, 0xC2, 0x4A, 0xCC, 0x62, 0x0D, 0x6A, 0x46, + 0x3C, 0x4D, 0x8B, 0xD1, 0x5E, 0xFA, 0x64, 0xCB, 0xB4, 0x97, 0xBE, 0x2B, + 0xBC, 0x77, 0x2E, 0x03, 0xD3, 0x19, 0x59, 0xC1, 0x1D, 0x06, 0x41, 0x6B, + 0x55, 0xF0, 0x99, 0x69, 0xEA, 0x9C, 0x18, 0xAE, 0x63, 0xDF, 0xE7, 0xBB, + 0x00, 0x73, 0x66, 0xFB, 0x96, 0x4C, 0x85, 0xE4, 0x3A, 0x09, 0x45, 0xAA, + 0x0F, 0xEE, 0x10, 0xEB, 0x2D, 0x7F, 0xF4, 0x29, 0xAC, 0xCF, 0xAD, 0x91, + 0x8D, 0x78, 0xC8, 0x95, 0xF9, 0x2F, 0xCE, 0xCD, 0x08, 0x7A, 0x88, 0x38, + 0x5C, 0x83, 0x2A, 0x28, 0x47, 0xDB, 0xB8, 0xC7, 0x93, 0xA4, 0x12, 0x53, + 0xFF, 0x87, 0x0E, 0x31, 0x36, 0x21, 0x58, 0x48, 0x01, 0x8E, 0x37, 0x74, + 0x32, 0xCA, 0xE9, 0xB1, 0xB7, 0xAB, 0x0C, 0xD7, 0xC4, 0x56, 0x42, 0x26, + 0x07, 0x98, 0x60, 0xD9, 0xB6, 0xB9, 0x11, 0x40, 0xEC, 0x20, 0x8C, 0xBD, + 0xA0, 0xC9, 0x84, 0x04, 0x49, 0x23, 0xF1, 0x4F, 0x50, 0x1F, 0x13, 0xDC, + 0xD8, 0xC0, 0x9E, 0x57, 0xE3, 0xC3, 0x7B, 0x65, 0x3B, 0x02, 0x8F, 0x3E, + 0xE8, 0x25, 0x92, 0xE5, 0x15, 0xDD, 0xFD, 0x17, 0xA9, 0xBF, 0xD4, 0x9A, + 0x7E, 0xC5, 0x39, 0x67, 0xFE, 0x76, 0x9D, 0x43, 0xA7, 0xE1, 0xD0, 0xF5, + 0x68, 0xF2, 0x1B, 0x34, 0x70, 0x05, 0xA3, 0x8A, 0xD5, 0x79, 0x86, 0xA8, + 0x30, 0xC6, 0x51, 0x4B, 0x1E, 0xA6, 0x27, 0xF6, 0x35, 0xD2, 0x6E, 0x24, + 0x16, 0x82, 0x5F, 0xDA, 0xE6, 0x75, 0xA2, 0xEF, 0x2C, 0xB2, 0x1C, 0x9F, + 0x5D, 0x6F, 0x80, 0x0A, 0x72, 0x44, 0x9B, 0x6C, 0x90, 0x0B, 0x5B, 0x33, + 0x7D, 0x5A, 0x52, 0xF3, 0x61, 0xA1, 0xF7, 0xB0, 0xD6, 0x3F, 0x7C, 0x6D, + 0xED, 0x14, 0xE0, 0xA5, 0x3D, 0x22, 0xB3, 0xF8, 0x89, 0xDE, 0x71, 0x1A, + 0xAF, 0xBA, 0xB5, 0x81 +}; + +static const uint8_t aria_is1[256] = +{ + 0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38, 0xBF, 0x40, 0xA3, 0x9E, + 0x81, 0xF3, 0xD7, 0xFB, 0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87, + 0x34, 0x8E, 0x43, 0x44, 0xC4, 0xDE, 0xE9, 0xCB, 0x54, 0x7B, 0x94, 0x32, + 0xA6, 0xC2, 0x23, 0x3D, 0xEE, 0x4C, 0x95, 0x0B, 0x42, 0xFA, 0xC3, 0x4E, + 0x08, 0x2E, 0xA1, 0x66, 0x28, 0xD9, 0x24, 0xB2, 0x76, 0x5B, 0xA2, 0x49, + 0x6D, 0x8B, 0xD1, 0x25, 0x72, 0xF8, 0xF6, 0x64, 0x86, 0x68, 0x98, 0x16, + 0xD4, 0xA4, 0x5C, 0xCC, 0x5D, 0x65, 0xB6, 0x92, 0x6C, 0x70, 0x48, 0x50, + 0xFD, 0xED, 0xB9, 0xDA, 0x5E, 0x15, 0x46, 0x57, 0xA7, 0x8D, 0x9D, 0x84, + 0x90, 0xD8, 0xAB, 0x00, 0x8C, 0xBC, 0xD3, 0x0A, 0xF7, 0xE4, 0x58, 0x05, + 0xB8, 0xB3, 0x45, 0x06, 0xD0, 0x2C, 0x1E, 0x8F, 0xCA, 0x3F, 0x0F, 0x02, + 0xC1, 0xAF, 0xBD, 0x03, 0x01, 0x13, 0x8A, 0x6B, 0x3A, 0x91, 0x11, 0x41, + 0x4F, 0x67, 0xDC, 0xEA, 0x97, 0xF2, 0xCF, 0xCE, 0xF0, 0xB4, 0xE6, 0x73, + 0x96, 0xAC, 0x74, 0x22, 0xE7, 0xAD, 0x35, 0x85, 0xE2, 0xF9, 0x37, 0xE8, + 0x1C, 0x75, 0xDF, 0x6E, 0x47, 0xF1, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89, + 0x6F, 0xB7, 0x62, 0x0E, 0xAA, 0x18, 0xBE, 0x1B, 0xFC, 0x56, 0x3E, 0x4B, + 0xC6, 0xD2, 0x79, 0x20, 0x9A, 0xDB, 0xC0, 0xFE, 0x78, 0xCD, 0x5A, 0xF4, + 0x1F, 0xDD, 0xA8, 0x33, 0x88, 0x07, 0xC7, 0x31, 0xB1, 0x12, 0x10, 0x59, + 0x27, 0x80, 0xEC, 0x5F, 0x60, 0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0x0D, + 0x2D, 0xE5, 0x7A, 0x9F, 0x93, 0xC9, 0x9C, 0xEF, 0xA0, 0xE0, 0x3B, 0x4D, + 0xAE, 0x2A, 0xF5, 0xB0, 0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 0x99, 0x61, + 0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26, 0xE1, 0x69, 0x14, 0x63, + 0x55, 0x21, 0x0C, 0x7D +}; + +static const uint8_t aria_is2[256] = +{ + 0x30, 0x68, 0x99, 0x1B, 0x87, 0xB9, 0x21, 0x78, 0x50, 0x39, 0xDB, 0xE1, + 0x72, 0x09, 0x62, 0x3C, 0x3E, 0x7E, 0x5E, 0x8E, 0xF1, 0xA0, 0xCC, 0xA3, + 0x2A, 0x1D, 0xFB, 0xB6, 0xD6, 0x20, 0xC4, 0x8D, 0x81, 0x65, 0xF5, 0x89, + 0xCB, 0x9D, 0x77, 0xC6, 0x57, 0x43, 0x56, 0x17, 0xD4, 0x40, 0x1A, 0x4D, + 0xC0, 0x63, 0x6C, 0xE3, 0xB7, 0xC8, 0x64, 0x6A, 0x53, 0xAA, 0x38, 0x98, + 0x0C, 0xF4, 0x9B, 0xED, 0x7F, 0x22, 0x76, 0xAF, 0xDD, 0x3A, 0x0B, 0x58, + 0x67, 0x88, 0x06, 0xC3, 0x35, 0x0D, 0x01, 0x8B, 0x8C, 0xC2, 0xE6, 0x5F, + 0x02, 0x24, 0x75, 0x93, 0x66, 0x1E, 0xE5, 0xE2, 0x54, 0xD8, 0x10, 0xCE, + 0x7A, 0xE8, 0x08, 0x2C, 0x12, 0x97, 0x32, 0xAB, 0xB4, 0x27, 0x0A, 0x23, + 0xDF, 0xEF, 0xCA, 0xD9, 0xB8, 0xFA, 0xDC, 0x31, 0x6B, 0xD1, 0xAD, 0x19, + 0x49, 0xBD, 0x51, 0x96, 0xEE, 0xE4, 0xA8, 0x41, 0xDA, 0xFF, 0xCD, 0x55, + 0x86, 0x36, 0xBE, 0x61, 0x52, 0xF8, 0xBB, 0x0E, 0x82, 0x48, 0x69, 0x9A, + 0xE0, 0x47, 0x9E, 0x5C, 0x04, 0x4B, 0x34, 0x15, 0x79, 0x26, 0xA7, 0xDE, + 0x29, 0xAE, 0x92, 0xD7, 0x84, 0xE9, 0xD2, 0xBA, 0x5D, 0xF3, 0xC5, 0xB0, + 0xBF, 0xA4, 0x3B, 0x71, 0x44, 0x46, 0x2B, 0xFC, 0xEB, 0x6F, 0xD5, 0xF6, + 0x14, 0xFE, 0x7C, 0x70, 0x5A, 0x7D, 0xFD, 0x2F, 0x18, 0x83, 0x16, 0xA5, + 0x91, 0x1F, 0x05, 0x95, 0x74, 0xA9, 0xC1, 0x5B, 0x4A, 0x85, 0x6D, 0x13, + 0x07, 0x4F, 0x4E, 0x45, 0xB2, 0x0F, 0xC9, 0x1C, 0xA6, 0xBC, 0xEC, 0x73, + 0x90, 0x7B, 0xCF, 0x59, 0x8F, 0xA1, 0xF9, 0x2D, 0xF2, 0xB1, 0x00, 0x94, + 0x37, 0x9F, 0xD0, 0x2E, 0x9C, 0x6E, 0x28, 0x3F, 0x80, 0xF0, 0x3D, 0xD3, + 0x25, 0x8A, 0xB5, 0xE7, 0x42, 0xB3, 0xC7, 0xEA, 0xF7, 0x4C, 0x11, 0x33, + 0x03, 0xA2, 0xAC, 0x60 +}; + +/* + * Helper for key schedule: r = FO( p, k ) ^ x + */ +static void aria_fo_xor( uint32_t r[4], const uint32_t p[4], + const uint32_t k[4], const uint32_t x[4] ) +{ + uint32_t a, b, c, d; + + a = p[0] ^ k[0]; + b = p[1] ^ k[1]; + c = p[2] ^ k[2]; + d = p[3] ^ k[3]; + + aria_sl( &a, &b, &c, &d, aria_sb1, aria_sb2, aria_is1, aria_is2 ); + aria_a( &a, &b, &c, &d ); + + r[0] = a ^ x[0]; + r[1] = b ^ x[1]; + r[2] = c ^ x[2]; + r[3] = d ^ x[3]; +} + +/* + * Helper for key schedule: r = FE( p, k ) ^ x + */ +static void aria_fe_xor( uint32_t r[4], const uint32_t p[4], + const uint32_t k[4], const uint32_t x[4] ) +{ + uint32_t a, b, c, d; + + a = p[0] ^ k[0]; + b = p[1] ^ k[1]; + c = p[2] ^ k[2]; + d = p[3] ^ k[3]; + + aria_sl( &a, &b, &c, &d, aria_is1, aria_is2, aria_sb1, aria_sb2 ); + aria_a( &a, &b, &c, &d ); + + r[0] = a ^ x[0]; + r[1] = b ^ x[1]; + r[2] = c ^ x[2]; + r[3] = d ^ x[3]; +} + +/* + * Big endian 128-bit rotation: r = a ^ (b <<< n), used only in key setup. + * + * We chose to store bytes into 32-bit words in little-endian format (see + * GET/PUT_UINT32_LE) so we need to reverse bytes here. + */ +static void aria_rot128( uint32_t r[4], const uint32_t a[4], + const uint32_t b[4], uint8_t n ) +{ + uint8_t i, j; + uint32_t t, u; + + const uint8_t n1 = n % 32; // bit offset + const uint8_t n2 = n1 ? 32 - n1 : 0; // reverse bit offset + + j = ( n / 32 ) % 4; // initial word offset + t = ARIA_P3( b[j] ); // big endian + for( i = 0; i < 4; i++ ) + { + j = ( j + 1 ) % 4; // get next word, big endian + u = ARIA_P3( b[j] ); + t <<= n1; // rotate + t |= u >> n2; + t = ARIA_P3( t ); // back to little endian + r[i] = a[i] ^ t; // store + t = u; // move to next word + } +} + +/* + * Set encryption key + */ +int mbedtls_aria_setkey_enc( mbedtls_aria_context *ctx, + const unsigned char *key, unsigned int keybits ) +{ + /* round constant masks */ + const uint32_t rc[3][4] = + { + { 0xB7C17C51, 0x940A2227, 0xE8AB13FE, 0xE06E9AFA }, + { 0xCC4AB16D, 0x20C8219E, 0xD5B128FF, 0xB0E25DEF }, + { 0x1D3792DB, 0x70E92621, 0x75972403, 0x0EC9E804 } + }; + + int i; + uint32_t w[4][4], *w2; + + if( keybits != 128 && keybits != 192 && keybits != 256 ) + return( MBEDTLS_ERR_ARIA_INVALID_KEY_LENGTH ); + + /* Copy key to W0 (and potential remainder to W1) */ + GET_UINT32_LE( w[0][0], key, 0 ); + GET_UINT32_LE( w[0][1], key, 4 ); + GET_UINT32_LE( w[0][2], key, 8 ); + GET_UINT32_LE( w[0][3], key, 12 ); + + memset( w[1], 0, 16 ); + if( keybits >= 192 ) + { + GET_UINT32_LE( w[1][0], key, 16 ); // 192 bit key + GET_UINT32_LE( w[1][1], key, 20 ); + } + if( keybits == 256 ) + { + GET_UINT32_LE( w[1][2], key, 24 ); // 256 bit key + GET_UINT32_LE( w[1][3], key, 28 ); + } + + i = ( keybits - 128 ) >> 6; // index: 0, 1, 2 + ctx->nr = 12 + 2 * i; // no. rounds: 12, 14, 16 + + aria_fo_xor( w[1], w[0], rc[i], w[1] ); // W1 = FO(W0, CK1) ^ KR + i = i < 2 ? i + 1 : 0; + aria_fe_xor( w[2], w[1], rc[i], w[0] ); // W2 = FE(W1, CK2) ^ W0 + i = i < 2 ? i + 1 : 0; + aria_fo_xor( w[3], w[2], rc[i], w[1] ); // W3 = FO(W2, CK3) ^ W1 + + for( i = 0; i < 4; i++ ) // create round keys + { + w2 = w[(i + 1) & 3]; + aria_rot128( ctx->rk[i ], w[i], w2, 128 - 19 ); + aria_rot128( ctx->rk[i + 4], w[i], w2, 128 - 31 ); + aria_rot128( ctx->rk[i + 8], w[i], w2, 61 ); + aria_rot128( ctx->rk[i + 12], w[i], w2, 31 ); + } + aria_rot128( ctx->rk[16], w[0], w[1], 19 ); + + /* w holds enough info to reconstruct the round keys */ + mbedtls_platform_zeroize( w, sizeof( w ) ); + + return( 0 ); +} + +/* + * Set decryption key + */ +int mbedtls_aria_setkey_dec( mbedtls_aria_context *ctx, + const unsigned char *key, unsigned int keybits ) +{ + int i, j, k, ret; + + ret = mbedtls_aria_setkey_enc( ctx, key, keybits ); + if( ret != 0 ) + return( ret ); + + /* flip the order of round keys */ + for( i = 0, j = ctx->nr; i < j; i++, j-- ) + { + for( k = 0; k < 4; k++ ) + { + uint32_t t = ctx->rk[i][k]; + ctx->rk[i][k] = ctx->rk[j][k]; + ctx->rk[j][k] = t; + } + } + + /* apply affine transform to middle keys */ + for( i = 1; i < ctx->nr; i++ ) + { + aria_a( &ctx->rk[i][0], &ctx->rk[i][1], + &ctx->rk[i][2], &ctx->rk[i][3] ); + } + + return( 0 ); +} + +/* + * Encrypt a block + */ +int mbedtls_aria_crypt_ecb( mbedtls_aria_context *ctx, + const unsigned char input[MBEDTLS_ARIA_BLOCKSIZE], + unsigned char output[MBEDTLS_ARIA_BLOCKSIZE] ) +{ + int i; + + uint32_t a, b, c, d; + + GET_UINT32_LE( a, input, 0 ); + GET_UINT32_LE( b, input, 4 ); + GET_UINT32_LE( c, input, 8 ); + GET_UINT32_LE( d, input, 12 ); + + i = 0; + while( 1 ) + { + a ^= ctx->rk[i][0]; + b ^= ctx->rk[i][1]; + c ^= ctx->rk[i][2]; + d ^= ctx->rk[i][3]; + i++; + + aria_sl( &a, &b, &c, &d, aria_sb1, aria_sb2, aria_is1, aria_is2 ); + aria_a( &a, &b, &c, &d ); + + a ^= ctx->rk[i][0]; + b ^= ctx->rk[i][1]; + c ^= ctx->rk[i][2]; + d ^= ctx->rk[i][3]; + i++; + + aria_sl( &a, &b, &c, &d, aria_is1, aria_is2, aria_sb1, aria_sb2 ); + if( i >= ctx->nr ) + break; + aria_a( &a, &b, &c, &d ); + } + + /* final key mixing */ + a ^= ctx->rk[i][0]; + b ^= ctx->rk[i][1]; + c ^= ctx->rk[i][2]; + d ^= ctx->rk[i][3]; + + PUT_UINT32_LE( a, output, 0 ); + PUT_UINT32_LE( b, output, 4 ); + PUT_UINT32_LE( c, output, 8 ); + PUT_UINT32_LE( d, output, 12 ); + + return( 0 ); +} + +/* Initialize context */ +void mbedtls_aria_init( mbedtls_aria_context *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_aria_context ) ); +} + +/* Clear context */ +void mbedtls_aria_free( mbedtls_aria_context *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_aria_context ) ); +} + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +/* + * ARIA-CBC buffer encryption/decryption + */ +int mbedtls_aria_crypt_cbc( mbedtls_aria_context *ctx, + int mode, + size_t length, + unsigned char iv[MBEDTLS_ARIA_BLOCKSIZE], + const unsigned char *input, + unsigned char *output ) +{ + int i; + unsigned char temp[MBEDTLS_ARIA_BLOCKSIZE]; + + if( length % MBEDTLS_ARIA_BLOCKSIZE ) + return( MBEDTLS_ERR_ARIA_INVALID_INPUT_LENGTH ); + + if( mode == MBEDTLS_ARIA_DECRYPT ) + { + while( length > 0 ) + { + memcpy( temp, input, MBEDTLS_ARIA_BLOCKSIZE ); + mbedtls_aria_crypt_ecb( ctx, input, output ); + + for( i = 0; i < MBEDTLS_ARIA_BLOCKSIZE; i++ ) + output[i] = (unsigned char)( output[i] ^ iv[i] ); + + memcpy( iv, temp, MBEDTLS_ARIA_BLOCKSIZE ); + + input += MBEDTLS_ARIA_BLOCKSIZE; + output += MBEDTLS_ARIA_BLOCKSIZE; + length -= MBEDTLS_ARIA_BLOCKSIZE; + } + } + else + { + while( length > 0 ) + { + for( i = 0; i < MBEDTLS_ARIA_BLOCKSIZE; i++ ) + output[i] = (unsigned char)( input[i] ^ iv[i] ); + + mbedtls_aria_crypt_ecb( ctx, output, output ); + memcpy( iv, output, MBEDTLS_ARIA_BLOCKSIZE ); + + input += MBEDTLS_ARIA_BLOCKSIZE; + output += MBEDTLS_ARIA_BLOCKSIZE; + length -= MBEDTLS_ARIA_BLOCKSIZE; + } + } + + return( 0 ); +} +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) +/* + * ARIA-CFB128 buffer encryption/decryption + */ +int mbedtls_aria_crypt_cfb128( mbedtls_aria_context *ctx, + int mode, + size_t length, + size_t *iv_off, + unsigned char iv[MBEDTLS_ARIA_BLOCKSIZE], + const unsigned char *input, + unsigned char *output ) +{ + unsigned char c; + size_t n = *iv_off; + + if( mode == MBEDTLS_ARIA_DECRYPT ) + { + while( length-- ) + { + if( n == 0 ) + mbedtls_aria_crypt_ecb( ctx, iv, iv ); + + c = *input++; + *output++ = c ^ iv[n]; + iv[n] = c; + + n = ( n + 1 ) & 0x0F; + } + } + else + { + while( length-- ) + { + if( n == 0 ) + mbedtls_aria_crypt_ecb( ctx, iv, iv ); + + iv[n] = *output++ = (unsigned char)( iv[n] ^ *input++ ); + + n = ( n + 1 ) & 0x0F; + } + } + + *iv_off = n; + + return( 0 ); +} +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +/* + * ARIA-CTR buffer encryption/decryption + */ +int mbedtls_aria_crypt_ctr( mbedtls_aria_context *ctx, + size_t length, + size_t *nc_off, + unsigned char nonce_counter[MBEDTLS_ARIA_BLOCKSIZE], + unsigned char stream_block[MBEDTLS_ARIA_BLOCKSIZE], + const unsigned char *input, + unsigned char *output ) +{ + int c, i; + size_t n = *nc_off; + + while( length-- ) + { + if( n == 0 ) { + mbedtls_aria_crypt_ecb( ctx, nonce_counter, + stream_block ); + + for( i = MBEDTLS_ARIA_BLOCKSIZE; i > 0; i-- ) + if( ++nonce_counter[i - 1] != 0 ) + break; + } + c = *input++; + *output++ = (unsigned char)( c ^ stream_block[n] ); + + n = ( n + 1 ) & 0x0F; + } + + *nc_off = n; + + return( 0 ); +} +#endif /* MBEDTLS_CIPHER_MODE_CTR */ +#endif /* !MBEDTLS_ARIA_ALT */ + +#if defined(MBEDTLS_SELF_TEST) + +/* + * Basic ARIA ECB test vectors from RFC 5794 + */ +static const uint8_t aria_test1_ecb_key[32] = // test key +{ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, // 128 bit + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, // 192 bit + 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F // 256 bit +}; + +static const uint8_t aria_test1_ecb_pt[MBEDTLS_ARIA_BLOCKSIZE] = // plaintext +{ + 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, // same for all + 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF // key sizes +}; + +static const uint8_t aria_test1_ecb_ct[3][MBEDTLS_ARIA_BLOCKSIZE] = // ciphertext +{ + { 0xD7, 0x18, 0xFB, 0xD6, 0xAB, 0x64, 0x4C, 0x73, // 128 bit + 0x9D, 0xA9, 0x5F, 0x3B, 0xE6, 0x45, 0x17, 0x78 }, + { 0x26, 0x44, 0x9C, 0x18, 0x05, 0xDB, 0xE7, 0xAA, // 192 bit + 0x25, 0xA4, 0x68, 0xCE, 0x26, 0x3A, 0x9E, 0x79 }, + { 0xF9, 0x2B, 0xD7, 0xC7, 0x9F, 0xB7, 0x2E, 0x2F, // 256 bit + 0x2B, 0x8F, 0x80, 0xC1, 0x97, 0x2D, 0x24, 0xFC } +}; + +/* + * Mode tests from "Test Vectors for ARIA" Version 1.0 + * http://210.104.33.10/ARIA/doc/ARIA-testvector-e.pdf + */ +#if (defined(MBEDTLS_CIPHER_MODE_CBC) || defined(MBEDTLS_CIPHER_MODE_CFB) || \ + defined(MBEDTLS_CIPHER_MODE_CTR)) +static const uint8_t aria_test2_key[32] = +{ + 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, // 128 bit + 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, + 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, // 192 bit + 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff // 256 bit +}; + +static const uint8_t aria_test2_pt[48] = +{ + 0x11, 0x11, 0x11, 0x11, 0xaa, 0xaa, 0xaa, 0xaa, // same for all + 0x11, 0x11, 0x11, 0x11, 0xbb, 0xbb, 0xbb, 0xbb, + 0x11, 0x11, 0x11, 0x11, 0xcc, 0xcc, 0xcc, 0xcc, + 0x11, 0x11, 0x11, 0x11, 0xdd, 0xdd, 0xdd, 0xdd, + 0x22, 0x22, 0x22, 0x22, 0xaa, 0xaa, 0xaa, 0xaa, + 0x22, 0x22, 0x22, 0x22, 0xbb, 0xbb, 0xbb, 0xbb, +}; +#endif + +#if (defined(MBEDTLS_CIPHER_MODE_CBC) || defined(MBEDTLS_CIPHER_MODE_CFB)) +static const uint8_t aria_test2_iv[MBEDTLS_ARIA_BLOCKSIZE] = +{ + 0x0f, 0x1e, 0x2d, 0x3c, 0x4b, 0x5a, 0x69, 0x78, // same for CBC, CFB + 0x87, 0x96, 0xa5, 0xb4, 0xc3, 0xd2, 0xe1, 0xf0 // CTR has zero IV +}; +#endif + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +static const uint8_t aria_test2_cbc_ct[3][48] = // CBC ciphertext +{ + { 0x49, 0xd6, 0x18, 0x60, 0xb1, 0x49, 0x09, 0x10, // 128-bit key + 0x9c, 0xef, 0x0d, 0x22, 0xa9, 0x26, 0x81, 0x34, + 0xfa, 0xdf, 0x9f, 0xb2, 0x31, 0x51, 0xe9, 0x64, + 0x5f, 0xba, 0x75, 0x01, 0x8b, 0xdb, 0x15, 0x38, + 0xb5, 0x33, 0x34, 0x63, 0x4b, 0xbf, 0x7d, 0x4c, + 0xd4, 0xb5, 0x37, 0x70, 0x33, 0x06, 0x0c, 0x15 }, + { 0xaf, 0xe6, 0xcf, 0x23, 0x97, 0x4b, 0x53, 0x3c, // 192-bit key + 0x67, 0x2a, 0x82, 0x62, 0x64, 0xea, 0x78, 0x5f, + 0x4e, 0x4f, 0x7f, 0x78, 0x0d, 0xc7, 0xf3, 0xf1, + 0xe0, 0x96, 0x2b, 0x80, 0x90, 0x23, 0x86, 0xd5, + 0x14, 0xe9, 0xc3, 0xe7, 0x72, 0x59, 0xde, 0x92, + 0xdd, 0x11, 0x02, 0xff, 0xab, 0x08, 0x6c, 0x1e }, + { 0x52, 0x3a, 0x8a, 0x80, 0x6a, 0xe6, 0x21, 0xf1, // 256-bit key + 0x55, 0xfd, 0xd2, 0x8d, 0xbc, 0x34, 0xe1, 0xab, + 0x7b, 0x9b, 0x42, 0x43, 0x2a, 0xd8, 0xb2, 0xef, + 0xb9, 0x6e, 0x23, 0xb1, 0x3f, 0x0a, 0x6e, 0x52, + 0xf3, 0x61, 0x85, 0xd5, 0x0a, 0xd0, 0x02, 0xc5, + 0xf6, 0x01, 0xbe, 0xe5, 0x49, 0x3f, 0x11, 0x8b } +}; +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) +static const uint8_t aria_test2_cfb_ct[3][48] = // CFB ciphertext +{ + { 0x37, 0x20, 0xe5, 0x3b, 0xa7, 0xd6, 0x15, 0x38, // 128-bit key + 0x34, 0x06, 0xb0, 0x9f, 0x0a, 0x05, 0xa2, 0x00, + 0xc0, 0x7c, 0x21, 0xe6, 0x37, 0x0f, 0x41, 0x3a, + 0x5d, 0x13, 0x25, 0x00, 0xa6, 0x82, 0x85, 0x01, + 0x7c, 0x61, 0xb4, 0x34, 0xc7, 0xb7, 0xca, 0x96, + 0x85, 0xa5, 0x10, 0x71, 0x86, 0x1e, 0x4d, 0x4b }, + { 0x41, 0x71, 0xf7, 0x19, 0x2b, 0xf4, 0x49, 0x54, // 192-bit key + 0x94, 0xd2, 0x73, 0x61, 0x29, 0x64, 0x0f, 0x5c, + 0x4d, 0x87, 0xa9, 0xa2, 0x13, 0x66, 0x4c, 0x94, + 0x48, 0x47, 0x7c, 0x6e, 0xcc, 0x20, 0x13, 0x59, + 0x8d, 0x97, 0x66, 0x95, 0x2d, 0xd8, 0xc3, 0x86, + 0x8f, 0x17, 0xe3, 0x6e, 0xf6, 0x6f, 0xd8, 0x4b }, + { 0x26, 0x83, 0x47, 0x05, 0xb0, 0xf2, 0xc0, 0xe2, // 256-bit key + 0x58, 0x8d, 0x4a, 0x7f, 0x09, 0x00, 0x96, 0x35, + 0xf2, 0x8b, 0xb9, 0x3d, 0x8c, 0x31, 0xf8, 0x70, + 0xec, 0x1e, 0x0b, 0xdb, 0x08, 0x2b, 0x66, 0xfa, + 0x40, 0x2d, 0xd9, 0xc2, 0x02, 0xbe, 0x30, 0x0c, + 0x45, 0x17, 0xd1, 0x96, 0xb1, 0x4d, 0x4c, 0xe1 } +}; +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +static const uint8_t aria_test2_ctr_ct[3][48] = // CTR ciphertext +{ + { 0xac, 0x5d, 0x7d, 0xe8, 0x05, 0xa0, 0xbf, 0x1c, // 128-bit key + 0x57, 0xc8, 0x54, 0x50, 0x1a, 0xf6, 0x0f, 0xa1, + 0x14, 0x97, 0xe2, 0xa3, 0x45, 0x19, 0xde, 0xa1, + 0x56, 0x9e, 0x91, 0xe5, 0xb5, 0xcc, 0xae, 0x2f, + 0xf3, 0xbf, 0xa1, 0xbf, 0x97, 0x5f, 0x45, 0x71, + 0xf4, 0x8b, 0xe1, 0x91, 0x61, 0x35, 0x46, 0xc3 }, + { 0x08, 0x62, 0x5c, 0xa8, 0xfe, 0x56, 0x9c, 0x19, // 192-bit key + 0xba, 0x7a, 0xf3, 0x76, 0x0a, 0x6e, 0xd1, 0xce, + 0xf4, 0xd1, 0x99, 0x26, 0x3e, 0x99, 0x9d, 0xde, + 0x14, 0x08, 0x2d, 0xbb, 0xa7, 0x56, 0x0b, 0x79, + 0xa4, 0xc6, 0xb4, 0x56, 0xb8, 0x70, 0x7d, 0xce, + 0x75, 0x1f, 0x98, 0x54, 0xf1, 0x88, 0x93, 0xdf }, + { 0x30, 0x02, 0x6c, 0x32, 0x96, 0x66, 0x14, 0x17, // 256-bit key + 0x21, 0x17, 0x8b, 0x99, 0xc0, 0xa1, 0xf1, 0xb2, + 0xf0, 0x69, 0x40, 0x25, 0x3f, 0x7b, 0x30, 0x89, + 0xe2, 0xa3, 0x0e, 0xa8, 0x6a, 0xa3, 0xc8, 0x8f, + 0x59, 0x40, 0xf0, 0x5a, 0xd7, 0xee, 0x41, 0xd7, + 0x13, 0x47, 0xbb, 0x72, 0x61, 0xe3, 0x48, 0xf1 } +}; +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#define ARIA_SELF_TEST_IF_FAIL \ + { \ + if( verbose ) \ + printf( "failed\n" ); \ + return( 1 ); \ + } else { \ + if( verbose ) \ + printf( "passed\n" ); \ + } + +/* + * Checkup routine + */ +int mbedtls_aria_self_test( int verbose ) +{ + int i; + uint8_t blk[MBEDTLS_ARIA_BLOCKSIZE]; + mbedtls_aria_context ctx; + +#if (defined(MBEDTLS_CIPHER_MODE_CFB) || defined(MBEDTLS_CIPHER_MODE_CTR)) + size_t j; +#endif + +#if (defined(MBEDTLS_CIPHER_MODE_CBC) || \ + defined(MBEDTLS_CIPHER_MODE_CFB) || \ + defined(MBEDTLS_CIPHER_MODE_CTR)) + uint8_t buf[48], iv[MBEDTLS_ARIA_BLOCKSIZE]; +#endif + + /* + * Test set 1 + */ + for( i = 0; i < 3; i++ ) + { + /* test ECB encryption */ + if( verbose ) + printf( " ARIA-ECB-%d (enc): ", 128 + 64 * i ); + mbedtls_aria_setkey_enc( &ctx, aria_test1_ecb_key, 128 + 64 * i ); + mbedtls_aria_crypt_ecb( &ctx, aria_test1_ecb_pt, blk ); + if( memcmp( blk, aria_test1_ecb_ct[i], MBEDTLS_ARIA_BLOCKSIZE ) != 0 ) + ARIA_SELF_TEST_IF_FAIL; + + /* test ECB decryption */ + if( verbose ) + printf( " ARIA-ECB-%d (dec): ", 128 + 64 * i ); + mbedtls_aria_setkey_dec( &ctx, aria_test1_ecb_key, 128 + 64 * i ); + mbedtls_aria_crypt_ecb( &ctx, aria_test1_ecb_ct[i], blk ); + if( memcmp( blk, aria_test1_ecb_pt, MBEDTLS_ARIA_BLOCKSIZE ) != 0 ) + ARIA_SELF_TEST_IF_FAIL; + } + if( verbose ) + printf( "\n" ); + + /* + * Test set 2 + */ +#if defined(MBEDTLS_CIPHER_MODE_CBC) + for( i = 0; i < 3; i++ ) + { + /* Test CBC encryption */ + if( verbose ) + printf( " ARIA-CBC-%d (enc): ", 128 + 64 * i ); + mbedtls_aria_setkey_enc( &ctx, aria_test2_key, 128 + 64 * i ); + memcpy( iv, aria_test2_iv, MBEDTLS_ARIA_BLOCKSIZE ); + memset( buf, 0x55, sizeof( buf ) ); + mbedtls_aria_crypt_cbc( &ctx, MBEDTLS_ARIA_ENCRYPT, 48, iv, + aria_test2_pt, buf ); + if( memcmp( buf, aria_test2_cbc_ct[i], 48 ) != 0 ) + ARIA_SELF_TEST_IF_FAIL; + + /* Test CBC decryption */ + if( verbose ) + printf( " ARIA-CBC-%d (dec): ", 128 + 64 * i ); + mbedtls_aria_setkey_dec( &ctx, aria_test2_key, 128 + 64 * i ); + memcpy( iv, aria_test2_iv, MBEDTLS_ARIA_BLOCKSIZE ); + memset( buf, 0xAA, sizeof( buf ) ); + mbedtls_aria_crypt_cbc( &ctx, MBEDTLS_ARIA_DECRYPT, 48, iv, + aria_test2_cbc_ct[i], buf ); + if( memcmp( buf, aria_test2_pt, 48 ) != 0 ) + ARIA_SELF_TEST_IF_FAIL; + } + if( verbose ) + printf( "\n" ); + +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) + for( i = 0; i < 3; i++ ) + { + /* Test CFB encryption */ + if( verbose ) + printf( " ARIA-CFB-%d (enc): ", 128 + 64 * i ); + mbedtls_aria_setkey_enc( &ctx, aria_test2_key, 128 + 64 * i ); + memcpy( iv, aria_test2_iv, MBEDTLS_ARIA_BLOCKSIZE ); + memset( buf, 0x55, sizeof( buf ) ); + j = 0; + mbedtls_aria_crypt_cfb128( &ctx, MBEDTLS_ARIA_ENCRYPT, 48, &j, iv, + aria_test2_pt, buf ); + if( memcmp( buf, aria_test2_cfb_ct[i], 48 ) != 0 ) + ARIA_SELF_TEST_IF_FAIL; + + /* Test CFB decryption */ + if( verbose ) + printf( " ARIA-CFB-%d (dec): ", 128 + 64 * i ); + mbedtls_aria_setkey_enc( &ctx, aria_test2_key, 128 + 64 * i ); + memcpy( iv, aria_test2_iv, MBEDTLS_ARIA_BLOCKSIZE ); + memset( buf, 0xAA, sizeof( buf ) ); + j = 0; + mbedtls_aria_crypt_cfb128( &ctx, MBEDTLS_ARIA_DECRYPT, 48, &j, + iv, aria_test2_cfb_ct[i], buf ); + if( memcmp( buf, aria_test2_pt, 48 ) != 0 ) + ARIA_SELF_TEST_IF_FAIL; + } + if( verbose ) + printf( "\n" ); +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) + for( i = 0; i < 3; i++ ) + { + /* Test CTR encryption */ + if( verbose ) + printf( " ARIA-CTR-%d (enc): ", 128 + 64 * i ); + mbedtls_aria_setkey_enc( &ctx, aria_test2_key, 128 + 64 * i ); + memset( iv, 0, MBEDTLS_ARIA_BLOCKSIZE ); // IV = 0 + memset( buf, 0x55, sizeof( buf ) ); + j = 0; + mbedtls_aria_crypt_ctr( &ctx, 48, &j, iv, blk, + aria_test2_pt, buf ); + if( memcmp( buf, aria_test2_ctr_ct[i], 48 ) != 0 ) + ARIA_SELF_TEST_IF_FAIL; + + /* Test CTR decryption */ + if( verbose ) + printf( " ARIA-CTR-%d (dec): ", 128 + 64 * i ); + mbedtls_aria_setkey_enc( &ctx, aria_test2_key, 128 + 64 * i ); + memset( iv, 0, MBEDTLS_ARIA_BLOCKSIZE ); // IV = 0 + memset( buf, 0xAA, sizeof( buf ) ); + j = 0; + mbedtls_aria_crypt_ctr( &ctx, 48, &j, iv, blk, + aria_test2_ctr_ct[i], buf ); + if( memcmp( buf, aria_test2_pt, 48 ) != 0 ) + ARIA_SELF_TEST_IF_FAIL; + } + if( verbose ) + printf( "\n" ); +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + + return( 0 ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_ARIA_C */ diff --git a/thirdparty/mbedtls/library/asn1parse.c b/thirdparty/mbedtls/library/asn1parse.c index 4dd65c03c0..171c340b8c 100644 --- a/thirdparty/mbedtls/library/asn1parse.c +++ b/thirdparty/mbedtls/library/asn1parse.c @@ -28,6 +28,7 @@ #if defined(MBEDTLS_ASN1_PARSE_C) #include "mbedtls/asn1.h" +#include "mbedtls/platform_util.h" #include <string.h> @@ -43,11 +44,6 @@ #define mbedtls_free free #endif -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize( void *v, size_t n ) { - volatile unsigned char *p = (unsigned char*)v; while( n-- ) *p++ = 0; -} - /* * ASN.1 DER decoding routines */ @@ -313,7 +309,7 @@ int mbedtls_asn1_get_alg( unsigned char **p, if( *p == end ) { - mbedtls_zeroize( params, sizeof(mbedtls_asn1_buf) ); + mbedtls_platform_zeroize( params, sizeof(mbedtls_asn1_buf) ); return( 0 ); } @@ -358,7 +354,7 @@ void mbedtls_asn1_free_named_data( mbedtls_asn1_named_data *cur ) mbedtls_free( cur->oid.p ); mbedtls_free( cur->val.p ); - mbedtls_zeroize( cur, sizeof( mbedtls_asn1_named_data ) ); + mbedtls_platform_zeroize( cur, sizeof( mbedtls_asn1_named_data ) ); } void mbedtls_asn1_free_named_data_list( mbedtls_asn1_named_data **head ) diff --git a/thirdparty/mbedtls/library/asn1write.c b/thirdparty/mbedtls/library/asn1write.c index 69b61b205f..72acdf3012 100644 --- a/thirdparty/mbedtls/library/asn1write.c +++ b/thirdparty/mbedtls/library/asn1write.c @@ -83,7 +83,9 @@ int mbedtls_asn1_write_len( unsigned char **p, unsigned char *start, size_t len return( 4 ); } +#if SIZE_MAX > 0xFFFFFFFF if( len <= 0xFFFFFFFF ) +#endif { if( *p - start < 5 ) return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); @@ -96,7 +98,9 @@ int mbedtls_asn1_write_len( unsigned char **p, unsigned char *start, size_t len return( 5 ); } +#if SIZE_MAX > 0xFFFFFFFF return( MBEDTLS_ERR_ASN1_INVALID_LENGTH ); +#endif } int mbedtls_asn1_write_tag( unsigned char **p, unsigned char *start, unsigned char tag ) @@ -232,10 +236,6 @@ int mbedtls_asn1_write_int( unsigned char **p, unsigned char *start, int val ) int ret; size_t len = 0; - // TODO negative values and values larger than 128 - // DER format assumes 2s complement for numbers, so the leftmost bit - // should be 0 for positive numbers and 1 for negative numbers. - // if( *p - start < 1 ) return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); diff --git a/thirdparty/mbedtls/library/bignum.c b/thirdparty/mbedtls/library/bignum.c index 9f13da4421..423e375fd1 100644 --- a/thirdparty/mbedtls/library/bignum.c +++ b/thirdparty/mbedtls/library/bignum.c @@ -45,6 +45,7 @@ #include "mbedtls/bignum.h" #include "mbedtls/bn_mul.h" +#include "mbedtls/platform_util.h" #include <string.h> @@ -58,16 +59,6 @@ #define mbedtls_free free #endif -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_mpi_zeroize( mbedtls_mpi_uint *v, size_t n ) { - volatile mbedtls_mpi_uint *p = v; while( n-- ) *p++ = 0; -} - -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize( void *v, size_t n ) { - volatile unsigned char *p = v; while( n-- ) *p++ = 0; -} - #define ciL (sizeof(mbedtls_mpi_uint)) /* chars in limb */ #define biL (ciL << 3) /* bits in limb */ #define biH (ciL << 2) /* half limb size */ @@ -81,6 +72,12 @@ static void mbedtls_zeroize( void *v, size_t n ) { #define BITS_TO_LIMBS(i) ( (i) / biL + ( (i) % biL != 0 ) ) #define CHARS_TO_LIMBS(i) ( (i) / ciL + ( (i) % ciL != 0 ) ) +/* Implementation that should never be optimized out by the compiler */ +static void mbedtls_mpi_zeroize( mbedtls_mpi_uint *v, size_t n ) +{ + mbedtls_platform_zeroize( v, ciL * n ); +} + /* * Initialize one MPI */ @@ -184,7 +181,7 @@ int mbedtls_mpi_shrink( mbedtls_mpi *X, size_t nblimbs ) */ int mbedtls_mpi_copy( mbedtls_mpi *X, const mbedtls_mpi *Y ) { - int ret; + int ret = 0; size_t i; if( X == Y ) @@ -203,9 +200,15 @@ int mbedtls_mpi_copy( mbedtls_mpi *X, const mbedtls_mpi *Y ) X->s = Y->s; - MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i ) ); + if( X->n < i ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i ) ); + } + else + { + memset( X->p + i, 0, ( X->n - i ) * ciL ); + } - memset( X->p, 0, X->n * ciL ); memcpy( X->p, Y->p, i * ciL ); cleanup: @@ -963,7 +966,7 @@ static void mpi_sub_hlp( size_t n, mbedtls_mpi_uint *s, mbedtls_mpi_uint *d ) while( c != 0 ) { z = ( *d < c ); *d -= c; - c = z; i++; d++; + c = z; d++; } } @@ -1201,8 +1204,8 @@ int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + j ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) ); - for( i++; j > 0; j-- ) - mpi_mul_hlp( i - 1, A->p, X->p + j - 1, B->p[j - 1] ); + for( ; j > 0; j-- ) + mpi_mul_hlp( i, A->p, X->p + j - 1, B->p[j - 1] ); X->s = A->s * B->s; @@ -1891,7 +1894,7 @@ int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size, MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( X, buf, size ) ); cleanup: - mbedtls_zeroize( buf, sizeof( buf ) ); + mbedtls_platform_zeroize( buf, sizeof( buf ) ); return( ret ); } @@ -2188,12 +2191,23 @@ int mbedtls_mpi_is_prime( const mbedtls_mpi *X, /* * Prime number generation + * + * If dh_flag is 0 and nbits is at least 1024, then the procedure + * follows the RSA probably-prime generation method of FIPS 186-4. + * NB. FIPS 186-4 only allows the specific bit lengths of 1024 and 1536. */ int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int dh_flag, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) { - int ret; +#ifdef MBEDTLS_HAVE_INT64 +// ceil(2^63.5) +#define CEIL_MAXUINT_DIV_SQRT2 0xb504f333f9de6485ULL +#else +// ceil(2^31.5) +#define CEIL_MAXUINT_DIV_SQRT2 0xb504f334U +#endif + int ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE; size_t k, n; mbedtls_mpi_uint r; mbedtls_mpi Y; @@ -2205,69 +2219,66 @@ int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int dh_flag, n = BITS_TO_LIMBS( nbits ); - MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( X, n * ciL, f_rng, p_rng ) ); - - k = mbedtls_mpi_bitlen( X ); - if( k > nbits ) MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, k - nbits + 1 ) ); - - mbedtls_mpi_set_bit( X, nbits-1, 1 ); + while( 1 ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( X, n * ciL, f_rng, p_rng ) ); + /* make sure generated number is at least (nbits-1)+0.5 bits (FIPS 186-4 §B.3.3 steps 4.4, 5.5) */ + if( X->p[n-1] < CEIL_MAXUINT_DIV_SQRT2 ) continue; - X->p[0] |= 1; + k = n * biL; + if( k > nbits ) MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, k - nbits ) ); + X->p[0] |= 1; - if( dh_flag == 0 ) - { - while( ( ret = mbedtls_mpi_is_prime( X, f_rng, p_rng ) ) != 0 ) + if( dh_flag == 0 ) { + ret = mbedtls_mpi_is_prime( X, f_rng, p_rng ); + if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ) goto cleanup; - - MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 2 ) ); } - } - else - { - /* - * An necessary condition for Y and X = 2Y + 1 to be prime - * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3). - * Make sure it is satisfied, while keeping X = 3 mod 4 - */ + else + { + /* + * An necessary condition for Y and X = 2Y + 1 to be prime + * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3). + * Make sure it is satisfied, while keeping X = 3 mod 4 + */ - X->p[0] |= 2; + X->p[0] |= 2; - MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, 3 ) ); - if( r == 0 ) - MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 8 ) ); - else if( r == 1 ) - MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 4 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, 3 ) ); + if( r == 0 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 8 ) ); + else if( r == 1 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 4 ) ); - /* Set Y = (X-1) / 2, which is X / 2 because X is odd */ - MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, X ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, 1 ) ); + /* Set Y = (X-1) / 2, which is X / 2 because X is odd */ + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, X ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, 1 ) ); - while( 1 ) - { - /* - * First, check small factors for X and Y - * before doing Miller-Rabin on any of them - */ - if( ( ret = mpi_check_small_factors( X ) ) == 0 && - ( ret = mpi_check_small_factors( &Y ) ) == 0 && - ( ret = mpi_miller_rabin( X, f_rng, p_rng ) ) == 0 && - ( ret = mpi_miller_rabin( &Y, f_rng, p_rng ) ) == 0 ) + while( 1 ) { - break; + /* + * First, check small factors for X and Y + * before doing Miller-Rabin on any of them + */ + if( ( ret = mpi_check_small_factors( X ) ) == 0 && + ( ret = mpi_check_small_factors( &Y ) ) == 0 && + ( ret = mpi_miller_rabin( X, f_rng, p_rng ) ) == 0 && + ( ret = mpi_miller_rabin( &Y, f_rng, p_rng ) ) == 0 ) + goto cleanup; + + if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ) + goto cleanup; + + /* + * Next candidates. We want to preserve Y = (X-1) / 2 and + * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3) + * so up Y by 6 and X by 12. + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 12 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &Y, &Y, 6 ) ); } - - if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ) - goto cleanup; - - /* - * Next candidates. We want to preserve Y = (X-1) / 2 and - * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3) - * so up Y by 6 and X by 12. - */ - MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 12 ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &Y, &Y, 6 ) ); } } diff --git a/thirdparty/mbedtls/library/blowfish.c b/thirdparty/mbedtls/library/blowfish.c index 9003f0dfeb..5b6bb9885f 100644 --- a/thirdparty/mbedtls/library/blowfish.c +++ b/thirdparty/mbedtls/library/blowfish.c @@ -34,16 +34,12 @@ #if defined(MBEDTLS_BLOWFISH_C) #include "mbedtls/blowfish.h" +#include "mbedtls/platform_util.h" #include <string.h> #if !defined(MBEDTLS_BLOWFISH_ALT) -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize( void *v, size_t n ) { - volatile unsigned char *p = (unsigned char*)v; while( n-- ) *p++ = 0; -} - /* * 32-bit integer manipulation macros (big endian) */ @@ -165,7 +161,7 @@ void mbedtls_blowfish_free( mbedtls_blowfish_context *ctx ) if( ctx == NULL ) return; - mbedtls_zeroize( ctx, sizeof( mbedtls_blowfish_context ) ); + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_blowfish_context ) ); } /* diff --git a/thirdparty/mbedtls/library/camellia.c b/thirdparty/mbedtls/library/camellia.c index ac6f96a83a..41b7da0fae 100644 --- a/thirdparty/mbedtls/library/camellia.c +++ b/thirdparty/mbedtls/library/camellia.c @@ -34,6 +34,7 @@ #if defined(MBEDTLS_CAMELLIA_C) #include "mbedtls/camellia.h" +#include "mbedtls/platform_util.h" #include <string.h> @@ -48,11 +49,6 @@ #if !defined(MBEDTLS_CAMELLIA_ALT) -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize( void *v, size_t n ) { - volatile unsigned char *p = (unsigned char*)v; while( n-- ) *p++ = 0; -} - /* * 32-bit integer manipulation macros (big endian) */ @@ -333,7 +329,7 @@ void mbedtls_camellia_free( mbedtls_camellia_context *ctx ) if( ctx == NULL ) return; - mbedtls_zeroize( ctx, sizeof( mbedtls_camellia_context ) ); + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_camellia_context ) ); } /* diff --git a/thirdparty/mbedtls/library/ccm.c b/thirdparty/mbedtls/library/ccm.c index 9101e5f7c7..804eaf80f1 100644 --- a/thirdparty/mbedtls/library/ccm.c +++ b/thirdparty/mbedtls/library/ccm.c @@ -37,6 +37,7 @@ #if defined(MBEDTLS_CCM_C) #include "mbedtls/ccm.h" +#include "mbedtls/platform_util.h" #include <string.h> @@ -51,11 +52,6 @@ #if !defined(MBEDTLS_CCM_ALT) -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize( void *v, size_t n ) { - volatile unsigned char *p = (unsigned char*)v; while( n-- ) *p++ = 0; -} - #define CCM_ENCRYPT 0 #define CCM_DECRYPT 1 @@ -102,7 +98,7 @@ int mbedtls_ccm_setkey( mbedtls_ccm_context *ctx, void mbedtls_ccm_free( mbedtls_ccm_context *ctx ) { mbedtls_cipher_free( &ctx->cipher_ctx ); - mbedtls_zeroize( ctx, sizeof( mbedtls_ccm_context ) ); + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_ccm_context ) ); } /* @@ -156,8 +152,10 @@ static int ccm_auth_crypt( mbedtls_ccm_context *ctx, int mode, size_t length, * Check length requirements: SP800-38C A.1 * Additional requirement: a < 2^16 - 2^8 to simplify the code. * 'length' checked later (when writing it to the first block) + * + * Also, loosen the requirements to enable support for CCM* (IEEE 802.15.4). */ - if( tag_len < 4 || tag_len > 16 || tag_len % 2 != 0 ) + if( tag_len == 2 || tag_len > 16 || tag_len % 2 != 0 ) return( MBEDTLS_ERR_CCM_BAD_INPUT ); /* Also implies q is within bounds */ @@ -306,7 +304,7 @@ static int ccm_auth_crypt( mbedtls_ccm_context *ctx, int mode, size_t length, /* * Authenticated encryption */ -int mbedtls_ccm_encrypt_and_tag( mbedtls_ccm_context *ctx, size_t length, +int mbedtls_ccm_star_encrypt_and_tag( mbedtls_ccm_context *ctx, size_t length, const unsigned char *iv, size_t iv_len, const unsigned char *add, size_t add_len, const unsigned char *input, unsigned char *output, @@ -316,10 +314,23 @@ int mbedtls_ccm_encrypt_and_tag( mbedtls_ccm_context *ctx, size_t length, add, add_len, input, output, tag, tag_len ) ); } +int mbedtls_ccm_encrypt_and_tag( mbedtls_ccm_context *ctx, size_t length, + const unsigned char *iv, size_t iv_len, + const unsigned char *add, size_t add_len, + const unsigned char *input, unsigned char *output, + unsigned char *tag, size_t tag_len ) +{ + if( tag_len == 0 ) + return( MBEDTLS_ERR_CCM_BAD_INPUT ); + + return( mbedtls_ccm_star_encrypt_and_tag( ctx, length, iv, iv_len, add, + add_len, input, output, tag, tag_len ) ); +} + /* * Authenticated decryption */ -int mbedtls_ccm_auth_decrypt( mbedtls_ccm_context *ctx, size_t length, +int mbedtls_ccm_star_auth_decrypt( mbedtls_ccm_context *ctx, size_t length, const unsigned char *iv, size_t iv_len, const unsigned char *add, size_t add_len, const unsigned char *input, unsigned char *output, @@ -343,13 +354,25 @@ int mbedtls_ccm_auth_decrypt( mbedtls_ccm_context *ctx, size_t length, if( diff != 0 ) { - mbedtls_zeroize( output, length ); + mbedtls_platform_zeroize( output, length ); return( MBEDTLS_ERR_CCM_AUTH_FAILED ); } return( 0 ); } +int mbedtls_ccm_auth_decrypt( mbedtls_ccm_context *ctx, size_t length, + const unsigned char *iv, size_t iv_len, + const unsigned char *add, size_t add_len, + const unsigned char *input, unsigned char *output, + const unsigned char *tag, size_t tag_len ) +{ + if( tag_len == 0 ) + return( MBEDTLS_ERR_CCM_BAD_INPUT ); + + return( mbedtls_ccm_star_auth_decrypt( ctx, length, iv, iv_len, add, + add_len, input, output, tag, tag_len ) ); +} #endif /* !MBEDTLS_CCM_ALT */ #if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C) diff --git a/thirdparty/mbedtls/library/chacha20.c b/thirdparty/mbedtls/library/chacha20.c new file mode 100644 index 0000000000..d14a51e044 --- /dev/null +++ b/thirdparty/mbedtls/library/chacha20.c @@ -0,0 +1,570 @@ +/** + * \file chacha20.c + * + * \brief ChaCha20 cipher. + * + * \author Daniel King <damaki.gh@gmail.com> + * + * Copyright (C) 2006-2016, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_CHACHA20_C) + +#include "mbedtls/chacha20.h" +#include "mbedtls/platform_util.h" + +#include <stddef.h> +#include <string.h> + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include <stdio.h> +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +#if !defined(MBEDTLS_CHACHA20_ALT) + +#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ + !defined(inline) && !defined(__cplusplus) +#define inline __inline +#endif + +#define BYTES_TO_U32_LE( data, offset ) \ + ( (uint32_t) data[offset] \ + | (uint32_t) ( (uint32_t) data[( offset ) + 1] << 8 ) \ + | (uint32_t) ( (uint32_t) data[( offset ) + 2] << 16 ) \ + | (uint32_t) ( (uint32_t) data[( offset ) + 3] << 24 ) \ + ) + +#define ROTL32( value, amount ) \ + ( (uint32_t) ( value << amount ) | ( value >> ( 32 - amount ) ) ) + +#define CHACHA20_CTR_INDEX ( 12U ) + +#define CHACHA20_BLOCK_SIZE_BYTES ( 4U * 16U ) + +/** + * \brief ChaCha20 quarter round operation. + * + * The quarter round is defined as follows (from RFC 7539): + * 1. a += b; d ^= a; d <<<= 16; + * 2. c += d; b ^= c; b <<<= 12; + * 3. a += b; d ^= a; d <<<= 8; + * 4. c += d; b ^= c; b <<<= 7; + * + * \param state ChaCha20 state to modify. + * \param a The index of 'a' in the state. + * \param b The index of 'b' in the state. + * \param c The index of 'c' in the state. + * \param d The index of 'd' in the state. + */ +static inline void chacha20_quarter_round( uint32_t state[16], + size_t a, + size_t b, + size_t c, + size_t d ) +{ + /* a += b; d ^= a; d <<<= 16; */ + state[a] += state[b]; + state[d] ^= state[a]; + state[d] = ROTL32( state[d], 16 ); + + /* c += d; b ^= c; b <<<= 12 */ + state[c] += state[d]; + state[b] ^= state[c]; + state[b] = ROTL32( state[b], 12 ); + + /* a += b; d ^= a; d <<<= 8; */ + state[a] += state[b]; + state[d] ^= state[a]; + state[d] = ROTL32( state[d], 8 ); + + /* c += d; b ^= c; b <<<= 7; */ + state[c] += state[d]; + state[b] ^= state[c]; + state[b] = ROTL32( state[b], 7 ); +} + +/** + * \brief Perform the ChaCha20 inner block operation. + * + * This function performs two rounds: the column round and the + * diagonal round. + * + * \param state The ChaCha20 state to update. + */ +static void chacha20_inner_block( uint32_t state[16] ) +{ + chacha20_quarter_round( state, 0, 4, 8, 12 ); + chacha20_quarter_round( state, 1, 5, 9, 13 ); + chacha20_quarter_round( state, 2, 6, 10, 14 ); + chacha20_quarter_round( state, 3, 7, 11, 15 ); + + chacha20_quarter_round( state, 0, 5, 10, 15 ); + chacha20_quarter_round( state, 1, 6, 11, 12 ); + chacha20_quarter_round( state, 2, 7, 8, 13 ); + chacha20_quarter_round( state, 3, 4, 9, 14 ); +} + +/** + * \brief Generates a keystream block. + * + * \param initial_state The initial ChaCha20 state (key, nonce, counter). + * \param keystream Generated keystream bytes are written to this buffer. + */ +static void chacha20_block( const uint32_t initial_state[16], + unsigned char keystream[64] ) +{ + uint32_t working_state[16]; + size_t i; + + memcpy( working_state, + initial_state, + CHACHA20_BLOCK_SIZE_BYTES ); + + for( i = 0U; i < 10U; i++ ) + chacha20_inner_block( working_state ); + + working_state[ 0] += initial_state[ 0]; + working_state[ 1] += initial_state[ 1]; + working_state[ 2] += initial_state[ 2]; + working_state[ 3] += initial_state[ 3]; + working_state[ 4] += initial_state[ 4]; + working_state[ 5] += initial_state[ 5]; + working_state[ 6] += initial_state[ 6]; + working_state[ 7] += initial_state[ 7]; + working_state[ 8] += initial_state[ 8]; + working_state[ 9] += initial_state[ 9]; + working_state[10] += initial_state[10]; + working_state[11] += initial_state[11]; + working_state[12] += initial_state[12]; + working_state[13] += initial_state[13]; + working_state[14] += initial_state[14]; + working_state[15] += initial_state[15]; + + for( i = 0U; i < 16; i++ ) + { + size_t offset = i * 4U; + + keystream[offset ] = (unsigned char)( working_state[i] ); + keystream[offset + 1U] = (unsigned char)( working_state[i] >> 8 ); + keystream[offset + 2U] = (unsigned char)( working_state[i] >> 16 ); + keystream[offset + 3U] = (unsigned char)( working_state[i] >> 24 ); + } + + mbedtls_platform_zeroize( working_state, sizeof( working_state ) ); +} + +void mbedtls_chacha20_init( mbedtls_chacha20_context *ctx ) +{ + if( ctx != NULL ) + { + mbedtls_platform_zeroize( ctx->state, sizeof( ctx->state ) ); + mbedtls_platform_zeroize( ctx->keystream8, sizeof( ctx->keystream8 ) ); + + /* Initially, there's no keystream bytes available */ + ctx->keystream_bytes_used = CHACHA20_BLOCK_SIZE_BYTES; + } +} + +void mbedtls_chacha20_free( mbedtls_chacha20_context *ctx ) +{ + if( ctx != NULL ) + { + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_chacha20_context ) ); + } +} + +int mbedtls_chacha20_setkey( mbedtls_chacha20_context *ctx, + const unsigned char key[32] ) +{ + if( ( ctx == NULL ) || ( key == NULL ) ) + { + return( MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA ); + } + + /* ChaCha20 constants - the string "expand 32-byte k" */ + ctx->state[0] = 0x61707865; + ctx->state[1] = 0x3320646e; + ctx->state[2] = 0x79622d32; + ctx->state[3] = 0x6b206574; + + /* Set key */ + ctx->state[4] = BYTES_TO_U32_LE( key, 0 ); + ctx->state[5] = BYTES_TO_U32_LE( key, 4 ); + ctx->state[6] = BYTES_TO_U32_LE( key, 8 ); + ctx->state[7] = BYTES_TO_U32_LE( key, 12 ); + ctx->state[8] = BYTES_TO_U32_LE( key, 16 ); + ctx->state[9] = BYTES_TO_U32_LE( key, 20 ); + ctx->state[10] = BYTES_TO_U32_LE( key, 24 ); + ctx->state[11] = BYTES_TO_U32_LE( key, 28 ); + + return( 0 ); +} + +int mbedtls_chacha20_starts( mbedtls_chacha20_context* ctx, + const unsigned char nonce[12], + uint32_t counter ) +{ + if( ( ctx == NULL ) || ( nonce == NULL ) ) + { + return( MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA ); + } + + /* Counter */ + ctx->state[12] = counter; + + /* Nonce */ + ctx->state[13] = BYTES_TO_U32_LE( nonce, 0 ); + ctx->state[14] = BYTES_TO_U32_LE( nonce, 4 ); + ctx->state[15] = BYTES_TO_U32_LE( nonce, 8 ); + + mbedtls_platform_zeroize( ctx->keystream8, sizeof( ctx->keystream8 ) ); + + /* Initially, there's no keystream bytes available */ + ctx->keystream_bytes_used = CHACHA20_BLOCK_SIZE_BYTES; + + return( 0 ); +} + +int mbedtls_chacha20_update( mbedtls_chacha20_context *ctx, + size_t size, + const unsigned char *input, + unsigned char *output ) +{ + size_t offset = 0U; + size_t i; + + if( ctx == NULL ) + { + return( MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA ); + } + else if( ( size > 0U ) && ( ( input == NULL ) || ( output == NULL ) ) ) + { + /* input and output pointers are allowed to be NULL only if size == 0 */ + return( MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA ); + } + + /* Use leftover keystream bytes, if available */ + while( size > 0U && ctx->keystream_bytes_used < CHACHA20_BLOCK_SIZE_BYTES ) + { + output[offset] = input[offset] + ^ ctx->keystream8[ctx->keystream_bytes_used]; + + ctx->keystream_bytes_used++; + offset++; + size--; + } + + /* Process full blocks */ + while( size >= CHACHA20_BLOCK_SIZE_BYTES ) + { + /* Generate new keystream block and increment counter */ + chacha20_block( ctx->state, ctx->keystream8 ); + ctx->state[CHACHA20_CTR_INDEX]++; + + for( i = 0U; i < 64U; i += 8U ) + { + output[offset + i ] = input[offset + i ] ^ ctx->keystream8[i ]; + output[offset + i+1] = input[offset + i+1] ^ ctx->keystream8[i+1]; + output[offset + i+2] = input[offset + i+2] ^ ctx->keystream8[i+2]; + output[offset + i+3] = input[offset + i+3] ^ ctx->keystream8[i+3]; + output[offset + i+4] = input[offset + i+4] ^ ctx->keystream8[i+4]; + output[offset + i+5] = input[offset + i+5] ^ ctx->keystream8[i+5]; + output[offset + i+6] = input[offset + i+6] ^ ctx->keystream8[i+6]; + output[offset + i+7] = input[offset + i+7] ^ ctx->keystream8[i+7]; + } + + offset += CHACHA20_BLOCK_SIZE_BYTES; + size -= CHACHA20_BLOCK_SIZE_BYTES; + } + + /* Last (partial) block */ + if( size > 0U ) + { + /* Generate new keystream block and increment counter */ + chacha20_block( ctx->state, ctx->keystream8 ); + ctx->state[CHACHA20_CTR_INDEX]++; + + for( i = 0U; i < size; i++) + { + output[offset + i] = input[offset + i] ^ ctx->keystream8[i]; + } + + ctx->keystream_bytes_used = size; + + } + + return( 0 ); +} + +int mbedtls_chacha20_crypt( const unsigned char key[32], + const unsigned char nonce[12], + uint32_t counter, + size_t data_len, + const unsigned char* input, + unsigned char* output ) +{ + mbedtls_chacha20_context ctx; + int ret; + + mbedtls_chacha20_init( &ctx ); + + ret = mbedtls_chacha20_setkey( &ctx, key ); + if( ret != 0 ) + goto cleanup; + + ret = mbedtls_chacha20_starts( &ctx, nonce, counter ); + if( ret != 0 ) + goto cleanup; + + ret = mbedtls_chacha20_update( &ctx, data_len, input, output ); + +cleanup: + mbedtls_chacha20_free( &ctx ); + return( ret ); +} + +#endif /* !MBEDTLS_CHACHA20_ALT */ + +#if defined(MBEDTLS_SELF_TEST) + +static const unsigned char test_keys[2][32] = +{ + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 + } +}; + +static const unsigned char test_nonces[2][12] = +{ + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00 + }, + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x02 + } +}; + +static const uint32_t test_counters[2] = +{ + 0U, + 1U +}; + +static const unsigned char test_input[2][375] = +{ + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + { + 0x41, 0x6e, 0x79, 0x20, 0x73, 0x75, 0x62, 0x6d, + 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x74, + 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x49, 0x45, + 0x54, 0x46, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x6e, + 0x64, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x74, + 0x68, 0x65, 0x20, 0x43, 0x6f, 0x6e, 0x74, 0x72, + 0x69, 0x62, 0x75, 0x74, 0x6f, 0x72, 0x20, 0x66, + 0x6f, 0x72, 0x20, 0x70, 0x75, 0x62, 0x6c, 0x69, + 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x61, + 0x73, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x6f, 0x72, + 0x20, 0x70, 0x61, 0x72, 0x74, 0x20, 0x6f, 0x66, + 0x20, 0x61, 0x6e, 0x20, 0x49, 0x45, 0x54, 0x46, + 0x20, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, + 0x74, 0x2d, 0x44, 0x72, 0x61, 0x66, 0x74, 0x20, + 0x6f, 0x72, 0x20, 0x52, 0x46, 0x43, 0x20, 0x61, + 0x6e, 0x64, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x73, + 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74, + 0x20, 0x6d, 0x61, 0x64, 0x65, 0x20, 0x77, 0x69, + 0x74, 0x68, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, + 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6e, 0x20, 0x49, + 0x45, 0x54, 0x46, 0x20, 0x61, 0x63, 0x74, 0x69, + 0x76, 0x69, 0x74, 0x79, 0x20, 0x69, 0x73, 0x20, + 0x63, 0x6f, 0x6e, 0x73, 0x69, 0x64, 0x65, 0x72, + 0x65, 0x64, 0x20, 0x61, 0x6e, 0x20, 0x22, 0x49, + 0x45, 0x54, 0x46, 0x20, 0x43, 0x6f, 0x6e, 0x74, + 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, + 0x22, 0x2e, 0x20, 0x53, 0x75, 0x63, 0x68, 0x20, + 0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, + 0x74, 0x73, 0x20, 0x69, 0x6e, 0x63, 0x6c, 0x75, + 0x64, 0x65, 0x20, 0x6f, 0x72, 0x61, 0x6c, 0x20, + 0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, + 0x74, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x49, 0x45, + 0x54, 0x46, 0x20, 0x73, 0x65, 0x73, 0x73, 0x69, + 0x6f, 0x6e, 0x73, 0x2c, 0x20, 0x61, 0x73, 0x20, + 0x77, 0x65, 0x6c, 0x6c, 0x20, 0x61, 0x73, 0x20, + 0x77, 0x72, 0x69, 0x74, 0x74, 0x65, 0x6e, 0x20, + 0x61, 0x6e, 0x64, 0x20, 0x65, 0x6c, 0x65, 0x63, + 0x74, 0x72, 0x6f, 0x6e, 0x69, 0x63, 0x20, 0x63, + 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x63, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x6d, 0x61, + 0x64, 0x65, 0x20, 0x61, 0x74, 0x20, 0x61, 0x6e, + 0x79, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x20, 0x6f, + 0x72, 0x20, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x2c, + 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x61, + 0x72, 0x65, 0x20, 0x61, 0x64, 0x64, 0x72, 0x65, + 0x73, 0x73, 0x65, 0x64, 0x20, 0x74, 0x6f + } +}; + +static const unsigned char test_output[2][375] = +{ + { + 0x76, 0xb8, 0xe0, 0xad, 0xa0, 0xf1, 0x3d, 0x90, + 0x40, 0x5d, 0x6a, 0xe5, 0x53, 0x86, 0xbd, 0x28, + 0xbd, 0xd2, 0x19, 0xb8, 0xa0, 0x8d, 0xed, 0x1a, + 0xa8, 0x36, 0xef, 0xcc, 0x8b, 0x77, 0x0d, 0xc7, + 0xda, 0x41, 0x59, 0x7c, 0x51, 0x57, 0x48, 0x8d, + 0x77, 0x24, 0xe0, 0x3f, 0xb8, 0xd8, 0x4a, 0x37, + 0x6a, 0x43, 0xb8, 0xf4, 0x15, 0x18, 0xa1, 0x1c, + 0xc3, 0x87, 0xb6, 0x69, 0xb2, 0xee, 0x65, 0x86 + }, + { + 0xa3, 0xfb, 0xf0, 0x7d, 0xf3, 0xfa, 0x2f, 0xde, + 0x4f, 0x37, 0x6c, 0xa2, 0x3e, 0x82, 0x73, 0x70, + 0x41, 0x60, 0x5d, 0x9f, 0x4f, 0x4f, 0x57, 0xbd, + 0x8c, 0xff, 0x2c, 0x1d, 0x4b, 0x79, 0x55, 0xec, + 0x2a, 0x97, 0x94, 0x8b, 0xd3, 0x72, 0x29, 0x15, + 0xc8, 0xf3, 0xd3, 0x37, 0xf7, 0xd3, 0x70, 0x05, + 0x0e, 0x9e, 0x96, 0xd6, 0x47, 0xb7, 0xc3, 0x9f, + 0x56, 0xe0, 0x31, 0xca, 0x5e, 0xb6, 0x25, 0x0d, + 0x40, 0x42, 0xe0, 0x27, 0x85, 0xec, 0xec, 0xfa, + 0x4b, 0x4b, 0xb5, 0xe8, 0xea, 0xd0, 0x44, 0x0e, + 0x20, 0xb6, 0xe8, 0xdb, 0x09, 0xd8, 0x81, 0xa7, + 0xc6, 0x13, 0x2f, 0x42, 0x0e, 0x52, 0x79, 0x50, + 0x42, 0xbd, 0xfa, 0x77, 0x73, 0xd8, 0xa9, 0x05, + 0x14, 0x47, 0xb3, 0x29, 0x1c, 0xe1, 0x41, 0x1c, + 0x68, 0x04, 0x65, 0x55, 0x2a, 0xa6, 0xc4, 0x05, + 0xb7, 0x76, 0x4d, 0x5e, 0x87, 0xbe, 0xa8, 0x5a, + 0xd0, 0x0f, 0x84, 0x49, 0xed, 0x8f, 0x72, 0xd0, + 0xd6, 0x62, 0xab, 0x05, 0x26, 0x91, 0xca, 0x66, + 0x42, 0x4b, 0xc8, 0x6d, 0x2d, 0xf8, 0x0e, 0xa4, + 0x1f, 0x43, 0xab, 0xf9, 0x37, 0xd3, 0x25, 0x9d, + 0xc4, 0xb2, 0xd0, 0xdf, 0xb4, 0x8a, 0x6c, 0x91, + 0x39, 0xdd, 0xd7, 0xf7, 0x69, 0x66, 0xe9, 0x28, + 0xe6, 0x35, 0x55, 0x3b, 0xa7, 0x6c, 0x5c, 0x87, + 0x9d, 0x7b, 0x35, 0xd4, 0x9e, 0xb2, 0xe6, 0x2b, + 0x08, 0x71, 0xcd, 0xac, 0x63, 0x89, 0x39, 0xe2, + 0x5e, 0x8a, 0x1e, 0x0e, 0xf9, 0xd5, 0x28, 0x0f, + 0xa8, 0xca, 0x32, 0x8b, 0x35, 0x1c, 0x3c, 0x76, + 0x59, 0x89, 0xcb, 0xcf, 0x3d, 0xaa, 0x8b, 0x6c, + 0xcc, 0x3a, 0xaf, 0x9f, 0x39, 0x79, 0xc9, 0x2b, + 0x37, 0x20, 0xfc, 0x88, 0xdc, 0x95, 0xed, 0x84, + 0xa1, 0xbe, 0x05, 0x9c, 0x64, 0x99, 0xb9, 0xfd, + 0xa2, 0x36, 0xe7, 0xe8, 0x18, 0xb0, 0x4b, 0x0b, + 0xc3, 0x9c, 0x1e, 0x87, 0x6b, 0x19, 0x3b, 0xfe, + 0x55, 0x69, 0x75, 0x3f, 0x88, 0x12, 0x8c, 0xc0, + 0x8a, 0xaa, 0x9b, 0x63, 0xd1, 0xa1, 0x6f, 0x80, + 0xef, 0x25, 0x54, 0xd7, 0x18, 0x9c, 0x41, 0x1f, + 0x58, 0x69, 0xca, 0x52, 0xc5, 0xb8, 0x3f, 0xa3, + 0x6f, 0xf2, 0x16, 0xb9, 0xc1, 0xd3, 0x00, 0x62, + 0xbe, 0xbc, 0xfd, 0x2d, 0xc5, 0xbc, 0xe0, 0x91, + 0x19, 0x34, 0xfd, 0xa7, 0x9a, 0x86, 0xf6, 0xe6, + 0x98, 0xce, 0xd7, 0x59, 0xc3, 0xff, 0x9b, 0x64, + 0x77, 0x33, 0x8f, 0x3d, 0xa4, 0xf9, 0xcd, 0x85, + 0x14, 0xea, 0x99, 0x82, 0xcc, 0xaf, 0xb3, 0x41, + 0xb2, 0x38, 0x4d, 0xd9, 0x02, 0xf3, 0xd1, 0xab, + 0x7a, 0xc6, 0x1d, 0xd2, 0x9c, 0x6f, 0x21, 0xba, + 0x5b, 0x86, 0x2f, 0x37, 0x30, 0xe3, 0x7c, 0xfd, + 0xc4, 0xfd, 0x80, 0x6c, 0x22, 0xf2, 0x21 + } +}; + +static const size_t test_lengths[2] = +{ + 64U, + 375U +}; + +#define ASSERT( cond, args ) \ + do \ + { \ + if( ! ( cond ) ) \ + { \ + if( verbose != 0 ) \ + mbedtls_printf args; \ + \ + return( -1 ); \ + } \ + } \ + while( 0 ) + +int mbedtls_chacha20_self_test( int verbose ) +{ + unsigned char output[381]; + unsigned i; + int ret; + + for( i = 0U; i < 2U; i++ ) + { + if( verbose != 0 ) + mbedtls_printf( " ChaCha20 test %u ", i ); + + ret = mbedtls_chacha20_crypt( test_keys[i], + test_nonces[i], + test_counters[i], + test_lengths[i], + test_input[i], + output ); + + ASSERT( 0 == ret, ( "error code: %i\n", ret ) ); + + ASSERT( 0 == memcmp( output, test_output[i], test_lengths[i] ), + ( "failed (output)\n" ) ); + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + return( 0 ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* !MBEDTLS_CHACHA20_C */ diff --git a/thirdparty/mbedtls/library/chachapoly.c b/thirdparty/mbedtls/library/chachapoly.c new file mode 100644 index 0000000000..860f877653 --- /dev/null +++ b/thirdparty/mbedtls/library/chachapoly.c @@ -0,0 +1,547 @@ +/** + * \file chachapoly.c + * + * \brief ChaCha20-Poly1305 AEAD construction based on RFC 7539. + * + * Copyright (C) 2006-2016, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_CHACHAPOLY_C) + +#include "mbedtls/chachapoly.h" +#include "mbedtls/platform_util.h" + +#include <string.h> + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include <stdio.h> +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +#if !defined(MBEDTLS_CHACHAPOLY_ALT) + +#define CHACHAPOLY_STATE_INIT ( 0 ) +#define CHACHAPOLY_STATE_AAD ( 1 ) +#define CHACHAPOLY_STATE_CIPHERTEXT ( 2 ) /* Encrypting or decrypting */ +#define CHACHAPOLY_STATE_FINISHED ( 3 ) + +/** + * \brief Adds nul bytes to pad the AAD for Poly1305. + * + * \param ctx The ChaCha20-Poly1305 context. + */ +static int chachapoly_pad_aad( mbedtls_chachapoly_context *ctx ) +{ + uint32_t partial_block_len = (uint32_t) ( ctx->aad_len % 16U ); + unsigned char zeroes[15]; + + if( partial_block_len == 0U ) + return( 0 ); + + memset( zeroes, 0, sizeof( zeroes ) ); + + return( mbedtls_poly1305_update( &ctx->poly1305_ctx, + zeroes, + 16U - partial_block_len ) ); +} + +/** + * \brief Adds nul bytes to pad the ciphertext for Poly1305. + * + * \param ctx The ChaCha20-Poly1305 context. + */ +static int chachapoly_pad_ciphertext( mbedtls_chachapoly_context *ctx ) +{ + uint32_t partial_block_len = (uint32_t) ( ctx->ciphertext_len % 16U ); + unsigned char zeroes[15]; + + if( partial_block_len == 0U ) + return( 0 ); + + memset( zeroes, 0, sizeof( zeroes ) ); + return( mbedtls_poly1305_update( &ctx->poly1305_ctx, + zeroes, + 16U - partial_block_len ) ); +} + +void mbedtls_chachapoly_init( mbedtls_chachapoly_context *ctx ) +{ + if( ctx != NULL ) + { + mbedtls_chacha20_init( &ctx->chacha20_ctx ); + mbedtls_poly1305_init( &ctx->poly1305_ctx ); + ctx->aad_len = 0U; + ctx->ciphertext_len = 0U; + ctx->state = CHACHAPOLY_STATE_INIT; + ctx->mode = MBEDTLS_CHACHAPOLY_ENCRYPT; + } +} + +void mbedtls_chachapoly_free( mbedtls_chachapoly_context *ctx ) +{ + if( ctx != NULL ) + { + mbedtls_chacha20_free( &ctx->chacha20_ctx ); + mbedtls_poly1305_free( &ctx->poly1305_ctx ); + ctx->aad_len = 0U; + ctx->ciphertext_len = 0U; + ctx->state = CHACHAPOLY_STATE_INIT; + ctx->mode = MBEDTLS_CHACHAPOLY_ENCRYPT; + } +} + +int mbedtls_chachapoly_setkey( mbedtls_chachapoly_context *ctx, + const unsigned char key[32] ) +{ + int ret; + + if( ( ctx == NULL ) || ( key == NULL ) ) + { + return( MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA ); + } + + ret = mbedtls_chacha20_setkey( &ctx->chacha20_ctx, key ); + + return( ret ); +} + +int mbedtls_chachapoly_starts( mbedtls_chachapoly_context *ctx, + const unsigned char nonce[12], + mbedtls_chachapoly_mode_t mode ) +{ + int ret; + unsigned char poly1305_key[64]; + + if( ( ctx == NULL ) || ( nonce == NULL ) ) + { + return( MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA ); + } + + /* Set counter = 0, will be update to 1 when generating Poly1305 key */ + ret = mbedtls_chacha20_starts( &ctx->chacha20_ctx, nonce, 0U ); + if( ret != 0 ) + goto cleanup; + + /* Generate the Poly1305 key by getting the ChaCha20 keystream output with + * counter = 0. This is the same as encrypting a buffer of zeroes. + * Only the first 256-bits (32 bytes) of the key is used for Poly1305. + * The other 256 bits are discarded. + */ + memset( poly1305_key, 0, sizeof( poly1305_key ) ); + ret = mbedtls_chacha20_update( &ctx->chacha20_ctx, sizeof( poly1305_key ), + poly1305_key, poly1305_key ); + if( ret != 0 ) + goto cleanup; + + ret = mbedtls_poly1305_starts( &ctx->poly1305_ctx, poly1305_key ); + + if( ret == 0 ) + { + ctx->aad_len = 0U; + ctx->ciphertext_len = 0U; + ctx->state = CHACHAPOLY_STATE_AAD; + ctx->mode = mode; + } + +cleanup: + mbedtls_platform_zeroize( poly1305_key, 64U ); + return( ret ); +} + +int mbedtls_chachapoly_update_aad( mbedtls_chachapoly_context *ctx, + const unsigned char *aad, + size_t aad_len ) +{ + if( ctx == NULL ) + { + return( MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA ); + } + else if( ( aad_len > 0U ) && ( aad == NULL ) ) + { + /* aad pointer is allowed to be NULL if aad_len == 0 */ + return( MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA ); + } + else if( ctx->state != CHACHAPOLY_STATE_AAD ) + { + return( MBEDTLS_ERR_CHACHAPOLY_BAD_STATE ); + } + + ctx->aad_len += aad_len; + + return( mbedtls_poly1305_update( &ctx->poly1305_ctx, aad, aad_len ) ); +} + +int mbedtls_chachapoly_update( mbedtls_chachapoly_context *ctx, + size_t len, + const unsigned char *input, + unsigned char *output ) +{ + int ret; + + if( ctx == NULL ) + { + return( MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA ); + } + else if( ( len > 0U ) && ( ( input == NULL ) || ( output == NULL ) ) ) + { + /* input and output pointers are allowed to be NULL if len == 0 */ + return( MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA ); + } + else if( ( ctx->state != CHACHAPOLY_STATE_AAD ) && + ( ctx->state != CHACHAPOLY_STATE_CIPHERTEXT ) ) + { + return( MBEDTLS_ERR_CHACHAPOLY_BAD_STATE ); + } + + if( ctx->state == CHACHAPOLY_STATE_AAD ) + { + ctx->state = CHACHAPOLY_STATE_CIPHERTEXT; + + ret = chachapoly_pad_aad( ctx ); + if( ret != 0 ) + return( ret ); + } + + ctx->ciphertext_len += len; + + if( ctx->mode == MBEDTLS_CHACHAPOLY_ENCRYPT ) + { + ret = mbedtls_chacha20_update( &ctx->chacha20_ctx, len, input, output ); + if( ret != 0 ) + return( ret ); + + ret = mbedtls_poly1305_update( &ctx->poly1305_ctx, output, len ); + if( ret != 0 ) + return( ret ); + } + else /* DECRYPT */ + { + ret = mbedtls_poly1305_update( &ctx->poly1305_ctx, input, len ); + if( ret != 0 ) + return( ret ); + + ret = mbedtls_chacha20_update( &ctx->chacha20_ctx, len, input, output ); + if( ret != 0 ) + return( ret ); + } + + return( 0 ); +} + +int mbedtls_chachapoly_finish( mbedtls_chachapoly_context *ctx, + unsigned char mac[16] ) +{ + int ret; + unsigned char len_block[16]; + + if( ( ctx == NULL ) || ( mac == NULL ) ) + { + return( MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA ); + } + else if( ctx->state == CHACHAPOLY_STATE_INIT ) + { + return( MBEDTLS_ERR_CHACHAPOLY_BAD_STATE ); + } + + if( ctx->state == CHACHAPOLY_STATE_AAD ) + { + ret = chachapoly_pad_aad( ctx ); + if( ret != 0 ) + return( ret ); + } + else if( ctx->state == CHACHAPOLY_STATE_CIPHERTEXT ) + { + ret = chachapoly_pad_ciphertext( ctx ); + if( ret != 0 ) + return( ret ); + } + + ctx->state = CHACHAPOLY_STATE_FINISHED; + + /* The lengths of the AAD and ciphertext are processed by + * Poly1305 as the final 128-bit block, encoded as little-endian integers. + */ + len_block[ 0] = (unsigned char)( ctx->aad_len ); + len_block[ 1] = (unsigned char)( ctx->aad_len >> 8 ); + len_block[ 2] = (unsigned char)( ctx->aad_len >> 16 ); + len_block[ 3] = (unsigned char)( ctx->aad_len >> 24 ); + len_block[ 4] = (unsigned char)( ctx->aad_len >> 32 ); + len_block[ 5] = (unsigned char)( ctx->aad_len >> 40 ); + len_block[ 6] = (unsigned char)( ctx->aad_len >> 48 ); + len_block[ 7] = (unsigned char)( ctx->aad_len >> 56 ); + len_block[ 8] = (unsigned char)( ctx->ciphertext_len ); + len_block[ 9] = (unsigned char)( ctx->ciphertext_len >> 8 ); + len_block[10] = (unsigned char)( ctx->ciphertext_len >> 16 ); + len_block[11] = (unsigned char)( ctx->ciphertext_len >> 24 ); + len_block[12] = (unsigned char)( ctx->ciphertext_len >> 32 ); + len_block[13] = (unsigned char)( ctx->ciphertext_len >> 40 ); + len_block[14] = (unsigned char)( ctx->ciphertext_len >> 48 ); + len_block[15] = (unsigned char)( ctx->ciphertext_len >> 56 ); + + ret = mbedtls_poly1305_update( &ctx->poly1305_ctx, len_block, 16U ); + if( ret != 0 ) + return( ret ); + + ret = mbedtls_poly1305_finish( &ctx->poly1305_ctx, mac ); + + return( ret ); +} + +static int chachapoly_crypt_and_tag( mbedtls_chachapoly_context *ctx, + mbedtls_chachapoly_mode_t mode, + size_t length, + const unsigned char nonce[12], + const unsigned char *aad, + size_t aad_len, + const unsigned char *input, + unsigned char *output, + unsigned char tag[16] ) +{ + int ret; + + ret = mbedtls_chachapoly_starts( ctx, nonce, mode ); + if( ret != 0 ) + goto cleanup; + + ret = mbedtls_chachapoly_update_aad( ctx, aad, aad_len ); + if( ret != 0 ) + goto cleanup; + + ret = mbedtls_chachapoly_update( ctx, length, input, output ); + if( ret != 0 ) + goto cleanup; + + ret = mbedtls_chachapoly_finish( ctx, tag ); + +cleanup: + return( ret ); +} + +int mbedtls_chachapoly_encrypt_and_tag( mbedtls_chachapoly_context *ctx, + size_t length, + const unsigned char nonce[12], + const unsigned char *aad, + size_t aad_len, + const unsigned char *input, + unsigned char *output, + unsigned char tag[16] ) +{ + return( chachapoly_crypt_and_tag( ctx, MBEDTLS_CHACHAPOLY_ENCRYPT, + length, nonce, aad, aad_len, + input, output, tag ) ); +} + +int mbedtls_chachapoly_auth_decrypt( mbedtls_chachapoly_context *ctx, + size_t length, + const unsigned char nonce[12], + const unsigned char *aad, + size_t aad_len, + const unsigned char tag[16], + const unsigned char *input, + unsigned char *output ) +{ + int ret; + unsigned char check_tag[16]; + size_t i; + int diff; + + if( tag == NULL ) + return( MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA ); + + if( ( ret = chachapoly_crypt_and_tag( ctx, + MBEDTLS_CHACHAPOLY_DECRYPT, length, nonce, + aad, aad_len, input, output, check_tag ) ) != 0 ) + { + return( ret ); + } + + /* Check tag in "constant-time" */ + for( diff = 0, i = 0; i < sizeof( check_tag ); i++ ) + diff |= tag[i] ^ check_tag[i]; + + if( diff != 0 ) + { + mbedtls_platform_zeroize( output, length ); + return( MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED ); + } + + return( 0 ); +} + +#endif /* MBEDTLS_CHACHAPOLY_ALT */ + +#if defined(MBEDTLS_SELF_TEST) + +static const unsigned char test_key[1][32] = +{ + { + 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, + 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, + 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, + 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f + } +}; + +static const unsigned char test_nonce[1][12] = +{ + { + 0x07, 0x00, 0x00, 0x00, /* 32-bit common part */ + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47 /* 64-bit IV */ + } +}; + +static const unsigned char test_aad[1][12] = +{ + { + 0x50, 0x51, 0x52, 0x53, 0xc0, 0xc1, 0xc2, 0xc3, + 0xc4, 0xc5, 0xc6, 0xc7 + } +}; + +static const size_t test_aad_len[1] = +{ + 12U +}; + +static const unsigned char test_input[1][114] = +{ + { + 0x4c, 0x61, 0x64, 0x69, 0x65, 0x73, 0x20, 0x61, + 0x6e, 0x64, 0x20, 0x47, 0x65, 0x6e, 0x74, 0x6c, + 0x65, 0x6d, 0x65, 0x6e, 0x20, 0x6f, 0x66, 0x20, + 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x61, 0x73, + 0x73, 0x20, 0x6f, 0x66, 0x20, 0x27, 0x39, 0x39, + 0x3a, 0x20, 0x49, 0x66, 0x20, 0x49, 0x20, 0x63, + 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x6f, 0x66, 0x66, + 0x65, 0x72, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x6f, + 0x6e, 0x6c, 0x79, 0x20, 0x6f, 0x6e, 0x65, 0x20, + 0x74, 0x69, 0x70, 0x20, 0x66, 0x6f, 0x72, 0x20, + 0x74, 0x68, 0x65, 0x20, 0x66, 0x75, 0x74, 0x75, + 0x72, 0x65, 0x2c, 0x20, 0x73, 0x75, 0x6e, 0x73, + 0x63, 0x72, 0x65, 0x65, 0x6e, 0x20, 0x77, 0x6f, + 0x75, 0x6c, 0x64, 0x20, 0x62, 0x65, 0x20, 0x69, + 0x74, 0x2e + } +}; + +static const unsigned char test_output[1][114] = +{ + { + 0xd3, 0x1a, 0x8d, 0x34, 0x64, 0x8e, 0x60, 0xdb, + 0x7b, 0x86, 0xaf, 0xbc, 0x53, 0xef, 0x7e, 0xc2, + 0xa4, 0xad, 0xed, 0x51, 0x29, 0x6e, 0x08, 0xfe, + 0xa9, 0xe2, 0xb5, 0xa7, 0x36, 0xee, 0x62, 0xd6, + 0x3d, 0xbe, 0xa4, 0x5e, 0x8c, 0xa9, 0x67, 0x12, + 0x82, 0xfa, 0xfb, 0x69, 0xda, 0x92, 0x72, 0x8b, + 0x1a, 0x71, 0xde, 0x0a, 0x9e, 0x06, 0x0b, 0x29, + 0x05, 0xd6, 0xa5, 0xb6, 0x7e, 0xcd, 0x3b, 0x36, + 0x92, 0xdd, 0xbd, 0x7f, 0x2d, 0x77, 0x8b, 0x8c, + 0x98, 0x03, 0xae, 0xe3, 0x28, 0x09, 0x1b, 0x58, + 0xfa, 0xb3, 0x24, 0xe4, 0xfa, 0xd6, 0x75, 0x94, + 0x55, 0x85, 0x80, 0x8b, 0x48, 0x31, 0xd7, 0xbc, + 0x3f, 0xf4, 0xde, 0xf0, 0x8e, 0x4b, 0x7a, 0x9d, + 0xe5, 0x76, 0xd2, 0x65, 0x86, 0xce, 0xc6, 0x4b, + 0x61, 0x16 + } +}; + +static const size_t test_input_len[1] = +{ + 114U +}; + +static const unsigned char test_mac[1][16] = +{ + { + 0x1a, 0xe1, 0x0b, 0x59, 0x4f, 0x09, 0xe2, 0x6a, + 0x7e, 0x90, 0x2e, 0xcb, 0xd0, 0x60, 0x06, 0x91 + } +}; + +#define ASSERT( cond, args ) \ + do \ + { \ + if( ! ( cond ) ) \ + { \ + if( verbose != 0 ) \ + mbedtls_printf args; \ + \ + return( -1 ); \ + } \ + } \ + while( 0 ) + +int mbedtls_chachapoly_self_test( int verbose ) +{ + mbedtls_chachapoly_context ctx; + unsigned i; + int ret; + unsigned char output[200]; + unsigned char mac[16]; + + for( i = 0U; i < 1U; i++ ) + { + if( verbose != 0 ) + mbedtls_printf( " ChaCha20-Poly1305 test %u ", i ); + + mbedtls_chachapoly_init( &ctx ); + + ret = mbedtls_chachapoly_setkey( &ctx, test_key[i] ); + ASSERT( 0 == ret, ( "setkey() error code: %i\n", ret ) ); + + ret = mbedtls_chachapoly_encrypt_and_tag( &ctx, + test_input_len[i], + test_nonce[i], + test_aad[i], + test_aad_len[i], + test_input[i], + output, + mac ); + + ASSERT( 0 == ret, ( "crypt_and_tag() error code: %i\n", ret ) ); + + ASSERT( 0 == memcmp( output, test_output[i], test_input_len[i] ), + ( "failure (wrong output)\n" ) ); + + ASSERT( 0 == memcmp( mac, test_mac[i], 16U ), + ( "failure (wrong MAC)\n" ) ); + + mbedtls_chachapoly_free( &ctx ); + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + return( 0 ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_CHACHAPOLY_C */ diff --git a/thirdparty/mbedtls/library/cipher.c b/thirdparty/mbedtls/library/cipher.c index ff0327380c..7ae6c4ac5d 100644 --- a/thirdparty/mbedtls/library/cipher.c +++ b/thirdparty/mbedtls/library/cipher.c @@ -33,10 +33,15 @@ #include "mbedtls/cipher.h" #include "mbedtls/cipher_internal.h" +#include "mbedtls/platform_util.h" #include <stdlib.h> #include <string.h> +#if defined(MBEDTLS_CHACHAPOLY_C) +#include "mbedtls/chachapoly.h" +#endif + #if defined(MBEDTLS_GCM_C) #include "mbedtls/gcm.h" #endif @@ -45,6 +50,10 @@ #include "mbedtls/ccm.h" #endif +#if defined(MBEDTLS_CHACHA20_C) +#include "mbedtls/chacha20.h" +#endif + #if defined(MBEDTLS_CMAC_C) #include "mbedtls/cmac.h" #endif @@ -56,14 +65,25 @@ #define mbedtls_free free #endif -#if defined(MBEDTLS_ARC4_C) || defined(MBEDTLS_CIPHER_NULL_CIPHER) -#define MBEDTLS_CIPHER_MODE_STREAM -#endif +#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CHACHAPOLY_C) +/* Compare the contents of two buffers in constant time. + * Returns 0 if the contents are bitwise identical, otherwise returns + * a non-zero value. + * This is currently only used by GCM and ChaCha20+Poly1305. + */ +static int mbedtls_constant_time_memcmp( const void *v1, const void *v2, size_t len ) +{ + const unsigned char *p1 = (const unsigned char*) v1; + const unsigned char *p2 = (const unsigned char*) v2; + size_t i; + unsigned char diff; + + for( diff = 0, i = 0; i < len; i++ ) + diff |= p1[i] ^ p2[i]; -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize( void *v, size_t n ) { - volatile unsigned char *p = (unsigned char*)v; while( n-- ) *p++ = 0; + return (int)diff; } +#endif /* MBEDTLS_GCM_C || MBEDTLS_CHACHAPOLY_C */ static int supported_init = 0; @@ -141,7 +161,8 @@ void mbedtls_cipher_free( mbedtls_cipher_context_t *ctx ) #if defined(MBEDTLS_CMAC_C) if( ctx->cmac_ctx ) { - mbedtls_zeroize( ctx->cmac_ctx, sizeof( mbedtls_cmac_context_t ) ); + mbedtls_platform_zeroize( ctx->cmac_ctx, + sizeof( mbedtls_cmac_context_t ) ); mbedtls_free( ctx->cmac_ctx ); } #endif @@ -149,7 +170,7 @@ void mbedtls_cipher_free( mbedtls_cipher_context_t *ctx ) if( ctx->cipher_ctx ) ctx->cipher_info->base->ctx_free_func( ctx->cipher_ctx ); - mbedtls_zeroize( ctx, sizeof(mbedtls_cipher_context_t) ); + mbedtls_platform_zeroize( ctx, sizeof(mbedtls_cipher_context_t) ); } int mbedtls_cipher_setup( mbedtls_cipher_context_t *ctx, const mbedtls_cipher_info_t *cipher_info ) @@ -194,10 +215,11 @@ int mbedtls_cipher_setkey( mbedtls_cipher_context_t *ctx, const unsigned char *k ctx->operation = operation; /* - * For CFB and CTR mode always use the encryption key schedule + * For OFB, CFB and CTR mode always use the encryption key schedule */ if( MBEDTLS_ENCRYPT == operation || MBEDTLS_MODE_CFB == ctx->cipher_info->mode || + MBEDTLS_MODE_OFB == ctx->cipher_info->mode || MBEDTLS_MODE_CTR == ctx->cipher_info->mode ) { return ctx->cipher_info->base->setkey_enc_func( ctx->cipher_ctx, key, @@ -234,6 +256,18 @@ int mbedtls_cipher_set_iv( mbedtls_cipher_context_t *ctx, return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); } +#if defined(MBEDTLS_CHACHA20_C) + if ( ctx->cipher_info->type == MBEDTLS_CIPHER_CHACHA20 ) + { + if ( 0 != mbedtls_chacha20_starts( (mbedtls_chacha20_context*)ctx->cipher_ctx, + iv, + 0U ) ) /* Initial counter value */ + { + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + } +#endif + memcpy( ctx->iv, iv, actual_iv_size ); ctx->iv_size = actual_iv_size; @@ -250,22 +284,45 @@ int mbedtls_cipher_reset( mbedtls_cipher_context_t *ctx ) return( 0 ); } -#if defined(MBEDTLS_GCM_C) +#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CHACHAPOLY_C) int mbedtls_cipher_update_ad( mbedtls_cipher_context_t *ctx, const unsigned char *ad, size_t ad_len ) { if( NULL == ctx || NULL == ctx->cipher_info ) return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); +#if defined(MBEDTLS_GCM_C) if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode ) { return mbedtls_gcm_starts( (mbedtls_gcm_context *) ctx->cipher_ctx, ctx->operation, ctx->iv, ctx->iv_size, ad, ad_len ); } +#endif + +#if defined(MBEDTLS_CHACHAPOLY_C) + if (MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type ) + { + int result; + mbedtls_chachapoly_mode_t mode; + + mode = ( ctx->operation == MBEDTLS_ENCRYPT ) + ? MBEDTLS_CHACHAPOLY_ENCRYPT + : MBEDTLS_CHACHAPOLY_DECRYPT; + + result = mbedtls_chachapoly_starts( (mbedtls_chachapoly_context*) ctx->cipher_ctx, + ctx->iv, + mode ); + if ( result != 0 ) + return( result ); + + return mbedtls_chachapoly_update_aad( (mbedtls_chachapoly_context*) ctx->cipher_ctx, + ad, ad_len ); + } +#endif return( 0 ); } -#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_GCM_C || MBEDTLS_CHACHAPOLY_C */ int mbedtls_cipher_update( mbedtls_cipher_context_t *ctx, const unsigned char *input, size_t ilen, unsigned char *output, size_t *olen ) @@ -306,6 +363,15 @@ int mbedtls_cipher_update( mbedtls_cipher_context_t *ctx, const unsigned char *i } #endif +#if defined(MBEDTLS_CHACHAPOLY_C) + if ( ctx->cipher_info->type == MBEDTLS_CIPHER_CHACHA20_POLY1305 ) + { + *olen = ilen; + return mbedtls_chachapoly_update( (mbedtls_chachapoly_context*) ctx->cipher_ctx, + ilen, input, output ); + } +#endif + if ( 0 == block_size ) { return MBEDTLS_ERR_CIPHER_INVALID_CONTEXT; @@ -325,8 +391,10 @@ int mbedtls_cipher_update( mbedtls_cipher_context_t *ctx, const unsigned char *i /* * If there is not enough data for a full block, cache it. */ - if( ( ctx->operation == MBEDTLS_DECRYPT && + if( ( ctx->operation == MBEDTLS_DECRYPT && NULL != ctx->add_padding && ilen <= block_size - ctx->unprocessed_len ) || + ( ctx->operation == MBEDTLS_DECRYPT && NULL == ctx->add_padding && + ilen < block_size - ctx->unprocessed_len ) || ( ctx->operation == MBEDTLS_ENCRYPT && ilen < block_size - ctx->unprocessed_len ) ) { @@ -372,9 +440,17 @@ int mbedtls_cipher_update( mbedtls_cipher_context_t *ctx, const unsigned char *i return MBEDTLS_ERR_CIPHER_INVALID_CONTEXT; } + /* Encryption: only cache partial blocks + * Decryption w/ padding: always keep at least one whole block + * Decryption w/o padding: only cache partial blocks + */ copy_len = ilen % block_size; - if( copy_len == 0 && ctx->operation == MBEDTLS_DECRYPT ) + if( copy_len == 0 && + ctx->operation == MBEDTLS_DECRYPT && + NULL != ctx->add_padding) + { copy_len = block_size; + } memcpy( ctx->unprocessed_data, &( input[ilen - copy_len] ), copy_len ); @@ -417,6 +493,21 @@ int mbedtls_cipher_update( mbedtls_cipher_context_t *ctx, const unsigned char *i } #endif /* MBEDTLS_CIPHER_MODE_CFB */ +#if defined(MBEDTLS_CIPHER_MODE_OFB) + if( ctx->cipher_info->mode == MBEDTLS_MODE_OFB ) + { + if( 0 != ( ret = ctx->cipher_info->base->ofb_func( ctx->cipher_ctx, + ilen, &ctx->unprocessed_len, ctx->iv, input, output ) ) ) + { + return( ret ); + } + + *olen = ilen; + + return( 0 ); + } +#endif /* MBEDTLS_CIPHER_MODE_OFB */ + #if defined(MBEDTLS_CIPHER_MODE_CTR) if( ctx->cipher_info->mode == MBEDTLS_MODE_CTR ) { @@ -433,6 +524,27 @@ int mbedtls_cipher_update( mbedtls_cipher_context_t *ctx, const unsigned char *i } #endif /* MBEDTLS_CIPHER_MODE_CTR */ +#if defined(MBEDTLS_CIPHER_MODE_XTS) + if( ctx->cipher_info->mode == MBEDTLS_MODE_XTS ) + { + if( ctx->unprocessed_len > 0 ) { + /* We can only process an entire data unit at a time. */ + return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); + } + + ret = ctx->cipher_info->base->xts_func( ctx->cipher_ctx, + ctx->operation, ilen, ctx->iv, input, output ); + if( ret != 0 ) + { + return( ret ); + } + + *olen = ilen; + + return( 0 ); + } +#endif /* MBEDTLS_CIPHER_MODE_XTS */ + #if defined(MBEDTLS_CIPHER_MODE_STREAM) if( ctx->cipher_info->mode == MBEDTLS_MODE_STREAM ) { @@ -632,13 +744,21 @@ int mbedtls_cipher_finish( mbedtls_cipher_context_t *ctx, *olen = 0; if( MBEDTLS_MODE_CFB == ctx->cipher_info->mode || + MBEDTLS_MODE_OFB == ctx->cipher_info->mode || MBEDTLS_MODE_CTR == ctx->cipher_info->mode || MBEDTLS_MODE_GCM == ctx->cipher_info->mode || + MBEDTLS_MODE_XTS == ctx->cipher_info->mode || MBEDTLS_MODE_STREAM == ctx->cipher_info->mode ) { return( 0 ); } + if ( ( MBEDTLS_CIPHER_CHACHA20 == ctx->cipher_info->type ) || + ( MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type ) ) + { + return( 0 ); + } + if( MBEDTLS_MODE_ECB == ctx->cipher_info->mode ) { if( ctx->unprocessed_len != 0 ) @@ -750,7 +870,7 @@ int mbedtls_cipher_set_padding_mode( mbedtls_cipher_context_t *ctx, mbedtls_ciph } #endif /* MBEDTLS_CIPHER_MODE_WITH_PADDING */ -#if defined(MBEDTLS_GCM_C) +#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CHACHAPOLY_C) int mbedtls_cipher_write_tag( mbedtls_cipher_context_t *ctx, unsigned char *tag, size_t tag_len ) { @@ -760,8 +880,22 @@ int mbedtls_cipher_write_tag( mbedtls_cipher_context_t *ctx, if( MBEDTLS_ENCRYPT != ctx->operation ) return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); +#if defined(MBEDTLS_GCM_C) if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode ) return mbedtls_gcm_finish( (mbedtls_gcm_context *) ctx->cipher_ctx, tag, tag_len ); +#endif + +#if defined(MBEDTLS_CHACHAPOLY_C) + if ( MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type ) + { + /* Don't allow truncated MAC for Poly1305 */ + if ( tag_len != 16U ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + return mbedtls_chachapoly_finish( (mbedtls_chachapoly_context*) ctx->cipher_ctx, + tag ); + } +#endif return( 0 ); } @@ -769,6 +903,7 @@ int mbedtls_cipher_write_tag( mbedtls_cipher_context_t *ctx, int mbedtls_cipher_check_tag( mbedtls_cipher_context_t *ctx, const unsigned char *tag, size_t tag_len ) { + unsigned char check_tag[16]; int ret; if( NULL == ctx || NULL == ctx->cipher_info || @@ -777,12 +912,9 @@ int mbedtls_cipher_check_tag( mbedtls_cipher_context_t *ctx, return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); } +#if defined(MBEDTLS_GCM_C) if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode ) { - unsigned char check_tag[16]; - size_t i; - int diff; - if( tag_len > sizeof( check_tag ) ) return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); @@ -793,18 +925,38 @@ int mbedtls_cipher_check_tag( mbedtls_cipher_context_t *ctx, } /* Check the tag in "constant-time" */ - for( diff = 0, i = 0; i < tag_len; i++ ) - diff |= tag[i] ^ check_tag[i]; + if( mbedtls_constant_time_memcmp( tag, check_tag, tag_len ) != 0 ) + return( MBEDTLS_ERR_CIPHER_AUTH_FAILED ); + + return( 0 ); + } +#endif /* MBEDTLS_GCM_C */ + +#if defined(MBEDTLS_CHACHAPOLY_C) + if ( MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type ) + { + /* Don't allow truncated MAC for Poly1305 */ + if ( tag_len != sizeof( check_tag ) ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); - if( diff != 0 ) + ret = mbedtls_chachapoly_finish( (mbedtls_chachapoly_context*) ctx->cipher_ctx, + check_tag ); + if ( ret != 0 ) + { + return( ret ); + } + + /* Check the tag in "constant-time" */ + if( mbedtls_constant_time_memcmp( tag, check_tag, tag_len ) != 0 ) return( MBEDTLS_ERR_CIPHER_AUTH_FAILED ); return( 0 ); } +#endif /* MBEDTLS_CHACHAPOLY_C */ return( 0 ); } -#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_GCM_C || MBEDTLS_CHACHAPOLY_C */ /* * Packet-oriented wrapper for non-AEAD modes @@ -863,6 +1015,21 @@ int mbedtls_cipher_auth_encrypt( mbedtls_cipher_context_t *ctx, tag, tag_len ) ); } #endif /* MBEDTLS_CCM_C */ +#if defined(MBEDTLS_CHACHAPOLY_C) + if ( MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type ) + { + /* ChachaPoly has fixed length nonce and MAC (tag) */ + if ( ( iv_len != ctx->cipher_info->iv_size ) || + ( tag_len != 16U ) ) + { + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + + *olen = ilen; + return( mbedtls_chachapoly_encrypt_and_tag( ctx->cipher_ctx, + ilen, iv, ad, ad_len, input, output, tag ) ); + } +#endif /* MBEDTLS_CHACHAPOLY_C */ return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); } @@ -909,6 +1076,28 @@ int mbedtls_cipher_auth_decrypt( mbedtls_cipher_context_t *ctx, return( ret ); } #endif /* MBEDTLS_CCM_C */ +#if defined(MBEDTLS_CHACHAPOLY_C) + if ( MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type ) + { + int ret; + + /* ChachaPoly has fixed length nonce and MAC (tag) */ + if ( ( iv_len != ctx->cipher_info->iv_size ) || + ( tag_len != 16U ) ) + { + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + + *olen = ilen; + ret = mbedtls_chachapoly_auth_decrypt( ctx->cipher_ctx, ilen, + iv, ad, ad_len, tag, input, output ); + + if( ret == MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED ) + ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED; + + return( ret ); + } +#endif /* MBEDTLS_CHACHAPOLY_C */ return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); } diff --git a/thirdparty/mbedtls/library/cipher_wrap.c b/thirdparty/mbedtls/library/cipher_wrap.c index dc76af8ff4..893490acc8 100644 --- a/thirdparty/mbedtls/library/cipher_wrap.c +++ b/thirdparty/mbedtls/library/cipher_wrap.c @@ -33,6 +33,10 @@ #include "mbedtls/cipher_internal.h" +#if defined(MBEDTLS_CHACHAPOLY_C) +#include "mbedtls/chachapoly.h" +#endif + #if defined(MBEDTLS_AES_C) #include "mbedtls/aes.h" #endif @@ -45,6 +49,10 @@ #include "mbedtls/camellia.h" #endif +#if defined(MBEDTLS_ARIA_C) +#include "mbedtls/aria.h" +#endif + #if defined(MBEDTLS_DES_C) #include "mbedtls/des.h" #endif @@ -53,6 +61,10 @@ #include "mbedtls/blowfish.h" #endif +#if defined(MBEDTLS_CHACHA20_C) +#include "mbedtls/chacha20.h" +#endif + #if defined(MBEDTLS_GCM_C) #include "mbedtls/gcm.h" #endif @@ -138,6 +150,15 @@ static int aes_crypt_cfb128_wrap( void *ctx, mbedtls_operation_t operation, } #endif /* MBEDTLS_CIPHER_MODE_CFB */ +#if defined(MBEDTLS_CIPHER_MODE_OFB) +static int aes_crypt_ofb_wrap( void *ctx, size_t length, size_t *iv_off, + unsigned char *iv, const unsigned char *input, unsigned char *output ) +{ + return mbedtls_aes_crypt_ofb( (mbedtls_aes_context *) ctx, length, iv_off, + iv, input, output ); +} +#endif /* MBEDTLS_CIPHER_MODE_OFB */ + #if defined(MBEDTLS_CIPHER_MODE_CTR) static int aes_crypt_ctr_wrap( void *ctx, size_t length, size_t *nc_off, unsigned char *nonce_counter, unsigned char *stream_block, @@ -148,6 +169,33 @@ static int aes_crypt_ctr_wrap( void *ctx, size_t length, size_t *nc_off, } #endif /* MBEDTLS_CIPHER_MODE_CTR */ +#if defined(MBEDTLS_CIPHER_MODE_XTS) +static int aes_crypt_xts_wrap( void *ctx, mbedtls_operation_t operation, + size_t length, + const unsigned char data_unit[16], + const unsigned char *input, + unsigned char *output ) +{ + mbedtls_aes_xts_context *xts_ctx = ctx; + int mode; + + switch( operation ) + { + case MBEDTLS_ENCRYPT: + mode = MBEDTLS_AES_ENCRYPT; + break; + case MBEDTLS_DECRYPT: + mode = MBEDTLS_AES_DECRYPT; + break; + default: + return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; + } + + return mbedtls_aes_crypt_xts( xts_ctx, mode, length, + data_unit, input, output ); +} +#endif /* MBEDTLS_CIPHER_MODE_XTS */ + static int aes_setkey_dec_wrap( void *ctx, const unsigned char *key, unsigned int key_bitlen ) { @@ -187,9 +235,15 @@ static const mbedtls_cipher_base_t aes_info = { #if defined(MBEDTLS_CIPHER_MODE_CFB) aes_crypt_cfb128_wrap, #endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + aes_crypt_ofb_wrap, +#endif #if defined(MBEDTLS_CIPHER_MODE_CTR) aes_crypt_ctr_wrap, #endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + NULL, +#endif #if defined(MBEDTLS_CIPHER_MODE_STREAM) NULL, #endif @@ -302,6 +356,41 @@ static const mbedtls_cipher_info_t aes_256_cfb128_info = { }; #endif /* MBEDTLS_CIPHER_MODE_CFB */ +#if defined(MBEDTLS_CIPHER_MODE_OFB) +static const mbedtls_cipher_info_t aes_128_ofb_info = { + MBEDTLS_CIPHER_AES_128_OFB, + MBEDTLS_MODE_OFB, + 128, + "AES-128-OFB", + 16, + 0, + 16, + &aes_info +}; + +static const mbedtls_cipher_info_t aes_192_ofb_info = { + MBEDTLS_CIPHER_AES_192_OFB, + MBEDTLS_MODE_OFB, + 192, + "AES-192-OFB", + 16, + 0, + 16, + &aes_info +}; + +static const mbedtls_cipher_info_t aes_256_ofb_info = { + MBEDTLS_CIPHER_AES_256_OFB, + MBEDTLS_MODE_OFB, + 256, + "AES-256-OFB", + 16, + 0, + 16, + &aes_info +}; +#endif /* MBEDTLS_CIPHER_MODE_OFB */ + #if defined(MBEDTLS_CIPHER_MODE_CTR) static const mbedtls_cipher_info_t aes_128_ctr_info = { MBEDTLS_CIPHER_AES_128_CTR, @@ -337,6 +426,92 @@ static const mbedtls_cipher_info_t aes_256_ctr_info = { }; #endif /* MBEDTLS_CIPHER_MODE_CTR */ +#if defined(MBEDTLS_CIPHER_MODE_XTS) +static int xts_aes_setkey_enc_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + mbedtls_aes_xts_context *xts_ctx = ctx; + return( mbedtls_aes_xts_setkey_enc( xts_ctx, key, key_bitlen ) ); +} + +static int xts_aes_setkey_dec_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + mbedtls_aes_xts_context *xts_ctx = ctx; + return( mbedtls_aes_xts_setkey_dec( xts_ctx, key, key_bitlen ) ); +} + +static void *xts_aes_ctx_alloc( void ) +{ + mbedtls_aes_xts_context *xts_ctx = mbedtls_calloc( 1, sizeof( *xts_ctx ) ); + + if( xts_ctx != NULL ) + mbedtls_aes_xts_init( xts_ctx ); + + return( xts_ctx ); +} + +static void xts_aes_ctx_free( void *ctx ) +{ + mbedtls_aes_xts_context *xts_ctx = ctx; + + if( xts_ctx == NULL ) + return; + + mbedtls_aes_xts_free( xts_ctx ); + mbedtls_free( xts_ctx ); +} + +static const mbedtls_cipher_base_t xts_aes_info = { + MBEDTLS_CIPHER_ID_AES, + NULL, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + aes_crypt_xts_wrap, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + NULL, +#endif + xts_aes_setkey_enc_wrap, + xts_aes_setkey_dec_wrap, + xts_aes_ctx_alloc, + xts_aes_ctx_free +}; + +static const mbedtls_cipher_info_t aes_128_xts_info = { + MBEDTLS_CIPHER_AES_128_XTS, + MBEDTLS_MODE_XTS, + 256, + "AES-128-XTS", + 16, + 0, + 16, + &xts_aes_info +}; + +static const mbedtls_cipher_info_t aes_256_xts_info = { + MBEDTLS_CIPHER_AES_256_XTS, + MBEDTLS_MODE_XTS, + 512, + "AES-256-XTS", + 16, + 0, + 16, + &xts_aes_info +}; +#endif /* MBEDTLS_CIPHER_MODE_XTS */ + #if defined(MBEDTLS_GCM_C) static int gcm_aes_setkey_wrap( void *ctx, const unsigned char *key, unsigned int key_bitlen ) @@ -354,9 +529,15 @@ static const mbedtls_cipher_base_t gcm_aes_info = { #if defined(MBEDTLS_CIPHER_MODE_CFB) NULL, #endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + NULL, +#endif #if defined(MBEDTLS_CIPHER_MODE_CTR) NULL, #endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + NULL, +#endif #if defined(MBEDTLS_CIPHER_MODE_STREAM) NULL, #endif @@ -417,9 +598,15 @@ static const mbedtls_cipher_base_t ccm_aes_info = { #if defined(MBEDTLS_CIPHER_MODE_CFB) NULL, #endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + NULL, +#endif #if defined(MBEDTLS_CIPHER_MODE_CTR) NULL, #endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + NULL, +#endif #if defined(MBEDTLS_CIPHER_MODE_STREAM) NULL, #endif @@ -544,9 +731,15 @@ static const mbedtls_cipher_base_t camellia_info = { #if defined(MBEDTLS_CIPHER_MODE_CFB) camellia_crypt_cfb128_wrap, #endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + NULL, +#endif #if defined(MBEDTLS_CIPHER_MODE_CTR) camellia_crypt_ctr_wrap, #endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + NULL, +#endif #if defined(MBEDTLS_CIPHER_MODE_STREAM) NULL, #endif @@ -711,9 +904,15 @@ static const mbedtls_cipher_base_t gcm_camellia_info = { #if defined(MBEDTLS_CIPHER_MODE_CFB) NULL, #endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + NULL, +#endif #if defined(MBEDTLS_CIPHER_MODE_CTR) NULL, #endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + NULL, +#endif #if defined(MBEDTLS_CIPHER_MODE_STREAM) NULL, #endif @@ -774,9 +973,15 @@ static const mbedtls_cipher_base_t ccm_camellia_info = { #if defined(MBEDTLS_CIPHER_MODE_CFB) NULL, #endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + NULL, +#endif #if defined(MBEDTLS_CIPHER_MODE_CTR) NULL, #endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + NULL, +#endif #if defined(MBEDTLS_CIPHER_MODE_STREAM) NULL, #endif @@ -822,6 +1027,382 @@ static const mbedtls_cipher_info_t camellia_256_ccm_info = { #endif /* MBEDTLS_CAMELLIA_C */ +#if defined(MBEDTLS_ARIA_C) + +static int aria_crypt_ecb_wrap( void *ctx, mbedtls_operation_t operation, + const unsigned char *input, unsigned char *output ) +{ + (void) operation; + return mbedtls_aria_crypt_ecb( (mbedtls_aria_context *) ctx, input, + output ); +} + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +static int aria_crypt_cbc_wrap( void *ctx, mbedtls_operation_t operation, + size_t length, unsigned char *iv, + const unsigned char *input, unsigned char *output ) +{ + return mbedtls_aria_crypt_cbc( (mbedtls_aria_context *) ctx, operation, length, iv, + input, output ); +} +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) +static int aria_crypt_cfb128_wrap( void *ctx, mbedtls_operation_t operation, + size_t length, size_t *iv_off, unsigned char *iv, + const unsigned char *input, unsigned char *output ) +{ + return mbedtls_aria_crypt_cfb128( (mbedtls_aria_context *) ctx, operation, length, + iv_off, iv, input, output ); +} +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +static int aria_crypt_ctr_wrap( void *ctx, size_t length, size_t *nc_off, + unsigned char *nonce_counter, unsigned char *stream_block, + const unsigned char *input, unsigned char *output ) +{ + return mbedtls_aria_crypt_ctr( (mbedtls_aria_context *) ctx, length, nc_off, + nonce_counter, stream_block, input, output ); +} +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + +static int aria_setkey_dec_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + return mbedtls_aria_setkey_dec( (mbedtls_aria_context *) ctx, key, key_bitlen ); +} + +static int aria_setkey_enc_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + return mbedtls_aria_setkey_enc( (mbedtls_aria_context *) ctx, key, key_bitlen ); +} + +static void * aria_ctx_alloc( void ) +{ + mbedtls_aria_context *ctx; + ctx = mbedtls_calloc( 1, sizeof( mbedtls_aria_context ) ); + + if( ctx == NULL ) + return( NULL ); + + mbedtls_aria_init( ctx ); + + return( ctx ); +} + +static void aria_ctx_free( void *ctx ) +{ + mbedtls_aria_free( (mbedtls_aria_context *) ctx ); + mbedtls_free( ctx ); +} + +static const mbedtls_cipher_base_t aria_info = { + MBEDTLS_CIPHER_ID_ARIA, + aria_crypt_ecb_wrap, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + aria_crypt_cbc_wrap, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + aria_crypt_cfb128_wrap, +#endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + aria_crypt_ctr_wrap, +#endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + NULL, +#endif + aria_setkey_enc_wrap, + aria_setkey_dec_wrap, + aria_ctx_alloc, + aria_ctx_free +}; + +static const mbedtls_cipher_info_t aria_128_ecb_info = { + MBEDTLS_CIPHER_ARIA_128_ECB, + MBEDTLS_MODE_ECB, + 128, + "ARIA-128-ECB", + 16, + 0, + 16, + &aria_info +}; + +static const mbedtls_cipher_info_t aria_192_ecb_info = { + MBEDTLS_CIPHER_ARIA_192_ECB, + MBEDTLS_MODE_ECB, + 192, + "ARIA-192-ECB", + 16, + 0, + 16, + &aria_info +}; + +static const mbedtls_cipher_info_t aria_256_ecb_info = { + MBEDTLS_CIPHER_ARIA_256_ECB, + MBEDTLS_MODE_ECB, + 256, + "ARIA-256-ECB", + 16, + 0, + 16, + &aria_info +}; + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +static const mbedtls_cipher_info_t aria_128_cbc_info = { + MBEDTLS_CIPHER_ARIA_128_CBC, + MBEDTLS_MODE_CBC, + 128, + "ARIA-128-CBC", + 16, + 0, + 16, + &aria_info +}; + +static const mbedtls_cipher_info_t aria_192_cbc_info = { + MBEDTLS_CIPHER_ARIA_192_CBC, + MBEDTLS_MODE_CBC, + 192, + "ARIA-192-CBC", + 16, + 0, + 16, + &aria_info +}; + +static const mbedtls_cipher_info_t aria_256_cbc_info = { + MBEDTLS_CIPHER_ARIA_256_CBC, + MBEDTLS_MODE_CBC, + 256, + "ARIA-256-CBC", + 16, + 0, + 16, + &aria_info +}; +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) +static const mbedtls_cipher_info_t aria_128_cfb128_info = { + MBEDTLS_CIPHER_ARIA_128_CFB128, + MBEDTLS_MODE_CFB, + 128, + "ARIA-128-CFB128", + 16, + 0, + 16, + &aria_info +}; + +static const mbedtls_cipher_info_t aria_192_cfb128_info = { + MBEDTLS_CIPHER_ARIA_192_CFB128, + MBEDTLS_MODE_CFB, + 192, + "ARIA-192-CFB128", + 16, + 0, + 16, + &aria_info +}; + +static const mbedtls_cipher_info_t aria_256_cfb128_info = { + MBEDTLS_CIPHER_ARIA_256_CFB128, + MBEDTLS_MODE_CFB, + 256, + "ARIA-256-CFB128", + 16, + 0, + 16, + &aria_info +}; +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +static const mbedtls_cipher_info_t aria_128_ctr_info = { + MBEDTLS_CIPHER_ARIA_128_CTR, + MBEDTLS_MODE_CTR, + 128, + "ARIA-128-CTR", + 16, + 0, + 16, + &aria_info +}; + +static const mbedtls_cipher_info_t aria_192_ctr_info = { + MBEDTLS_CIPHER_ARIA_192_CTR, + MBEDTLS_MODE_CTR, + 192, + "ARIA-192-CTR", + 16, + 0, + 16, + &aria_info +}; + +static const mbedtls_cipher_info_t aria_256_ctr_info = { + MBEDTLS_CIPHER_ARIA_256_CTR, + MBEDTLS_MODE_CTR, + 256, + "ARIA-256-CTR", + 16, + 0, + 16, + &aria_info +}; +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + +#if defined(MBEDTLS_GCM_C) +static int gcm_aria_setkey_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + return mbedtls_gcm_setkey( (mbedtls_gcm_context *) ctx, MBEDTLS_CIPHER_ID_ARIA, + key, key_bitlen ); +} + +static const mbedtls_cipher_base_t gcm_aria_info = { + MBEDTLS_CIPHER_ID_ARIA, + NULL, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + NULL, +#endif + gcm_aria_setkey_wrap, + gcm_aria_setkey_wrap, + gcm_ctx_alloc, + gcm_ctx_free, +}; + +static const mbedtls_cipher_info_t aria_128_gcm_info = { + MBEDTLS_CIPHER_ARIA_128_GCM, + MBEDTLS_MODE_GCM, + 128, + "ARIA-128-GCM", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &gcm_aria_info +}; + +static const mbedtls_cipher_info_t aria_192_gcm_info = { + MBEDTLS_CIPHER_ARIA_192_GCM, + MBEDTLS_MODE_GCM, + 192, + "ARIA-192-GCM", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &gcm_aria_info +}; + +static const mbedtls_cipher_info_t aria_256_gcm_info = { + MBEDTLS_CIPHER_ARIA_256_GCM, + MBEDTLS_MODE_GCM, + 256, + "ARIA-256-GCM", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &gcm_aria_info +}; +#endif /* MBEDTLS_GCM_C */ + +#if defined(MBEDTLS_CCM_C) +static int ccm_aria_setkey_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + return mbedtls_ccm_setkey( (mbedtls_ccm_context *) ctx, MBEDTLS_CIPHER_ID_ARIA, + key, key_bitlen ); +} + +static const mbedtls_cipher_base_t ccm_aria_info = { + MBEDTLS_CIPHER_ID_ARIA, + NULL, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + NULL, +#endif + ccm_aria_setkey_wrap, + ccm_aria_setkey_wrap, + ccm_ctx_alloc, + ccm_ctx_free, +}; + +static const mbedtls_cipher_info_t aria_128_ccm_info = { + MBEDTLS_CIPHER_ARIA_128_CCM, + MBEDTLS_MODE_CCM, + 128, + "ARIA-128-CCM", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &ccm_aria_info +}; + +static const mbedtls_cipher_info_t aria_192_ccm_info = { + MBEDTLS_CIPHER_ARIA_192_CCM, + MBEDTLS_MODE_CCM, + 192, + "ARIA-192-CCM", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &ccm_aria_info +}; + +static const mbedtls_cipher_info_t aria_256_ccm_info = { + MBEDTLS_CIPHER_ARIA_256_CCM, + MBEDTLS_MODE_CCM, + 256, + "ARIA-256-CCM", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &ccm_aria_info +}; +#endif /* MBEDTLS_CCM_C */ + +#endif /* MBEDTLS_ARIA_C */ + #if defined(MBEDTLS_DES_C) static int des_crypt_ecb_wrap( void *ctx, mbedtls_operation_t operation, @@ -950,9 +1531,15 @@ static const mbedtls_cipher_base_t des_info = { #if defined(MBEDTLS_CIPHER_MODE_CFB) NULL, #endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + NULL, +#endif #if defined(MBEDTLS_CIPHER_MODE_CTR) NULL, #endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + NULL, +#endif #if defined(MBEDTLS_CIPHER_MODE_STREAM) NULL, #endif @@ -995,9 +1582,15 @@ static const mbedtls_cipher_base_t des_ede_info = { #if defined(MBEDTLS_CIPHER_MODE_CFB) NULL, #endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + NULL, +#endif #if defined(MBEDTLS_CIPHER_MODE_CTR) NULL, #endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + NULL, +#endif #if defined(MBEDTLS_CIPHER_MODE_STREAM) NULL, #endif @@ -1040,9 +1633,15 @@ static const mbedtls_cipher_base_t des_ede3_info = { #if defined(MBEDTLS_CIPHER_MODE_CFB) NULL, #endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + NULL, +#endif #if defined(MBEDTLS_CIPHER_MODE_CTR) NULL, #endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + NULL, +#endif #if defined(MBEDTLS_CIPHER_MODE_STREAM) NULL, #endif @@ -1149,9 +1748,15 @@ static const mbedtls_cipher_base_t blowfish_info = { #if defined(MBEDTLS_CIPHER_MODE_CFB) blowfish_crypt_cfb64_wrap, #endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + NULL, +#endif #if defined(MBEDTLS_CIPHER_MODE_CTR) blowfish_crypt_ctr_wrap, #endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + NULL, +#endif #if defined(MBEDTLS_CIPHER_MODE_STREAM) NULL, #endif @@ -1259,9 +1864,15 @@ static const mbedtls_cipher_base_t arc4_base_info = { #if defined(MBEDTLS_CIPHER_MODE_CFB) NULL, #endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + NULL, +#endif #if defined(MBEDTLS_CIPHER_MODE_CTR) NULL, #endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + NULL, +#endif #if defined(MBEDTLS_CIPHER_MODE_STREAM) arc4_crypt_stream_wrap, #endif @@ -1283,6 +1894,162 @@ static const mbedtls_cipher_info_t arc4_128_info = { }; #endif /* MBEDTLS_ARC4_C */ +#if defined(MBEDTLS_CHACHA20_C) + +static int chacha20_setkey_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + if( key_bitlen != 256U ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + if ( 0 != mbedtls_chacha20_setkey( (mbedtls_chacha20_context*)ctx, key ) ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + return( 0 ); +} + +static int chacha20_stream_wrap( void *ctx, size_t length, + const unsigned char *input, + unsigned char *output ) +{ + int ret; + + ret = mbedtls_chacha20_update( ctx, length, input, output ); + if( ret == MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + return( ret ); +} + +static void * chacha20_ctx_alloc( void ) +{ + mbedtls_chacha20_context *ctx; + ctx = mbedtls_calloc( 1, sizeof( mbedtls_chacha20_context ) ); + + if( ctx == NULL ) + return( NULL ); + + mbedtls_chacha20_init( ctx ); + + return( ctx ); +} + +static void chacha20_ctx_free( void *ctx ) +{ + mbedtls_chacha20_free( (mbedtls_chacha20_context *) ctx ); + mbedtls_free( ctx ); +} + +static const mbedtls_cipher_base_t chacha20_base_info = { + MBEDTLS_CIPHER_ID_CHACHA20, + NULL, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + chacha20_stream_wrap, +#endif + chacha20_setkey_wrap, + chacha20_setkey_wrap, + chacha20_ctx_alloc, + chacha20_ctx_free +}; +static const mbedtls_cipher_info_t chacha20_info = { + MBEDTLS_CIPHER_CHACHA20, + MBEDTLS_MODE_STREAM, + 256, + "CHACHA20", + 12, + 0, + 1, + &chacha20_base_info +}; +#endif /* MBEDTLS_CHACHA20_C */ + +#if defined(MBEDTLS_CHACHAPOLY_C) + +static int chachapoly_setkey_wrap( void *ctx, + const unsigned char *key, + unsigned int key_bitlen ) +{ + if( key_bitlen != 256U ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + if ( 0 != mbedtls_chachapoly_setkey( (mbedtls_chachapoly_context*)ctx, key ) ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + return( 0 ); +} + +static void * chachapoly_ctx_alloc( void ) +{ + mbedtls_chachapoly_context *ctx; + ctx = mbedtls_calloc( 1, sizeof( mbedtls_chachapoly_context ) ); + + if( ctx == NULL ) + return( NULL ); + + mbedtls_chachapoly_init( ctx ); + + return( ctx ); +} + +static void chachapoly_ctx_free( void *ctx ) +{ + mbedtls_chachapoly_free( (mbedtls_chachapoly_context *) ctx ); + mbedtls_free( ctx ); +} + +static const mbedtls_cipher_base_t chachapoly_base_info = { + MBEDTLS_CIPHER_ID_CHACHA20, + NULL, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + NULL, +#endif + chachapoly_setkey_wrap, + chachapoly_setkey_wrap, + chachapoly_ctx_alloc, + chachapoly_ctx_free +}; +static const mbedtls_cipher_info_t chachapoly_info = { + MBEDTLS_CIPHER_CHACHA20_POLY1305, + MBEDTLS_MODE_CHACHAPOLY, + 256, + "CHACHA20-POLY1305", + 12, + 0, + 1, + &chachapoly_base_info +}; +#endif /* MBEDTLS_CHACHAPOLY_C */ + #if defined(MBEDTLS_CIPHER_NULL_CIPHER) static int null_crypt_stream( void *ctx, size_t length, const unsigned char *input, @@ -1322,9 +2089,15 @@ static const mbedtls_cipher_base_t null_base_info = { #if defined(MBEDTLS_CIPHER_MODE_CFB) NULL, #endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + NULL, +#endif #if defined(MBEDTLS_CIPHER_MODE_CTR) NULL, #endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + NULL, +#endif #if defined(MBEDTLS_CIPHER_MODE_STREAM) null_crypt_stream, #endif @@ -1362,11 +2135,20 @@ const mbedtls_cipher_definition_t mbedtls_cipher_definitions[] = { MBEDTLS_CIPHER_AES_192_CFB128, &aes_192_cfb128_info }, { MBEDTLS_CIPHER_AES_256_CFB128, &aes_256_cfb128_info }, #endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + { MBEDTLS_CIPHER_AES_128_OFB, &aes_128_ofb_info }, + { MBEDTLS_CIPHER_AES_192_OFB, &aes_192_ofb_info }, + { MBEDTLS_CIPHER_AES_256_OFB, &aes_256_ofb_info }, +#endif #if defined(MBEDTLS_CIPHER_MODE_CTR) { MBEDTLS_CIPHER_AES_128_CTR, &aes_128_ctr_info }, { MBEDTLS_CIPHER_AES_192_CTR, &aes_192_ctr_info }, { MBEDTLS_CIPHER_AES_256_CTR, &aes_256_ctr_info }, #endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + { MBEDTLS_CIPHER_AES_128_XTS, &aes_128_xts_info }, + { MBEDTLS_CIPHER_AES_256_XTS, &aes_256_xts_info }, +#endif #if defined(MBEDTLS_GCM_C) { MBEDTLS_CIPHER_AES_128_GCM, &aes_128_gcm_info }, { MBEDTLS_CIPHER_AES_192_GCM, &aes_192_gcm_info }, @@ -1427,6 +2209,37 @@ const mbedtls_cipher_definition_t mbedtls_cipher_definitions[] = #endif #endif /* MBEDTLS_CAMELLIA_C */ +#if defined(MBEDTLS_ARIA_C) + { MBEDTLS_CIPHER_ARIA_128_ECB, &aria_128_ecb_info }, + { MBEDTLS_CIPHER_ARIA_192_ECB, &aria_192_ecb_info }, + { MBEDTLS_CIPHER_ARIA_256_ECB, &aria_256_ecb_info }, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_CIPHER_ARIA_128_CBC, &aria_128_cbc_info }, + { MBEDTLS_CIPHER_ARIA_192_CBC, &aria_192_cbc_info }, + { MBEDTLS_CIPHER_ARIA_256_CBC, &aria_256_cbc_info }, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + { MBEDTLS_CIPHER_ARIA_128_CFB128, &aria_128_cfb128_info }, + { MBEDTLS_CIPHER_ARIA_192_CFB128, &aria_192_cfb128_info }, + { MBEDTLS_CIPHER_ARIA_256_CFB128, &aria_256_cfb128_info }, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + { MBEDTLS_CIPHER_ARIA_128_CTR, &aria_128_ctr_info }, + { MBEDTLS_CIPHER_ARIA_192_CTR, &aria_192_ctr_info }, + { MBEDTLS_CIPHER_ARIA_256_CTR, &aria_256_ctr_info }, +#endif +#if defined(MBEDTLS_GCM_C) + { MBEDTLS_CIPHER_ARIA_128_GCM, &aria_128_gcm_info }, + { MBEDTLS_CIPHER_ARIA_192_GCM, &aria_192_gcm_info }, + { MBEDTLS_CIPHER_ARIA_256_GCM, &aria_256_gcm_info }, +#endif +#if defined(MBEDTLS_CCM_C) + { MBEDTLS_CIPHER_ARIA_128_CCM, &aria_128_ccm_info }, + { MBEDTLS_CIPHER_ARIA_192_CCM, &aria_192_ccm_info }, + { MBEDTLS_CIPHER_ARIA_256_CCM, &aria_256_ccm_info }, +#endif +#endif /* MBEDTLS_ARIA_C */ + #if defined(MBEDTLS_DES_C) { MBEDTLS_CIPHER_DES_ECB, &des_ecb_info }, { MBEDTLS_CIPHER_DES_EDE_ECB, &des_ede_ecb_info }, @@ -1438,6 +2251,14 @@ const mbedtls_cipher_definition_t mbedtls_cipher_definitions[] = #endif #endif /* MBEDTLS_DES_C */ +#if defined(MBEDTLS_CHACHA20_C) + { MBEDTLS_CIPHER_CHACHA20, &chacha20_info }, +#endif + +#if defined(MBEDTLS_CHACHAPOLY_C) + { MBEDTLS_CIPHER_CHACHA20_POLY1305, &chachapoly_info }, +#endif + #if defined(MBEDTLS_CIPHER_NULL_CIPHER) { MBEDTLS_CIPHER_NULL, &null_cipher_info }, #endif /* MBEDTLS_CIPHER_NULL_CIPHER */ diff --git a/thirdparty/mbedtls/library/cmac.c b/thirdparty/mbedtls/library/cmac.c index 9dbff90386..5d101e1c7d 100644 --- a/thirdparty/mbedtls/library/cmac.c +++ b/thirdparty/mbedtls/library/cmac.c @@ -49,6 +49,7 @@ #if defined(MBEDTLS_CMAC_C) #include "mbedtls/cmac.h" +#include "mbedtls/platform_util.h" #include <string.h> @@ -67,11 +68,6 @@ #if !defined(MBEDTLS_CMAC_ALT) || defined(MBEDTLS_SELF_TEST) -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize( void *v, size_t n ) { - volatile unsigned char *p = (unsigned char*)v; while( n-- ) *p++ = 0; -} - /* * Multiplication by u in the Galois field of GF(2^n) * @@ -144,7 +140,7 @@ static int cmac_generate_subkeys( mbedtls_cipher_context_t *ctx, unsigned char L[MBEDTLS_CIPHER_BLKSIZE_MAX]; size_t olen, block_size; - mbedtls_zeroize( L, sizeof( L ) ); + mbedtls_platform_zeroize( L, sizeof( L ) ); block_size = ctx->cipher_info->block_size; @@ -162,7 +158,7 @@ static int cmac_generate_subkeys( mbedtls_cipher_context_t *ctx, goto exit; exit: - mbedtls_zeroize( L, sizeof( L ) ); + mbedtls_platform_zeroize( L, sizeof( L ) ); return( ret ); } @@ -238,7 +234,7 @@ int mbedtls_cipher_cmac_starts( mbedtls_cipher_context_t *ctx, ctx->cmac_ctx = cmac_ctx; - mbedtls_zeroize( cmac_ctx->state, sizeof( cmac_ctx->state ) ); + mbedtls_platform_zeroize( cmac_ctx->state, sizeof( cmac_ctx->state ) ); return 0; } @@ -330,8 +326,8 @@ int mbedtls_cipher_cmac_finish( mbedtls_cipher_context_t *ctx, block_size = ctx->cipher_info->block_size; state = cmac_ctx->state; - mbedtls_zeroize( K1, sizeof( K1 ) ); - mbedtls_zeroize( K2, sizeof( K2 ) ); + mbedtls_platform_zeroize( K1, sizeof( K1 ) ); + mbedtls_platform_zeroize( K2, sizeof( K2 ) ); cmac_generate_subkeys( ctx, K1, K2 ); last_block = cmac_ctx->unprocessed_block; @@ -361,14 +357,14 @@ int mbedtls_cipher_cmac_finish( mbedtls_cipher_context_t *ctx, exit: /* Wipe the generated keys on the stack, and any other transients to avoid * side channel leakage */ - mbedtls_zeroize( K1, sizeof( K1 ) ); - mbedtls_zeroize( K2, sizeof( K2 ) ); + mbedtls_platform_zeroize( K1, sizeof( K1 ) ); + mbedtls_platform_zeroize( K2, sizeof( K2 ) ); cmac_ctx->unprocessed_len = 0; - mbedtls_zeroize( cmac_ctx->unprocessed_block, - sizeof( cmac_ctx->unprocessed_block ) ); + mbedtls_platform_zeroize( cmac_ctx->unprocessed_block, + sizeof( cmac_ctx->unprocessed_block ) ); - mbedtls_zeroize( state, MBEDTLS_CIPHER_BLKSIZE_MAX ); + mbedtls_platform_zeroize( state, MBEDTLS_CIPHER_BLKSIZE_MAX ); return( ret ); } @@ -383,10 +379,10 @@ int mbedtls_cipher_cmac_reset( mbedtls_cipher_context_t *ctx ) /* Reset the internal state */ cmac_ctx->unprocessed_len = 0; - mbedtls_zeroize( cmac_ctx->unprocessed_block, - sizeof( cmac_ctx->unprocessed_block ) ); - mbedtls_zeroize( cmac_ctx->state, - sizeof( cmac_ctx->state ) ); + mbedtls_platform_zeroize( cmac_ctx->unprocessed_block, + sizeof( cmac_ctx->unprocessed_block ) ); + mbedtls_platform_zeroize( cmac_ctx->state, + sizeof( cmac_ctx->state ) ); return( 0 ); } @@ -466,7 +462,7 @@ int mbedtls_aes_cmac_prf_128( const unsigned char *key, size_t key_length, output ); exit: - mbedtls_zeroize( int_key, sizeof( int_key ) ); + mbedtls_platform_zeroize( int_key, sizeof( int_key ) ); return( ret ); } @@ -771,7 +767,7 @@ static int cmac_test_subkeys( int verbose, int block_size, int num_tests ) { - int i, ret; + int i, ret = 0; mbedtls_cipher_context_t ctx; const mbedtls_cipher_info_t *cipher_info; unsigned char K1[MBEDTLS_CIPHER_BLKSIZE_MAX]; @@ -832,6 +828,7 @@ static int cmac_test_subkeys( int verbose, mbedtls_cipher_free( &ctx ); } + ret = 0; goto exit; cleanup: @@ -853,7 +850,7 @@ static int cmac_test_wth_cipher( int verbose, int num_tests ) { const mbedtls_cipher_info_t *cipher_info; - int i, ret; + int i, ret = 0; unsigned char output[MBEDTLS_CIPHER_BLKSIZE_MAX]; cipher_info = mbedtls_cipher_info_from_type( cipher_type ); @@ -887,6 +884,7 @@ static int cmac_test_wth_cipher( int verbose, if( verbose != 0 ) mbedtls_printf( "passed\n" ); } + ret = 0; exit: return( ret ); diff --git a/thirdparty/mbedtls/library/ctr_drbg.c b/thirdparty/mbedtls/library/ctr_drbg.c index ff532a0134..d0e5ba862d 100644 --- a/thirdparty/mbedtls/library/ctr_drbg.c +++ b/thirdparty/mbedtls/library/ctr_drbg.c @@ -33,6 +33,7 @@ #if defined(MBEDTLS_CTR_DRBG_C) #include "mbedtls/ctr_drbg.h" +#include "mbedtls/platform_util.h" #include <string.h> @@ -49,11 +50,6 @@ #endif /* MBEDTLS_PLATFORM_C */ #endif /* MBEDTLS_SELF_TEST */ -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize( void *v, size_t n ) { - volatile unsigned char *p = v; while( n-- ) *p++ = 0; -} - /* * CTR_DRBG context initialization */ @@ -125,7 +121,7 @@ void mbedtls_ctr_drbg_free( mbedtls_ctr_drbg_context *ctx ) mbedtls_mutex_free( &ctx->mutex ); #endif mbedtls_aes_free( &ctx->aes_ctx ); - mbedtls_zeroize( ctx, sizeof( mbedtls_ctr_drbg_context ) ); + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_ctr_drbg_context ) ); } void mbedtls_ctr_drbg_set_prediction_resistance( mbedtls_ctr_drbg_context *ctx, int resistance ) @@ -245,16 +241,16 @@ exit: /* * tidy up the stack */ - mbedtls_zeroize( buf, sizeof( buf ) ); - mbedtls_zeroize( tmp, sizeof( tmp ) ); - mbedtls_zeroize( key, sizeof( key ) ); - mbedtls_zeroize( chain, sizeof( chain ) ); + mbedtls_platform_zeroize( buf, sizeof( buf ) ); + mbedtls_platform_zeroize( tmp, sizeof( tmp ) ); + mbedtls_platform_zeroize( key, sizeof( key ) ); + mbedtls_platform_zeroize( chain, sizeof( chain ) ); if( 0 != ret ) { /* * wipe partial seed from memory */ - mbedtls_zeroize( output, MBEDTLS_CTR_DRBG_SEEDLEN ); + mbedtls_platform_zeroize( output, MBEDTLS_CTR_DRBG_SEEDLEN ); } return( ret ); @@ -493,7 +489,7 @@ int mbedtls_ctr_drbg_write_seed_file( mbedtls_ctr_drbg_context *ctx, const char ret = 0; exit: - mbedtls_zeroize( buf, sizeof( buf ) ); + mbedtls_platform_zeroize( buf, sizeof( buf ) ); fclose( f ); return( ret ); @@ -526,7 +522,7 @@ int mbedtls_ctr_drbg_update_seed_file( mbedtls_ctr_drbg_context *ctx, const char fclose( f ); - mbedtls_zeroize( buf, sizeof( buf ) ); + mbedtls_platform_zeroize( buf, sizeof( buf ) ); if( ret != 0 ) return( ret ); diff --git a/thirdparty/mbedtls/library/des.c b/thirdparty/mbedtls/library/des.c index 09f95cfc3b..ca9e071f32 100644 --- a/thirdparty/mbedtls/library/des.c +++ b/thirdparty/mbedtls/library/des.c @@ -34,6 +34,7 @@ #if defined(MBEDTLS_DES_C) #include "mbedtls/des.h" +#include "mbedtls/platform_util.h" #include <string.h> @@ -48,11 +49,6 @@ #if !defined(MBEDTLS_DES_ALT) -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize( void *v, size_t n ) { - volatile unsigned char *p = (unsigned char*)v; while( n-- ) *p++ = 0; -} - /* * 32-bit integer manipulation macros (big endian) */ @@ -316,7 +312,7 @@ void mbedtls_des_free( mbedtls_des_context *ctx ) if( ctx == NULL ) return; - mbedtls_zeroize( ctx, sizeof( mbedtls_des_context ) ); + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_des_context ) ); } void mbedtls_des3_init( mbedtls_des3_context *ctx ) @@ -329,7 +325,7 @@ void mbedtls_des3_free( mbedtls_des3_context *ctx ) if( ctx == NULL ) return; - mbedtls_zeroize( ctx, sizeof( mbedtls_des3_context ) ); + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_des3_context ) ); } static const unsigned char odd_parity_table[128] = { 1, 2, 4, 7, 8, @@ -553,7 +549,7 @@ int mbedtls_des3_set2key_enc( mbedtls_des3_context *ctx, uint32_t sk[96]; des3_set2key( ctx->sk, sk, key ); - mbedtls_zeroize( sk, sizeof( sk ) ); + mbedtls_platform_zeroize( sk, sizeof( sk ) ); return( 0 ); } @@ -567,7 +563,7 @@ int mbedtls_des3_set2key_dec( mbedtls_des3_context *ctx, uint32_t sk[96]; des3_set2key( sk, ctx->sk, key ); - mbedtls_zeroize( sk, sizeof( sk ) ); + mbedtls_platform_zeroize( sk, sizeof( sk ) ); return( 0 ); } @@ -604,7 +600,7 @@ int mbedtls_des3_set3key_enc( mbedtls_des3_context *ctx, uint32_t sk[96]; des3_set3key( ctx->sk, sk, key ); - mbedtls_zeroize( sk, sizeof( sk ) ); + mbedtls_platform_zeroize( sk, sizeof( sk ) ); return( 0 ); } @@ -618,7 +614,7 @@ int mbedtls_des3_set3key_dec( mbedtls_des3_context *ctx, uint32_t sk[96]; des3_set3key( sk, ctx->sk, key ); - mbedtls_zeroize( sk, sizeof( sk ) ); + mbedtls_platform_zeroize( sk, sizeof( sk ) ); return( 0 ); } diff --git a/thirdparty/mbedtls/library/dhm.c b/thirdparty/mbedtls/library/dhm.c index 28ac31003c..82cbb0ce88 100644 --- a/thirdparty/mbedtls/library/dhm.c +++ b/thirdparty/mbedtls/library/dhm.c @@ -36,6 +36,7 @@ #if defined(MBEDTLS_DHM_C) #include "mbedtls/dhm.h" +#include "mbedtls/platform_util.h" #include <string.h> @@ -58,10 +59,6 @@ #endif #if !defined(MBEDTLS_DHM_ALT) -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize( void *v, size_t n ) { - volatile unsigned char *p = v; while( n-- ) *p++ = 0; -} /* * helper to validate the mbedtls_mpi size and import it @@ -437,7 +434,7 @@ void mbedtls_dhm_free( mbedtls_dhm_context *ctx ) mbedtls_mpi_free( &ctx->GX ); mbedtls_mpi_free( &ctx->X ); mbedtls_mpi_free( &ctx->G ); mbedtls_mpi_free( &ctx->P ); - mbedtls_zeroize( ctx, sizeof( mbedtls_dhm_context ) ); + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_dhm_context ) ); } #if defined(MBEDTLS_ASN1_PARSE_C) @@ -575,7 +572,7 @@ static int load_file( const char *path, unsigned char **buf, size_t *n ) { fclose( f ); - mbedtls_zeroize( *buf, *n + 1 ); + mbedtls_platform_zeroize( *buf, *n + 1 ); mbedtls_free( *buf ); return( MBEDTLS_ERR_DHM_FILE_IO_ERROR ); @@ -605,7 +602,7 @@ int mbedtls_dhm_parse_dhmfile( mbedtls_dhm_context *dhm, const char *path ) ret = mbedtls_dhm_parse_dhm( dhm, buf, n ); - mbedtls_zeroize( buf, n ); + mbedtls_platform_zeroize( buf, n ); mbedtls_free( buf ); return( ret ); diff --git a/thirdparty/mbedtls/library/ecdsa.c b/thirdparty/mbedtls/library/ecdsa.c index 826fefe5c6..17a88bdd29 100644 --- a/thirdparty/mbedtls/library/ecdsa.c +++ b/thirdparty/mbedtls/library/ecdsa.c @@ -400,6 +400,9 @@ int mbedtls_ecdsa_read_signature( mbedtls_ecdsa_context *ctx, &ctx->Q, &r, &s ) ) != 0 ) goto cleanup; + /* At this point we know that the buffer starts with a valid signature. + * Return 0 if the buffer just contains the signature, and a specific + * error code if the valid signature is followed by more data. */ if( p != end ) ret = MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH; diff --git a/thirdparty/mbedtls/library/ecjpake.c b/thirdparty/mbedtls/library/ecjpake.c index e8f40862be..ec5a4007db 100644 --- a/thirdparty/mbedtls/library/ecjpake.c +++ b/thirdparty/mbedtls/library/ecjpake.c @@ -301,7 +301,7 @@ cleanup: */ static int ecjpake_zkp_write( const mbedtls_md_info_t *md_info, const mbedtls_ecp_group *grp, - const int pf, + const int pf, const mbedtls_ecp_point *G, const mbedtls_mpi *x, const mbedtls_ecp_point *X, diff --git a/thirdparty/mbedtls/library/ecp.c b/thirdparty/mbedtls/library/ecp.c index b41baef27a..41db3fbe5b 100644 --- a/thirdparty/mbedtls/library/ecp.c +++ b/thirdparty/mbedtls/library/ecp.c @@ -26,6 +26,7 @@ * GECC = Guide to Elliptic Curve Cryptography - Hankerson, Menezes, Vanstone * FIPS 186-3 http://csrc.nist.gov/publications/fips/fips186-3/fips_186-3.pdf * RFC 4492 for the related TLS structures and constants + * RFC 7748 for the Curve448 and Curve25519 curve definitions * * [Curve25519] http://cr.yp.to/ecdh/curve25519-20060209.pdf * @@ -50,6 +51,7 @@ #include "mbedtls/ecp.h" #include "mbedtls/threading.h" +#include "mbedtls/platform_util.h" #include <string.h> @@ -72,11 +74,6 @@ #define inline __inline #endif -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize( void *v, size_t n ) { - volatile unsigned char *p = v; while( n-- ) *p++ = 0; -} - #if defined(MBEDTLS_SELF_TEST) /* * Counts of point addition and doubling, and field multiplications. @@ -99,7 +96,8 @@ static unsigned long add_count, dbl_count, mul_count; #define ECP_SHORTWEIERSTRASS #endif -#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) +#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) || \ + defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) #define ECP_MONTGOMERY #endif @@ -346,7 +344,7 @@ void mbedtls_ecp_group_free( mbedtls_ecp_group *grp ) mbedtls_free( grp->T ); } - mbedtls_zeroize( grp, sizeof( mbedtls_ecp_group ) ); + mbedtls_platform_zeroize( grp, sizeof( mbedtls_ecp_group ) ); } /* @@ -1852,6 +1850,8 @@ cleanup: static int ecp_check_pubkey_mx( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt ) { /* [Curve25519 p. 5] Just check X is the correct number of bytes */ + /* Allow any public value, if it's too big then we'll just reduce it mod p + * (RFC 7748 sec. 5 para. 3). */ if( mbedtls_mpi_size( &pt->X ) > ( grp->nbits + 7 ) / 8 ) return( MBEDTLS_ERR_ECP_INVALID_KEY ); @@ -1887,14 +1887,18 @@ int mbedtls_ecp_check_privkey( const mbedtls_ecp_group *grp, const mbedtls_mpi * #if defined(ECP_MONTGOMERY) if( ecp_get_type( grp ) == ECP_TYPE_MONTGOMERY ) { - /* see [Curve25519] page 5 */ + /* see RFC 7748 sec. 5 para. 5 */ if( mbedtls_mpi_get_bit( d, 0 ) != 0 || mbedtls_mpi_get_bit( d, 1 ) != 0 || - mbedtls_mpi_get_bit( d, 2 ) != 0 || mbedtls_mpi_bitlen( d ) - 1 != grp->nbits ) /* mbedtls_mpi_bitlen is one-based! */ return( MBEDTLS_ERR_ECP_INVALID_KEY ); else - return( 0 ); + + /* see [Curve25519] page 5 */ + if( grp->nbits == 254 && mbedtls_mpi_get_bit( d, 2 ) != 0 ) + return( MBEDTLS_ERR_ECP_INVALID_KEY ); + + return( 0 ); } #endif /* ECP_MONTGOMERY */ #if defined(ECP_SHORTWEIERSTRASS) @@ -1941,10 +1945,14 @@ int mbedtls_ecp_gen_keypair_base( mbedtls_ecp_group *grp, else MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, grp->nbits, 1 ) ); - /* Make sure the last three bits are unset */ + /* Make sure the last two bits are unset for Curve448, three bits for + Curve25519 */ MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, 0, 0 ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, 1, 0 ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, 2, 0 ) ); + if( grp->nbits == 254 ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, 2, 0 ) ); + } } else #endif /* ECP_MONTGOMERY */ diff --git a/thirdparty/mbedtls/library/ecp_curves.c b/thirdparty/mbedtls/library/ecp_curves.c index df5ac3eea5..68e2441ae8 100644 --- a/thirdparty/mbedtls/library/ecp_curves.c +++ b/thirdparty/mbedtls/library/ecp_curves.c @@ -627,6 +627,9 @@ static int ecp_mod_p521( mbedtls_mpi * ); #if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) static int ecp_mod_p255( mbedtls_mpi * ); #endif +#if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) +static int ecp_mod_p448( mbedtls_mpi * ); +#endif #if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) static int ecp_mod_p192k1( mbedtls_mpi * ); #endif @@ -670,7 +673,12 @@ static int ecp_use_curve25519( mbedtls_ecp_group *grp ) MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &grp->P, &grp->P, 19 ) ); grp->pbits = mbedtls_mpi_bitlen( &grp->P ); - /* Y intentionaly not set, since we use x/z coordinates. + /* N = 2^252 + 27742317777372353535851937790883648493 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &grp->N, 16, + "14DEF9DEA2F79CD65812631A5CF5D3ED" ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( &grp->N, 252, 1 ) ); + + /* Y intentionally not set, since we use x/z coordinates. * This is used as a marker to identify Montgomery curves! */ MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &grp->G.X, 9 ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &grp->G.Z, 1 ) ); @@ -687,6 +695,52 @@ cleanup: } #endif /* MBEDTLS_ECP_DP_CURVE25519_ENABLED */ +#if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) +/* + * Specialized function for creating the Curve448 group + */ +static int ecp_use_curve448( mbedtls_ecp_group *grp ) +{ + mbedtls_mpi Ns; + int ret; + + mbedtls_mpi_init( &Ns ); + + /* Actually ( A + 2 ) / 4 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &grp->A, 16, "98AA" ) ); + + /* P = 2^448 - 2^224 - 1 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &grp->P, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &grp->P, 224 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &grp->P, &grp->P, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &grp->P, 224 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &grp->P, &grp->P, 1 ) ); + grp->pbits = mbedtls_mpi_bitlen( &grp->P ); + + /* Y intentionally not set, since we use x/z coordinates. + * This is used as a marker to identify Montgomery curves! */ + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &grp->G.X, 5 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &grp->G.Z, 1 ) ); + mbedtls_mpi_free( &grp->G.Y ); + + /* N = 2^446 - 13818066809895115352007386748515426880336692474882178609894547503885 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( &grp->N, 446, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &Ns, 16, + "8335DC163BB124B65129C96FDE933D8D723A70AADC873D6D54A7BB0D" ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &grp->N, &grp->N, &Ns ) ); + + /* Actually, the required msb for private keys */ + grp->nbits = 447; + +cleanup: + mbedtls_mpi_free( &Ns ); + if( ret != 0 ) + mbedtls_ecp_group_free( grp ); + + return( ret ); +} +#endif /* MBEDTLS_ECP_DP_CURVE448_ENABLED */ + /* * Set a group using well-known domain parameters */ @@ -767,6 +821,12 @@ int mbedtls_ecp_group_load( mbedtls_ecp_group *grp, mbedtls_ecp_group_id id ) return( ecp_use_curve25519( grp ) ); #endif /* MBEDTLS_ECP_DP_CURVE25519_ENABLED */ +#if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) + case MBEDTLS_ECP_DP_CURVE448: + grp->modp = ecp_mod_p448; + return( ecp_use_curve448( grp ) ); +#endif /* MBEDTLS_ECP_DP_CURVE448_ENABLED */ + default: mbedtls_ecp_group_free( grp ); return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE ); @@ -1176,7 +1236,7 @@ static int ecp_mod_p255( mbedtls_mpi *N ) M.s = 1; M.n = N->n - ( P255_WIDTH - 1 ); if( M.n > P255_WIDTH + 1 ) - M.n = P255_WIDTH + 1; + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); M.p = Mp; memset( Mp, 0, sizeof Mp ); memcpy( Mp, N->p + P255_WIDTH - 1, M.n * sizeof( mbedtls_mpi_uint ) ); @@ -1197,6 +1257,77 @@ cleanup: } #endif /* MBEDTLS_ECP_DP_CURVE25519_ENABLED */ +#if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) + +/* Size of p448 in terms of mbedtls_mpi_uint */ +#define P448_WIDTH ( 448 / 8 / sizeof( mbedtls_mpi_uint ) ) + +/* Number of limbs fully occupied by 2^224 (max), and limbs used by it (min) */ +#define DIV_ROUND_UP( X, Y ) ( ( ( X ) + ( Y ) - 1 ) / ( Y ) ) +#define P224_WIDTH_MIN ( 28 / sizeof( mbedtls_mpi_uint ) ) +#define P224_WIDTH_MAX DIV_ROUND_UP( 28, sizeof( mbedtls_mpi_uint ) ) +#define P224_UNUSED_BITS ( ( P224_WIDTH_MAX * sizeof( mbedtls_mpi_uint ) * 8 ) - 224 ) + +/* + * Fast quasi-reduction modulo p448 = 2^448 - 2^224 - 1 + * Write N as A0 + 2^448 A1 and A1 as B0 + 2^224 B1, and return + * A0 + A1 + B1 + (B0 + B1) * 2^224. This is different to the reference + * implementation of Curve448, which uses its own special 56-bit limbs rather + * than a generic bignum library. We could squeeze some extra speed out on + * 32-bit machines by splitting N up into 32-bit limbs and doing the + * arithmetic using the limbs directly as we do for the NIST primes above, + * but for 64-bit targets it should use half the number of operations if we do + * the reduction with 224-bit limbs, since mpi_add_mpi will then use 64-bit adds. + */ +static int ecp_mod_p448( mbedtls_mpi *N ) +{ + int ret; + size_t i; + mbedtls_mpi M, Q; + mbedtls_mpi_uint Mp[P448_WIDTH + 1], Qp[P448_WIDTH]; + + if( N->n <= P448_WIDTH ) + return( 0 ); + + /* M = A1 */ + M.s = 1; + M.n = N->n - ( P448_WIDTH ); + if( M.n > P448_WIDTH ) + /* Shouldn't be called with N larger than 2^896! */ + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + M.p = Mp; + memset( Mp, 0, sizeof( Mp ) ); + memcpy( Mp, N->p + P448_WIDTH, M.n * sizeof( mbedtls_mpi_uint ) ); + + /* N = A0 */ + for( i = P448_WIDTH; i < N->n; i++ ) + N->p[i] = 0; + + /* N += A1 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( N, N, &M ) ); + + /* Q = B1, N += B1 */ + Q = M; + Q.p = Qp; + memcpy( Qp, Mp, sizeof( Qp ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Q, 224 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( N, N, &Q ) ); + + /* M = (B0 + B1) * 2^224, N += M */ + if( sizeof( mbedtls_mpi_uint ) > 4 ) + Mp[P224_WIDTH_MIN] &= ( (mbedtls_mpi_uint)-1 ) >> ( P224_UNUSED_BITS ); + for( i = P224_WIDTH_MAX; i < M.n; ++i ) + Mp[i] = 0; + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &M, &M, &Q ) ); + M.n = P448_WIDTH + 1; /* Make room for shifted carry bit from the addition */ + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &M, 224 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( N, N, &M ) ); + +cleanup: + return( ret ); +} +#endif /* MBEDTLS_ECP_DP_CURVE448_ENABLED */ + #if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) || \ defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) || \ defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) diff --git a/thirdparty/mbedtls/library/entropy.c b/thirdparty/mbedtls/library/entropy.c index e17512e779..f8db1a5503 100644 --- a/thirdparty/mbedtls/library/entropy.c +++ b/thirdparty/mbedtls/library/entropy.c @@ -35,6 +35,7 @@ #include "mbedtls/entropy.h" #include "mbedtls/entropy_poll.h" +#include "mbedtls/platform_util.h" #include <string.h> @@ -59,11 +60,6 @@ #include "mbedtls/havege.h" #endif -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize( void *v, size_t n ) { - volatile unsigned char *p = v; while( n-- ) *p++ = 0; -} - #define ENTROPY_MAX_LOOP 256 /**< Maximum amount to loop before error */ void mbedtls_entropy_init( mbedtls_entropy_context *ctx ) @@ -140,7 +136,7 @@ void mbedtls_entropy_free( mbedtls_entropy_context *ctx ) ctx->initial_entropy_run = 0; #endif ctx->source_count = 0; - mbedtls_zeroize( ctx->source, sizeof( ctx->source ) ); + mbedtls_platform_zeroize( ctx->source, sizeof( ctx->source ) ); ctx->accumulator_started = 0; } @@ -232,7 +228,7 @@ static int entropy_update( mbedtls_entropy_context *ctx, unsigned char source_id #endif cleanup: - mbedtls_zeroize( tmp, sizeof( tmp ) ); + mbedtls_platform_zeroize( tmp, sizeof( tmp ) ); return( ret ); } @@ -300,7 +296,7 @@ static int entropy_gather_internal( mbedtls_entropy_context *ctx ) ret = MBEDTLS_ERR_ENTROPY_NO_STRONG_SOURCE; cleanup: - mbedtls_zeroize( buf, sizeof( buf ) ); + mbedtls_platform_zeroize( buf, sizeof( buf ) ); return( ret ); } @@ -433,7 +429,7 @@ int mbedtls_entropy_func( void *data, unsigned char *output, size_t len ) ret = 0; exit: - mbedtls_zeroize( buf, sizeof( buf ) ); + mbedtls_platform_zeroize( buf, sizeof( buf ) ); #if defined(MBEDTLS_THREADING_C) if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) @@ -486,7 +482,7 @@ int mbedtls_entropy_write_seed_file( mbedtls_entropy_context *ctx, const char *p ret = 0; exit: - mbedtls_zeroize( buf, sizeof( buf ) ); + mbedtls_platform_zeroize( buf, sizeof( buf ) ); fclose( f ); return( ret ); @@ -516,7 +512,7 @@ int mbedtls_entropy_update_seed_file( mbedtls_entropy_context *ctx, const char * fclose( f ); - mbedtls_zeroize( buf, sizeof( buf ) ); + mbedtls_platform_zeroize( buf, sizeof( buf ) ); if( ret != 0 ) return( ret ); diff --git a/thirdparty/mbedtls/library/entropy_poll.c b/thirdparty/mbedtls/library/entropy_poll.c index ed350735d0..f44a753f4d 100644 --- a/thirdparty/mbedtls/library/entropy_poll.c +++ b/thirdparty/mbedtls/library/entropy_poll.c @@ -19,19 +19,25 @@ * This file is part of mbed TLS (https://tls.mbed.org) */ +#if defined(__linux__) +/* Ensure that syscall() is available even when compiling with -std=c99 */ +#define _GNU_SOURCE +#endif + #if !defined(MBEDTLS_CONFIG_FILE) #include "mbedtls/config.h" #else #include MBEDTLS_CONFIG_FILE #endif +#include <string.h> + #if defined(MBEDTLS_ENTROPY_C) #include "mbedtls/entropy.h" #include "mbedtls/entropy_poll.h" #if defined(MBEDTLS_TIMING_C) -#include <string.h> #include "mbedtls/timing.h" #endif #if defined(MBEDTLS_HAVEGE_C) @@ -44,7 +50,8 @@ #if !defined(MBEDTLS_NO_PLATFORM_ENTROPY) #if !defined(unix) && !defined(__unix__) && !defined(__unix) && \ - !defined(__APPLE__) && !defined(_WIN32) + !defined(__APPLE__) && !defined(_WIN32) && !defined(__QNXNTO__) && \ + !defined(__HAIKU__) #error "Platform entropy sources only work on Unix and Windows, see MBEDTLS_NO_PLATFORM_ENTROPY in config.h" #endif diff --git a/thirdparty/mbedtls/library/entropy_poll.c.orig b/thirdparty/mbedtls/library/entropy_poll.c.orig new file mode 100644 index 0000000000..040aa117dc --- /dev/null +++ b/thirdparty/mbedtls/library/entropy_poll.c.orig @@ -0,0 +1,275 @@ +/* + * Platform-specific and custom entropy polling functions + * + * Copyright (C) 2006-2016, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +#if defined(__linux__) +/* Ensure that syscall() is available even when compiling with -std=c99 */ +#define _GNU_SOURCE +#endif + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include <string.h> + +#if defined(MBEDTLS_ENTROPY_C) + +#include "mbedtls/entropy.h" +#include "mbedtls/entropy_poll.h" + +#if defined(MBEDTLS_TIMING_C) +#include "mbedtls/timing.h" +#endif +#if defined(MBEDTLS_HAVEGE_C) +#include "mbedtls/havege.h" +#endif +#if defined(MBEDTLS_ENTROPY_NV_SEED) +#include "mbedtls/platform.h" +#endif + +#if !defined(MBEDTLS_NO_PLATFORM_ENTROPY) + +#if !defined(unix) && !defined(__unix__) && !defined(__unix) && \ + !defined(__APPLE__) && !defined(_WIN32) && !defined(__QNXNTO__) && \ + !defined(__HAIKU__) +#error "Platform entropy sources only work on Unix and Windows, see MBEDTLS_NO_PLATFORM_ENTROPY in config.h" +#endif + +#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) + +#if !defined(_WIN32_WINNT) +#define _WIN32_WINNT 0x0400 +#endif +#include <windows.h> +#include <wincrypt.h> + +int mbedtls_platform_entropy_poll( void *data, unsigned char *output, size_t len, + size_t *olen ) +{ + HCRYPTPROV provider; + ((void) data); + *olen = 0; + + if( CryptAcquireContext( &provider, NULL, NULL, + PROV_RSA_FULL, CRYPT_VERIFYCONTEXT ) == FALSE ) + { + return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED ); + } + + if( CryptGenRandom( provider, (DWORD) len, output ) == FALSE ) + { + CryptReleaseContext( provider, 0 ); + return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED ); + } + + CryptReleaseContext( provider, 0 ); + *olen = len; + + return( 0 ); +} +#else /* _WIN32 && !EFIX64 && !EFI32 */ + +/* + * Test for Linux getrandom() support. + * Since there is no wrapper in the libc yet, use the generic syscall wrapper + * available in GNU libc and compatible libc's (eg uClibc). + */ +#if defined(__linux__) && defined(__GLIBC__) +#include <unistd.h> +#include <sys/syscall.h> +#if defined(SYS_getrandom) +#define HAVE_GETRANDOM + +static int getrandom_wrapper( void *buf, size_t buflen, unsigned int flags ) +{ + /* MemSan cannot understand that the syscall writes to the buffer */ +#if defined(__has_feature) +#if __has_feature(memory_sanitizer) + memset( buf, 0, buflen ); +#endif +#endif + + return( syscall( SYS_getrandom, buf, buflen, flags ) ); +} + +#include <sys/utsname.h> +/* Check if version is at least 3.17.0 */ +static int check_version_3_17_plus( void ) +{ + int minor; + struct utsname un; + const char *ver; + + /* Get version information */ + uname(&un); + ver = un.release; + + /* Check major version; assume a single digit */ + if( ver[0] < '3' || ver[0] > '9' || ver [1] != '.' ) + return( -1 ); + + if( ver[0] - '0' > 3 ) + return( 0 ); + + /* Ok, so now we know major == 3, check minor. + * Assume 1 or 2 digits. */ + if( ver[2] < '0' || ver[2] > '9' ) + return( -1 ); + + minor = ver[2] - '0'; + + if( ver[3] >= '0' && ver[3] <= '9' ) + minor = 10 * minor + ver[3] - '0'; + else if( ver [3] != '.' ) + return( -1 ); + + if( minor < 17 ) + return( -1 ); + + return( 0 ); +} +static int has_getrandom = -1; +#endif /* SYS_getrandom */ +#endif /* __linux__ */ + +#include <stdio.h> + +int mbedtls_platform_entropy_poll( void *data, + unsigned char *output, size_t len, size_t *olen ) +{ + FILE *file; + size_t read_len; + ((void) data); + +#if defined(HAVE_GETRANDOM) + if( has_getrandom == -1 ) + has_getrandom = ( check_version_3_17_plus() == 0 ); + + if( has_getrandom ) + { + int ret; + + if( ( ret = getrandom_wrapper( output, len, 0 ) ) < 0 ) + return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED ); + + *olen = ret; + return( 0 ); + } +#endif /* HAVE_GETRANDOM */ + + *olen = 0; + + file = fopen( "/dev/urandom", "rb" ); + if( file == NULL ) + return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED ); + + read_len = fread( output, 1, len, file ); + if( read_len != len ) + { + fclose( file ); + return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED ); + } + + fclose( file ); + *olen = len; + + return( 0 ); +} +#endif /* _WIN32 && !EFIX64 && !EFI32 */ +#endif /* !MBEDTLS_NO_PLATFORM_ENTROPY */ + +#if defined(MBEDTLS_TEST_NULL_ENTROPY) +int mbedtls_null_entropy_poll( void *data, + unsigned char *output, size_t len, size_t *olen ) +{ + ((void) data); + ((void) output); + *olen = 0; + + if( len < sizeof(unsigned char) ) + return( 0 ); + + *olen = sizeof(unsigned char); + + return( 0 ); +} +#endif + +#if defined(MBEDTLS_TIMING_C) +int mbedtls_hardclock_poll( void *data, + unsigned char *output, size_t len, size_t *olen ) +{ + unsigned long timer = mbedtls_timing_hardclock(); + ((void) data); + *olen = 0; + + if( len < sizeof(unsigned long) ) + return( 0 ); + + memcpy( output, &timer, sizeof(unsigned long) ); + *olen = sizeof(unsigned long); + + return( 0 ); +} +#endif /* MBEDTLS_TIMING_C */ + +#if defined(MBEDTLS_HAVEGE_C) +int mbedtls_havege_poll( void *data, + unsigned char *output, size_t len, size_t *olen ) +{ + mbedtls_havege_state *hs = (mbedtls_havege_state *) data; + *olen = 0; + + if( mbedtls_havege_random( hs, output, len ) != 0 ) + return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED ); + + *olen = len; + + return( 0 ); +} +#endif /* MBEDTLS_HAVEGE_C */ + +#if defined(MBEDTLS_ENTROPY_NV_SEED) +int mbedtls_nv_seed_poll( void *data, + unsigned char *output, size_t len, size_t *olen ) +{ + unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE]; + size_t use_len = MBEDTLS_ENTROPY_BLOCK_SIZE; + ((void) data); + + memset( buf, 0, MBEDTLS_ENTROPY_BLOCK_SIZE ); + + if( mbedtls_nv_seed_read( buf, MBEDTLS_ENTROPY_BLOCK_SIZE ) < 0 ) + return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED ); + + if( len < use_len ) + use_len = len; + + memcpy( output, buf, use_len ); + *olen = use_len; + + return( 0 ); +} +#endif /* MBEDTLS_ENTROPY_NV_SEED */ + +#endif /* MBEDTLS_ENTROPY_C */ diff --git a/thirdparty/mbedtls/library/error.c b/thirdparty/mbedtls/library/error.c index 0292480aee..774244b454 100644 --- a/thirdparty/mbedtls/library/error.c +++ b/thirdparty/mbedtls/library/error.c @@ -49,6 +49,10 @@ #include "mbedtls/arc4.h" #endif +#if defined(MBEDTLS_ARIA_C) +#include "mbedtls/aria.h" +#endif + #if defined(MBEDTLS_BASE64_C) #include "mbedtls/base64.h" #endif @@ -69,6 +73,14 @@ #include "mbedtls/ccm.h" #endif +#if defined(MBEDTLS_CHACHA20_C) +#include "mbedtls/chacha20.h" +#endif + +#if defined(MBEDTLS_CHACHAPOLY_C) +#include "mbedtls/chachapoly.h" +#endif + #if defined(MBEDTLS_CIPHER_C) #include "mbedtls/cipher.h" #endif @@ -101,6 +113,10 @@ #include "mbedtls/gcm.h" #endif +#if defined(MBEDTLS_HKDF_C) +#include "mbedtls/hkdf.h" +#endif + #if defined(MBEDTLS_HMAC_DRBG_C) #include "mbedtls/hmac_drbg.h" #endif @@ -149,6 +165,10 @@ #include "mbedtls/pkcs5.h" #endif +#if defined(MBEDTLS_POLY1305_C) +#include "mbedtls/poly1305.h" +#endif + #if defined(MBEDTLS_RIPEMD160_C) #include "mbedtls/ripemd160.h" #endif @@ -256,19 +276,19 @@ void mbedtls_strerror( int ret, char *buf, size_t buflen ) if( use_ret == -(MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL) ) mbedtls_snprintf( buf, buflen, "ECP - The buffer is too small to write to" ); if( use_ret == -(MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE) ) - mbedtls_snprintf( buf, buflen, "ECP - Requested curve not available" ); + mbedtls_snprintf( buf, buflen, "ECP - The requested feature is not available, for example, the requested curve is not supported" ); if( use_ret == -(MBEDTLS_ERR_ECP_VERIFY_FAILED) ) mbedtls_snprintf( buf, buflen, "ECP - The signature is not valid" ); if( use_ret == -(MBEDTLS_ERR_ECP_ALLOC_FAILED) ) mbedtls_snprintf( buf, buflen, "ECP - Memory allocation failed" ); if( use_ret == -(MBEDTLS_ERR_ECP_RANDOM_FAILED) ) - mbedtls_snprintf( buf, buflen, "ECP - Generation of random value, such as (ephemeral) key, failed" ); + mbedtls_snprintf( buf, buflen, "ECP - Generation of random value, such as ephemeral key, failed" ); if( use_ret == -(MBEDTLS_ERR_ECP_INVALID_KEY) ) mbedtls_snprintf( buf, buflen, "ECP - Invalid private or public key" ); if( use_ret == -(MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH) ) - mbedtls_snprintf( buf, buflen, "ECP - Signature is valid but shorter than the user-supplied length" ); + mbedtls_snprintf( buf, buflen, "ECP - The buffer contains a valid signature followed by more data" ); if( use_ret == -(MBEDTLS_ERR_ECP_HW_ACCEL_FAILED) ) - mbedtls_snprintf( buf, buflen, "ECP - ECP hardware accelerator failed" ); + mbedtls_snprintf( buf, buflen, "ECP - The ECP hardware accelerator failed" ); #endif /* MBEDTLS_ECP_C */ #if defined(MBEDTLS_MD_C) @@ -333,7 +353,7 @@ void mbedtls_strerror( int ret, char *buf, size_t buflen ) if( use_ret == -(MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE) ) mbedtls_snprintf( buf, buflen, "PK - Unavailable feature, e.g. RSA disabled for RSA key" ); if( use_ret == -(MBEDTLS_ERR_PK_SIG_LEN_MISMATCH) ) - mbedtls_snprintf( buf, buflen, "PK - The signature is valid but its length is less than expected" ); + mbedtls_snprintf( buf, buflen, "PK - The buffer contains a valid signature followed by more data" ); if( use_ret == -(MBEDTLS_ERR_PK_HW_ACCEL_FAILED) ) mbedtls_snprintf( buf, buflen, "PK - PK hardware accelerator failed" ); #endif /* MBEDTLS_PK_C */ @@ -478,7 +498,7 @@ void mbedtls_strerror( int ret, char *buf, size_t buflen ) if( use_ret == -(MBEDTLS_ERR_SSL_NO_USABLE_CIPHERSUITE) ) mbedtls_snprintf( buf, buflen, "SSL - None of the common ciphersuites is usable (eg, no suitable certificate, see debug messages)" ); if( use_ret == -(MBEDTLS_ERR_SSL_WANT_READ) ) - mbedtls_snprintf( buf, buflen, "SSL - Connection requires a read call" ); + mbedtls_snprintf( buf, buflen, "SSL - No data of requested type currently available on underlying transport" ); if( use_ret == -(MBEDTLS_ERR_SSL_WANT_WRITE) ) mbedtls_snprintf( buf, buflen, "SSL - Connection requires a write call" ); if( use_ret == -(MBEDTLS_ERR_SSL_TIMEOUT) ) @@ -491,6 +511,10 @@ void mbedtls_strerror( int ret, char *buf, size_t buflen ) mbedtls_snprintf( buf, buflen, "SSL - The alert message received indicates a non-fatal error" ); if( use_ret == -(MBEDTLS_ERR_SSL_INVALID_VERIFY_HASH) ) mbedtls_snprintf( buf, buflen, "SSL - Couldn't set the hash for verifying CertificateVerify" ); + if( use_ret == -(MBEDTLS_ERR_SSL_CONTINUE_PROCESSING) ) + mbedtls_snprintf( buf, buflen, "SSL - Internal-only message signaling that further message-processing should be done" ); + if( use_ret == -(MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS) ) + mbedtls_snprintf( buf, buflen, "SSL - The asynchronous operation is not completed yet" ); #endif /* MBEDTLS_SSL_TLS_C */ #if defined(MBEDTLS_X509_USE_C) || defined(MBEDTLS_X509_CREATE_C) @@ -570,6 +594,8 @@ void mbedtls_strerror( int ret, char *buf, size_t buflen ) mbedtls_snprintf( buf, buflen, "AES - Invalid key length" ); if( use_ret == -(MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH) ) mbedtls_snprintf( buf, buflen, "AES - Invalid data input length" ); + if( use_ret == -(MBEDTLS_ERR_AES_BAD_INPUT_DATA) ) + mbedtls_snprintf( buf, buflen, "AES - Invalid input data" ); if( use_ret == -(MBEDTLS_ERR_AES_FEATURE_UNAVAILABLE) ) mbedtls_snprintf( buf, buflen, "AES - Feature not available. For example, an unsupported AES key size" ); if( use_ret == -(MBEDTLS_ERR_AES_HW_ACCEL_FAILED) ) @@ -581,6 +607,17 @@ void mbedtls_strerror( int ret, char *buf, size_t buflen ) mbedtls_snprintf( buf, buflen, "ARC4 - ARC4 hardware accelerator failed" ); #endif /* MBEDTLS_ARC4_C */ +#if defined(MBEDTLS_ARIA_C) + if( use_ret == -(MBEDTLS_ERR_ARIA_INVALID_KEY_LENGTH) ) + mbedtls_snprintf( buf, buflen, "ARIA - Invalid key length" ); + if( use_ret == -(MBEDTLS_ERR_ARIA_INVALID_INPUT_LENGTH) ) + mbedtls_snprintf( buf, buflen, "ARIA - Invalid data input length" ); + if( use_ret == -(MBEDTLS_ERR_ARIA_FEATURE_UNAVAILABLE) ) + mbedtls_snprintf( buf, buflen, "ARIA - Feature not available. For example, an unsupported ARIA key size" ); + if( use_ret == -(MBEDTLS_ERR_ARIA_HW_ACCEL_FAILED) ) + mbedtls_snprintf( buf, buflen, "ARIA - ARIA hardware accelerator failed" ); +#endif /* MBEDTLS_ARIA_C */ + #if defined(MBEDTLS_ASN1_PARSE_C) if( use_ret == -(MBEDTLS_ERR_ASN1_OUT_OF_DATA) ) mbedtls_snprintf( buf, buflen, "ASN1 - Out of data when parsing an ASN1 data structure" ); @@ -651,6 +688,22 @@ void mbedtls_strerror( int ret, char *buf, size_t buflen ) mbedtls_snprintf( buf, buflen, "CCM - CCM hardware accelerator failed" ); #endif /* MBEDTLS_CCM_C */ +#if defined(MBEDTLS_CHACHA20_C) + if( use_ret == -(MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA) ) + mbedtls_snprintf( buf, buflen, "CHACHA20 - Invalid input parameter(s)" ); + if( use_ret == -(MBEDTLS_ERR_CHACHA20_FEATURE_UNAVAILABLE) ) + mbedtls_snprintf( buf, buflen, "CHACHA20 - Feature not available. For example, s part of the API is not implemented" ); + if( use_ret == -(MBEDTLS_ERR_CHACHA20_HW_ACCEL_FAILED) ) + mbedtls_snprintf( buf, buflen, "CHACHA20 - Chacha20 hardware accelerator failed" ); +#endif /* MBEDTLS_CHACHA20_C */ + +#if defined(MBEDTLS_CHACHAPOLY_C) + if( use_ret == -(MBEDTLS_ERR_CHACHAPOLY_BAD_STATE) ) + mbedtls_snprintf( buf, buflen, "CHACHAPOLY - The requested operation is not permitted in the current state" ); + if( use_ret == -(MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED) ) + mbedtls_snprintf( buf, buflen, "CHACHAPOLY - Authenticated decryption failed: data was not authentic" ); +#endif /* MBEDTLS_CHACHAPOLY_C */ + #if defined(MBEDTLS_CMAC_C) if( use_ret == -(MBEDTLS_ERR_CMAC_HW_ACCEL_FAILED) ) mbedtls_snprintf( buf, buflen, "CMAC - CMAC hardware accelerator failed" ); @@ -696,6 +749,11 @@ void mbedtls_strerror( int ret, char *buf, size_t buflen ) mbedtls_snprintf( buf, buflen, "GCM - Bad input parameters to function" ); #endif /* MBEDTLS_GCM_C */ +#if defined(MBEDTLS_HKDF_C) + if( use_ret == -(MBEDTLS_ERR_HKDF_BAD_INPUT_DATA) ) + mbedtls_snprintf( buf, buflen, "HKDF - Bad input parameters to function" ); +#endif /* MBEDTLS_HKDF_C */ + #if defined(MBEDTLS_HMAC_DRBG_C) if( use_ret == -(MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG) ) mbedtls_snprintf( buf, buflen, "HMAC_DRBG - Too many random requested in single call" ); @@ -745,6 +803,10 @@ void mbedtls_strerror( int ret, char *buf, size_t buflen ) mbedtls_snprintf( buf, buflen, "NET - Buffer is too small to hold the data" ); if( use_ret == -(MBEDTLS_ERR_NET_INVALID_CONTEXT) ) mbedtls_snprintf( buf, buflen, "NET - The context is invalid, eg because it was free()ed" ); + if( use_ret == -(MBEDTLS_ERR_NET_POLL_FAILED) ) + mbedtls_snprintf( buf, buflen, "NET - Polling the net context failed" ); + if( use_ret == -(MBEDTLS_ERR_NET_BAD_INPUT_DATA) ) + mbedtls_snprintf( buf, buflen, "NET - Input invalid" ); #endif /* MBEDTLS_NET_C */ #if defined(MBEDTLS_OID_C) @@ -759,6 +821,15 @@ void mbedtls_strerror( int ret, char *buf, size_t buflen ) mbedtls_snprintf( buf, buflen, "PADLOCK - Input data should be aligned" ); #endif /* MBEDTLS_PADLOCK_C */ +#if defined(MBEDTLS_POLY1305_C) + if( use_ret == -(MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA) ) + mbedtls_snprintf( buf, buflen, "POLY1305 - Invalid input parameter(s)" ); + if( use_ret == -(MBEDTLS_ERR_POLY1305_FEATURE_UNAVAILABLE) ) + mbedtls_snprintf( buf, buflen, "POLY1305 - Feature not available. For example, s part of the API is not implemented" ); + if( use_ret == -(MBEDTLS_ERR_POLY1305_HW_ACCEL_FAILED) ) + mbedtls_snprintf( buf, buflen, "POLY1305 - Poly1305 hardware accelerator failed" ); +#endif /* MBEDTLS_POLY1305_C */ + #if defined(MBEDTLS_RIPEMD160_C) if( use_ret == -(MBEDTLS_ERR_RIPEMD160_HW_ACCEL_FAILED) ) mbedtls_snprintf( buf, buflen, "RIPEMD160 - RIPEMD160 hardware accelerator failed" ); diff --git a/thirdparty/mbedtls/library/gcm.c b/thirdparty/mbedtls/library/gcm.c index 294a86d3d4..57b027933d 100644 --- a/thirdparty/mbedtls/library/gcm.c +++ b/thirdparty/mbedtls/library/gcm.c @@ -38,6 +38,7 @@ #if defined(MBEDTLS_GCM_C) #include "mbedtls/gcm.h" +#include "mbedtls/platform_util.h" #include <string.h> @@ -80,11 +81,6 @@ } #endif -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize( void *v, size_t n ) { - volatile unsigned char *p = v; while( n-- ) *p++ = 0; -} - /* * Initialize a context */ @@ -498,7 +494,7 @@ int mbedtls_gcm_auth_decrypt( mbedtls_gcm_context *ctx, if( diff != 0 ) { - mbedtls_zeroize( output, length ); + mbedtls_platform_zeroize( output, length ); return( MBEDTLS_ERR_GCM_AUTH_FAILED ); } @@ -508,7 +504,7 @@ int mbedtls_gcm_auth_decrypt( mbedtls_gcm_context *ctx, void mbedtls_gcm_free( mbedtls_gcm_context *ctx ) { mbedtls_cipher_free( &ctx->cipher_ctx ); - mbedtls_zeroize( ctx, sizeof( mbedtls_gcm_context ) ); + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_gcm_context ) ); } #endif /* !MBEDTLS_GCM_ALT */ diff --git a/thirdparty/mbedtls/library/havege.c b/thirdparty/mbedtls/library/havege.c index 2b75ef7bd8..4dcac02875 100644 --- a/thirdparty/mbedtls/library/havege.c +++ b/thirdparty/mbedtls/library/havege.c @@ -36,14 +36,10 @@ #include "mbedtls/havege.h" #include "mbedtls/timing.h" +#include "mbedtls/platform_util.h" #include <string.h> -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize( void *v, size_t n ) { - volatile unsigned char *p = v; while( n-- ) *p++ = 0; -} - /* ------------------------------------------------------------------------ * On average, one iteration accesses two 8-word blocks in the havege WALK * table, and generates 16 words in the RES array. @@ -208,7 +204,7 @@ void mbedtls_havege_free( mbedtls_havege_state *hs ) if( hs == NULL ) return; - mbedtls_zeroize( hs, sizeof( mbedtls_havege_state ) ); + mbedtls_platform_zeroize( hs, sizeof( mbedtls_havege_state ) ); } /* diff --git a/thirdparty/mbedtls/library/hkdf.c b/thirdparty/mbedtls/library/hkdf.c new file mode 100644 index 0000000000..82d8a429f4 --- /dev/null +++ b/thirdparty/mbedtls/library/hkdf.c @@ -0,0 +1,192 @@ +/* + * HKDF implementation -- RFC 5869 + * + * Copyright (C) 2016-2018, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_HKDF_C) + +#include <string.h> +#include "mbedtls/hkdf.h" +#include "mbedtls/platform_util.h" + +int mbedtls_hkdf( const mbedtls_md_info_t *md, const unsigned char *salt, + size_t salt_len, const unsigned char *ikm, size_t ikm_len, + const unsigned char *info, size_t info_len, + unsigned char *okm, size_t okm_len ) +{ + int ret; + unsigned char prk[MBEDTLS_MD_MAX_SIZE]; + + ret = mbedtls_hkdf_extract( md, salt, salt_len, ikm, ikm_len, prk ); + + if( ret == 0 ) + { + ret = mbedtls_hkdf_expand( md, prk, mbedtls_md_get_size( md ), + info, info_len, okm, okm_len ); + } + + mbedtls_platform_zeroize( prk, sizeof( prk ) ); + + return( ret ); +} + +int mbedtls_hkdf_extract( const mbedtls_md_info_t *md, + const unsigned char *salt, size_t salt_len, + const unsigned char *ikm, size_t ikm_len, + unsigned char *prk ) +{ + unsigned char null_salt[MBEDTLS_MD_MAX_SIZE] = { '\0' }; + + if( salt == NULL ) + { + size_t hash_len; + + if( salt_len != 0 ) + { + return MBEDTLS_ERR_HKDF_BAD_INPUT_DATA; + } + + hash_len = mbedtls_md_get_size( md ); + + if( hash_len == 0 ) + { + return MBEDTLS_ERR_HKDF_BAD_INPUT_DATA; + } + + salt = null_salt; + salt_len = hash_len; + } + + return( mbedtls_md_hmac( md, salt, salt_len, ikm, ikm_len, prk ) ); +} + +int mbedtls_hkdf_expand( const mbedtls_md_info_t *md, const unsigned char *prk, + size_t prk_len, const unsigned char *info, + size_t info_len, unsigned char *okm, size_t okm_len ) +{ + size_t hash_len; + size_t where = 0; + size_t n; + size_t t_len = 0; + size_t i; + int ret = 0; + mbedtls_md_context_t ctx; + unsigned char t[MBEDTLS_MD_MAX_SIZE]; + + if( okm == NULL ) + { + return( MBEDTLS_ERR_HKDF_BAD_INPUT_DATA ); + } + + hash_len = mbedtls_md_get_size( md ); + + if( prk_len < hash_len || hash_len == 0 ) + { + return( MBEDTLS_ERR_HKDF_BAD_INPUT_DATA ); + } + + if( info == NULL ) + { + info = (const unsigned char *) ""; + info_len = 0; + } + + n = okm_len / hash_len; + + if( (okm_len % hash_len) != 0 ) + { + n++; + } + + /* + * Per RFC 5869 Section 2.3, okm_len must not exceed + * 255 times the hash length + */ + if( n > 255 ) + { + return( MBEDTLS_ERR_HKDF_BAD_INPUT_DATA ); + } + + mbedtls_md_init( &ctx ); + + if( (ret = mbedtls_md_setup( &ctx, md, 1) ) != 0 ) + { + goto exit; + } + + /* + * Compute T = T(1) | T(2) | T(3) | ... | T(N) + * Where T(N) is defined in RFC 5869 Section 2.3 + */ + for( i = 1; i <= n; i++ ) + { + size_t num_to_copy; + unsigned char c = i & 0xff; + + ret = mbedtls_md_hmac_starts( &ctx, prk, prk_len ); + if( ret != 0 ) + { + goto exit; + } + + ret = mbedtls_md_hmac_update( &ctx, t, t_len ); + if( ret != 0 ) + { + goto exit; + } + + ret = mbedtls_md_hmac_update( &ctx, info, info_len ); + if( ret != 0 ) + { + goto exit; + } + + /* The constant concatenated to the end of each T(n) is a single octet. + * */ + ret = mbedtls_md_hmac_update( &ctx, &c, 1 ); + if( ret != 0 ) + { + goto exit; + } + + ret = mbedtls_md_hmac_finish( &ctx, t ); + if( ret != 0 ) + { + goto exit; + } + + num_to_copy = i != n ? hash_len : okm_len - where; + memcpy( okm + where, t, num_to_copy ); + where += hash_len; + t_len = hash_len; + } + +exit: + mbedtls_md_free( &ctx ); + mbedtls_platform_zeroize( t, sizeof( t ) ); + + return( ret ); +} + +#endif /* MBEDTLS_HKDF_C */ diff --git a/thirdparty/mbedtls/library/hmac_drbg.c b/thirdparty/mbedtls/library/hmac_drbg.c index 24c609e9ce..dad55ff861 100644 --- a/thirdparty/mbedtls/library/hmac_drbg.c +++ b/thirdparty/mbedtls/library/hmac_drbg.c @@ -34,6 +34,7 @@ #if defined(MBEDTLS_HMAC_DRBG_C) #include "mbedtls/hmac_drbg.h" +#include "mbedtls/platform_util.h" #include <string.h> @@ -50,11 +51,6 @@ #endif /* MBEDTLS_SELF_TEST */ #endif /* MBEDTLS_PLATFORM_C */ -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize( void *v, size_t n ) { - volatile unsigned char *p = v; while( n-- ) *p++ = 0; -} - /* * HMAC_DRBG context initialization */ @@ -338,7 +334,7 @@ void mbedtls_hmac_drbg_free( mbedtls_hmac_drbg_context *ctx ) mbedtls_mutex_free( &ctx->mutex ); #endif mbedtls_md_free( &ctx->md_ctx ); - mbedtls_zeroize( ctx, sizeof( mbedtls_hmac_drbg_context ) ); + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_hmac_drbg_context ) ); } #if defined(MBEDTLS_FS_IO) @@ -364,7 +360,7 @@ int mbedtls_hmac_drbg_write_seed_file( mbedtls_hmac_drbg_context *ctx, const cha exit: fclose( f ); - mbedtls_zeroize( buf, sizeof( buf ) ); + mbedtls_platform_zeroize( buf, sizeof( buf ) ); return( ret ); } @@ -396,7 +392,7 @@ int mbedtls_hmac_drbg_update_seed_file( mbedtls_hmac_drbg_context *ctx, const ch fclose( f ); - mbedtls_zeroize( buf, sizeof( buf ) ); + mbedtls_platform_zeroize( buf, sizeof( buf ) ); if( ret != 0 ) return( ret ); diff --git a/thirdparty/mbedtls/library/md.c b/thirdparty/mbedtls/library/md.c index 00249af78b..303cdcbeeb 100644 --- a/thirdparty/mbedtls/library/md.c +++ b/thirdparty/mbedtls/library/md.c @@ -33,6 +33,7 @@ #include "mbedtls/md.h" #include "mbedtls/md_internal.h" +#include "mbedtls/platform_util.h" #if defined(MBEDTLS_PLATFORM_C) #include "mbedtls/platform.h" @@ -48,11 +49,6 @@ #include <stdio.h> #endif -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize( void *v, size_t n ) { - volatile unsigned char *p = v; while( n-- ) *p++ = 0; -} - /* * Reminder: update profiles in x509_crt.c when adding a new hash! */ @@ -193,11 +189,12 @@ void mbedtls_md_free( mbedtls_md_context_t *ctx ) if( ctx->hmac_ctx != NULL ) { - mbedtls_zeroize( ctx->hmac_ctx, 2 * ctx->md_info->block_size ); + mbedtls_platform_zeroize( ctx->hmac_ctx, + 2 * ctx->md_info->block_size ); mbedtls_free( ctx->hmac_ctx ); } - mbedtls_zeroize( ctx, sizeof( mbedtls_md_context_t ) ); + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_md_context_t ) ); } int mbedtls_md_clone( mbedtls_md_context_t *dst, @@ -311,7 +308,7 @@ int mbedtls_md_file( const mbedtls_md_info_t *md_info, const char *path, unsigne ret = md_info->finish_func( ctx.md_ctx, output ); cleanup: - mbedtls_zeroize( buf, sizeof( buf ) ); + mbedtls_platform_zeroize( buf, sizeof( buf ) ); fclose( f ); mbedtls_md_free( &ctx ); @@ -361,7 +358,7 @@ int mbedtls_md_hmac_starts( mbedtls_md_context_t *ctx, const unsigned char *key, goto cleanup; cleanup: - mbedtls_zeroize( sum, sizeof( sum ) ); + mbedtls_platform_zeroize( sum, sizeof( sum ) ); return( ret ); } diff --git a/thirdparty/mbedtls/library/md2.c b/thirdparty/mbedtls/library/md2.c index b88aa406af..1c0b3df52d 100644 --- a/thirdparty/mbedtls/library/md2.c +++ b/thirdparty/mbedtls/library/md2.c @@ -34,6 +34,7 @@ #if defined(MBEDTLS_MD2_C) #include "mbedtls/md2.h" +#include "mbedtls/platform_util.h" #include <string.h> @@ -48,11 +49,6 @@ #if !defined(MBEDTLS_MD2_ALT) -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize( void *v, size_t n ) { - volatile unsigned char *p = v; while( n-- ) *p++ = 0; -} - static const unsigned char PI_SUBST[256] = { 0x29, 0x2E, 0x43, 0xC9, 0xA2, 0xD8, 0x7C, 0x01, 0x3D, 0x36, @@ -93,7 +89,7 @@ void mbedtls_md2_free( mbedtls_md2_context *ctx ) if( ctx == NULL ) return; - mbedtls_zeroize( ctx, sizeof( mbedtls_md2_context ) ); + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_md2_context ) ); } void mbedtls_md2_clone( mbedtls_md2_context *dst, diff --git a/thirdparty/mbedtls/library/md4.c b/thirdparty/mbedtls/library/md4.c index ba704f58e8..3f8ddff31d 100644 --- a/thirdparty/mbedtls/library/md4.c +++ b/thirdparty/mbedtls/library/md4.c @@ -34,6 +34,7 @@ #if defined(MBEDTLS_MD4_C) #include "mbedtls/md4.h" +#include "mbedtls/platform_util.h" #include <string.h> @@ -48,11 +49,6 @@ #if !defined(MBEDTLS_MD4_ALT) -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize( void *v, size_t n ) { - volatile unsigned char *p = v; while( n-- ) *p++ = 0; -} - /* * 32-bit integer manipulation macros (little endian) */ @@ -86,7 +82,7 @@ void mbedtls_md4_free( mbedtls_md4_context *ctx ) if( ctx == NULL ) return; - mbedtls_zeroize( ctx, sizeof( mbedtls_md4_context ) ); + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_md4_context ) ); } void mbedtls_md4_clone( mbedtls_md4_context *dst, diff --git a/thirdparty/mbedtls/library/md5.c b/thirdparty/mbedtls/library/md5.c index 8440ebffcf..2a740cda81 100644 --- a/thirdparty/mbedtls/library/md5.c +++ b/thirdparty/mbedtls/library/md5.c @@ -33,6 +33,7 @@ #if defined(MBEDTLS_MD5_C) #include "mbedtls/md5.h" +#include "mbedtls/platform_util.h" #include <string.h> @@ -47,11 +48,6 @@ #if !defined(MBEDTLS_MD5_ALT) -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize( void *v, size_t n ) { - volatile unsigned char *p = v; while( n-- ) *p++ = 0; -} - /* * 32-bit integer manipulation macros (little endian) */ @@ -85,7 +81,7 @@ void mbedtls_md5_free( mbedtls_md5_context *ctx ) if( ctx == NULL ) return; - mbedtls_zeroize( ctx, sizeof( mbedtls_md5_context ) ); + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_md5_context ) ); } void mbedtls_md5_clone( mbedtls_md5_context *dst, @@ -313,14 +309,6 @@ void mbedtls_md5_update( mbedtls_md5_context *ctx, } #endif -static const unsigned char md5_padding[64] = -{ - 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 -}; - /* * MD5 final digest */ @@ -328,26 +316,48 @@ int mbedtls_md5_finish_ret( mbedtls_md5_context *ctx, unsigned char output[16] ) { int ret; - uint32_t last, padn; + uint32_t used; uint32_t high, low; - unsigned char msglen[8]; - high = ( ctx->total[0] >> 29 ) - | ( ctx->total[1] << 3 ); - low = ( ctx->total[0] << 3 ); + /* + * Add padding: 0x80 then 0x00 until 8 bytes remain for the length + */ + used = ctx->total[0] & 0x3F; - PUT_UINT32_LE( low, msglen, 0 ); - PUT_UINT32_LE( high, msglen, 4 ); + ctx->buffer[used++] = 0x80; - last = ctx->total[0] & 0x3F; - padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last ); + if( used <= 56 ) + { + /* Enough room for padding + length in current block */ + memset( ctx->buffer + used, 0, 56 - used ); + } + else + { + /* We'll need an extra block */ + memset( ctx->buffer + used, 0, 64 - used ); - if( ( ret = mbedtls_md5_update_ret( ctx, md5_padding, padn ) ) != 0 ) + if( ( ret = mbedtls_internal_md5_process( ctx, ctx->buffer ) ) != 0 ) return( ret ); - if( ( ret = mbedtls_md5_update_ret( ctx, msglen, 8 ) ) != 0 ) - return( ret ); + memset( ctx->buffer, 0, 56 ); + } + + /* + * Add message length + */ + high = ( ctx->total[0] >> 29 ) + | ( ctx->total[1] << 3 ); + low = ( ctx->total[0] << 3 ); + + PUT_UINT32_LE( low, ctx->buffer, 56 ); + PUT_UINT32_LE( high, ctx->buffer, 60 ); + + if( ( ret = mbedtls_internal_md5_process( ctx, ctx->buffer ) ) != 0 ) + return( ret ); + /* + * Output final state + */ PUT_UINT32_LE( ctx->state[0], output, 0 ); PUT_UINT32_LE( ctx->state[1], output, 4 ); PUT_UINT32_LE( ctx->state[2], output, 8 ); diff --git a/thirdparty/mbedtls/library/memory_buffer_alloc.c b/thirdparty/mbedtls/library/memory_buffer_alloc.c index 821ae2c708..51ea7c41d7 100644 --- a/thirdparty/mbedtls/library/memory_buffer_alloc.c +++ b/thirdparty/mbedtls/library/memory_buffer_alloc.c @@ -31,6 +31,7 @@ /* No need for the header guard as MBEDTLS_MEMORY_BUFFER_ALLOC_C is dependent upon MBEDTLS_PLATFORM_C */ #include "mbedtls/platform.h" +#include "mbedtls/platform_util.h" #include <string.h> @@ -42,11 +43,6 @@ #include "mbedtls/threading.h" #endif -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize( void *v, size_t n ) { - volatile unsigned char *p = v; while( n-- ) *p++ = 0; -} - #define MAGIC1 0xFF00AA55 #define MAGIC2 0xEE119966 #define MAX_BT 20 @@ -522,7 +518,9 @@ void mbedtls_memory_buffer_alloc_status( void ) heap.alloc_count, heap.free_count ); if( heap.first->next == NULL ) + { mbedtls_fprintf( stderr, "All memory de-allocated in stack buffer\n" ); + } else { mbedtls_fprintf( stderr, "Memory currently allocated:\n" ); @@ -612,7 +610,7 @@ void mbedtls_memory_buffer_alloc_free( void ) #if defined(MBEDTLS_THREADING_C) mbedtls_mutex_free( &heap.mutex ); #endif - mbedtls_zeroize( &heap, sizeof(buffer_alloc_ctx) ); + mbedtls_platform_zeroize( &heap, sizeof(buffer_alloc_ctx) ); } #if defined(MBEDTLS_SELF_TEST) diff --git a/thirdparty/mbedtls/library/net_sockets.c b/thirdparty/mbedtls/library/net_sockets.c index 2fb548caa9..816b1303df 100644 --- a/thirdparty/mbedtls/library/net_sockets.c +++ b/thirdparty/mbedtls/library/net_sockets.c @@ -19,6 +19,11 @@ * This file is part of mbed TLS (https://tls.mbed.org) */ +/* Enable definition of getaddrinfo() even when compiling with -std=c99. Must + * be set before config.h, which pulls in glibc's features.h indirectly. + * Harmless on other platforms. */ +#define _POSIX_C_SOURCE 200112L + #if !defined(MBEDTLS_CONFIG_FILE) #include "mbedtls/config.h" #else @@ -28,7 +33,8 @@ #if defined(MBEDTLS_NET_C) #if !defined(unix) && !defined(__unix__) && !defined(__unix) && \ - !defined(__APPLE__) && !defined(_WIN32) + !defined(__APPLE__) && !defined(_WIN32) && !defined(__QNXNTO__) && \ + !defined(__HAIKU__) #error "This module only works on Unix and Windows, see MBEDTLS_NET_C in config.h" #endif @@ -45,13 +51,13 @@ #if (defined(_WIN32) || defined(_WIN32_WCE)) && !defined(EFIX64) && \ !defined(EFI32) -/* GODOT ADDITION */ +#define IS_EINTR( ret ) ( ( ret ) == WSAEINTR ) + #if !defined(_WIN32_WINNT) || (_WIN32_WINNT < 0x0501) #undef _WIN32_WINNT /* Enables getaddrinfo() & Co */ #define _WIN32_WINNT 0x0501 #endif -/* END GODOT ADDITION */ #include <ws2tcpip.h> @@ -85,6 +91,8 @@ static int wsa_init_done = 0; #include <netdb.h> #include <errno.h> +#define IS_EINTR( ret ) ( ( ret ) == EINTR ) + #endif /* ( _WIN32 || _WIN32_WCE ) && !EFIX64 && !EFI32 */ /* Some MS functions want int and MSVC warns if we pass size_t, @@ -274,7 +282,7 @@ static int net_would_block( const mbedtls_net_context *ctx ) static int net_would_block( const mbedtls_net_context *ctx ) { int err = errno; - + /* * Never return 'WOULD BLOCK' on a non-blocking socket */ @@ -442,6 +450,72 @@ int mbedtls_net_set_nonblock( mbedtls_net_context *ctx ) } /* + * Check if data is available on the socket + */ + +int mbedtls_net_poll( mbedtls_net_context *ctx, uint32_t rw, uint32_t timeout ) +{ + int ret; + struct timeval tv; + + fd_set read_fds; + fd_set write_fds; + + int fd = ctx->fd; + + if( fd < 0 ) + return( MBEDTLS_ERR_NET_INVALID_CONTEXT ); + +#if defined(__has_feature) +#if __has_feature(memory_sanitizer) + /* Ensure that memory sanitizers consider read_fds and write_fds as + * initialized even on platforms such as Glibc/x86_64 where FD_ZERO + * is implemented in assembly. */ + memset( &read_fds, 0, sizeof( read_fds ) ); + memset( &write_fds, 0, sizeof( write_fds ) ); +#endif +#endif + + FD_ZERO( &read_fds ); + if( rw & MBEDTLS_NET_POLL_READ ) + { + rw &= ~MBEDTLS_NET_POLL_READ; + FD_SET( fd, &read_fds ); + } + + FD_ZERO( &write_fds ); + if( rw & MBEDTLS_NET_POLL_WRITE ) + { + rw &= ~MBEDTLS_NET_POLL_WRITE; + FD_SET( fd, &write_fds ); + } + + if( rw != 0 ) + return( MBEDTLS_ERR_NET_BAD_INPUT_DATA ); + + tv.tv_sec = timeout / 1000; + tv.tv_usec = ( timeout % 1000 ) * 1000; + + do + { + ret = select( fd + 1, &read_fds, &write_fds, NULL, + timeout == (uint32_t) -1 ? NULL : &tv ); + } + while( IS_EINTR( ret ) ); + + if( ret < 0 ) + return( MBEDTLS_ERR_NET_POLL_FAILED ); + + ret = 0; + if( FD_ISSET( fd, &read_fds ) ) + ret |= MBEDTLS_NET_POLL_READ; + if( FD_ISSET( fd, &write_fds ) ) + ret |= MBEDTLS_NET_POLL_WRITE; + + return( ret ); +} + +/* * Portable usleep helper */ void mbedtls_net_usleep( unsigned long usec ) @@ -500,8 +574,8 @@ int mbedtls_net_recv( void *ctx, unsigned char *buf, size_t len ) /* * Read at most 'len' characters, blocking for at most 'timeout' ms */ -int mbedtls_net_recv_timeout( void *ctx, unsigned char *buf, size_t len, - uint32_t timeout ) +int mbedtls_net_recv_timeout( void *ctx, unsigned char *buf, + size_t len, uint32_t timeout ) { int ret; struct timeval tv; diff --git a/thirdparty/mbedtls/library/nist_kw.c b/thirdparty/mbedtls/library/nist_kw.c new file mode 100644 index 0000000000..176af9fe08 --- /dev/null +++ b/thirdparty/mbedtls/library/nist_kw.c @@ -0,0 +1,755 @@ +/* + * Implementation of NIST SP 800-38F key wrapping, supporting KW and KWP modes + * only + * + * Copyright (C) 2018, Arm Limited (or its affiliates), All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of Mbed TLS (https://tls.mbed.org) + */ +/* + * Definition of Key Wrapping: + * https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-38F.pdf + * RFC 3394 "Advanced Encryption Standard (AES) Key Wrap Algorithm" + * RFC 5649 "Advanced Encryption Standard (AES) Key Wrap with Padding Algorithm" + * + * Note: RFC 3394 defines different methodology for intermediate operations for + * the wrapping and unwrapping operation than the definition in NIST SP 800-38F. + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_NIST_KW_C) + +#include "mbedtls/nist_kw.h" +#include "mbedtls/platform_util.h" + +#include <stdint.h> +#include <string.h> + +#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include <stdio.h> +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */ + +#if !defined(MBEDTLS_NIST_KW_ALT) + +#define KW_SEMIBLOCK_LENGTH 8 +#define MIN_SEMIBLOCKS_COUNT 3 + +/* constant-time buffer comparison */ +static inline unsigned char mbedtls_nist_kw_safer_memcmp( const void *a, const void *b, size_t n ) +{ + size_t i; + volatile const unsigned char *A = (volatile const unsigned char *) a; + volatile const unsigned char *B = (volatile const unsigned char *) b; + volatile unsigned char diff = 0; + + for( i = 0; i < n; i++ ) + { + /* Read volatile data in order before computing diff. + * This avoids IAR compiler warning: + * 'the order of volatile accesses is undefined ..' */ + unsigned char x = A[i], y = B[i]; + diff |= x ^ y; + } + + return( diff ); +} + +/*! The 64-bit default integrity check value (ICV) for KW mode. */ +static const unsigned char NIST_KW_ICV1[] = {0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6}; +/*! The 32-bit default integrity check value (ICV) for KWP mode. */ +static const unsigned char NIST_KW_ICV2[] = {0xA6, 0x59, 0x59, 0xA6}; + +#ifndef GET_UINT32_BE +#define GET_UINT32_BE(n,b,i) \ +do { \ + (n) = ( (uint32_t) (b)[(i) ] << 24 ) \ + | ( (uint32_t) (b)[(i) + 1] << 16 ) \ + | ( (uint32_t) (b)[(i) + 2] << 8 ) \ + | ( (uint32_t) (b)[(i) + 3] ); \ +} while( 0 ) +#endif + +#ifndef PUT_UINT32_BE +#define PUT_UINT32_BE(n,b,i) \ +do { \ + (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \ + (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \ + (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \ + (b)[(i) + 3] = (unsigned char) ( (n) ); \ +} while( 0 ) +#endif + +/* + * Initialize context + */ +void mbedtls_nist_kw_init( mbedtls_nist_kw_context *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_nist_kw_context ) ); +} + +int mbedtls_nist_kw_setkey( mbedtls_nist_kw_context *ctx, + mbedtls_cipher_id_t cipher, + const unsigned char *key, + unsigned int keybits, + const int is_wrap ) +{ + int ret; + const mbedtls_cipher_info_t *cipher_info; + + cipher_info = mbedtls_cipher_info_from_values( cipher, + keybits, + MBEDTLS_MODE_ECB ); + if( cipher_info == NULL ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + if( cipher_info->block_size != 16 ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + /* + * SP 800-38F currently defines AES cipher as the only block cipher allowed: + * "For KW and KWP, the underlying block cipher shall be approved, and the + * block size shall be 128 bits. Currently, the AES block cipher, with key + * lengths of 128, 192, or 256 bits, is the only block cipher that fits + * this profile." + * Currently we don't support other 128 bit block ciphers for key wrapping, + * such as Camellia and Aria. + */ + if( cipher != MBEDTLS_CIPHER_ID_AES ) + return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); + + mbedtls_cipher_free( &ctx->cipher_ctx ); + + if( ( ret = mbedtls_cipher_setup( &ctx->cipher_ctx, cipher_info ) ) != 0 ) + return( ret ); + + if( ( ret = mbedtls_cipher_setkey( &ctx->cipher_ctx, key, keybits, + is_wrap ? MBEDTLS_ENCRYPT : + MBEDTLS_DECRYPT ) + ) != 0 ) + { + return( ret ); + } + + return( 0 ); +} + +/* + * Free context + */ +void mbedtls_nist_kw_free( mbedtls_nist_kw_context *ctx ) +{ + mbedtls_cipher_free( &ctx->cipher_ctx ); + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_nist_kw_context ) ); +} + +/* + * Helper function for Xoring the uint64_t "t" with the encrypted A. + * Defined in NIST SP 800-38F section 6.1 + */ +static void calc_a_xor_t( unsigned char A[KW_SEMIBLOCK_LENGTH], uint64_t t ) +{ + size_t i = 0; + for( i = 0; i < sizeof( t ); i++ ) + { + A[i] ^= ( t >> ( ( sizeof( t ) - 1 - i ) * 8 ) ) & 0xff; + } +} + +/* + * KW-AE as defined in SP 800-38F section 6.2 + * KWP-AE as defined in SP 800-38F section 6.3 + */ +int mbedtls_nist_kw_wrap( mbedtls_nist_kw_context *ctx, + mbedtls_nist_kw_mode_t mode, + const unsigned char *input, size_t in_len, + unsigned char *output, size_t *out_len, size_t out_size ) +{ + int ret = 0; + size_t semiblocks = 0; + size_t s; + size_t olen, padlen = 0; + uint64_t t = 0; + unsigned char outbuff[KW_SEMIBLOCK_LENGTH * 2]; + unsigned char inbuff[KW_SEMIBLOCK_LENGTH * 2]; + unsigned char *R2 = output + KW_SEMIBLOCK_LENGTH; + unsigned char *A = output; + + *out_len = 0; + /* + * Generate the String to work on + */ + if( mode == MBEDTLS_KW_MODE_KW ) + { + if( out_size < in_len + KW_SEMIBLOCK_LENGTH ) + { + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + + /* + * According to SP 800-38F Table 1, the plaintext length for KW + * must be between 2 to 2^54-1 semiblocks inclusive. + */ + if( in_len < 16 || +#if SIZE_MAX > 0x1FFFFFFFFFFFFF8 + in_len > 0x1FFFFFFFFFFFFF8 || +#endif + in_len % KW_SEMIBLOCK_LENGTH != 0 ) + { + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + + memcpy( output, NIST_KW_ICV1, KW_SEMIBLOCK_LENGTH ); + memmove( output + KW_SEMIBLOCK_LENGTH, input, in_len ); + } + else + { + if( in_len % 8 != 0 ) + { + padlen = ( 8 - ( in_len % 8 ) ); + } + + if( out_size < in_len + KW_SEMIBLOCK_LENGTH + padlen ) + { + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + + /* + * According to SP 800-38F Table 1, the plaintext length for KWP + * must be between 1 and 2^32-1 octets inclusive. + */ + if( in_len < 1 +#if SIZE_MAX > 0xFFFFFFFF + || in_len > 0xFFFFFFFF +#endif + ) + { + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + + memcpy( output, NIST_KW_ICV2, KW_SEMIBLOCK_LENGTH / 2 ); + PUT_UINT32_BE( ( in_len & 0xffffffff ), output, + KW_SEMIBLOCK_LENGTH / 2 ); + + memcpy( output + KW_SEMIBLOCK_LENGTH, input, in_len ); + memset( output + KW_SEMIBLOCK_LENGTH + in_len, 0, padlen ); + } + semiblocks = ( ( in_len + padlen ) / KW_SEMIBLOCK_LENGTH ) + 1; + + s = 6 * ( semiblocks - 1 ); + + if( mode == MBEDTLS_KW_MODE_KWP + && in_len <= KW_SEMIBLOCK_LENGTH ) + { + memcpy( inbuff, output, 16 ); + ret = mbedtls_cipher_update( &ctx->cipher_ctx, + inbuff, 16, output, &olen ); + if( ret != 0 ) + goto cleanup; + } + else + { + /* + * Do the wrapping function W, as defined in RFC 3394 section 2.2.1 + */ + if( semiblocks < MIN_SEMIBLOCKS_COUNT ) + { + ret = MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; + goto cleanup; + } + + /* Calculate intermediate values */ + for( t = 1; t <= s; t++ ) + { + memcpy( inbuff, A, KW_SEMIBLOCK_LENGTH ); + memcpy( inbuff + KW_SEMIBLOCK_LENGTH, R2, KW_SEMIBLOCK_LENGTH ); + + ret = mbedtls_cipher_update( &ctx->cipher_ctx, + inbuff, 16, outbuff, &olen ); + if( ret != 0 ) + goto cleanup; + + memcpy( A, outbuff, KW_SEMIBLOCK_LENGTH ); + calc_a_xor_t( A, t ); + + memcpy( R2, outbuff + KW_SEMIBLOCK_LENGTH, KW_SEMIBLOCK_LENGTH ); + R2 += KW_SEMIBLOCK_LENGTH; + if( R2 >= output + ( semiblocks * KW_SEMIBLOCK_LENGTH ) ) + R2 = output + KW_SEMIBLOCK_LENGTH; + } + } + + *out_len = semiblocks * KW_SEMIBLOCK_LENGTH; + +cleanup: + + if( ret != 0) + { + memset( output, 0, semiblocks * KW_SEMIBLOCK_LENGTH ); + } + mbedtls_platform_zeroize( inbuff, KW_SEMIBLOCK_LENGTH * 2 ); + mbedtls_platform_zeroize( outbuff, KW_SEMIBLOCK_LENGTH * 2 ); + mbedtls_cipher_finish( &ctx->cipher_ctx, NULL, &olen ); + return( ret ); +} + +/* + * W-1 function as defined in RFC 3394 section 2.2.2 + * This function assumes the following: + * 1. Output buffer is at least of size ( semiblocks - 1 ) * KW_SEMIBLOCK_LENGTH. + * 2. The input buffer is of size semiblocks * KW_SEMIBLOCK_LENGTH. + * 3. Minimal number of semiblocks is 3. + * 4. A is a buffer to hold the first semiblock of the input buffer. + */ +static int unwrap( mbedtls_nist_kw_context *ctx, + const unsigned char *input, size_t semiblocks, + unsigned char A[KW_SEMIBLOCK_LENGTH], + unsigned char *output, size_t* out_len ) +{ + int ret = 0; + const size_t s = 6 * ( semiblocks - 1 ); + size_t olen; + uint64_t t = 0; + unsigned char outbuff[KW_SEMIBLOCK_LENGTH * 2]; + unsigned char inbuff[KW_SEMIBLOCK_LENGTH * 2]; + unsigned char *R = output + ( semiblocks - 2 ) * KW_SEMIBLOCK_LENGTH; + *out_len = 0; + + if( semiblocks < MIN_SEMIBLOCKS_COUNT ) + { + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + + memcpy( A, input, KW_SEMIBLOCK_LENGTH ); + memmove( output, input + KW_SEMIBLOCK_LENGTH, ( semiblocks - 1 ) * KW_SEMIBLOCK_LENGTH ); + + /* Calculate intermediate values */ + for( t = s; t >= 1; t-- ) + { + calc_a_xor_t( A, t ); + + memcpy( inbuff, A, KW_SEMIBLOCK_LENGTH ); + memcpy( inbuff + KW_SEMIBLOCK_LENGTH, R, KW_SEMIBLOCK_LENGTH ); + + ret = mbedtls_cipher_update( &ctx->cipher_ctx, + inbuff, 16, outbuff, &olen ); + if( ret != 0 ) + goto cleanup; + + memcpy( A, outbuff, KW_SEMIBLOCK_LENGTH ); + + /* Set R as LSB64 of outbuff */ + memcpy( R, outbuff + KW_SEMIBLOCK_LENGTH, KW_SEMIBLOCK_LENGTH ); + + if( R == output ) + R = output + ( semiblocks - 2 ) * KW_SEMIBLOCK_LENGTH; + else + R -= KW_SEMIBLOCK_LENGTH; + } + + *out_len = ( semiblocks - 1 ) * KW_SEMIBLOCK_LENGTH; + +cleanup: + if( ret != 0) + memset( output, 0, ( semiblocks - 1 ) * KW_SEMIBLOCK_LENGTH ); + mbedtls_platform_zeroize( inbuff, sizeof( inbuff ) ); + mbedtls_platform_zeroize( outbuff, sizeof( outbuff ) ); + + return( ret ); +} + +/* + * KW-AD as defined in SP 800-38F section 6.2 + * KWP-AD as defined in SP 800-38F section 6.3 + */ +int mbedtls_nist_kw_unwrap( mbedtls_nist_kw_context *ctx, + mbedtls_nist_kw_mode_t mode, + const unsigned char *input, size_t in_len, + unsigned char *output, size_t *out_len, size_t out_size ) +{ + int ret = 0; + size_t i, olen; + unsigned char A[KW_SEMIBLOCK_LENGTH]; + unsigned char diff, bad_padding = 0; + + *out_len = 0; + if( out_size < in_len - KW_SEMIBLOCK_LENGTH ) + { + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + + if( mode == MBEDTLS_KW_MODE_KW ) + { + /* + * According to SP 800-38F Table 1, the ciphertext length for KW + * must be between 3 to 2^54 semiblocks inclusive. + */ + if( in_len < 24 || +#if SIZE_MAX > 0x200000000000000 + in_len > 0x200000000000000 || +#endif + in_len % KW_SEMIBLOCK_LENGTH != 0 ) + { + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + + ret = unwrap( ctx, input, in_len / KW_SEMIBLOCK_LENGTH, + A, output, out_len ); + if( ret != 0 ) + goto cleanup; + + /* Check ICV in "constant-time" */ + diff = mbedtls_nist_kw_safer_memcmp( NIST_KW_ICV1, A, KW_SEMIBLOCK_LENGTH ); + + if( diff != 0 ) + { + ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED; + goto cleanup; + } + + } + else if( mode == MBEDTLS_KW_MODE_KWP ) + { + size_t padlen = 0; + uint32_t Plen; + /* + * According to SP 800-38F Table 1, the ciphertext length for KWP + * must be between 2 to 2^29 semiblocks inclusive. + */ + if( in_len < KW_SEMIBLOCK_LENGTH * 2 || +#if SIZE_MAX > 0x100000000 + in_len > 0x100000000 || +#endif + in_len % KW_SEMIBLOCK_LENGTH != 0 ) + { + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + + if( in_len == KW_SEMIBLOCK_LENGTH * 2 ) + { + unsigned char outbuff[KW_SEMIBLOCK_LENGTH * 2]; + ret = mbedtls_cipher_update( &ctx->cipher_ctx, + input, 16, outbuff, &olen ); + if( ret != 0 ) + goto cleanup; + + memcpy( A, outbuff, KW_SEMIBLOCK_LENGTH ); + memcpy( output, outbuff + KW_SEMIBLOCK_LENGTH, KW_SEMIBLOCK_LENGTH ); + mbedtls_platform_zeroize( outbuff, sizeof( outbuff ) ); + *out_len = KW_SEMIBLOCK_LENGTH; + } + else + { + /* in_len >= KW_SEMIBLOCK_LENGTH * 3 */ + ret = unwrap( ctx, input, in_len / KW_SEMIBLOCK_LENGTH, + A, output, out_len ); + if( ret != 0 ) + goto cleanup; + } + + /* Check ICV in "constant-time" */ + diff = mbedtls_nist_kw_safer_memcmp( NIST_KW_ICV2, A, KW_SEMIBLOCK_LENGTH / 2 ); + + if( diff != 0 ) + { + ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED; + } + + GET_UINT32_BE( Plen, A, KW_SEMIBLOCK_LENGTH / 2 ); + + /* + * Plen is the length of the plaintext, when the input is valid. + * If Plen is larger than the plaintext and padding, padlen will be + * larger than 8, because of the type wrap around. + */ + padlen = in_len - KW_SEMIBLOCK_LENGTH - Plen; + if ( padlen > 7 ) + { + padlen &= 7; + ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED; + } + + /* Check padding in "constant-time" */ + for( diff = 0, i = 0; i < KW_SEMIBLOCK_LENGTH; i++ ) + { + if( i >= KW_SEMIBLOCK_LENGTH - padlen ) + diff |= output[*out_len - KW_SEMIBLOCK_LENGTH + i]; + else + bad_padding |= output[*out_len - KW_SEMIBLOCK_LENGTH + i]; + } + + if( diff != 0 ) + { + ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED; + } + + if( ret != 0 ) + { + goto cleanup; + } + memset( output + Plen, 0, padlen ); + *out_len = Plen; + } + else + { + ret = MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; + goto cleanup; + } + +cleanup: + if( ret != 0 ) + { + memset( output, 0, *out_len ); + *out_len = 0; + } + + mbedtls_platform_zeroize( &bad_padding, sizeof( bad_padding) ); + mbedtls_platform_zeroize( &diff, sizeof( diff ) ); + mbedtls_platform_zeroize( A, sizeof( A ) ); + mbedtls_cipher_finish( &ctx->cipher_ctx, NULL, &olen ); + return( ret ); +} + +#endif /* !MBEDTLS_NIST_KW_ALT */ + +#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C) + +#define KW_TESTS 3 + +/* + * Test vectors taken from NIST + * https://csrc.nist.gov/Projects/Cryptographic-Algorithm-Validation-Program/CAVP-TESTING-BLOCK-CIPHER-MODES#KW + */ +static const unsigned int key_len[KW_TESTS] = { 16, 24, 32 }; + +static const unsigned char kw_key[KW_TESTS][32] = { + { 0x75, 0x75, 0xda, 0x3a, 0x93, 0x60, 0x7c, 0xc2, + 0xbf, 0xd8, 0xce, 0xc7, 0xaa, 0xdf, 0xd9, 0xa6 }, + { 0x2d, 0x85, 0x26, 0x08, 0x1d, 0x02, 0xfb, 0x5b, + 0x85, 0xf6, 0x9a, 0xc2, 0x86, 0xec, 0xd5, 0x7d, + 0x40, 0xdf, 0x5d, 0xf3, 0x49, 0x47, 0x44, 0xd3 }, + { 0x11, 0x2a, 0xd4, 0x1b, 0x48, 0x56, 0xc7, 0x25, + 0x4a, 0x98, 0x48, 0xd3, 0x0f, 0xdd, 0x78, 0x33, + 0x5b, 0x03, 0x9a, 0x48, 0xa8, 0x96, 0x2c, 0x4d, + 0x1c, 0xb7, 0x8e, 0xab, 0xd5, 0xda, 0xd7, 0x88 } +}; + +static const unsigned char kw_msg[KW_TESTS][40] = { + { 0x42, 0x13, 0x6d, 0x3c, 0x38, 0x4a, 0x3e, 0xea, + 0xc9, 0x5a, 0x06, 0x6f, 0xd2, 0x8f, 0xed, 0x3f }, + { 0x95, 0xc1, 0x1b, 0xf5, 0x35, 0x3a, 0xfe, 0xdb, + 0x98, 0xfd, 0xd6, 0xc8, 0xca, 0x6f, 0xdb, 0x6d, + 0xa5, 0x4b, 0x74, 0xb4, 0x99, 0x0f, 0xdc, 0x45, + 0xc0, 0x9d, 0x15, 0x8f, 0x51, 0xce, 0x62, 0x9d, + 0xe2, 0xaf, 0x26, 0xe3, 0x25, 0x0e, 0x6b, 0x4c }, + { 0x1b, 0x20, 0xbf, 0x19, 0x90, 0xb0, 0x65, 0xd7, + 0x98, 0xe1, 0xb3, 0x22, 0x64, 0xad, 0x50, 0xa8, + 0x74, 0x74, 0x92, 0xba, 0x09, 0xa0, 0x4d, 0xd1 } +}; + +static const size_t kw_msg_len[KW_TESTS] = { 16, 40, 24 }; +static const size_t kw_out_len[KW_TESTS] = { 24, 48, 32 }; +static const unsigned char kw_res[KW_TESTS][48] = { + { 0x03, 0x1f, 0x6b, 0xd7, 0xe6, 0x1e, 0x64, 0x3d, + 0xf6, 0x85, 0x94, 0x81, 0x6f, 0x64, 0xca, 0xa3, + 0xf5, 0x6f, 0xab, 0xea, 0x25, 0x48, 0xf5, 0xfb }, + { 0x44, 0x3c, 0x6f, 0x15, 0x09, 0x83, 0x71, 0x91, + 0x3e, 0x5c, 0x81, 0x4c, 0xa1, 0xa0, 0x42, 0xec, + 0x68, 0x2f, 0x7b, 0x13, 0x6d, 0x24, 0x3a, 0x4d, + 0x6c, 0x42, 0x6f, 0xc6, 0x97, 0x15, 0x63, 0xe8, + 0xa1, 0x4a, 0x55, 0x8e, 0x09, 0x64, 0x16, 0x19, + 0xbf, 0x03, 0xfc, 0xaf, 0x90, 0xb1, 0xfc, 0x2d }, + { 0xba, 0x8a, 0x25, 0x9a, 0x47, 0x1b, 0x78, 0x7d, + 0xd5, 0xd5, 0x40, 0xec, 0x25, 0xd4, 0x3d, 0x87, + 0x20, 0x0f, 0xda, 0xdc, 0x6d, 0x1f, 0x05, 0xd9, + 0x16, 0x58, 0x4f, 0xa9, 0xf6, 0xcb, 0xf5, 0x12 } +}; + +static const unsigned char kwp_key[KW_TESTS][32] = { + { 0x78, 0x65, 0xe2, 0x0f, 0x3c, 0x21, 0x65, 0x9a, + 0xb4, 0x69, 0x0b, 0x62, 0x9c, 0xdf, 0x3c, 0xc4 }, + { 0xf5, 0xf8, 0x96, 0xa3, 0xbd, 0x2f, 0x4a, 0x98, + 0x23, 0xef, 0x16, 0x2b, 0x00, 0xb8, 0x05, 0xd7, + 0xde, 0x1e, 0xa4, 0x66, 0x26, 0x96, 0xa2, 0x58 }, + { 0x95, 0xda, 0x27, 0x00, 0xca, 0x6f, 0xd9, 0xa5, + 0x25, 0x54, 0xee, 0x2a, 0x8d, 0xf1, 0x38, 0x6f, + 0x5b, 0x94, 0xa1, 0xa6, 0x0e, 0xd8, 0xa4, 0xae, + 0xf6, 0x0a, 0x8d, 0x61, 0xab, 0x5f, 0x22, 0x5a } +}; + +static const unsigned char kwp_msg[KW_TESTS][31] = { + { 0xbd, 0x68, 0x43, 0xd4, 0x20, 0x37, 0x8d, 0xc8, + 0x96 }, + { 0x6c, 0xcd, 0xd5, 0x85, 0x18, 0x40, 0x97, 0xeb, + 0xd5, 0xc3, 0xaf, 0x3e, 0x47, 0xd0, 0x2c, 0x19, + 0x14, 0x7b, 0x4d, 0x99, 0x5f, 0x96, 0x43, 0x66, + 0x91, 0x56, 0x75, 0x8c, 0x13, 0x16, 0x8f }, + { 0xd1 } +}; +static const size_t kwp_msg_len[KW_TESTS] = { 9, 31, 1 }; + +static const unsigned char kwp_res[KW_TESTS][48] = { + { 0x41, 0xec, 0xa9, 0x56, 0xd4, 0xaa, 0x04, 0x7e, + 0xb5, 0xcf, 0x4e, 0xfe, 0x65, 0x96, 0x61, 0xe7, + 0x4d, 0xb6, 0xf8, 0xc5, 0x64, 0xe2, 0x35, 0x00 }, + { 0x4e, 0x9b, 0xc2, 0xbc, 0xbc, 0x6c, 0x1e, 0x13, + 0xd3, 0x35, 0xbc, 0xc0, 0xf7, 0x73, 0x6a, 0x88, + 0xfa, 0x87, 0x53, 0x66, 0x15, 0xbb, 0x8e, 0x63, + 0x8b, 0xcc, 0x81, 0x66, 0x84, 0x68, 0x17, 0x90, + 0x67, 0xcf, 0xa9, 0x8a, 0x9d, 0x0e, 0x33, 0x26 }, + { 0x06, 0xba, 0x7a, 0xe6, 0xf3, 0x24, 0x8c, 0xfd, + 0xcf, 0x26, 0x75, 0x07, 0xfa, 0x00, 0x1b, 0xc4 } +}; +static const size_t kwp_out_len[KW_TESTS] = { 24, 40, 16 }; + +int mbedtls_nist_kw_self_test( int verbose ) +{ + mbedtls_nist_kw_context ctx; + unsigned char out[48]; + size_t olen; + int i; + int ret = 0; + mbedtls_nist_kw_init( &ctx ); + + for( i = 0; i < KW_TESTS; i++ ) + { + if( verbose != 0 ) + mbedtls_printf( " KW-AES-%u ", (unsigned int) key_len[i] * 8 ); + + ret = mbedtls_nist_kw_setkey( &ctx, MBEDTLS_CIPHER_ID_AES, + kw_key[i], key_len[i] * 8, 1 ); + if( ret != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( " KW: setup failed " ); + + goto end; + } + + ret = mbedtls_nist_kw_wrap( &ctx, MBEDTLS_KW_MODE_KW, kw_msg[i], + kw_msg_len[i], out, &olen, sizeof( out ) ); + if( ret != 0 || kw_out_len[i] != olen || + memcmp( out, kw_res[i], kw_out_len[i] ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed. "); + + ret = 1; + goto end; + } + + if( ( ret = mbedtls_nist_kw_setkey( &ctx, MBEDTLS_CIPHER_ID_AES, + kw_key[i], key_len[i] * 8, 0 ) ) + != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( " KW: setup failed "); + + goto end; + } + + ret = mbedtls_nist_kw_unwrap( &ctx, MBEDTLS_KW_MODE_KW, + out, olen, out, &olen, sizeof( out ) ); + + if( ret != 0 || olen != kw_msg_len[i] || + memcmp( out, kw_msg[i], kw_msg_len[i] ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + goto end; + } + + if( verbose != 0 ) + mbedtls_printf( " passed\n" ); + } + + for( i = 0; i < KW_TESTS; i++ ) + { + olen = sizeof( out ); + if( verbose != 0 ) + mbedtls_printf( " KWP-AES-%u ", (unsigned int) key_len[i] * 8 ); + + ret = mbedtls_nist_kw_setkey( &ctx, MBEDTLS_CIPHER_ID_AES, kwp_key[i], + key_len[i] * 8, 1 ); + if( ret != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( " KWP: setup failed " ); + + goto end; + } + ret = mbedtls_nist_kw_wrap( &ctx, MBEDTLS_KW_MODE_KWP, kwp_msg[i], + kwp_msg_len[i], out, &olen, sizeof( out ) ); + + if( ret != 0 || kwp_out_len[i] != olen || + memcmp( out, kwp_res[i], kwp_out_len[i] ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed. "); + + ret = 1; + goto end; + } + + if( ( ret = mbedtls_nist_kw_setkey( &ctx, MBEDTLS_CIPHER_ID_AES, + kwp_key[i], key_len[i] * 8, 0 ) ) + != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( " KWP: setup failed "); + + goto end; + } + + ret = mbedtls_nist_kw_unwrap( &ctx, MBEDTLS_KW_MODE_KWP, out, + olen, out, &olen, sizeof( out ) ); + + if( ret != 0 || olen != kwp_msg_len[i] || + memcmp( out, kwp_msg[i], kwp_msg_len[i] ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed. "); + + ret = 1; + goto end; + } + + if( verbose != 0 ) + mbedtls_printf( " passed\n" ); + } +end: + mbedtls_nist_kw_free( &ctx ); + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + return( ret ); +} + +#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */ + +#endif /* MBEDTLS_NIST_KW_C */ diff --git a/thirdparty/mbedtls/library/pem.c b/thirdparty/mbedtls/library/pem.c index ac86d7e479..6069a23dec 100644 --- a/thirdparty/mbedtls/library/pem.c +++ b/thirdparty/mbedtls/library/pem.c @@ -33,6 +33,7 @@ #include "mbedtls/aes.h" #include "mbedtls/md5.h" #include "mbedtls/cipher.h" +#include "mbedtls/platform_util.h" #include <string.h> @@ -45,11 +46,6 @@ #endif #if defined(MBEDTLS_PEM_PARSE_C) -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize( void *v, size_t n ) { - volatile unsigned char *p = v; while( n-- ) *p++ = 0; -} - void mbedtls_pem_init( mbedtls_pem_context *ctx ) { memset( ctx, 0, sizeof( mbedtls_pem_context ) ); @@ -135,7 +131,7 @@ static int pem_pbkdf1( unsigned char *key, size_t keylen, exit: mbedtls_md5_free( &md5_ctx ); - mbedtls_zeroize( md5sum, 16 ); + mbedtls_platform_zeroize( md5sum, 16 ); return( ret ); } @@ -164,7 +160,7 @@ static int pem_des_decrypt( unsigned char des_iv[8], exit: mbedtls_des_free( &des_ctx ); - mbedtls_zeroize( des_key, 8 ); + mbedtls_platform_zeroize( des_key, 8 ); return( ret ); } @@ -192,7 +188,7 @@ static int pem_des3_decrypt( unsigned char des3_iv[8], exit: mbedtls_des3_free( &des3_ctx ); - mbedtls_zeroize( des3_key, 24 ); + mbedtls_platform_zeroize( des3_key, 24 ); return( ret ); } @@ -222,7 +218,7 @@ static int pem_aes_decrypt( unsigned char aes_iv[16], unsigned int keylen, exit: mbedtls_aes_free( &aes_ctx ); - mbedtls_zeroize( aes_key, keylen ); + mbedtls_platform_zeroize( aes_key, keylen ); return( ret ); } @@ -359,7 +355,7 @@ int mbedtls_pem_read_buffer( mbedtls_pem_context *ctx, const char *header, const if( ( ret = mbedtls_base64_decode( buf, len, &len, s1, s2 - s1 ) ) != 0 ) { - mbedtls_zeroize( buf, len ); + mbedtls_platform_zeroize( buf, len ); mbedtls_free( buf ); return( MBEDTLS_ERR_PEM_INVALID_DATA + ret ); } @@ -370,7 +366,7 @@ int mbedtls_pem_read_buffer( mbedtls_pem_context *ctx, const char *header, const ( defined(MBEDTLS_DES_C) || defined(MBEDTLS_AES_C) ) if( pwd == NULL ) { - mbedtls_zeroize( buf, len ); + mbedtls_platform_zeroize( buf, len ); mbedtls_free( buf ); return( MBEDTLS_ERR_PEM_PASSWORD_REQUIRED ); } @@ -403,16 +399,16 @@ int mbedtls_pem_read_buffer( mbedtls_pem_context *ctx, const char *header, const * The result will be ASN.1 starting with a SEQUENCE tag, with 1 to 3 * length bytes (allow 4 to be sure) in all known use cases. * - * Use that as heurisitic to try detecting password mismatchs. + * Use that as a heuristic to try to detect password mismatches. */ if( len <= 2 || buf[0] != 0x30 || buf[1] > 0x83 ) { - mbedtls_zeroize( buf, len ); + mbedtls_platform_zeroize( buf, len ); mbedtls_free( buf ); return( MBEDTLS_ERR_PEM_PASSWORD_MISMATCH ); } #else - mbedtls_zeroize( buf, len ); + mbedtls_platform_zeroize( buf, len ); mbedtls_free( buf ); return( MBEDTLS_ERR_PEM_FEATURE_UNAVAILABLE ); #endif /* MBEDTLS_MD5_C && MBEDTLS_CIPHER_MODE_CBC && @@ -428,11 +424,11 @@ int mbedtls_pem_read_buffer( mbedtls_pem_context *ctx, const char *header, const void mbedtls_pem_free( mbedtls_pem_context *ctx ) { if( ctx->buf != NULL ) - mbedtls_zeroize( ctx->buf, ctx->buflen ); + mbedtls_platform_zeroize( ctx->buf, ctx->buflen ); mbedtls_free( ctx->buf ); mbedtls_free( ctx->info ); - mbedtls_zeroize( ctx, sizeof( mbedtls_pem_context ) ); + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_pem_context ) ); } #endif /* MBEDTLS_PEM_PARSE_C */ diff --git a/thirdparty/mbedtls/library/pk.c b/thirdparty/mbedtls/library/pk.c index b52c73fbc6..f05b139e3f 100644 --- a/thirdparty/mbedtls/library/pk.c +++ b/thirdparty/mbedtls/library/pk.c @@ -29,6 +29,8 @@ #include "mbedtls/pk.h" #include "mbedtls/pk_internal.h" +#include "mbedtls/platform_util.h" + #if defined(MBEDTLS_RSA_C) #include "mbedtls/rsa.h" #endif @@ -42,11 +44,6 @@ #include <limits.h> #include <stdint.h> -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize( void *v, size_t n ) { - volatile unsigned char *p = v; while( n-- ) *p++ = 0; -} - /* * Initialise a mbedtls_pk_context */ @@ -69,7 +66,7 @@ void mbedtls_pk_free( mbedtls_pk_context *ctx ) ctx->pk_info->ctx_free_func( ctx->pk_ctx ); - mbedtls_zeroize( ctx, sizeof( mbedtls_pk_context ) ); + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_pk_context ) ); } /* diff --git a/thirdparty/mbedtls/library/pk_wrap.c b/thirdparty/mbedtls/library/pk_wrap.c index a4bb35fc8f..2c7d2d79b8 100644 --- a/thirdparty/mbedtls/library/pk_wrap.c +++ b/thirdparty/mbedtls/library/pk_wrap.c @@ -41,6 +41,10 @@ #include "mbedtls/ecdsa.h" #endif +#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) +#include "mbedtls/platform_util.h" +#endif + #if defined(MBEDTLS_PLATFORM_C) #include "mbedtls/platform.h" #else @@ -52,13 +56,6 @@ #include <limits.h> #include <stdint.h> -#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize( void *v, size_t n ) { - volatile unsigned char *p = v; while( n-- ) *p++ = 0; -} -#endif - #if defined(MBEDTLS_RSA_C) static int rsa_can_do( mbedtls_pk_type_t type ) { @@ -93,6 +90,11 @@ static int rsa_verify_wrap( void *ctx, mbedtls_md_type_t md_alg, (unsigned int) hash_len, hash, sig ) ) != 0 ) return( ret ); + /* The buffer contains a valid signature followed by extra data. + * We have a special error code for that so that so that callers can + * use mbedtls_pk_verify() to check "Does the buffer start with a + * valid signature?" and not just "Does the buffer contain a valid + * signature?". */ if( sig_len > rsa_len ) return( MBEDTLS_ERR_PK_SIG_LEN_MISMATCH ); @@ -493,7 +495,7 @@ static void *rsa_alt_alloc_wrap( void ) static void rsa_alt_free_wrap( void *ctx ) { - mbedtls_zeroize( ctx, sizeof( mbedtls_rsa_alt_context ) ); + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_rsa_alt_context ) ); mbedtls_free( ctx ); } diff --git a/thirdparty/mbedtls/library/pkcs12.c b/thirdparty/mbedtls/library/pkcs12.c index c603a13577..16a15cb63e 100644 --- a/thirdparty/mbedtls/library/pkcs12.c +++ b/thirdparty/mbedtls/library/pkcs12.c @@ -36,6 +36,7 @@ #include "mbedtls/pkcs12.h" #include "mbedtls/asn1.h" #include "mbedtls/cipher.h" +#include "mbedtls/platform_util.h" #include <string.h> @@ -47,11 +48,6 @@ #include "mbedtls/des.h" #endif -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize( void *v, size_t n ) { - volatile unsigned char *p = v; while( n-- ) *p++ = 0; -} - static int pkcs12_parse_pbe_params( mbedtls_asn1_buf *params, mbedtls_asn1_buf *salt, int *iterations ) { @@ -166,7 +162,7 @@ int mbedtls_pkcs12_pbe_sha1_rc4_128( mbedtls_asn1_buf *pbe_params, int mode, goto exit; exit: - mbedtls_zeroize( key, sizeof( key ) ); + mbedtls_platform_zeroize( key, sizeof( key ) ); mbedtls_arc4_free( &ctx ); return( ret ); @@ -223,8 +219,8 @@ int mbedtls_pkcs12_pbe( mbedtls_asn1_buf *pbe_params, int mode, ret = MBEDTLS_ERR_PKCS12_PASSWORD_MISMATCH; exit: - mbedtls_zeroize( key, sizeof( key ) ); - mbedtls_zeroize( iv, sizeof( iv ) ); + mbedtls_platform_zeroize( key, sizeof( key ) ); + mbedtls_platform_zeroize( iv, sizeof( iv ) ); mbedtls_cipher_free( &cipher_ctx ); return( ret ); @@ -352,10 +348,10 @@ int mbedtls_pkcs12_derivation( unsigned char *data, size_t datalen, ret = 0; exit: - mbedtls_zeroize( salt_block, sizeof( salt_block ) ); - mbedtls_zeroize( pwd_block, sizeof( pwd_block ) ); - mbedtls_zeroize( hash_block, sizeof( hash_block ) ); - mbedtls_zeroize( hash_output, sizeof( hash_output ) ); + mbedtls_platform_zeroize( salt_block, sizeof( salt_block ) ); + mbedtls_platform_zeroize( pwd_block, sizeof( pwd_block ) ); + mbedtls_platform_zeroize( hash_block, sizeof( hash_block ) ); + mbedtls_platform_zeroize( hash_output, sizeof( hash_output ) ); mbedtls_md_free( &md_ctx ); diff --git a/thirdparty/mbedtls/library/pkcs5.c b/thirdparty/mbedtls/library/pkcs5.c index 95f44fa98b..f04f0ab25e 100644 --- a/thirdparty/mbedtls/library/pkcs5.c +++ b/thirdparty/mbedtls/library/pkcs5.c @@ -38,9 +38,12 @@ #if defined(MBEDTLS_PKCS5_C) #include "mbedtls/pkcs5.h" + +#if defined(MBEDTLS_ASN1_PARSE_C) #include "mbedtls/asn1.h" #include "mbedtls/cipher.h" #include "mbedtls/oid.h" +#endif /* MBEDTLS_ASN1_PARSE_C */ #include <string.h> @@ -51,6 +54,22 @@ #define mbedtls_printf printf #endif +#if !defined(MBEDTLS_ASN1_PARSE_C) +int mbedtls_pkcs5_pbes2( const mbedtls_asn1_buf *pbe_params, int mode, + const unsigned char *pwd, size_t pwdlen, + const unsigned char *data, size_t datalen, + unsigned char *output ) +{ + ((void) pbe_params); + ((void) mode); + ((void) pwd); + ((void) pwdlen); + ((void) data); + ((void) datalen); + ((void) output); + return( MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE ); +} +#else static int pkcs5_parse_pbkdf2_params( const mbedtls_asn1_buf *params, mbedtls_asn1_buf *salt, int *iterations, int *keylen, mbedtls_md_type_t *md_type ) @@ -211,6 +230,7 @@ exit: return( ret ); } +#endif /* MBEDTLS_ASN1_PARSE_C */ int mbedtls_pkcs5_pbkdf2_hmac( mbedtls_md_context_t *ctx, const unsigned char *password, size_t plen, const unsigned char *salt, size_t slen, @@ -229,8 +249,10 @@ int mbedtls_pkcs5_pbkdf2_hmac( mbedtls_md_context_t *ctx, const unsigned char *p memset( counter, 0, 4 ); counter[3] = 1; +#if UINT_MAX > 0xFFFFFFFF if( iteration_count > 0xFFFFFFFF ) return( MBEDTLS_ERR_PKCS5_BAD_INPUT_DATA ); +#endif while( key_length ) { diff --git a/thirdparty/mbedtls/library/pkparse.c b/thirdparty/mbedtls/library/pkparse.c index 9022db2f93..d6ac987e23 100644 --- a/thirdparty/mbedtls/library/pkparse.c +++ b/thirdparty/mbedtls/library/pkparse.c @@ -30,6 +30,7 @@ #include "mbedtls/pk.h" #include "mbedtls/asn1.h" #include "mbedtls/oid.h" +#include "mbedtls/platform_util.h" #include <string.h> @@ -60,14 +61,6 @@ #define mbedtls_free free #endif -#if defined(MBEDTLS_FS_IO) || \ - defined(MBEDTLS_PKCS12_C) || defined(MBEDTLS_PKCS5_C) -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize( void *v, size_t n ) { - volatile unsigned char *p = v; while( n-- ) *p++ = 0; -} -#endif - #if defined(MBEDTLS_FS_IO) /* * Load all data from a file into a given buffer. @@ -105,7 +98,7 @@ int mbedtls_pk_load_file( const char *path, unsigned char **buf, size_t *n ) { fclose( f ); - mbedtls_zeroize( *buf, *n ); + mbedtls_platform_zeroize( *buf, *n ); mbedtls_free( *buf ); return( MBEDTLS_ERR_PK_FILE_IO_ERROR ); @@ -140,7 +133,7 @@ int mbedtls_pk_parse_keyfile( mbedtls_pk_context *ctx, ret = mbedtls_pk_parse_key( ctx, buf, n, (const unsigned char *) pwd, strlen( pwd ) ); - mbedtls_zeroize( buf, n ); + mbedtls_platform_zeroize( buf, n ); mbedtls_free( buf ); return( ret ); @@ -160,7 +153,7 @@ int mbedtls_pk_parse_public_keyfile( mbedtls_pk_context *ctx, const char *path ) ret = mbedtls_pk_parse_public_key( ctx, buf, n ); - mbedtls_zeroize( buf, n ); + mbedtls_platform_zeroize( buf, n ); mbedtls_free( buf ); return( ret ); @@ -861,7 +854,10 @@ static int pk_parse_key_sec1_der( mbedtls_ecp_keypair *eck, mbedtls_ecp_keypair_free( eck ); return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); } + } + if( p != end ) + { /* * Is 'publickey' present? If not, or if we can't read it (eg because it * is compressed), create it from the private key. @@ -1265,7 +1261,6 @@ int mbedtls_pk_parse_key( mbedtls_pk_context *pk, return( ret ); #endif /* MBEDTLS_PKCS12_C || MBEDTLS_PKCS5_C */ #else - ((void) ret); ((void) pwd); ((void) pwdlen); #endif /* MBEDTLS_PEM_PARSE_C */ @@ -1292,7 +1287,7 @@ int mbedtls_pk_parse_key( mbedtls_pk_context *pk, ret = pk_parse_key_pkcs8_encrypted_der( pk, key_copy, keylen, pwd, pwdlen ); - mbedtls_zeroize( key_copy, keylen ); + mbedtls_platform_zeroize( key_copy, keylen ); mbedtls_free( key_copy ); } diff --git a/thirdparty/mbedtls/library/platform.c b/thirdparty/mbedtls/library/platform.c index a295f9b9af..b24b2fa652 100644 --- a/thirdparty/mbedtls/library/platform.c +++ b/thirdparty/mbedtls/library/platform.c @@ -28,14 +28,7 @@ #if defined(MBEDTLS_PLATFORM_C) #include "mbedtls/platform.h" - -#if defined(MBEDTLS_ENTROPY_NV_SEED) && \ - !defined(MBEDTLS_PLATFORM_NO_STD_FUNCTIONS) && defined(MBEDTLS_FS_IO) -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize( void *v, size_t n ) { - volatile unsigned char *p = (unsigned char*)v; while( n-- ) *p++ = 0; -} -#endif +#include "mbedtls/platform_util.h" #if defined(MBEDTLS_PLATFORM_MEMORY) #if !defined(MBEDTLS_PLATFORM_STD_CALLOC) @@ -58,14 +51,24 @@ static void platform_free_uninit( void *ptr ) #define MBEDTLS_PLATFORM_STD_FREE platform_free_uninit #endif /* !MBEDTLS_PLATFORM_STD_FREE */ -void * (*mbedtls_calloc)( size_t, size_t ) = MBEDTLS_PLATFORM_STD_CALLOC; -void (*mbedtls_free)( void * ) = MBEDTLS_PLATFORM_STD_FREE; +static void * (*mbedtls_calloc_func)( size_t, size_t ) = MBEDTLS_PLATFORM_STD_CALLOC; +static void (*mbedtls_free_func)( void * ) = MBEDTLS_PLATFORM_STD_FREE; + +void * mbedtls_calloc( size_t nmemb, size_t size ) +{ + return (*mbedtls_calloc_func)( nmemb, size ); +} + +void mbedtls_free( void * ptr ) +{ + (*mbedtls_free_func)( ptr ); +} int mbedtls_platform_set_calloc_free( void * (*calloc_func)( size_t, size_t ), void (*free_func)( void * ) ) { - mbedtls_calloc = calloc_func; - mbedtls_free = free_func; + mbedtls_calloc_func = calloc_func; + mbedtls_free_func = free_func; return( 0 ); } #endif /* MBEDTLS_PLATFORM_MEMORY */ @@ -241,7 +244,7 @@ int mbedtls_platform_std_nv_seed_read( unsigned char *buf, size_t buf_len ) if( ( n = fread( buf, 1, buf_len, file ) ) != buf_len ) { fclose( file ); - mbedtls_zeroize( buf, buf_len ); + mbedtls_platform_zeroize( buf, buf_len ); return( -1 ); } diff --git a/thirdparty/mbedtls/library/platform_util.c b/thirdparty/mbedtls/library/platform_util.c new file mode 100644 index 0000000000..1a57de9393 --- /dev/null +++ b/thirdparty/mbedtls/library/platform_util.c @@ -0,0 +1,67 @@ +/* + * Common and shared functions used by multiple modules in the Mbed TLS + * library. + * + * Copyright (C) 2018, Arm Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of Mbed TLS (https://tls.mbed.org) + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "mbedtls/platform_util.h" + +#include <stddef.h> +#include <string.h> + +#if !defined(MBEDTLS_PLATFORM_ZEROIZE_ALT) +/* + * This implementation should never be optimized out by the compiler + * + * This implementation for mbedtls_platform_zeroize() was inspired from Colin + * Percival's blog article at: + * + * http://www.daemonology.net/blog/2014-09-04-how-to-zero-a-buffer.html + * + * It uses a volatile function pointer to the standard memset(). Because the + * pointer is volatile the compiler expects it to change at + * any time and will not optimize out the call that could potentially perform + * other operations on the input buffer instead of just setting it to 0. + * Nevertheless, as pointed out by davidtgoldblatt on Hacker News + * (refer to http://www.daemonology.net/blog/2014-09-05-erratum.html for + * details), optimizations of the following form are still possible: + * + * if( memset_func != memset ) + * memset_func( buf, 0, len ); + * + * Note that it is extremely difficult to guarantee that + * mbedtls_platform_zeroize() will not be optimized out by aggressive compilers + * in a portable way. For this reason, Mbed TLS also provides the configuration + * option MBEDTLS_PLATFORM_ZEROIZE_ALT, which allows users to configure + * mbedtls_platform_zeroize() to use a suitable implementation for their + * platform and needs. + */ +static void * (* const volatile memset_func)( void *, int, size_t ) = memset; + +void mbedtls_platform_zeroize( void *buf, size_t len ) +{ + memset_func( buf, 0, len ); +} +#endif /* MBEDTLS_PLATFORM_ZEROIZE_ALT */ diff --git a/thirdparty/mbedtls/library/poly1305.c b/thirdparty/mbedtls/library/poly1305.c new file mode 100644 index 0000000000..e22d3afb68 --- /dev/null +++ b/thirdparty/mbedtls/library/poly1305.c @@ -0,0 +1,563 @@ +/** + * \file poly1305.c + * + * \brief Poly1305 authentication algorithm. + * + * Copyright (C) 2006-2016, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_POLY1305_C) + +#include "mbedtls/poly1305.h" +#include "mbedtls/platform_util.h" + +#include <string.h> + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include <stdio.h> +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +#if !defined(MBEDTLS_POLY1305_ALT) + +#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ + !defined(inline) && !defined(__cplusplus) +#define inline __inline +#endif + +#define POLY1305_BLOCK_SIZE_BYTES ( 16U ) + +#define BYTES_TO_U32_LE( data, offset ) \ + ( (uint32_t) data[offset] \ + | (uint32_t) ( (uint32_t) data[( offset ) + 1] << 8 ) \ + | (uint32_t) ( (uint32_t) data[( offset ) + 2] << 16 ) \ + | (uint32_t) ( (uint32_t) data[( offset ) + 3] << 24 ) \ + ) + +/* + * Our implementation is tuned for 32-bit platforms with a 64-bit multiplier. + * However we provided an alternative for platforms without such a multiplier. + */ +#if defined(MBEDTLS_NO_64BIT_MULTIPLICATION) +static uint64_t mul64( uint32_t a, uint32_t b ) +{ + /* a = al + 2**16 ah, b = bl + 2**16 bh */ + const uint16_t al = (uint16_t) a; + const uint16_t bl = (uint16_t) b; + const uint16_t ah = a >> 16; + const uint16_t bh = b >> 16; + + /* ab = al*bl + 2**16 (ah*bl + bl*bh) + 2**32 ah*bh */ + const uint32_t lo = (uint32_t) al * bl; + const uint64_t me = (uint64_t)( (uint32_t) ah * bl ) + (uint32_t) al * bh; + const uint32_t hi = (uint32_t) ah * bh; + + return( lo + ( me << 16 ) + ( (uint64_t) hi << 32 ) ); +} +#else +static inline uint64_t mul64( uint32_t a, uint32_t b ) +{ + return( (uint64_t) a * b ); +} +#endif + + +/** + * \brief Process blocks with Poly1305. + * + * \param ctx The Poly1305 context. + * \param nblocks Number of blocks to process. Note that this + * function only processes full blocks. + * \param input Buffer containing the input block(s). + * \param needs_padding Set to 0 if the padding bit has already been + * applied to the input data before calling this + * function. Otherwise, set this parameter to 1. + */ +static void poly1305_process( mbedtls_poly1305_context *ctx, + size_t nblocks, + const unsigned char *input, + uint32_t needs_padding ) +{ + uint64_t d0, d1, d2, d3; + uint32_t acc0, acc1, acc2, acc3, acc4; + uint32_t r0, r1, r2, r3; + uint32_t rs1, rs2, rs3; + size_t offset = 0U; + size_t i; + + r0 = ctx->r[0]; + r1 = ctx->r[1]; + r2 = ctx->r[2]; + r3 = ctx->r[3]; + + rs1 = r1 + ( r1 >> 2U ); + rs2 = r2 + ( r2 >> 2U ); + rs3 = r3 + ( r3 >> 2U ); + + acc0 = ctx->acc[0]; + acc1 = ctx->acc[1]; + acc2 = ctx->acc[2]; + acc3 = ctx->acc[3]; + acc4 = ctx->acc[4]; + + /* Process full blocks */ + for( i = 0U; i < nblocks; i++ ) + { + /* The input block is treated as a 128-bit little-endian integer */ + d0 = BYTES_TO_U32_LE( input, offset + 0 ); + d1 = BYTES_TO_U32_LE( input, offset + 4 ); + d2 = BYTES_TO_U32_LE( input, offset + 8 ); + d3 = BYTES_TO_U32_LE( input, offset + 12 ); + + /* Compute: acc += (padded) block as a 130-bit integer */ + d0 += (uint64_t) acc0; + d1 += (uint64_t) acc1 + ( d0 >> 32U ); + d2 += (uint64_t) acc2 + ( d1 >> 32U ); + d3 += (uint64_t) acc3 + ( d2 >> 32U ); + acc0 = (uint32_t) d0; + acc1 = (uint32_t) d1; + acc2 = (uint32_t) d2; + acc3 = (uint32_t) d3; + acc4 += (uint32_t) ( d3 >> 32U ) + needs_padding; + + /* Compute: acc *= r */ + d0 = mul64( acc0, r0 ) + + mul64( acc1, rs3 ) + + mul64( acc2, rs2 ) + + mul64( acc3, rs1 ); + d1 = mul64( acc0, r1 ) + + mul64( acc1, r0 ) + + mul64( acc2, rs3 ) + + mul64( acc3, rs2 ) + + mul64( acc4, rs1 ); + d2 = mul64( acc0, r2 ) + + mul64( acc1, r1 ) + + mul64( acc2, r0 ) + + mul64( acc3, rs3 ) + + mul64( acc4, rs2 ); + d3 = mul64( acc0, r3 ) + + mul64( acc1, r2 ) + + mul64( acc2, r1 ) + + mul64( acc3, r0 ) + + mul64( acc4, rs3 ); + acc4 *= r0; + + /* Compute: acc %= (2^130 - 5) (partial remainder) */ + d1 += ( d0 >> 32 ); + d2 += ( d1 >> 32 ); + d3 += ( d2 >> 32 ); + acc0 = (uint32_t) d0; + acc1 = (uint32_t) d1; + acc2 = (uint32_t) d2; + acc3 = (uint32_t) d3; + acc4 = (uint32_t) ( d3 >> 32 ) + acc4; + + d0 = (uint64_t) acc0 + ( acc4 >> 2 ) + ( acc4 & 0xFFFFFFFCU ); + acc4 &= 3U; + acc0 = (uint32_t) d0; + d0 = (uint64_t) acc1 + ( d0 >> 32U ); + acc1 = (uint32_t) d0; + d0 = (uint64_t) acc2 + ( d0 >> 32U ); + acc2 = (uint32_t) d0; + d0 = (uint64_t) acc3 + ( d0 >> 32U ); + acc3 = (uint32_t) d0; + d0 = (uint64_t) acc4 + ( d0 >> 32U ); + acc4 = (uint32_t) d0; + + offset += POLY1305_BLOCK_SIZE_BYTES; + } + + ctx->acc[0] = acc0; + ctx->acc[1] = acc1; + ctx->acc[2] = acc2; + ctx->acc[3] = acc3; + ctx->acc[4] = acc4; +} + +/** + * \brief Compute the Poly1305 MAC + * + * \param ctx The Poly1305 context. + * \param mac The buffer to where the MAC is written. Must be + * big enough to contain the 16-byte MAC. + */ +static void poly1305_compute_mac( const mbedtls_poly1305_context *ctx, + unsigned char mac[16] ) +{ + uint64_t d; + uint32_t g0, g1, g2, g3, g4; + uint32_t acc0, acc1, acc2, acc3, acc4; + uint32_t mask; + uint32_t mask_inv; + + acc0 = ctx->acc[0]; + acc1 = ctx->acc[1]; + acc2 = ctx->acc[2]; + acc3 = ctx->acc[3]; + acc4 = ctx->acc[4]; + + /* Before adding 's' we ensure that the accumulator is mod 2^130 - 5. + * We do this by calculating acc - (2^130 - 5), then checking if + * the 131st bit is set. If it is, then reduce: acc -= (2^130 - 5) + */ + + /* Calculate acc + -(2^130 - 5) */ + d = ( (uint64_t) acc0 + 5U ); + g0 = (uint32_t) d; + d = ( (uint64_t) acc1 + ( d >> 32 ) ); + g1 = (uint32_t) d; + d = ( (uint64_t) acc2 + ( d >> 32 ) ); + g2 = (uint32_t) d; + d = ( (uint64_t) acc3 + ( d >> 32 ) ); + g3 = (uint32_t) d; + g4 = acc4 + (uint32_t) ( d >> 32U ); + + /* mask == 0xFFFFFFFF if 131st bit is set, otherwise mask == 0 */ + mask = (uint32_t) 0U - ( g4 >> 2U ); + mask_inv = ~mask; + + /* If 131st bit is set then acc=g, otherwise, acc is unmodified */ + acc0 = ( acc0 & mask_inv ) | ( g0 & mask ); + acc1 = ( acc1 & mask_inv ) | ( g1 & mask ); + acc2 = ( acc2 & mask_inv ) | ( g2 & mask ); + acc3 = ( acc3 & mask_inv ) | ( g3 & mask ); + + /* Add 's' */ + d = (uint64_t) acc0 + ctx->s[0]; + acc0 = (uint32_t) d; + d = (uint64_t) acc1 + ctx->s[1] + ( d >> 32U ); + acc1 = (uint32_t) d; + d = (uint64_t) acc2 + ctx->s[2] + ( d >> 32U ); + acc2 = (uint32_t) d; + acc3 += ctx->s[3] + (uint32_t) ( d >> 32U ); + + /* Compute MAC (128 least significant bits of the accumulator) */ + mac[ 0] = (unsigned char)( acc0 ); + mac[ 1] = (unsigned char)( acc0 >> 8 ); + mac[ 2] = (unsigned char)( acc0 >> 16 ); + mac[ 3] = (unsigned char)( acc0 >> 24 ); + mac[ 4] = (unsigned char)( acc1 ); + mac[ 5] = (unsigned char)( acc1 >> 8 ); + mac[ 6] = (unsigned char)( acc1 >> 16 ); + mac[ 7] = (unsigned char)( acc1 >> 24 ); + mac[ 8] = (unsigned char)( acc2 ); + mac[ 9] = (unsigned char)( acc2 >> 8 ); + mac[10] = (unsigned char)( acc2 >> 16 ); + mac[11] = (unsigned char)( acc2 >> 24 ); + mac[12] = (unsigned char)( acc3 ); + mac[13] = (unsigned char)( acc3 >> 8 ); + mac[14] = (unsigned char)( acc3 >> 16 ); + mac[15] = (unsigned char)( acc3 >> 24 ); +} + +void mbedtls_poly1305_init( mbedtls_poly1305_context *ctx ) +{ + if( ctx != NULL ) + { + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_poly1305_context ) ); + } +} + +void mbedtls_poly1305_free( mbedtls_poly1305_context *ctx ) +{ + if( ctx != NULL ) + { + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_poly1305_context ) ); + } +} + +int mbedtls_poly1305_starts( mbedtls_poly1305_context *ctx, + const unsigned char key[32] ) +{ + if( ctx == NULL || key == NULL ) + { + return( MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA ); + } + + /* r &= 0x0ffffffc0ffffffc0ffffffc0fffffff */ + ctx->r[0] = BYTES_TO_U32_LE( key, 0 ) & 0x0FFFFFFFU; + ctx->r[1] = BYTES_TO_U32_LE( key, 4 ) & 0x0FFFFFFCU; + ctx->r[2] = BYTES_TO_U32_LE( key, 8 ) & 0x0FFFFFFCU; + ctx->r[3] = BYTES_TO_U32_LE( key, 12 ) & 0x0FFFFFFCU; + + ctx->s[0] = BYTES_TO_U32_LE( key, 16 ); + ctx->s[1] = BYTES_TO_U32_LE( key, 20 ); + ctx->s[2] = BYTES_TO_U32_LE( key, 24 ); + ctx->s[3] = BYTES_TO_U32_LE( key, 28 ); + + /* Initial accumulator state */ + ctx->acc[0] = 0U; + ctx->acc[1] = 0U; + ctx->acc[2] = 0U; + ctx->acc[3] = 0U; + ctx->acc[4] = 0U; + + /* Queue initially empty */ + mbedtls_platform_zeroize( ctx->queue, sizeof( ctx->queue ) ); + ctx->queue_len = 0U; + + return( 0 ); +} + +int mbedtls_poly1305_update( mbedtls_poly1305_context *ctx, + const unsigned char *input, + size_t ilen ) +{ + size_t offset = 0U; + size_t remaining = ilen; + size_t queue_free_len; + size_t nblocks; + + if( ctx == NULL ) + { + return( MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA ); + } + else if( ( ilen > 0U ) && ( input == NULL ) ) + { + /* input pointer is allowed to be NULL only if ilen == 0 */ + return( MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA ); + } + + if( ( remaining > 0U ) && ( ctx->queue_len > 0U ) ) + { + queue_free_len = ( POLY1305_BLOCK_SIZE_BYTES - ctx->queue_len ); + + if( ilen < queue_free_len ) + { + /* Not enough data to complete the block. + * Store this data with the other leftovers. + */ + memcpy( &ctx->queue[ctx->queue_len], + input, + ilen ); + + ctx->queue_len += ilen; + + remaining = 0U; + } + else + { + /* Enough data to produce a complete block */ + memcpy( &ctx->queue[ctx->queue_len], + input, + queue_free_len ); + + ctx->queue_len = 0U; + + poly1305_process( ctx, 1U, ctx->queue, 1U ); /* add padding bit */ + + offset += queue_free_len; + remaining -= queue_free_len; + } + } + + if( remaining >= POLY1305_BLOCK_SIZE_BYTES ) + { + nblocks = remaining / POLY1305_BLOCK_SIZE_BYTES; + + poly1305_process( ctx, nblocks, &input[offset], 1U ); + + offset += nblocks * POLY1305_BLOCK_SIZE_BYTES; + remaining %= POLY1305_BLOCK_SIZE_BYTES; + } + + if( remaining > 0U ) + { + /* Store partial block */ + ctx->queue_len = remaining; + memcpy( ctx->queue, &input[offset], remaining ); + } + + return( 0 ); +} + +int mbedtls_poly1305_finish( mbedtls_poly1305_context *ctx, + unsigned char mac[16] ) +{ + if( ( ctx == NULL ) || ( mac == NULL ) ) + { + return( MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA ); + } + + /* Process any leftover data */ + if( ctx->queue_len > 0U ) + { + /* Add padding bit */ + ctx->queue[ctx->queue_len] = 1U; + ctx->queue_len++; + + /* Pad with zeroes */ + memset( &ctx->queue[ctx->queue_len], + 0, + POLY1305_BLOCK_SIZE_BYTES - ctx->queue_len ); + + poly1305_process( ctx, 1U, /* Process 1 block */ + ctx->queue, 0U ); /* Already padded above */ + } + + poly1305_compute_mac( ctx, mac ); + + return( 0 ); +} + +int mbedtls_poly1305_mac( const unsigned char key[32], + const unsigned char *input, + size_t ilen, + unsigned char mac[16] ) +{ + mbedtls_poly1305_context ctx; + int ret; + + mbedtls_poly1305_init( &ctx ); + + ret = mbedtls_poly1305_starts( &ctx, key ); + if( ret != 0 ) + goto cleanup; + + ret = mbedtls_poly1305_update( &ctx, input, ilen ); + if( ret != 0 ) + goto cleanup; + + ret = mbedtls_poly1305_finish( &ctx, mac ); + +cleanup: + mbedtls_poly1305_free( &ctx ); + return( ret ); +} + +#endif /* MBEDTLS_POLY1305_ALT */ + +#if defined(MBEDTLS_SELF_TEST) + +static const unsigned char test_keys[2][32] = +{ + { + 0x85, 0xd6, 0xbe, 0x78, 0x57, 0x55, 0x6d, 0x33, + 0x7f, 0x44, 0x52, 0xfe, 0x42, 0xd5, 0x06, 0xa8, + 0x01, 0x03, 0x80, 0x8a, 0xfb, 0x0d, 0xb2, 0xfd, + 0x4a, 0xbf, 0xf6, 0xaf, 0x41, 0x49, 0xf5, 0x1b + }, + { + 0x1c, 0x92, 0x40, 0xa5, 0xeb, 0x55, 0xd3, 0x8a, + 0xf3, 0x33, 0x88, 0x86, 0x04, 0xf6, 0xb5, 0xf0, + 0x47, 0x39, 0x17, 0xc1, 0x40, 0x2b, 0x80, 0x09, + 0x9d, 0xca, 0x5c, 0xbc, 0x20, 0x70, 0x75, 0xc0 + } +}; + +static const unsigned char test_data[2][127] = +{ + { + 0x43, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x67, 0x72, + 0x61, 0x70, 0x68, 0x69, 0x63, 0x20, 0x46, 0x6f, + 0x72, 0x75, 0x6d, 0x20, 0x52, 0x65, 0x73, 0x65, + 0x61, 0x72, 0x63, 0x68, 0x20, 0x47, 0x72, 0x6f, + 0x75, 0x70 + }, + { + 0x27, 0x54, 0x77, 0x61, 0x73, 0x20, 0x62, 0x72, + 0x69, 0x6c, 0x6c, 0x69, 0x67, 0x2c, 0x20, 0x61, + 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, + 0x6c, 0x69, 0x74, 0x68, 0x79, 0x20, 0x74, 0x6f, + 0x76, 0x65, 0x73, 0x0a, 0x44, 0x69, 0x64, 0x20, + 0x67, 0x79, 0x72, 0x65, 0x20, 0x61, 0x6e, 0x64, + 0x20, 0x67, 0x69, 0x6d, 0x62, 0x6c, 0x65, 0x20, + 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, + 0x61, 0x62, 0x65, 0x3a, 0x0a, 0x41, 0x6c, 0x6c, + 0x20, 0x6d, 0x69, 0x6d, 0x73, 0x79, 0x20, 0x77, + 0x65, 0x72, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, + 0x62, 0x6f, 0x72, 0x6f, 0x67, 0x6f, 0x76, 0x65, + 0x73, 0x2c, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, + 0x68, 0x65, 0x20, 0x6d, 0x6f, 0x6d, 0x65, 0x20, + 0x72, 0x61, 0x74, 0x68, 0x73, 0x20, 0x6f, 0x75, + 0x74, 0x67, 0x72, 0x61, 0x62, 0x65, 0x2e + } +}; + +static const size_t test_data_len[2] = +{ + 34U, + 127U +}; + +static const unsigned char test_mac[2][16] = +{ + { + 0xa8, 0x06, 0x1d, 0xc1, 0x30, 0x51, 0x36, 0xc6, + 0xc2, 0x2b, 0x8b, 0xaf, 0x0c, 0x01, 0x27, 0xa9 + }, + { + 0x45, 0x41, 0x66, 0x9a, 0x7e, 0xaa, 0xee, 0x61, + 0xe7, 0x08, 0xdc, 0x7c, 0xbc, 0xc5, 0xeb, 0x62 + } +}; + +#define ASSERT( cond, args ) \ + do \ + { \ + if( ! ( cond ) ) \ + { \ + if( verbose != 0 ) \ + mbedtls_printf args; \ + \ + return( -1 ); \ + } \ + } \ + while( 0 ) + +int mbedtls_poly1305_self_test( int verbose ) +{ + unsigned char mac[16]; + unsigned i; + int ret; + + for( i = 0U; i < 2U; i++ ) + { + if( verbose != 0 ) + mbedtls_printf( " Poly1305 test %u ", i ); + + ret = mbedtls_poly1305_mac( test_keys[i], + test_data[i], + test_data_len[i], + mac ); + ASSERT( 0 == ret, ( "error code: %i\n", ret ) ); + + ASSERT( 0 == memcmp( mac, test_mac[i], 16U ), ( "failed (mac)\n" ) ); + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + return( 0 ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_POLY1305_C */ diff --git a/thirdparty/mbedtls/library/ripemd160.c b/thirdparty/mbedtls/library/ripemd160.c index 2ba48b7fdb..bd25ada62c 100644 --- a/thirdparty/mbedtls/library/ripemd160.c +++ b/thirdparty/mbedtls/library/ripemd160.c @@ -34,6 +34,7 @@ #if defined(MBEDTLS_RIPEMD160_C) #include "mbedtls/ripemd160.h" +#include "mbedtls/platform_util.h" #include <string.h> @@ -71,11 +72,6 @@ } #endif -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize( void *v, size_t n ) { - volatile unsigned char *p = v; while( n-- ) *p++ = 0; -} - void mbedtls_ripemd160_init( mbedtls_ripemd160_context *ctx ) { memset( ctx, 0, sizeof( mbedtls_ripemd160_context ) ); @@ -86,7 +82,7 @@ void mbedtls_ripemd160_free( mbedtls_ripemd160_context *ctx ) if( ctx == NULL ) return; - mbedtls_zeroize( ctx, sizeof( mbedtls_ripemd160_context ) ); + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_ripemd160_context ) ); } void mbedtls_ripemd160_clone( mbedtls_ripemd160_context *dst, diff --git a/thirdparty/mbedtls/library/rsa.c b/thirdparty/mbedtls/library/rsa.c index c9f7ba91b6..88c1cf1007 100644 --- a/thirdparty/mbedtls/library/rsa.c +++ b/thirdparty/mbedtls/library/rsa.c @@ -48,6 +48,7 @@ #include "mbedtls/rsa.h" #include "mbedtls/rsa_internal.h" #include "mbedtls/oid.h" +#include "mbedtls/platform_util.h" #include <string.h> @@ -70,11 +71,7 @@ #if !defined(MBEDTLS_RSA_ALT) -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize( void *v, size_t n ) { - volatile unsigned char *p = (unsigned char*)v; while( n-- ) *p++ = 0; -} - +#if defined(MBEDTLS_PKCS1_V15) /* constant-time buffer comparison */ static inline int mbedtls_safer_memcmp( const void *a, const void *b, size_t n ) { @@ -88,6 +85,7 @@ static inline int mbedtls_safer_memcmp( const void *a, const void *b, size_t n ) return( diff ); } +#endif /* MBEDTLS_PKCS1_V15 */ int mbedtls_rsa_import( mbedtls_rsa_context *ctx, const mbedtls_mpi *N, @@ -493,6 +491,9 @@ size_t mbedtls_rsa_get_len( const mbedtls_rsa_context *ctx ) /* * Generate an RSA keypair + * + * This generation method follows the RSA key pair generation procedure of + * FIPS 186-4 if 2^16 < exponent < 2^256 and nbits = 2048 or nbits = 3072. */ int mbedtls_rsa_gen_key( mbedtls_rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), @@ -500,7 +501,7 @@ int mbedtls_rsa_gen_key( mbedtls_rsa_context *ctx, unsigned int nbits, int exponent ) { int ret; - mbedtls_mpi H, G; + mbedtls_mpi H, G, L; if( f_rng == NULL || nbits < 128 || exponent < 3 ) return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); @@ -510,10 +511,13 @@ int mbedtls_rsa_gen_key( mbedtls_rsa_context *ctx, mbedtls_mpi_init( &H ); mbedtls_mpi_init( &G ); + mbedtls_mpi_init( &L ); /* * find primes P and Q with Q < P so that: - * GCD( E, (P-1)*(Q-1) ) == 1 + * 1. |P-Q| > 2^( nbits / 2 - 100 ) + * 2. GCD( E, (P-1)*(Q-1) ) == 1 + * 3. E^-1 mod LCM(P-1, Q-1) > 2^( nbits / 2 ) */ MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &ctx->E, exponent ) ); @@ -525,40 +529,51 @@ int mbedtls_rsa_gen_key( mbedtls_rsa_context *ctx, MBEDTLS_MPI_CHK( mbedtls_mpi_gen_prime( &ctx->Q, nbits >> 1, 0, f_rng, p_rng ) ); - if( mbedtls_mpi_cmp_mpi( &ctx->P, &ctx->Q ) == 0 ) + /* make sure the difference between p and q is not too small (FIPS 186-4 §B.3.3 step 5.4) */ + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &H, &ctx->P, &ctx->Q ) ); + if( mbedtls_mpi_bitlen( &H ) <= ( ( nbits >= 200 ) ? ( ( nbits >> 1 ) - 99 ) : 0 ) ) continue; - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->N, &ctx->P, &ctx->Q ) ); - if( mbedtls_mpi_bitlen( &ctx->N ) != nbits ) - continue; - - if( mbedtls_mpi_cmp_mpi( &ctx->P, &ctx->Q ) < 0 ) + /* not required by any standards, but some users rely on the fact that P > Q */ + if( H.s < 0 ) mbedtls_mpi_swap( &ctx->P, &ctx->Q ); /* Temporarily replace P,Q by P-1, Q-1 */ MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &ctx->P, &ctx->P, 1 ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &ctx->Q, &ctx->Q, 1 ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &H, &ctx->P, &ctx->Q ) ); + + /* check GCD( E, (P-1)*(Q-1) ) == 1 (FIPS 186-4 §B.3.1 criterion 2(a)) */ MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, &ctx->E, &H ) ); + if( mbedtls_mpi_cmp_int( &G, 1 ) != 0 ) + continue; + + /* compute smallest possible D = E^-1 mod LCM(P-1, Q-1) (FIPS 186-4 §B.3.1 criterion 3(b)) */ + MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, &ctx->P, &ctx->Q ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &L, NULL, &H, &G ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &ctx->D, &ctx->E, &L ) ); + + if( mbedtls_mpi_bitlen( &ctx->D ) <= ( ( nbits + 1 ) / 2 ) ) // (FIPS 186-4 §B.3.1 criterion 3(a)) + continue; + + break; } - while( mbedtls_mpi_cmp_int( &G, 1 ) != 0 ); + while( 1 ); /* Restore P,Q */ MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &ctx->P, &ctx->P, 1 ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &ctx->Q, &ctx->Q, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->N, &ctx->P, &ctx->Q ) ); + ctx->len = mbedtls_mpi_size( &ctx->N ); +#if !defined(MBEDTLS_RSA_NO_CRT) /* - * D = E^-1 mod ((P-1)*(Q-1)) * DP = D mod (P - 1) * DQ = D mod (Q - 1) * QP = Q^-1 mod P */ - - MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &ctx->D, &ctx->E, &H ) ); - -#if !defined(MBEDTLS_RSA_NO_CRT) MBEDTLS_MPI_CHK( mbedtls_rsa_deduce_crt( &ctx->P, &ctx->Q, &ctx->D, &ctx->DP, &ctx->DQ, &ctx->QP ) ); #endif /* MBEDTLS_RSA_NO_CRT */ @@ -570,6 +585,7 @@ cleanup: mbedtls_mpi_free( &H ); mbedtls_mpi_free( &G ); + mbedtls_mpi_free( &L ); if( ret != 0 ) { @@ -1040,7 +1056,7 @@ static int mgf_mask( unsigned char *dst, size_t dlen, unsigned char *src, } exit: - mbedtls_zeroize( mask, sizeof( mask ) ); + mbedtls_platform_zeroize( mask, sizeof( mask ) ); return( ret ); } @@ -1354,8 +1370,8 @@ int mbedtls_rsa_rsaes_oaep_decrypt( mbedtls_rsa_context *ctx, ret = 0; cleanup: - mbedtls_zeroize( buf, sizeof( buf ) ); - mbedtls_zeroize( lhash, sizeof( lhash ) ); + mbedtls_platform_zeroize( buf, sizeof( buf ) ); + mbedtls_platform_zeroize( lhash, sizeof( lhash ) ); return( ret ); } @@ -1452,7 +1468,7 @@ int mbedtls_rsa_rsaes_pkcs1_v15_decrypt( mbedtls_rsa_context *ctx, ret = 0; cleanup: - mbedtls_zeroize( buf, sizeof( buf ) ); + mbedtls_platform_zeroize( buf, sizeof( buf ) ); return( ret ); } @@ -1583,7 +1599,7 @@ int mbedtls_rsa_rsassa_pss_sign( mbedtls_rsa_context *ctx, p += hlen; *p++ = 0xBC; - mbedtls_zeroize( salt, sizeof( salt ) ); + mbedtls_platform_zeroize( salt, sizeof( salt ) ); exit: mbedtls_md_free( &md_ctx ); @@ -1725,7 +1741,7 @@ static int rsa_rsassa_pkcs1_v15_encode( mbedtls_md_type_t md_alg, * after the initial bounds check. */ if( p != dst + dst_len ) { - mbedtls_zeroize( dst, dst_len ); + mbedtls_platform_zeroize( dst, dst_len ); return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); } @@ -2062,13 +2078,13 @@ cleanup: if( encoded != NULL ) { - mbedtls_zeroize( encoded, sig_len ); + mbedtls_platform_zeroize( encoded, sig_len ); mbedtls_free( encoded ); } if( encoded_expected != NULL ) { - mbedtls_zeroize( encoded_expected, sig_len ); + mbedtls_platform_zeroize( encoded_expected, sig_len ); mbedtls_free( encoded_expected ); } diff --git a/thirdparty/mbedtls/library/sha1.c b/thirdparty/mbedtls/library/sha1.c index 1f29a0fbf8..bab6087c4e 100644 --- a/thirdparty/mbedtls/library/sha1.c +++ b/thirdparty/mbedtls/library/sha1.c @@ -33,6 +33,7 @@ #if defined(MBEDTLS_SHA1_C) #include "mbedtls/sha1.h" +#include "mbedtls/platform_util.h" #include <string.h> @@ -47,11 +48,6 @@ #if !defined(MBEDTLS_SHA1_ALT) -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize( void *v, size_t n ) { - volatile unsigned char *p = (unsigned char*)v; while( n-- ) *p++ = 0; -} - /* * 32-bit integer manipulation macros (big endian) */ @@ -85,7 +81,7 @@ void mbedtls_sha1_free( mbedtls_sha1_context *ctx ) if( ctx == NULL ) return; - mbedtls_zeroize( ctx, sizeof( mbedtls_sha1_context ) ); + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_sha1_context ) ); } void mbedtls_sha1_clone( mbedtls_sha1_context *dst, @@ -346,14 +342,6 @@ void mbedtls_sha1_update( mbedtls_sha1_context *ctx, } #endif -static const unsigned char sha1_padding[64] = -{ - 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 -}; - /* * SHA-1 final digest */ @@ -361,25 +349,48 @@ int mbedtls_sha1_finish_ret( mbedtls_sha1_context *ctx, unsigned char output[20] ) { int ret; - uint32_t last, padn; + uint32_t used; uint32_t high, low; - unsigned char msglen[8]; + /* + * Add padding: 0x80 then 0x00 until 8 bytes remain for the length + */ + used = ctx->total[0] & 0x3F; + + ctx->buffer[used++] = 0x80; + + if( used <= 56 ) + { + /* Enough room for padding + length in current block */ + memset( ctx->buffer + used, 0, 56 - used ); + } + else + { + /* We'll need an extra block */ + memset( ctx->buffer + used, 0, 64 - used ); + + if( ( ret = mbedtls_internal_sha1_process( ctx, ctx->buffer ) ) != 0 ) + return( ret ); + + memset( ctx->buffer, 0, 56 ); + } + + /* + * Add message length + */ high = ( ctx->total[0] >> 29 ) | ( ctx->total[1] << 3 ); low = ( ctx->total[0] << 3 ); - PUT_UINT32_BE( high, msglen, 0 ); - PUT_UINT32_BE( low, msglen, 4 ); - - last = ctx->total[0] & 0x3F; - padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last ); + PUT_UINT32_BE( high, ctx->buffer, 56 ); + PUT_UINT32_BE( low, ctx->buffer, 60 ); - if( ( ret = mbedtls_sha1_update_ret( ctx, sha1_padding, padn ) ) != 0 ) - return( ret ); - if( ( ret = mbedtls_sha1_update_ret( ctx, msglen, 8 ) ) != 0 ) + if( ( ret = mbedtls_internal_sha1_process( ctx, ctx->buffer ) ) != 0 ) return( ret ); + /* + * Output final state + */ PUT_UINT32_BE( ctx->state[0], output, 0 ); PUT_UINT32_BE( ctx->state[1], output, 4 ); PUT_UINT32_BE( ctx->state[2], output, 8 ); diff --git a/thirdparty/mbedtls/library/sha256.c b/thirdparty/mbedtls/library/sha256.c index f39bcbab6c..dbb4a89861 100644 --- a/thirdparty/mbedtls/library/sha256.c +++ b/thirdparty/mbedtls/library/sha256.c @@ -33,6 +33,7 @@ #if defined(MBEDTLS_SHA256_C) #include "mbedtls/sha256.h" +#include "mbedtls/platform_util.h" #include <string.h> @@ -50,11 +51,6 @@ #if !defined(MBEDTLS_SHA256_ALT) -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize( void *v, size_t n ) { - volatile unsigned char *p = v; while( n-- ) *p++ = 0; -} - /* * 32-bit integer manipulation macros (big endian) */ @@ -88,7 +84,7 @@ void mbedtls_sha256_free( mbedtls_sha256_context *ctx ) if( ctx == NULL ) return; - mbedtls_zeroize( ctx, sizeof( mbedtls_sha256_context ) ); + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_sha256_context ) ); } void mbedtls_sha256_clone( mbedtls_sha256_context *dst, @@ -315,14 +311,6 @@ void mbedtls_sha256_update( mbedtls_sha256_context *ctx, } #endif -static const unsigned char sha256_padding[64] = -{ - 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 -}; - /* * SHA-256 final digest */ @@ -330,26 +318,48 @@ int mbedtls_sha256_finish_ret( mbedtls_sha256_context *ctx, unsigned char output[32] ) { int ret; - uint32_t last, padn; + uint32_t used; uint32_t high, low; - unsigned char msglen[8]; + /* + * Add padding: 0x80 then 0x00 until 8 bytes remain for the length + */ + used = ctx->total[0] & 0x3F; + + ctx->buffer[used++] = 0x80; + + if( used <= 56 ) + { + /* Enough room for padding + length in current block */ + memset( ctx->buffer + used, 0, 56 - used ); + } + else + { + /* We'll need an extra block */ + memset( ctx->buffer + used, 0, 64 - used ); + + if( ( ret = mbedtls_internal_sha256_process( ctx, ctx->buffer ) ) != 0 ) + return( ret ); + + memset( ctx->buffer, 0, 56 ); + } + + /* + * Add message length + */ high = ( ctx->total[0] >> 29 ) | ( ctx->total[1] << 3 ); low = ( ctx->total[0] << 3 ); - PUT_UINT32_BE( high, msglen, 0 ); - PUT_UINT32_BE( low, msglen, 4 ); - - last = ctx->total[0] & 0x3F; - padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last ); - - if( ( ret = mbedtls_sha256_update_ret( ctx, sha256_padding, padn ) ) != 0 ) - return( ret ); + PUT_UINT32_BE( high, ctx->buffer, 56 ); + PUT_UINT32_BE( low, ctx->buffer, 60 ); - if( ( ret = mbedtls_sha256_update_ret( ctx, msglen, 8 ) ) != 0 ) + if( ( ret = mbedtls_internal_sha256_process( ctx, ctx->buffer ) ) != 0 ) return( ret ); + /* + * Output final state + */ PUT_UINT32_BE( ctx->state[0], output, 0 ); PUT_UINT32_BE( ctx->state[1], output, 4 ); PUT_UINT32_BE( ctx->state[2], output, 8 ); diff --git a/thirdparty/mbedtls/library/sha512.c b/thirdparty/mbedtls/library/sha512.c index 97cee07c56..a9440e8af5 100644 --- a/thirdparty/mbedtls/library/sha512.c +++ b/thirdparty/mbedtls/library/sha512.c @@ -33,6 +33,7 @@ #if defined(MBEDTLS_SHA512_C) #include "mbedtls/sha512.h" +#include "mbedtls/platform_util.h" #if defined(_MSC_VER) || defined(__WATCOMC__) #define UL64(x) x##ui64 @@ -56,11 +57,6 @@ #if !defined(MBEDTLS_SHA512_ALT) -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize( void *v, size_t n ) { - volatile unsigned char *p = v; while( n-- ) *p++ = 0; -} - /* * 64-bit integer manipulation macros (big endian) */ @@ -102,7 +98,7 @@ void mbedtls_sha512_free( mbedtls_sha512_context *ctx ) if( ctx == NULL ) return; - mbedtls_zeroize( ctx, sizeof( mbedtls_sha512_context ) ); + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_sha512_context ) ); } void mbedtls_sha512_clone( mbedtls_sha512_context *dst, @@ -345,18 +341,6 @@ void mbedtls_sha512_update( mbedtls_sha512_context *ctx, } #endif -static const unsigned char sha512_padding[128] = -{ - 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 -}; - /* * SHA-512 final digest */ @@ -364,26 +348,48 @@ int mbedtls_sha512_finish_ret( mbedtls_sha512_context *ctx, unsigned char output[64] ) { int ret; - size_t last, padn; + unsigned used; uint64_t high, low; - unsigned char msglen[16]; - high = ( ctx->total[0] >> 61 ) - | ( ctx->total[1] << 3 ); - low = ( ctx->total[0] << 3 ); + /* + * Add padding: 0x80 then 0x00 until 16 bytes remain for the length + */ + used = ctx->total[0] & 0x7F; - PUT_UINT64_BE( high, msglen, 0 ); - PUT_UINT64_BE( low, msglen, 8 ); + ctx->buffer[used++] = 0x80; - last = (size_t)( ctx->total[0] & 0x7F ); - padn = ( last < 112 ) ? ( 112 - last ) : ( 240 - last ); + if( used <= 112 ) + { + /* Enough room for padding + length in current block */ + memset( ctx->buffer + used, 0, 112 - used ); + } + else + { + /* We'll need an extra block */ + memset( ctx->buffer + used, 0, 128 - used ); - if( ( ret = mbedtls_sha512_update_ret( ctx, sha512_padding, padn ) ) != 0 ) + if( ( ret = mbedtls_internal_sha512_process( ctx, ctx->buffer ) ) != 0 ) return( ret ); - if( ( ret = mbedtls_sha512_update_ret( ctx, msglen, 16 ) ) != 0 ) - return( ret ); + memset( ctx->buffer, 0, 112 ); + } + /* + * Add message length + */ + high = ( ctx->total[0] >> 61 ) + | ( ctx->total[1] << 3 ); + low = ( ctx->total[0] << 3 ); + + PUT_UINT64_BE( high, ctx->buffer, 112 ); + PUT_UINT64_BE( low, ctx->buffer, 120 ); + + if( ( ret = mbedtls_internal_sha512_process( ctx, ctx->buffer ) ) != 0 ) + return( ret ); + + /* + * Output final state + */ PUT_UINT64_BE( ctx->state[0], output, 0 ); PUT_UINT64_BE( ctx->state[1], output, 8 ); PUT_UINT64_BE( ctx->state[2], output, 16 ); diff --git a/thirdparty/mbedtls/library/ssl_ciphersuites.c b/thirdparty/mbedtls/library/ssl_ciphersuites.c index 95e6163ccc..59cdc7a806 100644 --- a/thirdparty/mbedtls/library/ssl_ciphersuites.c +++ b/thirdparty/mbedtls/library/ssl_ciphersuites.c @@ -47,7 +47,7 @@ * 1. By key exchange: * Forward-secure non-PSK > forward-secure PSK > ECJPAKE > other non-PSK > other PSK * 2. By key length and cipher: - * AES-256 > Camellia-256 > AES-128 > Camellia-128 > 3DES + * ChaCha > AES-256 > Camellia-256 > ARIA-256 > AES-128 > Camellia-128 > ARIA-128 > 3DES * 3. By cipher mode when relevant GCM > CCM > CBC > CCM_8 * 4. By hash function used when relevant * 5. By key exchange/auth again: EC > non-EC @@ -57,6 +57,11 @@ static const int ciphersuite_preference[] = #if defined(MBEDTLS_SSL_CIPHERSUITES) MBEDTLS_SSL_CIPHERSUITES, #else + /* Chacha-Poly ephemeral suites */ + MBEDTLS_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, + MBEDTLS_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, + MBEDTLS_TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256, + /* All AES-256 ephemeral suites */ MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, @@ -81,6 +86,14 @@ static const int ciphersuite_preference[] = MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256, MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA, + /* All ARIA-256 ephemeral suites */ + MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384, + MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384, + MBEDTLS_TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384, + MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384, + MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384, + MBEDTLS_TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384, + /* All AES-128 ephemeral suites */ MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, @@ -105,12 +118,22 @@ static const int ciphersuite_preference[] = MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256, MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA, + /* All ARIA-128 ephemeral suites */ + MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256, + MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256, + MBEDTLS_TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256, + MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256, + MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256, + MBEDTLS_TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256, + /* All remaining >= 128-bit ephemeral suites */ MBEDTLS_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, MBEDTLS_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, MBEDTLS_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA, /* The PSK ephemeral suites */ + MBEDTLS_TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256, + MBEDTLS_TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256, MBEDTLS_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384, MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM, MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384, @@ -121,6 +144,9 @@ static const int ciphersuite_preference[] = MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384, MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384, MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM_8, + MBEDTLS_TLS_DHE_PSK_WITH_ARIA_256_GCM_SHA384, + MBEDTLS_TLS_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384, + MBEDTLS_TLS_DHE_PSK_WITH_ARIA_256_CBC_SHA384, MBEDTLS_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256, MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CCM, @@ -132,6 +158,9 @@ static const int ciphersuite_preference[] = MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256, MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256, MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CCM_8, + MBEDTLS_TLS_DHE_PSK_WITH_ARIA_128_GCM_SHA256, + MBEDTLS_TLS_ECDHE_PSK_WITH_ARIA_128_CBC_SHA256, + MBEDTLS_TLS_DHE_PSK_WITH_ARIA_128_CBC_SHA256, MBEDTLS_TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA, MBEDTLS_TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA, @@ -161,6 +190,14 @@ static const int ciphersuite_preference[] = MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384, MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384, + /* All ARIA-256 suites */ + MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384, + MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_256_GCM_SHA384, + MBEDTLS_TLS_RSA_WITH_ARIA_256_GCM_SHA384, + MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_256_CBC_SHA384, + MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_256_CBC_SHA384, + MBEDTLS_TLS_RSA_WITH_ARIA_256_CBC_SHA384, + /* All AES-128 suites */ MBEDTLS_TLS_RSA_WITH_AES_128_GCM_SHA256, MBEDTLS_TLS_RSA_WITH_AES_128_CCM, @@ -183,27 +220,41 @@ static const int ciphersuite_preference[] = MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256, MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256, + /* All ARIA-128 suites */ + MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256, + MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_128_GCM_SHA256, + MBEDTLS_TLS_RSA_WITH_ARIA_128_GCM_SHA256, + MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_128_CBC_SHA256, + MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_128_CBC_SHA256, + MBEDTLS_TLS_RSA_WITH_ARIA_128_CBC_SHA256, + /* All remaining >= 128-bit suites */ MBEDTLS_TLS_RSA_WITH_3DES_EDE_CBC_SHA, MBEDTLS_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA, MBEDTLS_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, /* The RSA PSK suites */ + MBEDTLS_TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256, MBEDTLS_TLS_RSA_PSK_WITH_AES_256_GCM_SHA384, MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA384, MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA, MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384, MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384, + MBEDTLS_TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384, + MBEDTLS_TLS_RSA_PSK_WITH_ARIA_256_CBC_SHA384, MBEDTLS_TLS_RSA_PSK_WITH_AES_128_GCM_SHA256, MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA256, MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA, MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256, MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256, + MBEDTLS_TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256, + MBEDTLS_TLS_RSA_PSK_WITH_ARIA_128_CBC_SHA256, MBEDTLS_TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA, /* The PSK suites */ + MBEDTLS_TLS_PSK_WITH_CHACHA20_POLY1305_SHA256, MBEDTLS_TLS_PSK_WITH_AES_256_GCM_SHA384, MBEDTLS_TLS_PSK_WITH_AES_256_CCM, MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA384, @@ -211,6 +262,8 @@ static const int ciphersuite_preference[] = MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384, MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384, MBEDTLS_TLS_PSK_WITH_AES_256_CCM_8, + MBEDTLS_TLS_PSK_WITH_ARIA_256_GCM_SHA384, + MBEDTLS_TLS_PSK_WITH_ARIA_256_CBC_SHA384, MBEDTLS_TLS_PSK_WITH_AES_128_GCM_SHA256, MBEDTLS_TLS_PSK_WITH_AES_128_CCM, @@ -219,6 +272,8 @@ static const int ciphersuite_preference[] = MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256, MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256, MBEDTLS_TLS_PSK_WITH_AES_128_CCM_8, + MBEDTLS_TLS_PSK_WITH_ARIA_128_GCM_SHA256, + MBEDTLS_TLS_PSK_WITH_ARIA_128_CBC_SHA256, MBEDTLS_TLS_PSK_WITH_3DES_EDE_CBC_SHA, @@ -266,6 +321,75 @@ static const int ciphersuite_preference[] = static const mbedtls_ssl_ciphersuite_t ciphersuite_definitions[] = { +#if defined(MBEDTLS_CHACHAPOLY_C) && \ + defined(MBEDTLS_SHA256_C) && \ + defined(MBEDTLS_SSL_PROTO_TLS1_2) +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) + { MBEDTLS_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, + "TLS-ECDHE-RSA-WITH-CHACHA20-POLY1305-SHA256", + MBEDTLS_CIPHER_CHACHA20_POLY1305, MBEDTLS_MD_SHA256, + MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, + "TLS-ECDHE-ECDSA-WITH-CHACHA20-POLY1305-SHA256", + MBEDTLS_CIPHER_CHACHA20_POLY1305, MBEDTLS_MD_SHA256, + MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) + { MBEDTLS_TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256, + "TLS-DHE-RSA-WITH-CHACHA20-POLY1305-SHA256", + MBEDTLS_CIPHER_CHACHA20_POLY1305, MBEDTLS_MD_SHA256, + MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) + { MBEDTLS_TLS_PSK_WITH_CHACHA20_POLY1305_SHA256, + "TLS-PSK-WITH-CHACHA20-POLY1305-SHA256", + MBEDTLS_CIPHER_CHACHA20_POLY1305, MBEDTLS_MD_SHA256, + MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) + { MBEDTLS_TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256, + "TLS-ECDHE-PSK-WITH-CHACHA20-POLY1305-SHA256", + MBEDTLS_CIPHER_CHACHA20_POLY1305, MBEDTLS_MD_SHA256, + MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) + { MBEDTLS_TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256, + "TLS-DHE-PSK-WITH-CHACHA20-POLY1305-SHA256", + MBEDTLS_CIPHER_CHACHA20_POLY1305, MBEDTLS_MD_SHA256, + MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) + { MBEDTLS_TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256, + "TLS-RSA-PSK-WITH-CHACHA20-POLY1305-SHA256", + MBEDTLS_CIPHER_CHACHA20_POLY1305, MBEDTLS_MD_SHA256, + MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#endif /* MBEDTLS_CHACHAPOLY_C && + MBEDTLS_SHA256_C && + MBEDTLS_SSL_PROTO_TLS1_2 */ #if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) #if defined(MBEDTLS_AES_C) #if defined(MBEDTLS_SHA1_C) @@ -1688,6 +1812,365 @@ static const mbedtls_ssl_ciphersuite_t ciphersuite_definitions[] = #endif /* MBEDTLS_DES_C */ #endif /* MBEDTLS_ENABLE_WEAK_CIPHERSUITES */ +#if defined(MBEDTLS_ARIA_C) + +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) + +#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA512_C)) + { MBEDTLS_TLS_RSA_WITH_ARIA_256_GCM_SHA384, + "TLS-RSA-WITH-ARIA-256-GCM-SHA384", + MBEDTLS_CIPHER_ARIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA512_C)) + { MBEDTLS_TLS_RSA_WITH_ARIA_256_CBC_SHA384, + "TLS-RSA-WITH-ARIA-256-CBC-SHA384", + MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA256_C)) + { MBEDTLS_TLS_RSA_WITH_ARIA_128_GCM_SHA256, + "TLS-RSA-WITH-ARIA-128-GCM-SHA256", + MBEDTLS_CIPHER_ARIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA256_C)) + { MBEDTLS_TLS_RSA_WITH_ARIA_128_CBC_SHA256, + "TLS-RSA-WITH-ARIA-128-CBC-SHA256", + MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif + +#endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) + +#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA512_C)) + { MBEDTLS_TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384, + "TLS-RSA-PSK-WITH-ARIA-256-GCM-SHA384", + MBEDTLS_CIPHER_ARIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA512_C)) + { MBEDTLS_TLS_RSA_PSK_WITH_ARIA_256_CBC_SHA384, + "TLS-RSA-PSK-WITH-ARIA-256-CBC-SHA384", + MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA256_C)) + { MBEDTLS_TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256, + "TLS-RSA-PSK-WITH-ARIA-128-GCM-SHA256", + MBEDTLS_CIPHER_ARIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA256_C)) + { MBEDTLS_TLS_RSA_PSK_WITH_ARIA_128_CBC_SHA256, + "TLS-RSA-PSK-WITH-ARIA-128-CBC-SHA256", + MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif + +#endif /* MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) + +#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA512_C)) + { MBEDTLS_TLS_PSK_WITH_ARIA_256_GCM_SHA384, + "TLS-PSK-WITH-ARIA-256-GCM-SHA384", + MBEDTLS_CIPHER_ARIA_256_GCM, MBEDTLS_MD_SHA384,MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA512_C)) + { MBEDTLS_TLS_PSK_WITH_ARIA_256_CBC_SHA384, + "TLS-PSK-WITH-ARIA-256-CBC-SHA384", + MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA256_C)) + { MBEDTLS_TLS_PSK_WITH_ARIA_128_GCM_SHA256, + "TLS-PSK-WITH-ARIA-128-GCM-SHA256", + MBEDTLS_CIPHER_ARIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA256_C)) + { MBEDTLS_TLS_PSK_WITH_ARIA_128_CBC_SHA256, + "TLS-PSK-WITH-ARIA-128-CBC-SHA256", + MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif + +#endif /* MBEDTLS_KEY_EXCHANGE_PSK_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) + +#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA512_C)) + { MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_256_GCM_SHA384, + "TLS-ECDH-RSA-WITH-ARIA-256-GCM-SHA384", + MBEDTLS_CIPHER_ARIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA512_C)) + { MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_256_CBC_SHA384, + "TLS-ECDH-RSA-WITH-ARIA-256-CBC-SHA384", + MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA256_C)) + { MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_128_GCM_SHA256, + "TLS-ECDH-RSA-WITH-ARIA-128-GCM-SHA256", + MBEDTLS_CIPHER_ARIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA256_C)) + { MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_128_CBC_SHA256, + "TLS-ECDH-RSA-WITH-ARIA-128-CBC-SHA256", + MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif + +#endif /* MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) + +#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA512_C)) + { MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384, + "TLS-ECDHE-RSA-WITH-ARIA-256-GCM-SHA384", + MBEDTLS_CIPHER_ARIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA512_C)) + { MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384, + "TLS-ECDHE-RSA-WITH-ARIA-256-CBC-SHA384", + MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA256_C)) + { MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256, + "TLS-ECDHE-RSA-WITH-ARIA-128-GCM-SHA256", + MBEDTLS_CIPHER_ARIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA256_C)) + { MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256, + "TLS-ECDHE-RSA-WITH-ARIA-128-CBC-SHA256", + MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif + +#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) + +#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA512_C)) + { MBEDTLS_TLS_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384, + "TLS-ECDHE-PSK-WITH-ARIA-256-CBC-SHA384", + MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA256_C)) + { MBEDTLS_TLS_ECDHE_PSK_WITH_ARIA_128_CBC_SHA256, + "TLS-ECDHE-PSK-WITH-ARIA-128-CBC-SHA256", + MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif + +#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) + +#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA512_C)) + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384, + "TLS-ECDHE-ECDSA-WITH-ARIA-256-GCM-SHA384", + MBEDTLS_CIPHER_ARIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA512_C)) + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384, + "TLS-ECDHE-ECDSA-WITH-ARIA-256-CBC-SHA384", + MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA256_C)) + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256, + "TLS-ECDHE-ECDSA-WITH-ARIA-128-GCM-SHA256", + MBEDTLS_CIPHER_ARIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA256_C)) + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256, + "TLS-ECDHE-ECDSA-WITH-ARIA-128-CBC-SHA256", + MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif + +#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) + +#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA512_C)) + { MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384, + "TLS-ECDH-ECDSA-WITH-ARIA-256-GCM-SHA384", + MBEDTLS_CIPHER_ARIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA512_C)) + { MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_256_CBC_SHA384, + "TLS-ECDH-ECDSA-WITH-ARIA-256-CBC-SHA384", + MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA256_C)) + { MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256, + "TLS-ECDH-ECDSA-WITH-ARIA-128-GCM-SHA256", + MBEDTLS_CIPHER_ARIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA256_C)) + { MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_128_CBC_SHA256, + "TLS-ECDH-ECDSA-WITH-ARIA-128-CBC-SHA256", + MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif + +#endif /* MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) + +#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA512_C)) + { MBEDTLS_TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384, + "TLS-DHE-RSA-WITH-ARIA-256-GCM-SHA384", + MBEDTLS_CIPHER_ARIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA512_C)) + { MBEDTLS_TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384, + "TLS-DHE-RSA-WITH-ARIA-256-CBC-SHA384", + MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA256_C)) + { MBEDTLS_TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256, + "TLS-DHE-RSA-WITH-ARIA-128-GCM-SHA256", + MBEDTLS_CIPHER_ARIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA256_C)) + { MBEDTLS_TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256, + "TLS-DHE-RSA-WITH-ARIA-128-CBC-SHA256", + MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif + +#endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) + +#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA512_C)) + { MBEDTLS_TLS_DHE_PSK_WITH_ARIA_256_GCM_SHA384, + "TLS-DHE-PSK-WITH-ARIA-256-GCM-SHA384", + MBEDTLS_CIPHER_ARIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA512_C)) + { MBEDTLS_TLS_DHE_PSK_WITH_ARIA_256_CBC_SHA384, + "TLS-DHE-PSK-WITH-ARIA-256-CBC-SHA384", + MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA256_C)) + { MBEDTLS_TLS_DHE_PSK_WITH_ARIA_128_GCM_SHA256, + "TLS-DHE-PSK-WITH-ARIA-128-GCM-SHA256", + MBEDTLS_CIPHER_ARIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA256_C)) + { MBEDTLS_TLS_DHE_PSK_WITH_ARIA_128_CBC_SHA256, + "TLS-DHE-PSK-WITH-ARIA-128-CBC-SHA256", + MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif + +#endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */ + +#endif /* MBEDTLS_ARIA_C */ + + { 0, "", MBEDTLS_CIPHER_NONE, MBEDTLS_MD_NONE, MBEDTLS_KEY_EXCHANGE_NONE, 0, 0, 0, 0, 0 } diff --git a/thirdparty/mbedtls/library/ssl_cli.c b/thirdparty/mbedtls/library/ssl_cli.c index 88864b8136..ba59c48989 100644 --- a/thirdparty/mbedtls/library/ssl_cli.c +++ b/thirdparty/mbedtls/library/ssl_cli.c @@ -48,10 +48,7 @@ #endif #if defined(MBEDTLS_SSL_SESSION_TICKETS) -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize( void *v, size_t n ) { - volatile unsigned char *p = v; while( n-- ) *p++ = 0; -} +#include "mbedtls/platform_util.h" #endif #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) @@ -60,7 +57,7 @@ static void ssl_write_hostname_ext( mbedtls_ssl_context *ssl, size_t *olen ) { unsigned char *p = buf; - const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN; + const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN; size_t hostname_len; *olen = 0; @@ -130,7 +127,7 @@ static void ssl_write_renegotiation_ext( mbedtls_ssl_context *ssl, size_t *olen ) { unsigned char *p = buf; - const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN; + const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN; *olen = 0; @@ -174,7 +171,7 @@ static void ssl_write_signature_algorithms_ext( mbedtls_ssl_context *ssl, size_t *olen ) { unsigned char *p = buf; - const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN; + const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN; size_t sig_alg_len = 0; const int *md; #if defined(MBEDTLS_RSA_C) || defined(MBEDTLS_ECDSA_C) @@ -259,7 +256,7 @@ static void ssl_write_supported_elliptic_curves_ext( mbedtls_ssl_context *ssl, size_t *olen ) { unsigned char *p = buf; - const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN; + const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN; unsigned char *elliptic_curve_list = p + 6; size_t elliptic_curve_len = 0; const mbedtls_ecp_curve_info *info; @@ -332,7 +329,7 @@ static void ssl_write_supported_point_formats_ext( mbedtls_ssl_context *ssl, size_t *olen ) { unsigned char *p = buf; - const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN; + const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN; *olen = 0; @@ -355,7 +352,7 @@ static void ssl_write_supported_point_formats_ext( mbedtls_ssl_context *ssl, *olen = 6; } -#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C || +#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C || MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) @@ -365,7 +362,7 @@ static void ssl_write_ecjpake_kkpp_ext( mbedtls_ssl_context *ssl, { int ret; unsigned char *p = buf; - const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN; + const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN; size_t kkpp_len; *olen = 0; @@ -442,7 +439,7 @@ static void ssl_write_max_fragment_length_ext( mbedtls_ssl_context *ssl, size_t *olen ) { unsigned char *p = buf; - const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN; + const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN; *olen = 0; @@ -475,7 +472,7 @@ static void ssl_write_truncated_hmac_ext( mbedtls_ssl_context *ssl, unsigned char *buf, size_t *olen ) { unsigned char *p = buf; - const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN; + const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN; *olen = 0; @@ -507,7 +504,7 @@ static void ssl_write_encrypt_then_mac_ext( mbedtls_ssl_context *ssl, unsigned char *buf, size_t *olen ) { unsigned char *p = buf; - const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN; + const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN; *olen = 0; @@ -541,7 +538,7 @@ static void ssl_write_extended_ms_ext( mbedtls_ssl_context *ssl, unsigned char *buf, size_t *olen ) { unsigned char *p = buf; - const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN; + const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN; *olen = 0; @@ -575,7 +572,7 @@ static void ssl_write_session_ticket_ext( mbedtls_ssl_context *ssl, unsigned char *buf, size_t *olen ) { unsigned char *p = buf; - const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN; + const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN; size_t tlen = ssl->session_negotiate->ticket_len; *olen = 0; @@ -619,7 +616,7 @@ static void ssl_write_alpn_ext( mbedtls_ssl_context *ssl, unsigned char *buf, size_t *olen ) { unsigned char *p = buf; - const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN; + const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN; size_t alpnlen = 0; const char **cur; @@ -717,6 +714,49 @@ static int ssl_generate_random( mbedtls_ssl_context *ssl ) return( 0 ); } +/** + * \brief Validate cipher suite against config in SSL context. + * + * \param suite_info cipher suite to validate + * \param ssl SSL context + * \param min_minor_ver Minimal minor version to accept a cipher suite + * \param max_minor_ver Maximal minor version to accept a cipher suite + * + * \return 0 if valid, else 1 + */ +static int ssl_validate_ciphersuite( const mbedtls_ssl_ciphersuite_t * suite_info, + const mbedtls_ssl_context * ssl, + int min_minor_ver, int max_minor_ver ) +{ + (void) ssl; + if( suite_info == NULL ) + return( 1 ); + + if( suite_info->min_minor_ver > max_minor_ver || + suite_info->max_minor_ver < min_minor_ver ) + return( 1 ); + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ( suite_info->flags & MBEDTLS_CIPHERSUITE_NODTLS ) ) + return( 1 ); +#endif + +#if defined(MBEDTLS_ARC4_C) + if( ssl->conf->arc4_disabled == MBEDTLS_SSL_ARC4_DISABLED && + suite_info->cipher == MBEDTLS_CIPHER_ARC4_128 ) + return( 1 ); +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + if( suite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE && + mbedtls_ecjpake_check( &ssl->handshake->ecjpake_ctx ) != 0 ) + return( 1 ); +#endif + + return( 0 ); +} + static int ssl_write_client_hello( mbedtls_ssl_context *ssl ) { int ret; @@ -869,31 +909,11 @@ static int ssl_write_client_hello( mbedtls_ssl_context *ssl ) { ciphersuite_info = mbedtls_ssl_ciphersuite_from_id( ciphersuites[i] ); - if( ciphersuite_info == NULL ) + if( ssl_validate_ciphersuite( ciphersuite_info, ssl, + ssl->conf->min_minor_ver, + ssl->conf->max_minor_ver ) != 0 ) continue; - if( ciphersuite_info->min_minor_ver > ssl->conf->max_minor_ver || - ciphersuite_info->max_minor_ver < ssl->conf->min_minor_ver ) - continue; - -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && - ( ciphersuite_info->flags & MBEDTLS_CIPHERSUITE_NODTLS ) ) - continue; -#endif - -#if defined(MBEDTLS_ARC4_C) - if( ssl->conf->arc4_disabled == MBEDTLS_SSL_ARC4_DISABLED && - ciphersuite_info->cipher == MBEDTLS_CIPHER_ARC4_128 ) - continue; -#endif - -#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) - if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE && - mbedtls_ecjpake_check( &ssl->handshake->ecjpake_ctx ) != 0 ) - continue; -#endif - MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, add ciphersuite: %04x", ciphersuites[i] ) ); @@ -938,7 +958,7 @@ static int ssl_write_client_hello( mbedtls_ssl_context *ssl ) #endif /* - * We don't support compression with DTLS right now: is many records come + * We don't support compression with DTLS right now: if many records come * in the same datagram, uncompressing one could overwrite the next one. * We don't want to add complexity for handling that case unless there is * an actual need for it. @@ -1227,14 +1247,14 @@ static int ssl_parse_supported_point_formats_ext( mbedtls_ssl_context *ssl, size_t list_size; const unsigned char *p; - list_size = buf[0]; - if( list_size + 1 != len ) + if( len == 0 || (size_t)( buf[0] + 1 ) != len ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); } + list_size = buf[0]; p = buf + 1; while( list_size > 0 ) @@ -1261,7 +1281,7 @@ static int ssl_parse_supported_point_formats_ext( mbedtls_ssl_context *ssl, MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); } -#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C || +#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C || MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) @@ -1690,22 +1710,9 @@ static int ssl_parse_server_hello( mbedtls_ssl_context *ssl ) MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, chosen ciphersuite: %04x", i ) ); MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, compress alg.: %d", buf[37 + n] ) ); - suite_info = mbedtls_ssl_ciphersuite_from_id( ssl->session_negotiate->ciphersuite ); - if( suite_info == NULL -#if defined(MBEDTLS_ARC4_C) - || ( ssl->conf->arc4_disabled && - suite_info->cipher == MBEDTLS_CIPHER_ARC4_128 ) -#endif - ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); - return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); - } - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, chosen ciphersuite: %s", suite_info->name ) ); - + /* + * Perform cipher suite validation in same way as in ssl_write_client_hello. + */ i = 0; while( 1 ) { @@ -1724,6 +1731,17 @@ static int ssl_parse_server_hello( mbedtls_ssl_context *ssl ) } } + suite_info = mbedtls_ssl_ciphersuite_from_id( ssl->session_negotiate->ciphersuite ); + if( ssl_validate_ciphersuite( suite_info, ssl, ssl->minor_ver, ssl->minor_ver ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, chosen ciphersuite: %s", suite_info->name ) ); + if( comp != MBEDTLS_SSL_COMPRESS_NULL #if defined(MBEDTLS_ZLIB_SUPPORT) && comp != MBEDTLS_SSL_COMPRESS_DEFLATE @@ -2099,7 +2117,7 @@ static int ssl_write_encrypted_pms( mbedtls_ssl_context *ssl, size_t len_bytes = ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ? 0 : 2; unsigned char *p = ssl->handshake->premaster + pms_offset; - if( offset + len_bytes > MBEDTLS_SSL_MAX_CONTENT_LEN ) + if( offset + len_bytes > MBEDTLS_SSL_OUT_CONTENT_LEN ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small for encrypted pms" ) ); return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); @@ -2142,7 +2160,7 @@ static int ssl_write_encrypted_pms( mbedtls_ssl_context *ssl, if( ( ret = mbedtls_pk_encrypt( &ssl->session_negotiate->peer_cert->pk, p, ssl->handshake->pmslen, ssl->out_msg + offset + len_bytes, olen, - MBEDTLS_SSL_MAX_CONTENT_LEN - offset - len_bytes, + MBEDTLS_SSL_OUT_CONTENT_LEN - offset - len_bytes, ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_rsa_pkcs1_encrypt", ret ); @@ -2526,10 +2544,9 @@ static int ssl_parse_server_key_exchange( mbedtls_ssl_context *ssl ) defined(MBEDTLS_SSL_PROTO_TLS1_2) if( md_alg != MBEDTLS_MD_NONE ) { - /* Info from md_alg will be used instead */ - hashlen = 0; - ret = mbedtls_ssl_get_key_exchange_md_tls1_2( ssl, hash, params, - params_len, md_alg ); + ret = mbedtls_ssl_get_key_exchange_md_tls1_2( ssl, hash, &hashlen, + params, params_len, + md_alg ); if( ret != 0 ) return( ret ); } @@ -2541,8 +2558,7 @@ static int ssl_parse_server_key_exchange( mbedtls_ssl_context *ssl ) return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); } - MBEDTLS_SSL_DEBUG_BUF( 3, "parameters hash", hash, hashlen != 0 ? hashlen : - (unsigned int) ( mbedtls_md_get_size( mbedtls_md_info_from_type( md_alg ) ) ) ); + MBEDTLS_SSL_DEBUG_BUF( 3, "parameters hash", hash, hashlen ); if( ssl->session_negotiate->peer_cert == NULL ) { @@ -2673,10 +2689,27 @@ static int ssl_parse_certificate_request( mbedtls_ssl_context *ssl ) buf = ssl->in_msg; /* certificate_types */ + if( ssl->in_hslen <= mbedtls_ssl_hs_hdr_len( ssl ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate request message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST ); + } cert_type_len = buf[mbedtls_ssl_hs_hdr_len( ssl )]; n = cert_type_len; - if( ssl->in_hslen < mbedtls_ssl_hs_hdr_len( ssl ) + 2 + n ) + /* + * In the subsequent code there are two paths that read from buf: + * * the length of the signature algorithms field (if minor version of + * SSL is 3), + * * distinguished name length otherwise. + * Both reach at most the index: + * ...hdr_len + 2 + n, + * therefore the buffer length at this point must be greater than that + * regardless of the actual code path. + */ + if( ssl->in_hslen <= mbedtls_ssl_hs_hdr_len( ssl ) + 3 + n ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate request message" ) ); mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, @@ -2691,9 +2724,32 @@ static int ssl_parse_certificate_request( mbedtls_ssl_context *ssl ) size_t sig_alg_len = ( ( buf[mbedtls_ssl_hs_hdr_len( ssl ) + 1 + n] << 8 ) | ( buf[mbedtls_ssl_hs_hdr_len( ssl ) + 2 + n] ) ); #if defined(MBEDTLS_DEBUG_C) - unsigned char* sig_alg = buf + mbedtls_ssl_hs_hdr_len( ssl ) + 3 + n; + unsigned char* sig_alg; size_t i; +#endif + + /* + * The furthest access in buf is in the loop few lines below: + * sig_alg[i + 1], + * where: + * sig_alg = buf + ...hdr_len + 3 + n, + * max(i) = sig_alg_len - 1. + * Therefore the furthest access is: + * buf[...hdr_len + 3 + n + sig_alg_len - 1 + 1], + * which reduces to: + * buf[...hdr_len + 3 + n + sig_alg_len], + * which is one less than we need the buf to be. + */ + if( ssl->in_hslen <= mbedtls_ssl_hs_hdr_len( ssl ) + 3 + n + sig_alg_len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate request message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST ); + } +#if defined(MBEDTLS_DEBUG_C) + sig_alg = buf + mbedtls_ssl_hs_hdr_len( ssl ) + 3 + n; for( i = 0; i < sig_alg_len; i += 2 ) { MBEDTLS_SSL_DEBUG_MSG( 3, ( "Supported Signature Algorithm found: %d" @@ -2702,14 +2758,6 @@ static int ssl_parse_certificate_request( mbedtls_ssl_context *ssl ) #endif n += 2 + sig_alg_len; - - if( ssl->in_hslen < mbedtls_ssl_hs_hdr_len( ssl ) + 2 + n ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate request message" ) ); - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); - return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST ); - } } #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ @@ -2878,7 +2926,7 @@ static int ssl_write_client_key_exchange( mbedtls_ssl_context *ssl ) i = 4; n = ssl->conf->psk_identity_len; - if( i + 2 + n > MBEDTLS_SSL_MAX_CONTENT_LEN ) + if( i + 2 + n > MBEDTLS_SSL_OUT_CONTENT_LEN ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "psk identity too long or " "SSL buffer too short" ) ); @@ -2914,7 +2962,7 @@ static int ssl_write_client_key_exchange( mbedtls_ssl_context *ssl ) */ n = ssl->handshake->dhm_ctx.len; - if( i + 2 + n > MBEDTLS_SSL_MAX_CONTENT_LEN ) + if( i + 2 + n > MBEDTLS_SSL_OUT_CONTENT_LEN ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "psk identity or DHM size too long" " or SSL buffer too short" ) ); @@ -2943,7 +2991,7 @@ static int ssl_write_client_key_exchange( mbedtls_ssl_context *ssl ) * ClientECDiffieHellmanPublic public; */ ret = mbedtls_ecdh_make_public( &ssl->handshake->ecdh_ctx, &n, - &ssl->out_msg[i], MBEDTLS_SSL_MAX_CONTENT_LEN - i, + &ssl->out_msg[i], MBEDTLS_SSL_OUT_CONTENT_LEN - i, ssl->conf->f_rng, ssl->conf->p_rng ); if( ret != 0 ) { @@ -2984,7 +3032,7 @@ static int ssl_write_client_key_exchange( mbedtls_ssl_context *ssl ) i = 4; ret = mbedtls_ecjpake_write_round_two( &ssl->handshake->ecjpake_ctx, - ssl->out_msg + i, MBEDTLS_SSL_MAX_CONTENT_LEN - i, &n, + ssl->out_msg + i, MBEDTLS_SSL_OUT_CONTENT_LEN - i, &n, ssl->conf->f_rng, ssl->conf->p_rng ); if( ret != 0 ) { @@ -3289,8 +3337,8 @@ static int ssl_parse_new_session_ticket( mbedtls_ssl_context *ssl ) if( ticket_len == 0 ) return( 0 ); - mbedtls_zeroize( ssl->session_negotiate->ticket, - ssl->session_negotiate->ticket_len ); + mbedtls_platform_zeroize( ssl->session_negotiate->ticket, + ssl->session_negotiate->ticket_len ); mbedtls_free( ssl->session_negotiate->ticket ); ssl->session_negotiate->ticket = NULL; ssl->session_negotiate->ticket_len = 0; diff --git a/thirdparty/mbedtls/library/ssl_cookie.c b/thirdparty/mbedtls/library/ssl_cookie.c index caf119990d..56e9bdd2bf 100644 --- a/thirdparty/mbedtls/library/ssl_cookie.c +++ b/thirdparty/mbedtls/library/ssl_cookie.c @@ -40,14 +40,10 @@ #include "mbedtls/ssl_cookie.h" #include "mbedtls/ssl_internal.h" +#include "mbedtls/platform_util.h" #include <string.h> -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize( void *v, size_t n ) { - volatile unsigned char *p = v; while( n-- ) *p++ = 0; -} - /* * If DTLS is in use, then at least one of SHA-1, SHA-256, SHA-512 is * available. Try SHA-256 first, 512 wastes resources since we need to stay @@ -101,7 +97,7 @@ void mbedtls_ssl_cookie_free( mbedtls_ssl_cookie_ctx *ctx ) mbedtls_mutex_free( &ctx->mutex ); #endif - mbedtls_zeroize( ctx, sizeof( mbedtls_ssl_cookie_ctx ) ); + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_ssl_cookie_ctx ) ); } int mbedtls_ssl_cookie_setup( mbedtls_ssl_cookie_ctx *ctx, @@ -122,7 +118,7 @@ int mbedtls_ssl_cookie_setup( mbedtls_ssl_cookie_ctx *ctx, if( ret != 0 ) return( ret ); - mbedtls_zeroize( key, sizeof( key ) ); + mbedtls_platform_zeroize( key, sizeof( key ) ); return( 0 ); } diff --git a/thirdparty/mbedtls/library/ssl_srv.c b/thirdparty/mbedtls/library/ssl_srv.c index aca4235e6e..52087ae6e1 100644 --- a/thirdparty/mbedtls/library/ssl_srv.c +++ b/thirdparty/mbedtls/library/ssl_srv.c @@ -38,6 +38,7 @@ #include "mbedtls/debug.h" #include "mbedtls/ssl.h" #include "mbedtls/ssl_internal.h" +#include "mbedtls/platform_util.h" #include <string.h> @@ -49,13 +50,6 @@ #include "mbedtls/platform_time.h" #endif -#if defined(MBEDTLS_SSL_SESSION_TICKETS) -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize( void *v, size_t n ) { - volatile unsigned char *p = v; while( n-- ) *p++ = 0; -} -#endif - #if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) int mbedtls_ssl_set_client_transport_id( mbedtls_ssl_context *ssl, const unsigned char *info, @@ -97,6 +91,13 @@ static int ssl_parse_servername_ext( mbedtls_ssl_context *ssl, MBEDTLS_SSL_DEBUG_MSG( 3, ( "parse ServerName extension" ) ); + if( len < 2 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } servername_list_size = ( ( buf[0] << 8 ) | ( buf[1] ) ); if( servername_list_size + 2 != len ) { @@ -107,7 +108,7 @@ static int ssl_parse_servername_ext( mbedtls_ssl_context *ssl, } p = buf + 2; - while( servername_list_size > 0 ) + while( servername_list_size > 2 ) { hostname_len = ( ( p[1] << 8 ) | p[2] ); if( hostname_len + 3 > servername_list_size ) @@ -211,6 +212,12 @@ static int ssl_parse_signature_algorithms_ext( mbedtls_ssl_context *ssl, mbedtls_md_type_t md_cur; mbedtls_pk_type_t sig_cur; + if ( len < 2 ) { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } sig_alg_list_size = ( ( buf[0] << 8 ) | ( buf[1] ) ); if( sig_alg_list_size + 2 != len || sig_alg_list_size % 2 != 0 ) @@ -279,6 +286,12 @@ static int ssl_parse_supported_elliptic_curves( mbedtls_ssl_context *ssl, const unsigned char *p; const mbedtls_ecp_curve_info *curve_info, **curves; + if ( len < 2 ) { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } list_size = ( ( buf[0] << 8 ) | ( buf[1] ) ); if( list_size + 2 != len || list_size % 2 != 0 ) @@ -338,14 +351,14 @@ static int ssl_parse_supported_point_formats( mbedtls_ssl_context *ssl, size_t list_size; const unsigned char *p; - list_size = buf[0]; - if( list_size + 1 != len ) + if( len == 0 || (size_t)( buf[0] + 1 ) != len ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); } + list_size = buf[0]; p = buf + 1; while( list_size > 0 ) @@ -553,7 +566,7 @@ static int ssl_parse_session_ticket_ext( mbedtls_ssl_context *ssl, memcpy( ssl->session_negotiate, &session, sizeof( mbedtls_ssl_session ) ); /* Zeroize instead of free as we copied the content */ - mbedtls_zeroize( &session, sizeof( mbedtls_ssl_session ) ); + mbedtls_platform_zeroize( &session, sizeof( mbedtls_ssl_session ) ); MBEDTLS_SSL_DEBUG_MSG( 3, ( "session successfully restored from ticket" ) ); @@ -715,7 +728,7 @@ static int ssl_pick_cert( mbedtls_ssl_context *ssl, MBEDTLS_SSL_DEBUG_CRT( 3, "candidate certificate chain, certificate", cur->cert ); - if( ! mbedtls_pk_can_do( cur->key, pk_alg ) ) + if( ! mbedtls_pk_can_do( &cur->cert->pk, pk_alg ) ) { MBEDTLS_SSL_DEBUG_MSG( 3, ( "certificate mismatch: key type" ) ); continue; @@ -739,7 +752,7 @@ static int ssl_pick_cert( mbedtls_ssl_context *ssl, #if defined(MBEDTLS_ECDSA_C) if( pk_alg == MBEDTLS_PK_ECDSA && - ssl_check_key_curve( cur->key, ssl->handshake->curves ) != 0 ) + ssl_check_key_curve( &cur->cert->pk, ssl->handshake->curves ) != 0 ) { MBEDTLS_SSL_DEBUG_MSG( 3, ( "certificate mismatch: elliptic curve" ) ); continue; @@ -793,7 +806,7 @@ static int ssl_ciphersuite_match( mbedtls_ssl_context *ssl, int suite_id, const mbedtls_ssl_ciphersuite_t *suite_info; #if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ - defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) + defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) mbedtls_pk_type_t sig_type; #endif @@ -1309,7 +1322,7 @@ read_record_header: else #endif { - if( msg_len > MBEDTLS_SSL_MAX_CONTENT_LEN ) + if( msg_len > MBEDTLS_SSL_IN_CONTENT_LEN ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); @@ -1662,10 +1675,16 @@ read_record_header: while( ext_len != 0 ) { - unsigned int ext_id = ( ( ext[0] << 8 ) - | ( ext[1] ) ); - unsigned int ext_size = ( ( ext[2] << 8 ) - | ( ext[3] ) ); + unsigned int ext_id; + unsigned int ext_size; + if ( ext_len < 4 ) { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + ext_id = ( ( ext[0] << 8 ) | ( ext[1] ) ); + ext_size = ( ( ext[2] << 8 ) | ( ext[3] ) ); if( ext_size + 4 > ext_len ) { @@ -2241,7 +2260,7 @@ static void ssl_write_ecjpake_kkpp_ext( mbedtls_ssl_context *ssl, { int ret; unsigned char *p = buf; - const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN; + const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN; size_t kkpp_len; *olen = 0; @@ -2348,7 +2367,7 @@ static int ssl_write_hello_verify_request( mbedtls_ssl_context *ssl ) cookie_len_byte = p++; if( ( ret = ssl->conf->f_cookie_write( ssl->conf->p_cookie, - &p, ssl->out_buf + MBEDTLS_SSL_BUFFER_LEN, + &p, ssl->out_buf + MBEDTLS_SSL_OUT_BUFFER_LEN, ssl->cli_id, ssl->cli_id_len ) ) != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, "f_cookie_write", ret ); @@ -2644,7 +2663,7 @@ static int ssl_write_certificate_request( mbedtls_ssl_context *ssl ) size_t dn_size, total_dn_size; /* excluding length bytes */ size_t ct_len, sa_len; /* including length bytes */ unsigned char *buf, *p; - const unsigned char * const end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN; + const unsigned char * const end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN; const mbedtls_x509_crt *crt; int authmode; @@ -2834,54 +2853,56 @@ static int ssl_get_ecdh_params_from_cert( mbedtls_ssl_context *ssl ) #endif /* MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ -static int ssl_write_server_key_exchange( mbedtls_ssl_context *ssl ) +#if defined(MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED) && \ + defined(MBEDTLS_SSL_ASYNC_PRIVATE) +static int ssl_resume_server_key_exchange( mbedtls_ssl_context *ssl, + size_t *signature_len ) +{ + /* Append the signature to ssl->out_msg, leaving 2 bytes for the + * signature length which will be added in ssl_write_server_key_exchange + * after the call to ssl_prepare_server_key_exchange. + * ssl_write_server_key_exchange also takes care of incrementing + * ssl->out_msglen. */ + unsigned char *sig_start = ssl->out_msg + ssl->out_msglen + 2; + size_t sig_max_len = ( ssl->out_buf + MBEDTLS_SSL_OUT_CONTENT_LEN + - sig_start ); + int ret = ssl->conf->f_async_resume( ssl, + sig_start, signature_len, sig_max_len ); + if( ret != MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS ) + { + ssl->handshake->async_in_progress = 0; + mbedtls_ssl_set_async_operation_data( ssl, NULL ); + } + MBEDTLS_SSL_DEBUG_RET( 2, "ssl_resume_server_key_exchange", ret ); + return( ret ); +} +#endif /* defined(MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED) && + defined(MBEDTLS_SSL_ASYNC_PRIVATE) */ + +/* Prepare the ServerKeyExchange message, up to and including + * calculating the signature if any, but excluding formatting the + * signature and sending the message. */ +static int ssl_prepare_server_key_exchange( mbedtls_ssl_context *ssl, + size_t *signature_len ) { - int ret; - size_t n = 0; const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info; - #if defined(MBEDTLS_KEY_EXCHANGE__SOME_PFS__ENABLED) - unsigned char *p = ssl->out_msg + 4; - size_t len; #if defined(MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED) - unsigned char *dig_signed = p; - size_t dig_signed_len = 0; + unsigned char *dig_signed = NULL; #endif /* MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED */ #endif /* MBEDTLS_KEY_EXCHANGE__SOME_PFS__ENABLED */ - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write server key exchange" ) ); - - /* - * - * Part 1: Extract static ECDH parameters and abort - * if ServerKeyExchange not needed. - * - */ - - /* For suites involving ECDH, extract DH parameters - * from certificate at this point. */ -#if defined(MBEDTLS_KEY_EXCHANGE__SOME__ECDH_ENABLED) - if( mbedtls_ssl_ciphersuite_uses_ecdh( ciphersuite_info ) ) - { - ssl_get_ecdh_params_from_cert( ssl ); - } -#endif /* MBEDTLS_KEY_EXCHANGE__SOME__ECDH_ENABLED */ + (void) ciphersuite_info; /* unused in some configurations */ +#if !defined(MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED) + (void) signature_len; +#endif /* MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED */ - /* Key exchanges not involving ephemeral keys don't use - * ServerKeyExchange, so end here. */ -#if defined(MBEDTLS_KEY_EXCHANGE__SOME_NON_PFS__ENABLED) - if( mbedtls_ssl_ciphersuite_no_pfs( ciphersuite_info ) ) - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write server key exchange" ) ); - ssl->state++; - return( 0 ); - } -#endif /* MBEDTLS_KEY_EXCHANGE__NON_PFS__ENABLED */ + ssl->out_msglen = 4; /* header (type:1, length:3) to be written later */ /* * - * Part 2: Provide key exchange parameters for chosen ciphersuite. + * Part 1: Provide key exchange parameters for chosen ciphersuite. * */ @@ -2891,18 +2912,21 @@ static int ssl_write_server_key_exchange( mbedtls_ssl_context *ssl ) #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE ) { - const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN; + int ret; + size_t len = 0; - ret = mbedtls_ecjpake_write_round_two( &ssl->handshake->ecjpake_ctx, - p, end - p, &len, ssl->conf->f_rng, ssl->conf->p_rng ); + ret = mbedtls_ecjpake_write_round_two( + &ssl->handshake->ecjpake_ctx, + ssl->out_msg + ssl->out_msglen, + MBEDTLS_SSL_OUT_CONTENT_LEN - ssl->out_msglen, &len, + ssl->conf->f_rng, ssl->conf->p_rng ); if( ret != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecjpake_write_round_two", ret ); return( ret ); } - p += len; - n += len; + ssl->out_msglen += len; } #endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ @@ -2916,10 +2940,8 @@ static int ssl_write_server_key_exchange( mbedtls_ssl_context *ssl ) if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK || ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK ) { - *(p++) = 0x00; - *(p++) = 0x00; - - n += 2; + ssl->out_msg[ssl->out_msglen++] = 0x00; + ssl->out_msg[ssl->out_msglen++] = 0x00; } #endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED || MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ @@ -2930,6 +2952,9 @@ static int ssl_write_server_key_exchange( mbedtls_ssl_context *ssl ) #if defined(MBEDTLS_KEY_EXCHANGE__SOME__DHE_ENABLED) if( mbedtls_ssl_ciphersuite_uses_dhe( ciphersuite_info ) ) { + int ret; + size_t len = 0; + if( ssl->conf->dhm_P.p == NULL || ssl->conf->dhm_G.p == NULL ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "no DH parameters set" ) ); @@ -2953,21 +2978,21 @@ static int ssl_write_server_key_exchange( mbedtls_ssl_context *ssl ) return( ret ); } - if( ( ret = mbedtls_dhm_make_params( &ssl->handshake->dhm_ctx, - (int) mbedtls_mpi_size( &ssl->handshake->dhm_ctx.P ), - p, &len, ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 ) + if( ( ret = mbedtls_dhm_make_params( + &ssl->handshake->dhm_ctx, + (int) mbedtls_mpi_size( &ssl->handshake->dhm_ctx.P ), + ssl->out_msg + ssl->out_msglen, &len, + ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_dhm_make_params", ret ); return( ret ); } -#if defined(MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED) - dig_signed = p; - dig_signed_len = len; +#if defined(MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED) + dig_signed = ssl->out_msg + ssl->out_msglen; #endif - p += len; - n += len; + ssl->out_msglen += len; MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: X ", &ssl->handshake->dhm_ctx.X ); MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: P ", &ssl->handshake->dhm_ctx.P ); @@ -2992,6 +3017,8 @@ static int ssl_write_server_key_exchange( mbedtls_ssl_context *ssl ) */ const mbedtls_ecp_curve_info **curve = NULL; const mbedtls_ecp_group_id *gid; + int ret; + size_t len = 0; /* Match our preference list against the offered curves */ for( gid = ssl->conf->curve_list; *gid != MBEDTLS_ECP_DP_NONE; gid++ ) @@ -3015,21 +3042,21 @@ curve_matching_done: return( ret ); } - if( ( ret = mbedtls_ecdh_make_params( &ssl->handshake->ecdh_ctx, &len, - p, MBEDTLS_SSL_MAX_CONTENT_LEN - n, - ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 ) + if( ( ret = mbedtls_ecdh_make_params( + &ssl->handshake->ecdh_ctx, &len, + ssl->out_msg + ssl->out_msglen, + MBEDTLS_SSL_OUT_CONTENT_LEN - ssl->out_msglen, + ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecdh_make_params", ret ); return( ret ); } #if defined(MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED) - dig_signed = p; - dig_signed_len = len; + dig_signed = ssl->out_msg + ssl->out_msglen; #endif - p += len; - n += len; + ssl->out_msglen += len; MBEDTLS_SSL_DEBUG_ECP( 3, "ECDH: Q ", &ssl->handshake->ecdh_ctx.Q ); } @@ -3037,20 +3064,21 @@ curve_matching_done: /* * - * Part 3: For key exchanges involving the server signing the + * Part 2: For key exchanges involving the server signing the * exchange parameters, compute and add the signature here. * */ #if defined(MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED) if( mbedtls_ssl_ciphersuite_uses_server_signature( ciphersuite_info ) ) { - size_t signature_len = 0; - unsigned int hashlen = 0; - unsigned char hash[64]; + size_t dig_signed_len = ssl->out_msg + ssl->out_msglen - dig_signed; + size_t hashlen = 0; + unsigned char hash[MBEDTLS_MD_MAX_SIZE]; + int ret; /* - * 3.1: Choose hash algorithm: - * A: For TLS 1.2, obey signature-hash-algorithm extension + * 2.1: Choose hash algorithm: + * A: For TLS 1.2, obey signature-hash-algorithm extension * to choose appropriate hash. * B: For SSL3, TLS1.0, TLS1.1 and ECDHE_ECDSA, use SHA1 * (RFC 4492, Sec. 5.4) @@ -3071,7 +3099,7 @@ curve_matching_done: sig_alg ) ) == MBEDTLS_MD_NONE ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); - /* (... because we choose a cipher suite + /* (... because we choose a cipher suite * only if there is a matching hash.) */ return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); } @@ -3096,7 +3124,7 @@ curve_matching_done: MBEDTLS_SSL_DEBUG_MSG( 3, ( "pick hash algorithm %d for signing", md_alg ) ); /* - * 3.2: Compute the hash to be signed + * 2.2: Compute the hash to be signed */ #if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ defined(MBEDTLS_SSL_PROTO_TLS1_1) @@ -3116,9 +3144,7 @@ curve_matching_done: defined(MBEDTLS_SSL_PROTO_TLS1_2) if( md_alg != MBEDTLS_MD_NONE ) { - /* Info from md_alg will be used instead */ - hashlen = 0; - ret = mbedtls_ssl_get_key_exchange_md_tls1_2( ssl, hash, + ret = mbedtls_ssl_get_key_exchange_md_tls1_2( ssl, hash, &hashlen, dig_signed, dig_signed_len, md_alg ); @@ -3133,18 +3159,11 @@ curve_matching_done: return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); } - MBEDTLS_SSL_DEBUG_BUF( 3, "parameters hash", hash, hashlen != 0 ? hashlen : - (unsigned int) ( mbedtls_md_get_size( mbedtls_md_info_from_type( md_alg ) ) ) ); + MBEDTLS_SSL_DEBUG_BUF( 3, "parameters hash", hash, hashlen ); /* - * 3.3: Compute and add the signature + * 2.3: Compute and add the signature */ - if( mbedtls_ssl_own_key( ssl ) == NULL ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no private key" ) ); - return( MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED ); - } - #if defined(MBEDTLS_SSL_PROTO_TLS1_2) if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) { @@ -3164,33 +3183,150 @@ curve_matching_done: * */ - *(p++) = mbedtls_ssl_hash_from_md_alg( md_alg ); - *(p++) = mbedtls_ssl_sig_from_pk_alg( sig_alg ); - - n += 2; + ssl->out_msg[ssl->out_msglen++] = + mbedtls_ssl_hash_from_md_alg( md_alg ); + ssl->out_msg[ssl->out_msglen++] = + mbedtls_ssl_sig_from_pk_alg( sig_alg ); } #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ - if( ( ret = mbedtls_pk_sign( mbedtls_ssl_own_key( ssl ), md_alg, hash, hashlen, - p + 2 , &signature_len, ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 ) +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) + if( ssl->conf->f_async_sign_start != NULL ) + { + ret = ssl->conf->f_async_sign_start( ssl, + mbedtls_ssl_own_cert( ssl ), + md_alg, hash, hashlen ); + switch( ret ) + { + case MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH: + /* act as if f_async_sign was null */ + break; + case 0: + ssl->handshake->async_in_progress = 1; + return( ssl_resume_server_key_exchange( ssl, signature_len ) ); + case MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS: + ssl->handshake->async_in_progress = 1; + return( MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS ); + default: + MBEDTLS_SSL_DEBUG_RET( 1, "f_async_sign_start", ret ); + return( ret ); + } + } +#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ + + if( mbedtls_ssl_own_key( ssl ) == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no private key" ) ); + return( MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED ); + } + + /* Append the signature to ssl->out_msg, leaving 2 bytes for the + * signature length which will be added in ssl_write_server_key_exchange + * after the call to ssl_prepare_server_key_exchange. + * ssl_write_server_key_exchange also takes care of incrementing + * ssl->out_msglen. */ + if( ( ret = mbedtls_pk_sign( mbedtls_ssl_own_key( ssl ), + md_alg, hash, hashlen, + ssl->out_msg + ssl->out_msglen + 2, + signature_len, + ssl->conf->f_rng, + ssl->conf->p_rng ) ) != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_pk_sign", ret ); return( ret ); } + } +#endif /* MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED */ + + return( 0 ); +} + +/* Prepare the ServerKeyExchange message and send it. For ciphersuites + * that do not include a ServerKeyExchange message, do nothing. Either + * way, if successful, move on to the next step in the SSL state + * machine. */ +static int ssl_write_server_key_exchange( mbedtls_ssl_context *ssl ) +{ + int ret; + size_t signature_len = 0; +#if defined(MBEDTLS_KEY_EXCHANGE__SOME_NON_PFS__ENABLED) + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = + ssl->transform_negotiate->ciphersuite_info; +#endif /* MBEDTLS_KEY_EXCHANGE__SOME_NON_PFS__ENABLED */ - *(p++) = (unsigned char)( signature_len >> 8 ); - *(p++) = (unsigned char)( signature_len ); - n += 2; + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write server key exchange" ) ); - MBEDTLS_SSL_DEBUG_BUF( 3, "my signature", p, signature_len ); +#if defined(MBEDTLS_KEY_EXCHANGE__SOME_NON_PFS__ENABLED) + /* Extract static ECDH parameters and abort if ServerKeyExchange + * is not needed. */ + if( mbedtls_ssl_ciphersuite_no_pfs( ciphersuite_info ) ) + { + /* For suites involving ECDH, extract DH parameters + * from certificate at this point. */ +#if defined(MBEDTLS_KEY_EXCHANGE__SOME__ECDH_ENABLED) + if( mbedtls_ssl_ciphersuite_uses_ecdh( ciphersuite_info ) ) + { + ssl_get_ecdh_params_from_cert( ssl ); + } +#endif /* MBEDTLS_KEY_EXCHANGE__SOME__ECDH_ENABLED */ - n += signature_len; + /* Key exchanges not involving ephemeral keys don't use + * ServerKeyExchange, so end here. */ + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write server key exchange" ) ); + ssl->state++; + return( 0 ); + } +#endif /* MBEDTLS_KEY_EXCHANGE__SOME_NON_PFS__ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED) && \ + defined(MBEDTLS_SSL_ASYNC_PRIVATE) + /* If we have already prepared the message and there is an ongoing + * signature operation, resume signing. */ + if( ssl->handshake->async_in_progress != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "resuming signature operation" ) ); + ret = ssl_resume_server_key_exchange( ssl, &signature_len ); + } + else +#endif /* defined(MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED) && + defined(MBEDTLS_SSL_ASYNC_PRIVATE) */ + { + /* ServerKeyExchange is needed. Prepare the message. */ + ret = ssl_prepare_server_key_exchange( ssl, &signature_len ); + } + + if( ret != 0 ) + { + /* If we're starting to write a new message, set ssl->out_msglen + * to 0. But if we're resuming after an asynchronous message, + * out_msglen is the amount of data written so far and mst be + * preserved. */ + if( ret == MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS ) + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write server key exchange (pending)" ) ); + else + ssl->out_msglen = 0; + return( ret ); } -#endif /* MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED */ - /* Done with actual work; add header and send. */ + /* If there is a signature, write its length. + * ssl_prepare_server_key_exchange already wrote the signature + * itself at its proper place in the output buffer. */ +#if defined(MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED) + if( signature_len != 0 ) + { + ssl->out_msg[ssl->out_msglen++] = (unsigned char)( signature_len >> 8 ); + ssl->out_msg[ssl->out_msglen++] = (unsigned char)( signature_len ); + + MBEDTLS_SSL_DEBUG_BUF( 3, "my signature", + ssl->out_msg + ssl->out_msglen, + signature_len ); + + /* Skip over the already-written signature */ + ssl->out_msglen += signature_len; + } +#endif /* MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED */ - ssl->out_msglen = 4 + n; + /* Add header and send. */ ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; ssl->out_msg[0] = MBEDTLS_SSL_HS_SERVER_KEY_EXCHANGE; @@ -3203,7 +3339,6 @@ curve_matching_done: } MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write server key exchange" ) ); - return( 0 ); } @@ -3278,33 +3413,59 @@ static int ssl_parse_client_dh_public( mbedtls_ssl_context *ssl, unsigned char * #if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) -static int ssl_parse_encrypted_pms( mbedtls_ssl_context *ssl, - const unsigned char *p, - const unsigned char *end, - size_t pms_offset ) + +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) +static int ssl_resume_decrypt_pms( mbedtls_ssl_context *ssl, + unsigned char *peer_pms, + size_t *peer_pmslen, + size_t peer_pmssize ) +{ + int ret = ssl->conf->f_async_resume( ssl, + peer_pms, peer_pmslen, peer_pmssize ); + if( ret != MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS ) + { + ssl->handshake->async_in_progress = 0; + mbedtls_ssl_set_async_operation_data( ssl, NULL ); + } + MBEDTLS_SSL_DEBUG_RET( 2, "ssl_decrypt_encrypted_pms", ret ); + return( ret ); +} +#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ + +static int ssl_decrypt_encrypted_pms( mbedtls_ssl_context *ssl, + const unsigned char *p, + const unsigned char *end, + unsigned char *peer_pms, + size_t *peer_pmslen, + size_t peer_pmssize ) { int ret; - size_t len = mbedtls_pk_get_len( mbedtls_ssl_own_key( ssl ) ); - unsigned char *pms = ssl->handshake->premaster + pms_offset; - unsigned char ver[2]; - unsigned char fake_pms[48], peer_pms[48]; - unsigned char mask; - size_t i, peer_pmslen; - unsigned int diff; + mbedtls_pk_context *private_key = mbedtls_ssl_own_key( ssl ); + mbedtls_pk_context *public_key = &mbedtls_ssl_own_cert( ssl )->pk; + size_t len = mbedtls_pk_get_len( public_key ); - if( ! mbedtls_pk_can_do( mbedtls_ssl_own_key( ssl ), MBEDTLS_PK_RSA ) ) +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) + /* If we have already started decoding the message and there is an ongoing + * decryption operation, resume signing. */ + if( ssl->handshake->async_in_progress != 0 ) { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no RSA private key" ) ); - return( MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED ); + MBEDTLS_SSL_DEBUG_MSG( 2, ( "resuming decryption operation" ) ); + return( ssl_resume_decrypt_pms( ssl, + peer_pms, peer_pmslen, peer_pmssize ) ); } +#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ /* - * Decrypt the premaster using own private RSA key + * Prepare to decrypt the premaster using own private RSA key */ #if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ defined(MBEDTLS_SSL_PROTO_TLS1_2) if( ssl->minor_ver != MBEDTLS_SSL_MINOR_VERSION_0 ) { + if ( p + 2 > end ) { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); + } if( *p++ != ( ( len >> 8 ) & 0xFF ) || *p++ != ( ( len ) & 0xFF ) ) { @@ -3320,30 +3481,120 @@ static int ssl_parse_encrypted_pms( mbedtls_ssl_context *ssl, return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); } + /* + * Decrypt the premaster secret + */ +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) + if( ssl->conf->f_async_decrypt_start != NULL ) + { + ret = ssl->conf->f_async_decrypt_start( ssl, + mbedtls_ssl_own_cert( ssl ), + p, len ); + switch( ret ) + { + case MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH: + /* act as if f_async_decrypt_start was null */ + break; + case 0: + ssl->handshake->async_in_progress = 1; + return( ssl_resume_decrypt_pms( ssl, + peer_pms, + peer_pmslen, + peer_pmssize ) ); + case MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS: + ssl->handshake->async_in_progress = 1; + return( MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS ); + default: + MBEDTLS_SSL_DEBUG_RET( 1, "f_async_decrypt_start", ret ); + return( ret ); + } + } +#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ + + if( ! mbedtls_pk_can_do( private_key, MBEDTLS_PK_RSA ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no RSA private key" ) ); + return( MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED ); + } + + ret = mbedtls_pk_decrypt( private_key, p, len, + peer_pms, peer_pmslen, peer_pmssize, + ssl->conf->f_rng, ssl->conf->p_rng ); + return( ret ); +} + +static int ssl_parse_encrypted_pms( mbedtls_ssl_context *ssl, + const unsigned char *p, + const unsigned char *end, + size_t pms_offset ) +{ + int ret; + unsigned char *pms = ssl->handshake->premaster + pms_offset; + unsigned char ver[2]; + unsigned char fake_pms[48], peer_pms[48]; + unsigned char mask; + size_t i, peer_pmslen; + unsigned int diff; + + /* In case of a failure in decryption, the decryption may write less than + * 2 bytes of output, but we always read the first two bytes. It doesn't + * matter in the end because diff will be nonzero in that case due to + * peer_pmslen being less than 48, and we only care whether diff is 0. + * But do initialize peer_pms for robustness anyway. This also makes + * memory analyzers happy (don't access uninitialized memory, even + * if it's an unsigned char). */ + peer_pms[0] = peer_pms[1] = ~0; + + ret = ssl_decrypt_encrypted_pms( ssl, p, end, + peer_pms, + &peer_pmslen, + sizeof( peer_pms ) ); + +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) + if ( ret == MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS ) + return( ret ); +#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ + mbedtls_ssl_write_version( ssl->handshake->max_major_ver, - ssl->handshake->max_minor_ver, - ssl->conf->transport, ver ); + ssl->handshake->max_minor_ver, + ssl->conf->transport, ver ); + + /* Avoid data-dependent branches while checking for invalid + * padding, to protect against timing-based Bleichenbacher-type + * attacks. */ + diff = (unsigned int) ret; + diff |= peer_pmslen ^ 48; + diff |= peer_pms[0] ^ ver[0]; + diff |= peer_pms[1] ^ ver[1]; + + /* mask = diff ? 0xff : 0x00 using bit operations to avoid branches */ + /* MSVC has a warning about unary minus on unsigned, but this is + * well-defined and precisely what we want to do here */ +#if defined(_MSC_VER) +#pragma warning( push ) +#pragma warning( disable : 4146 ) +#endif + mask = - ( ( diff | - diff ) >> ( sizeof( unsigned int ) * 8 - 1 ) ); +#if defined(_MSC_VER) +#pragma warning( pop ) +#endif /* * Protection against Bleichenbacher's attack: invalid PKCS#1 v1.5 padding * must not cause the connection to end immediately; instead, send a * bad_record_mac later in the handshake. - * Also, avoid data-dependant branches here to protect against - * timing-based variants. + * To protect against timing-based variants of the attack, we must + * not have any branch that depends on whether the decryption was + * successful. In particular, always generate the fake premaster secret, + * regardless of whether it will ultimately influence the output or not. */ ret = ssl->conf->f_rng( ssl->conf->p_rng, fake_pms, sizeof( fake_pms ) ); if( ret != 0 ) + { + /* It's ok to abort on an RNG failure, since this does not reveal + * anything about the RSA decryption. */ return( ret ); - - ret = mbedtls_pk_decrypt( mbedtls_ssl_own_key( ssl ), p, len, - peer_pms, &peer_pmslen, - sizeof( peer_pms ), - ssl->conf->f_rng, ssl->conf->p_rng ); - - diff = (unsigned int) ret; - diff |= peer_pmslen ^ 48; - diff |= peer_pms[0] ^ ver[0]; - diff |= peer_pms[1] ^ ver[1]; + } #if defined(MBEDTLS_SSL_DEBUG_ALL) if( diff != 0 ) @@ -3358,18 +3609,8 @@ static int ssl_parse_encrypted_pms( mbedtls_ssl_context *ssl, } ssl->handshake->pmslen = 48; - /* mask = diff ? 0xff : 0x00 using bit operations to avoid branches */ - /* MSVC has a warning about unary minus on unsigned, but this is - * well-defined and precisely what we want to do here */ -#if defined(_MSC_VER) -#pragma warning( push ) -#pragma warning( disable : 4146 ) -#endif - mask = - ( ( diff | - diff ) >> ( sizeof( unsigned int ) * 8 - 1 ) ); -#if defined(_MSC_VER) -#pragma warning( pop ) -#endif - + /* Set pms to either the true or the fake PMS, without + * data-dependent branches. */ for( i = 0; i < ssl->handshake->pmslen; i++ ) pms[i] = ( mask & fake_pms[i] ) | ( (~mask) & peer_pms[i] ); @@ -3451,6 +3692,20 @@ static int ssl_parse_client_key_exchange( mbedtls_ssl_context *ssl ) MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse client key exchange" ) ); +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) && \ + ( defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) ) + if( ( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA ) && + ( ssl->handshake->async_in_progress != 0 ) ) + { + /* We've already read a record and there is an asynchronous + * operation in progress to decrypt it. So skip reading the + * record. */ + MBEDTLS_SSL_DEBUG_MSG( 3, ( "will resume decryption of previously-read record" ) ); + } + else +#endif if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); @@ -3563,6 +3818,19 @@ static int ssl_parse_client_key_exchange( mbedtls_ssl_context *ssl ) #if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK ) { +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) + if ( ssl->handshake->async_in_progress != 0 ) + { + /* There is an asynchronous operation in progress to + * decrypt the encrypted premaster secret, so skip + * directly to resuming this operation. */ + MBEDTLS_SSL_DEBUG_MSG( 3, ( "PSK identity already parsed" ) ); + /* Update p to skip the PSK identity. ssl_parse_encrypted_pms + * won't actually use it, but maintain p anyway for robustness. */ + p += ssl->conf->psk_identity_len + 2; + } + else +#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ if( ( ret = ssl_parse_client_psk_identity( ssl, &p, end ) ) != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, ( "ssl_parse_client_psk_identity" ), ret ); @@ -3750,7 +4018,10 @@ static int ssl_parse_certificate_verify( mbedtls_ssl_context *ssl ) /* Read the message without adding it to the checksum */ do { - if( ( ret = mbedtls_ssl_read_record_layer( ssl ) ) != 0 ) + do ret = mbedtls_ssl_read_record_layer( ssl ); + while( ret == MBEDTLS_ERR_SSL_CONTINUE_PROCESSING ); + + if( ret != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, ( "mbedtls_ssl_read_record_layer" ), ret ); return( ret ); @@ -3758,7 +4029,8 @@ static int ssl_parse_certificate_verify( mbedtls_ssl_context *ssl ) ret = mbedtls_ssl_handle_message_type( ssl ); - } while( MBEDTLS_ERR_SSL_NON_FATAL == ret ); + } while( MBEDTLS_ERR_SSL_NON_FATAL == ret || + MBEDTLS_ERR_SSL_CONTINUE_PROCESSING == ret ); if( 0 != ret ) { @@ -3928,7 +4200,7 @@ static int ssl_write_new_session_ticket( mbedtls_ssl_context *ssl ) if( ( ret = ssl->conf->f_ticket_write( ssl->conf->p_ticket, ssl->session_negotiate, ssl->out_msg + 10, - ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN, + ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN, &tlen, &lifetime ) ) != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_ticket_write", ret ); diff --git a/thirdparty/mbedtls/library/ssl_ticket.c b/thirdparty/mbedtls/library/ssl_ticket.c index 4d9116d214..a2b304869e 100644 --- a/thirdparty/mbedtls/library/ssl_ticket.c +++ b/thirdparty/mbedtls/library/ssl_ticket.c @@ -36,14 +36,10 @@ #endif #include "mbedtls/ssl_ticket.h" +#include "mbedtls/platform_util.h" #include <string.h> -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize( void *v, size_t n ) { - volatile unsigned char *p = v; while( n-- ) *p++ = 0; -} - /* * Initialze context */ @@ -83,7 +79,7 @@ static int ssl_ticket_gen_key( mbedtls_ssl_ticket_context *ctx, mbedtls_cipher_get_key_bitlen( &key->ctx ), MBEDTLS_ENCRYPT ); - mbedtls_zeroize( buf, sizeof( buf ) ); + mbedtls_platform_zeroize( buf, sizeof( buf ) ); return( ret ); } @@ -483,7 +479,7 @@ void mbedtls_ssl_ticket_free( mbedtls_ssl_ticket_context *ctx ) mbedtls_mutex_free( &ctx->mutex ); #endif - mbedtls_zeroize( ctx, sizeof( mbedtls_ssl_ticket_context ) ); + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_ssl_ticket_context ) ); } #endif /* MBEDTLS_SSL_TICKET_C */ diff --git a/thirdparty/mbedtls/library/ssl_tls.c b/thirdparty/mbedtls/library/ssl_tls.c index 236e52d767..91f96c8ab6 100644 --- a/thirdparty/mbedtls/library/ssl_tls.c +++ b/thirdparty/mbedtls/library/ssl_tls.c @@ -46,6 +46,7 @@ #include "mbedtls/debug.h" #include "mbedtls/ssl.h" #include "mbedtls/ssl_internal.h" +#include "mbedtls/platform_util.h" #include <string.h> @@ -53,11 +54,6 @@ #include "mbedtls/oid.h" #endif -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize( void *v, size_t n ) { - volatile unsigned char *p = v; while( n-- ) *p++ = 0; -} - /* Length of the "epoch" field in the record header */ static inline size_t ssl_ep_len( const mbedtls_ssl_context *ssl ) { @@ -145,14 +141,24 @@ static void ssl_reset_retransmit_timeout( mbedtls_ssl_context *ssl ) * } MaxFragmentLength; * and we add 0 -> extension unused */ -static unsigned int mfl_code_to_length[MBEDTLS_SSL_MAX_FRAG_LEN_INVALID] = +static unsigned int ssl_mfl_code_to_length( int mfl ) { - MBEDTLS_SSL_MAX_CONTENT_LEN, /* MBEDTLS_SSL_MAX_FRAG_LEN_NONE */ - 512, /* MBEDTLS_SSL_MAX_FRAG_LEN_512 */ - 1024, /* MBEDTLS_SSL_MAX_FRAG_LEN_1024 */ - 2048, /* MBEDTLS_SSL_MAX_FRAG_LEN_2048 */ - 4096, /* MBEDTLS_SSL_MAX_FRAG_LEN_4096 */ -}; + switch( mfl ) + { + case MBEDTLS_SSL_MAX_FRAG_LEN_NONE: + return ( MBEDTLS_TLS_EXT_ADV_CONTENT_LEN ); + case MBEDTLS_SSL_MAX_FRAG_LEN_512: + return 512; + case MBEDTLS_SSL_MAX_FRAG_LEN_1024: + return 1024; + case MBEDTLS_SSL_MAX_FRAG_LEN_2048: + return 2048; + case MBEDTLS_SSL_MAX_FRAG_LEN_4096: + return 4096; + default: + return ( MBEDTLS_TLS_EXT_ADV_CONTENT_LEN ); + } +} #endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ #if defined(MBEDTLS_SSL_CLI_C) @@ -269,8 +275,8 @@ exit: mbedtls_md5_free( &md5 ); mbedtls_sha1_free( &sha1 ); - mbedtls_zeroize( padding, sizeof( padding ) ); - mbedtls_zeroize( sha1sum, sizeof( sha1sum ) ); + mbedtls_platform_zeroize( padding, sizeof( padding ) ); + mbedtls_platform_zeroize( sha1sum, sizeof( sha1sum ) ); return( ret ); } @@ -367,8 +373,8 @@ static int tls1_prf( const unsigned char *secret, size_t slen, mbedtls_md_free( &md_ctx ); - mbedtls_zeroize( tmp, sizeof( tmp ) ); - mbedtls_zeroize( h_i, sizeof( h_i ) ); + mbedtls_platform_zeroize( tmp, sizeof( tmp ) ); + mbedtls_platform_zeroize( h_i, sizeof( h_i ) ); return( 0 ); } @@ -432,8 +438,8 @@ static int tls_prf_generic( mbedtls_md_type_t md_type, mbedtls_md_free( &md_ctx ); - mbedtls_zeroize( tmp, sizeof( tmp ) ); - mbedtls_zeroize( h_i, sizeof( h_i ) ); + mbedtls_platform_zeroize( tmp, sizeof( tmp ) ); + mbedtls_platform_zeroize( h_i, sizeof( h_i ) ); return( 0 ); } @@ -642,7 +648,8 @@ int mbedtls_ssl_derive_keys( mbedtls_ssl_context *ssl ) return( ret ); } - mbedtls_zeroize( handshake->premaster, sizeof(handshake->premaster) ); + mbedtls_platform_zeroize( handshake->premaster, + sizeof(handshake->premaster) ); } else MBEDTLS_SSL_DEBUG_MSG( 3, ( "no premaster (session resumed)" ) ); @@ -653,7 +660,7 @@ int mbedtls_ssl_derive_keys( mbedtls_ssl_context *ssl ) memcpy( tmp, handshake->randbytes, 64 ); memcpy( handshake->randbytes, tmp + 32, 32 ); memcpy( handshake->randbytes + 32, tmp, 32 ); - mbedtls_zeroize( tmp, sizeof( tmp ) ); + mbedtls_platform_zeroize( tmp, sizeof( tmp ) ); /* * SSLv3: @@ -681,7 +688,8 @@ int mbedtls_ssl_derive_keys( mbedtls_ssl_context *ssl ) MBEDTLS_SSL_DEBUG_BUF( 4, "random bytes", handshake->randbytes, 64 ); MBEDTLS_SSL_DEBUG_BUF( 4, "key block", keyblk, 256 ); - mbedtls_zeroize( handshake->randbytes, sizeof( handshake->randbytes ) ); + mbedtls_platform_zeroize( handshake->randbytes, + sizeof( handshake->randbytes ) ); /* * Determine the appropriate key, IV and MAC length. @@ -690,18 +698,32 @@ int mbedtls_ssl_derive_keys( mbedtls_ssl_context *ssl ) transform->keylen = cipher_info->key_bitlen / 8; if( cipher_info->mode == MBEDTLS_MODE_GCM || - cipher_info->mode == MBEDTLS_MODE_CCM ) + cipher_info->mode == MBEDTLS_MODE_CCM || + cipher_info->mode == MBEDTLS_MODE_CHACHAPOLY ) { + size_t taglen, explicit_ivlen; + transform->maclen = 0; mac_key_len = 0; + /* All modes haves 96-bit IVs; + * GCM and CCM has 4 implicit and 8 explicit bytes + * ChachaPoly has all 12 bytes implicit + */ transform->ivlen = 12; - transform->fixed_ivlen = 4; + if( cipher_info->mode == MBEDTLS_MODE_CHACHAPOLY ) + transform->fixed_ivlen = 12; + else + transform->fixed_ivlen = 4; - /* Minimum length is expicit IV + tag */ - transform->minlen = transform->ivlen - transform->fixed_ivlen - + ( transform->ciphersuite_info->flags & - MBEDTLS_CIPHERSUITE_SHORT_TAG ? 8 : 16 ); + /* All modes have 128-bit tags, except CCM_8 (ciphersuite flag) */ + taglen = transform->ciphersuite_info->flags & + MBEDTLS_CIPHERSUITE_SHORT_TAG ? 8 : 16; + + + /* Minimum length of encrypted record */ + explicit_ivlen = transform->ivlen - transform->fixed_ivlen; + transform->minlen = explicit_ivlen + taglen; } else { @@ -855,8 +877,13 @@ int mbedtls_ssl_derive_keys( mbedtls_ssl_context *ssl ) defined(MBEDTLS_SSL_PROTO_TLS1_2) if( ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_1 ) { - mbedtls_md_hmac_starts( &transform->md_ctx_enc, mac_enc, mac_key_len ); - mbedtls_md_hmac_starts( &transform->md_ctx_dec, mac_dec, mac_key_len ); + /* For HMAC-based ciphersuites, initialize the HMAC transforms. + For AEAD-based ciphersuites, there is nothing to do here. */ + if( mac_key_len != 0 ) + { + mbedtls_md_hmac_starts( &transform->md_ctx_enc, mac_enc, mac_key_len ); + mbedtls_md_hmac_starts( &transform->md_ctx_dec, mac_dec, mac_key_len ); + } } else #endif @@ -943,7 +970,7 @@ int mbedtls_ssl_derive_keys( mbedtls_ssl_context *ssl ) } #endif /* MBEDTLS_CIPHER_MODE_CBC */ - mbedtls_zeroize( keyblk, sizeof( keyblk ) ); + mbedtls_platform_zeroize( keyblk, sizeof( keyblk ) ); #if defined(MBEDTLS_ZLIB_SUPPORT) // Initialize compression @@ -953,11 +980,11 @@ int mbedtls_ssl_derive_keys( mbedtls_ssl_context *ssl ) if( ssl->compress_buf == NULL ) { MBEDTLS_SSL_DEBUG_MSG( 3, ( "Allocating compression buffer" ) ); - ssl->compress_buf = mbedtls_calloc( 1, MBEDTLS_SSL_BUFFER_LEN ); + ssl->compress_buf = mbedtls_calloc( 1, MBEDTLS_SSL_COMPRESS_BUFFER_LEN ); if( ssl->compress_buf == NULL ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc(%d bytes) failed", - MBEDTLS_SSL_BUFFER_LEN ) ); + MBEDTLS_SSL_COMPRESS_BUFFER_LEN ) ); return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); } } @@ -1148,6 +1175,9 @@ int mbedtls_ssl_psk_derive_premaster( mbedtls_ssl_context *ssl, mbedtls_key_exch * other_secret already set by the ClientKeyExchange message, * and is 48 bytes long */ + if( end - p < 2 ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + *p++ = 0; *p++ = 48; p += 48; @@ -1269,10 +1299,31 @@ static void ssl_mac( mbedtls_md_context_t *md_ctx, #if defined(MBEDTLS_ARC4_C) || defined(MBEDTLS_CIPHER_NULL_CIPHER) || \ ( defined(MBEDTLS_CIPHER_MODE_CBC) && \ - ( defined(MBEDTLS_AES_C) || defined(MBEDTLS_CAMELLIA_C) ) ) + ( defined(MBEDTLS_AES_C) || defined(MBEDTLS_CAMELLIA_C) || defined(MBEDTLS_ARIA_C)) ) #define SSL_SOME_MODES_USE_MAC #endif +/* The function below is only used in the Lucky 13 counter-measure in + * ssl_decrypt_buf(). These are the defines that guard the call site. */ +#if defined(SSL_SOME_MODES_USE_MAC) && \ + ( defined(MBEDTLS_SSL_PROTO_TLS1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_2) ) +/* This function makes sure every byte in the memory region is accessed + * (in ascending addresses order) */ +static void ssl_read_memory( unsigned char *p, size_t len ) +{ + unsigned char acc = 0; + volatile unsigned char force; + + for( ; len != 0; p++, len-- ) + acc ^= *p; + + force = acc; + (void) force; +} +#endif /* SSL_SOME_MODES_USE_MAC && ( TLS1 || TLS1_1 || TLS1_2 ) */ + /* * Encryption/decryption functions */ @@ -1294,11 +1345,11 @@ static int ssl_encrypt_buf( mbedtls_ssl_context *ssl ) MBEDTLS_SSL_DEBUG_BUF( 4, "before encrypt: output payload", ssl->out_msg, ssl->out_msglen ); - if( ssl->out_msglen > MBEDTLS_SSL_MAX_CONTENT_LEN ) + if( ssl->out_msglen > MBEDTLS_SSL_OUT_CONTENT_LEN ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "Record content %u too large, maximum %d", (unsigned) ssl->out_msglen, - MBEDTLS_SSL_MAX_CONTENT_LEN ) ); + MBEDTLS_SSL_OUT_CONTENT_LEN ) ); return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); } @@ -1391,17 +1442,26 @@ static int ssl_encrypt_buf( mbedtls_ssl_context *ssl ) } else #endif /* MBEDTLS_ARC4_C || MBEDTLS_CIPHER_NULL_CIPHER */ -#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CCM_C) +#if defined(MBEDTLS_GCM_C) || \ + defined(MBEDTLS_CCM_C) || \ + defined(MBEDTLS_CHACHAPOLY_C) if( mode == MBEDTLS_MODE_GCM || - mode == MBEDTLS_MODE_CCM ) + mode == MBEDTLS_MODE_CCM || + mode == MBEDTLS_MODE_CHACHAPOLY ) { int ret; size_t enc_msglen, olen; unsigned char *enc_msg; unsigned char add_data[13]; - unsigned char taglen = ssl->transform_out->ciphersuite_info->flags & + unsigned char iv[12]; + mbedtls_ssl_transform *transform = ssl->transform_out; + unsigned char taglen = transform->ciphersuite_info->flags & MBEDTLS_CIPHERSUITE_SHORT_TAG ? 8 : 16; + size_t explicit_ivlen = transform->ivlen - transform->fixed_ivlen; + /* + * Prepare additional authenticated data + */ memcpy( add_data, ssl->out_ctr, 8 ); add_data[8] = ssl->out_msgtype; mbedtls_ssl_write_version( ssl->major_ver, ssl->minor_ver, @@ -1409,44 +1469,57 @@ static int ssl_encrypt_buf( mbedtls_ssl_context *ssl ) add_data[11] = ( ssl->out_msglen >> 8 ) & 0xFF; add_data[12] = ssl->out_msglen & 0xFF; - MBEDTLS_SSL_DEBUG_BUF( 4, "additional data used for AEAD", - add_data, 13 ); + MBEDTLS_SSL_DEBUG_BUF( 4, "additional data for AEAD", add_data, 13 ); /* * Generate IV */ - if( ssl->transform_out->ivlen - ssl->transform_out->fixed_ivlen != 8 ) + if( transform->ivlen == 12 && transform->fixed_ivlen == 4 ) + { + /* GCM and CCM: fixed || explicit (=seqnum) */ + memcpy( iv, transform->iv_enc, transform->fixed_ivlen ); + memcpy( iv + transform->fixed_ivlen, ssl->out_ctr, 8 ); + memcpy( ssl->out_iv, ssl->out_ctr, 8 ); + + } + else if( transform->ivlen == 12 && transform->fixed_ivlen == 12 ) + { + /* ChachaPoly: fixed XOR sequence number */ + unsigned char i; + + memcpy( iv, transform->iv_enc, transform->fixed_ivlen ); + + for( i = 0; i < 8; i++ ) + iv[i+4] ^= ssl->out_ctr[i]; + } + else { /* Reminder if we ever add an AEAD mode with a different size */ MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); } - memcpy( ssl->transform_out->iv_enc + ssl->transform_out->fixed_ivlen, - ssl->out_ctr, 8 ); - memcpy( ssl->out_iv, ssl->out_ctr, 8 ); - - MBEDTLS_SSL_DEBUG_BUF( 4, "IV used", ssl->out_iv, - ssl->transform_out->ivlen - ssl->transform_out->fixed_ivlen ); + MBEDTLS_SSL_DEBUG_BUF( 4, "IV used (internal)", + iv, transform->ivlen ); + MBEDTLS_SSL_DEBUG_BUF( 4, "IV used (transmitted)", + ssl->out_iv, explicit_ivlen ); /* - * Fix pointer positions and message length with added IV + * Fix message length with added IV */ enc_msg = ssl->out_msg; enc_msglen = ssl->out_msglen; - ssl->out_msglen += ssl->transform_out->ivlen - - ssl->transform_out->fixed_ivlen; + ssl->out_msglen += explicit_ivlen; MBEDTLS_SSL_DEBUG_MSG( 3, ( "before encrypt: msglen = %d, " - "including %d bytes of padding", - ssl->out_msglen, 0 ) ); + "including 0 bytes of padding", + ssl->out_msglen ) ); /* * Encrypt and authenticate */ - if( ( ret = mbedtls_cipher_auth_encrypt( &ssl->transform_out->cipher_ctx_enc, - ssl->transform_out->iv_enc, - ssl->transform_out->ivlen, + if( ( ret = mbedtls_cipher_auth_encrypt( &transform->cipher_ctx_enc, + iv, transform->ivlen, add_data, 13, enc_msg, enc_msglen, enc_msg, &olen, @@ -1470,7 +1543,7 @@ static int ssl_encrypt_buf( mbedtls_ssl_context *ssl ) else #endif /* MBEDTLS_GCM_C || MBEDTLS_CCM_C */ #if defined(MBEDTLS_CIPHER_MODE_CBC) && \ - ( defined(MBEDTLS_AES_C) || defined(MBEDTLS_CAMELLIA_C) ) + ( defined(MBEDTLS_AES_C) || defined(MBEDTLS_CAMELLIA_C) || defined(MBEDTLS_ARIA_C) ) if( mode == MBEDTLS_MODE_CBC ) { int ret; @@ -1586,7 +1659,7 @@ static int ssl_encrypt_buf( mbedtls_ssl_context *ssl ) } else #endif /* MBEDTLS_CIPHER_MODE_CBC && - ( MBEDTLS_AES_C || MBEDTLS_CAMELLIA_C ) */ + ( MBEDTLS_AES_C || MBEDTLS_CAMELLIA_C || MBEDTLS_ARIA_C ) */ { MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); @@ -1606,7 +1679,6 @@ static int ssl_encrypt_buf( mbedtls_ssl_context *ssl ) static int ssl_decrypt_buf( mbedtls_ssl_context *ssl ) { - size_t i; mbedtls_cipher_mode_t mode; int auth_done = 0; #if defined(SSL_SOME_MODES_USE_MAC) @@ -1656,20 +1728,27 @@ static int ssl_decrypt_buf( mbedtls_ssl_context *ssl ) } else #endif /* MBEDTLS_ARC4_C || MBEDTLS_CIPHER_NULL_CIPHER */ -#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CCM_C) +#if defined(MBEDTLS_GCM_C) || \ + defined(MBEDTLS_CCM_C) || \ + defined(MBEDTLS_CHACHAPOLY_C) if( mode == MBEDTLS_MODE_GCM || - mode == MBEDTLS_MODE_CCM ) + mode == MBEDTLS_MODE_CCM || + mode == MBEDTLS_MODE_CHACHAPOLY ) { int ret; size_t dec_msglen, olen; unsigned char *dec_msg; unsigned char *dec_msg_result; unsigned char add_data[13]; - unsigned char taglen = ssl->transform_in->ciphersuite_info->flags & + unsigned char iv[12]; + mbedtls_ssl_transform *transform = ssl->transform_in; + unsigned char taglen = transform->ciphersuite_info->flags & MBEDTLS_CIPHERSUITE_SHORT_TAG ? 8 : 16; - size_t explicit_iv_len = ssl->transform_in->ivlen - - ssl->transform_in->fixed_ivlen; + size_t explicit_iv_len = transform->ivlen - transform->fixed_ivlen; + /* + * Compute and update sizes + */ if( ssl->in_msglen < explicit_iv_len + taglen ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "msglen (%d) < explicit_iv_len (%d) " @@ -1683,6 +1762,9 @@ static int ssl_decrypt_buf( mbedtls_ssl_context *ssl ) dec_msg_result = ssl->in_msg; ssl->in_msglen = dec_msglen; + /* + * Prepare additional authenticated data + */ memcpy( add_data, ssl->in_ctr, 8 ); add_data[8] = ssl->in_msgtype; mbedtls_ssl_write_version( ssl->major_ver, ssl->minor_ver, @@ -1690,23 +1772,43 @@ static int ssl_decrypt_buf( mbedtls_ssl_context *ssl ) add_data[11] = ( ssl->in_msglen >> 8 ) & 0xFF; add_data[12] = ssl->in_msglen & 0xFF; - MBEDTLS_SSL_DEBUG_BUF( 4, "additional data used for AEAD", - add_data, 13 ); + MBEDTLS_SSL_DEBUG_BUF( 4, "additional data for AEAD", add_data, 13 ); + + /* + * Prepare IV + */ + if( transform->ivlen == 12 && transform->fixed_ivlen == 4 ) + { + /* GCM and CCM: fixed || explicit (transmitted) */ + memcpy( iv, transform->iv_dec, transform->fixed_ivlen ); + memcpy( iv + transform->fixed_ivlen, ssl->in_iv, 8 ); + + } + else if( transform->ivlen == 12 && transform->fixed_ivlen == 12 ) + { + /* ChachaPoly: fixed XOR sequence number */ + unsigned char i; + + memcpy( iv, transform->iv_dec, transform->fixed_ivlen ); - memcpy( ssl->transform_in->iv_dec + ssl->transform_in->fixed_ivlen, - ssl->in_iv, - ssl->transform_in->ivlen - ssl->transform_in->fixed_ivlen ); + for( i = 0; i < 8; i++ ) + iv[i+4] ^= ssl->in_ctr[i]; + } + else + { + /* Reminder if we ever add an AEAD mode with a different size */ + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } - MBEDTLS_SSL_DEBUG_BUF( 4, "IV used", ssl->transform_in->iv_dec, - ssl->transform_in->ivlen ); + MBEDTLS_SSL_DEBUG_BUF( 4, "IV used", iv, transform->ivlen ); MBEDTLS_SSL_DEBUG_BUF( 4, "TAG used", dec_msg + dec_msglen, taglen ); /* * Decrypt and authenticate */ if( ( ret = mbedtls_cipher_auth_decrypt( &ssl->transform_in->cipher_ctx_dec, - ssl->transform_in->iv_dec, - ssl->transform_in->ivlen, + iv, transform->ivlen, add_data, 13, dec_msg, dec_msglen, dec_msg_result, &olen, @@ -1730,7 +1832,7 @@ static int ssl_decrypt_buf( mbedtls_ssl_context *ssl ) else #endif /* MBEDTLS_GCM_C || MBEDTLS_CCM_C */ #if defined(MBEDTLS_CIPHER_MODE_CBC) && \ - ( defined(MBEDTLS_AES_C) || defined(MBEDTLS_CAMELLIA_C) ) + ( defined(MBEDTLS_AES_C) || defined(MBEDTLS_CAMELLIA_C) || defined(MBEDTLS_ARIA_C) ) if( mode == MBEDTLS_MODE_CBC ) { /* @@ -1824,6 +1926,7 @@ static int ssl_decrypt_buf( mbedtls_ssl_context *ssl ) */ if( ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_2 ) { + unsigned char i; dec_msglen -= ssl->transform_in->ivlen; ssl->in_msglen -= ssl->transform_in->ivlen; @@ -1897,27 +2000,28 @@ static int ssl_decrypt_buf( mbedtls_ssl_context *ssl ) * and fake check up to 256 bytes of padding */ size_t pad_count = 0, real_count = 1; - size_t padding_idx = ssl->in_msglen - padlen - 1; + size_t padding_idx = ssl->in_msglen - padlen; + size_t i; /* * Padding is guaranteed to be incorrect if: - * 1. padlen >= ssl->in_msglen + * 1. padlen > ssl->in_msglen * - * 2. padding_idx >= MBEDTLS_SSL_MAX_CONTENT_LEN + + * 2. padding_idx > MBEDTLS_SSL_IN_CONTENT_LEN + * ssl->transform_in->maclen * * In both cases we reset padding_idx to a safe value (0) to * prevent out-of-buffer reads. */ - correct &= ( ssl->in_msglen >= padlen + 1 ); - correct &= ( padding_idx < MBEDTLS_SSL_MAX_CONTENT_LEN + + correct &= ( padlen <= ssl->in_msglen ); + correct &= ( padding_idx <= MBEDTLS_SSL_IN_CONTENT_LEN + ssl->transform_in->maclen ); padding_idx *= correct; - for( i = 1; i <= 256; i++ ) + for( i = 0; i < 256; i++ ) { - real_count &= ( i <= padlen ); + real_count &= ( i < padlen ); pad_count += real_count * ( ssl->in_msg[padding_idx + i] == padlen - 1 ); } @@ -1942,14 +2046,16 @@ static int ssl_decrypt_buf( mbedtls_ssl_context *ssl ) } else #endif /* MBEDTLS_CIPHER_MODE_CBC && - ( MBEDTLS_AES_C || MBEDTLS_CAMELLIA_C ) */ + ( MBEDTLS_AES_C || MBEDTLS_CAMELLIA_C || MBEDTLS_ARIA_C ) */ { MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); } +#if defined(MBEDTLS_SSL_DEBUG_ALL) MBEDTLS_SSL_DEBUG_BUF( 4, "raw buffer after decryption", ssl->in_msg, ssl->in_msglen ); +#endif /* * Authenticate if not done yet. @@ -1982,20 +2088,69 @@ static int ssl_decrypt_buf( mbedtls_ssl_context *ssl ) { /* * Process MAC and always update for padlen afterwards to make - * total time independent of padlen - * - * extra_run compensates MAC check for padlen + * total time independent of padlen. * * Known timing attacks: * - Lucky Thirteen (http://www.isg.rhul.ac.uk/tls/TLStiming.pdf) * - * We use ( ( Lx + 8 ) / 64 ) to handle 'negative Lx' values - * correctly. (We round down instead of up, so -56 is the correct - * value for our calculations instead of -55) + * To compensate for different timings for the MAC calculation + * depending on how much padding was removed (which is determined + * by padlen), process extra_run more blocks through the hash + * function. + * + * The formula in the paper is + * extra_run = ceil( (L1-55) / 64 ) - ceil( (L2-55) / 64 ) + * where L1 is the size of the header plus the decrypted message + * plus CBC padding and L2 is the size of the header plus the + * decrypted message. This is for an underlying hash function + * with 64-byte blocks. + * We use ( (Lx+8) / 64 ) to handle 'negative Lx' values + * correctly. We round down instead of up, so -56 is the correct + * value for our calculations instead of -55. + * + * Repeat the formula rather than defining a block_size variable. + * This avoids requiring division by a variable at runtime + * (which would be marginally less efficient and would require + * linking an extra division function in some builds). */ size_t j, extra_run = 0; - extra_run = ( 13 + ssl->in_msglen + padlen + 8 ) / 64 - - ( 13 + ssl->in_msglen + 8 ) / 64; + + /* + * The next two sizes are the minimum and maximum values of + * in_msglen over all padlen values. + * + * They're independent of padlen, since we previously did + * in_msglen -= padlen. + * + * Note that max_len + maclen is never more than the buffer + * length, as we previously did in_msglen -= maclen too. + */ + const size_t max_len = ssl->in_msglen + padlen; + const size_t min_len = ( max_len > 256 ) ? max_len - 256 : 0; + + switch( ssl->transform_in->ciphersuite_info->mac ) + { +#if defined(MBEDTLS_MD5_C) || defined(MBEDTLS_SHA1_C) || \ + defined(MBEDTLS_SHA256_C) + case MBEDTLS_MD_MD5: + case MBEDTLS_MD_SHA1: + case MBEDTLS_MD_SHA256: + /* 8 bytes of message size, 64-byte compression blocks */ + extra_run = ( 13 + ssl->in_msglen + padlen + 8 ) / 64 - + ( 13 + ssl->in_msglen + 8 ) / 64; + break; +#endif +#if defined(MBEDTLS_SHA512_C) + case MBEDTLS_MD_SHA384: + /* 16 bytes of message size, 128-byte compression blocks */ + extra_run = ( 13 + ssl->in_msglen + padlen + 16 ) / 128 - + ( 13 + ssl->in_msglen + 16 ) / 128; + break; +#endif + default: + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } extra_run &= correct * 0xFF; @@ -2004,12 +2159,25 @@ static int ssl_decrypt_buf( mbedtls_ssl_context *ssl ) mbedtls_md_hmac_update( &ssl->transform_in->md_ctx_dec, ssl->in_len, 2 ); mbedtls_md_hmac_update( &ssl->transform_in->md_ctx_dec, ssl->in_msg, ssl->in_msglen ); + /* Make sure we access everything even when padlen > 0. This + * makes the synchronisation requirements for just-in-time + * Prime+Probe attacks much tighter and hopefully impractical. */ + ssl_read_memory( ssl->in_msg + ssl->in_msglen, padlen ); mbedtls_md_hmac_finish( &ssl->transform_in->md_ctx_dec, mac_expect ); - /* Call mbedtls_md_process at least once due to cache attacks */ + + /* Call mbedtls_md_process at least once due to cache attacks + * that observe whether md_process() was called of not */ for( j = 0; j < extra_run + 1; j++ ) mbedtls_md_process( &ssl->transform_in->md_ctx_dec, ssl->in_msg ); mbedtls_md_hmac_reset( &ssl->transform_in->md_ctx_dec ); + + /* Make sure we access all the memory that could contain the MAC, + * before we check it in the next code block. This makes the + * synchronisation requirements for just-in-time Prime+Probe + * attacks much tighter and hopefully impractical. */ + ssl_read_memory( ssl->in_msg + min_len, + max_len - min_len + ssl->transform_in->maclen ); } else #endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 || \ @@ -2019,9 +2187,11 @@ static int ssl_decrypt_buf( mbedtls_ssl_context *ssl ) return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); } +#if defined(MBEDTLS_SSL_DEBUG_ALL) MBEDTLS_SSL_DEBUG_BUF( 4, "expected mac", mac_expect, ssl->transform_in->maclen ); MBEDTLS_SSL_DEBUG_BUF( 4, "message mac", ssl->in_msg + ssl->in_msglen, ssl->transform_in->maclen ); +#endif if( mbedtls_ssl_safer_memcmp( ssl->in_msg + ssl->in_msglen, mac_expect, ssl->transform_in->maclen ) != 0 ) @@ -2050,6 +2220,16 @@ static int ssl_decrypt_buf( mbedtls_ssl_context *ssl ) if( ssl->in_msglen == 0 ) { +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 + && ssl->in_msgtype != MBEDTLS_SSL_MSG_APPLICATION_DATA ) + { + /* TLS v1.2 explicitly disallows zero-length messages which are not application data */ + MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid zero-length message type: %d", ssl->in_msgtype ) ); + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + ssl->nb_zero++; /* @@ -2074,6 +2254,7 @@ static int ssl_decrypt_buf( mbedtls_ssl_context *ssl ) else #endif { + unsigned char i; for( i = 8; i > ssl_ep_len( ssl ); i-- ) if( ++ssl->in_ctr[i - 1] != 0 ) break; @@ -2103,6 +2284,7 @@ static int ssl_compress_buf( mbedtls_ssl_context *ssl ) { int ret; unsigned char *msg_post = ssl->out_msg; + ptrdiff_t bytes_written = ssl->out_msg - ssl->out_buf; size_t len_pre = ssl->out_msglen; unsigned char *msg_pre = ssl->compress_buf; @@ -2122,7 +2304,7 @@ static int ssl_compress_buf( mbedtls_ssl_context *ssl ) ssl->transform_out->ctx_deflate.next_in = msg_pre; ssl->transform_out->ctx_deflate.avail_in = len_pre; ssl->transform_out->ctx_deflate.next_out = msg_post; - ssl->transform_out->ctx_deflate.avail_out = MBEDTLS_SSL_BUFFER_LEN; + ssl->transform_out->ctx_deflate.avail_out = MBEDTLS_SSL_OUT_BUFFER_LEN - bytes_written; ret = deflate( &ssl->transform_out->ctx_deflate, Z_SYNC_FLUSH ); if( ret != Z_OK ) @@ -2131,8 +2313,8 @@ static int ssl_compress_buf( mbedtls_ssl_context *ssl ) return( MBEDTLS_ERR_SSL_COMPRESSION_FAILED ); } - ssl->out_msglen = MBEDTLS_SSL_BUFFER_LEN - - ssl->transform_out->ctx_deflate.avail_out; + ssl->out_msglen = MBEDTLS_SSL_OUT_BUFFER_LEN - + ssl->transform_out->ctx_deflate.avail_out - bytes_written; MBEDTLS_SSL_DEBUG_MSG( 3, ( "after compression: msglen = %d, ", ssl->out_msglen ) ); @@ -2149,6 +2331,7 @@ static int ssl_decompress_buf( mbedtls_ssl_context *ssl ) { int ret; unsigned char *msg_post = ssl->in_msg; + ptrdiff_t header_bytes = ssl->in_msg - ssl->in_buf; size_t len_pre = ssl->in_msglen; unsigned char *msg_pre = ssl->compress_buf; @@ -2168,7 +2351,8 @@ static int ssl_decompress_buf( mbedtls_ssl_context *ssl ) ssl->transform_in->ctx_inflate.next_in = msg_pre; ssl->transform_in->ctx_inflate.avail_in = len_pre; ssl->transform_in->ctx_inflate.next_out = msg_post; - ssl->transform_in->ctx_inflate.avail_out = MBEDTLS_SSL_MAX_CONTENT_LEN; + ssl->transform_in->ctx_inflate.avail_out = MBEDTLS_SSL_IN_BUFFER_LEN - + header_bytes; ret = inflate( &ssl->transform_in->ctx_inflate, Z_SYNC_FLUSH ); if( ret != Z_OK ) @@ -2177,8 +2361,8 @@ static int ssl_decompress_buf( mbedtls_ssl_context *ssl ) return( MBEDTLS_ERR_SSL_COMPRESSION_FAILED ); } - ssl->in_msglen = MBEDTLS_SSL_MAX_CONTENT_LEN - - ssl->transform_in->ctx_inflate.avail_out; + ssl->in_msglen = MBEDTLS_SSL_IN_BUFFER_LEN - + ssl->transform_in->ctx_inflate.avail_out - header_bytes; MBEDTLS_SSL_DEBUG_MSG( 3, ( "after decompression: msglen = %d, ", ssl->in_msglen ) ); @@ -2252,7 +2436,7 @@ int mbedtls_ssl_fetch_input( mbedtls_ssl_context *ssl, size_t nb_want ) return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); } - if( nb_want > MBEDTLS_SSL_BUFFER_LEN - (size_t)( ssl->in_hdr - ssl->in_buf ) ) + if( nb_want > MBEDTLS_SSL_IN_BUFFER_LEN - (size_t)( ssl->in_hdr - ssl->in_buf ) ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "requesting more data than fits" ) ); return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); @@ -2332,10 +2516,13 @@ int mbedtls_ssl_fetch_input( mbedtls_ssl_context *ssl, size_t nb_want ) * that will end up being dropped. */ if( ssl_check_timer( ssl ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "timer has expired" ) ); ret = MBEDTLS_ERR_SSL_TIMEOUT; + } else { - len = MBEDTLS_SSL_BUFFER_LEN - ( ssl->in_hdr - ssl->in_buf ); + len = MBEDTLS_SSL_IN_BUFFER_LEN - ( ssl->in_hdr - ssl->in_buf ); if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER ) timeout = ssl->handshake->retransmit_timeout; @@ -2434,6 +2621,14 @@ int mbedtls_ssl_fetch_input( mbedtls_ssl_context *ssl, size_t nb_want ) if( ret < 0 ) return( ret ); + if ( (size_t)ret > len || ( INT_MAX > SIZE_MAX && ret > SIZE_MAX ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "f_recv returned %d bytes but only %lu were requested", + ret, (unsigned long)len ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + ssl->in_left += ret; } } @@ -2481,6 +2676,14 @@ int mbedtls_ssl_flush_output( mbedtls_ssl_context *ssl ) if( ret <= 0 ) return( ret ); + if( (size_t)ret > ssl->out_left || ( INT_MAX > SIZE_MAX && ret > SIZE_MAX ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "f_send returned %d bytes but only %lu bytes were sent", + ret, (unsigned long)ssl->out_left ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + ssl->out_left -= ret; } @@ -2773,12 +2976,12 @@ int mbedtls_ssl_write_record( mbedtls_ssl_context *ssl ) if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) { /* Make room for the additional DTLS fields */ - if( MBEDTLS_SSL_MAX_CONTENT_LEN - ssl->out_msglen < 8 ) + if( MBEDTLS_SSL_OUT_CONTENT_LEN - ssl->out_msglen < 8 ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "DTLS handshake message too large: " "size %u, maximum %u", (unsigned) ( ssl->in_hslen - 4 ), - (unsigned) ( MBEDTLS_SSL_MAX_CONTENT_LEN - 12 ) ) ); + (unsigned) ( MBEDTLS_SSL_OUT_CONTENT_LEN - 12 ) ) ); return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); } @@ -2991,7 +3194,7 @@ static int ssl_reassemble_dtls_handshake( mbedtls_ssl_context *ssl ) MBEDTLS_SSL_DEBUG_MSG( 2, ( "initialize reassembly, total length = %d", msg_len ) ); - if( ssl->in_hslen > MBEDTLS_SSL_MAX_CONTENT_LEN ) + if( ssl->in_hslen > MBEDTLS_SSL_IN_CONTENT_LEN ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "handshake message too large" ) ); return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); @@ -3064,7 +3267,7 @@ static int ssl_reassemble_dtls_handshake( mbedtls_ssl_context *ssl ) if( ssl_bitmask_check( bitmask, msg_len ) != 0 ) { MBEDTLS_SSL_DEBUG_MSG( 2, ( "message is not complete yet" ) ); - return( MBEDTLS_ERR_SSL_WANT_READ ); + return( MBEDTLS_ERR_SSL_CONTINUE_PROCESSING ); } MBEDTLS_SSL_DEBUG_MSG( 2, ( "handshake message completed" ) ); @@ -3095,7 +3298,7 @@ static int ssl_reassemble_dtls_handshake( mbedtls_ssl_context *ssl ) ssl->next_record_offset = new_remain - ssl->in_hdr; ssl->in_left = ssl->next_record_offset + remain_len; - if( ssl->in_left > MBEDTLS_SSL_BUFFER_LEN - + if( ssl->in_left > MBEDTLS_SSL_IN_BUFFER_LEN - (size_t)( ssl->in_hdr - ssl->in_buf ) ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "reassembled message too large for buffer" ) ); @@ -3141,9 +3344,11 @@ int mbedtls_ssl_prepare_handshake_record( mbedtls_ssl_context *ssl ) int ret; unsigned int recv_msg_seq = ( ssl->in_msg[4] << 8 ) | ssl->in_msg[5]; - /* ssl->handshake is NULL when receiving ClientHello for renego */ if( ssl->handshake != NULL && - recv_msg_seq != ssl->handshake->in_msg_seq ) + ( ( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER && + recv_msg_seq != ssl->handshake->in_msg_seq ) || + ( ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER && + ssl->in_msg[0] != MBEDTLS_SSL_HS_CLIENT_HELLO ) ) ) { /* Retransmit only on last message from previous flight, to avoid * too many retransmissions. @@ -3170,7 +3375,7 @@ int mbedtls_ssl_prepare_handshake_record( mbedtls_ssl_context *ssl ) ssl->handshake->in_msg_seq ) ); } - return( MBEDTLS_ERR_SSL_WANT_READ ); + return( MBEDTLS_ERR_SSL_CONTINUE_PROCESSING ); } /* Wait until message completion to increment in_msg_seq */ @@ -3469,7 +3674,7 @@ static int ssl_handle_possible_reconnect( mbedtls_ssl_context *ssl ) ssl->conf->p_cookie, ssl->cli_id, ssl->cli_id_len, ssl->in_buf, ssl->in_left, - ssl->out_buf, MBEDTLS_SSL_MAX_CONTENT_LEN, &len ); + ssl->out_buf, MBEDTLS_SSL_OUT_CONTENT_LEN, &len ); MBEDTLS_SSL_DEBUG_RET( 2, "ssl_check_dtls_clihlo_cookie", ret ); @@ -3566,88 +3771,30 @@ static int ssl_parse_record_header( mbedtls_ssl_context *ssl ) } /* Check length against the size of our buffer */ - if( ssl->in_msglen > MBEDTLS_SSL_BUFFER_LEN + if( ssl->in_msglen > MBEDTLS_SSL_IN_BUFFER_LEN - (size_t)( ssl->in_msg - ssl->in_buf ) ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) ); return( MBEDTLS_ERR_SSL_INVALID_RECORD ); } - /* Check length against bounds of the current transform and version */ - if( ssl->transform_in == NULL ) - { - if( ssl->in_msglen < 1 || - ssl->in_msglen > MBEDTLS_SSL_MAX_CONTENT_LEN ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) ); - return( MBEDTLS_ERR_SSL_INVALID_RECORD ); - } - } - else - { - if( ssl->in_msglen < ssl->transform_in->minlen ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) ); - return( MBEDTLS_ERR_SSL_INVALID_RECORD ); - } - -#if defined(MBEDTLS_SSL_PROTO_SSL3) - if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 && - ssl->in_msglen > ssl->transform_in->minlen + MBEDTLS_SSL_MAX_CONTENT_LEN ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) ); - return( MBEDTLS_ERR_SSL_INVALID_RECORD ); - } -#endif -#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ - defined(MBEDTLS_SSL_PROTO_TLS1_2) - /* - * TLS encrypted messages can have up to 256 bytes of padding - */ - if( ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_1 && - ssl->in_msglen > ssl->transform_in->minlen + - MBEDTLS_SSL_MAX_CONTENT_LEN + 256 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) ); - return( MBEDTLS_ERR_SSL_INVALID_RECORD ); - } -#endif - } - /* - * DTLS-related tests done last, because most of them may result in - * silently dropping the record (but not the whole datagram), and we only - * want to consider that after ensuring that the "basic" fields (type, - * version, length) are sane. + * DTLS-related tests. + * Check epoch before checking length constraint because + * the latter varies with the epoch. E.g., if a ChangeCipherSpec + * message gets duplicated before the corresponding Finished message, + * the second ChangeCipherSpec should be discarded because it belongs + * to an old epoch, but not because its length is shorter than + * the minimum record length for packets using the new record transform. + * Note that these two kinds of failures are handled differently, + * as an unexpected record is silently skipped but an invalid + * record leads to the entire datagram being dropped. */ #if defined(MBEDTLS_SSL_PROTO_DTLS) if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) { unsigned int rec_epoch = ( ssl->in_ctr[0] << 8 ) | ssl->in_ctr[1]; - /* Drop unexpected ChangeCipherSpec messages */ - if( ssl->in_msgtype == MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC && - ssl->state != MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC && - ssl->state != MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "dropping unexpected ChangeCipherSpec" ) ); - return( MBEDTLS_ERR_SSL_UNEXPECTED_RECORD ); - } - - /* Drop unexpected ApplicationData records, - * except at the beginning of renegotiations */ - if( ssl->in_msgtype == MBEDTLS_SSL_MSG_APPLICATION_DATA && - ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER -#if defined(MBEDTLS_SSL_RENEGOTIATION) - && ! ( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS && - ssl->state == MBEDTLS_SSL_SERVER_HELLO ) -#endif - ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "dropping unexpected ApplicationData" ) ); - return( MBEDTLS_ERR_SSL_UNEXPECTED_RECORD ); - } - /* Check epoch (and sequence number) with DTLS */ if( rec_epoch != ssl->in_epoch ) { @@ -3687,9 +3834,74 @@ static int ssl_parse_record_header( mbedtls_ssl_context *ssl ) return( MBEDTLS_ERR_SSL_UNEXPECTED_RECORD ); } #endif + + /* Drop unexpected ChangeCipherSpec messages */ + if( ssl->in_msgtype == MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC && + ssl->state != MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC && + ssl->state != MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "dropping unexpected ChangeCipherSpec" ) ); + return( MBEDTLS_ERR_SSL_UNEXPECTED_RECORD ); + } + + /* Drop unexpected ApplicationData records, + * except at the beginning of renegotiations */ + if( ssl->in_msgtype == MBEDTLS_SSL_MSG_APPLICATION_DATA && + ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER +#if defined(MBEDTLS_SSL_RENEGOTIATION) + && ! ( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS && + ssl->state == MBEDTLS_SSL_SERVER_HELLO ) +#endif + ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "dropping unexpected ApplicationData" ) ); + return( MBEDTLS_ERR_SSL_UNEXPECTED_RECORD ); + } } #endif /* MBEDTLS_SSL_PROTO_DTLS */ + + /* Check length against bounds of the current transform and version */ + if( ssl->transform_in == NULL ) + { + if( ssl->in_msglen < 1 || + ssl->in_msglen > MBEDTLS_SSL_IN_CONTENT_LEN ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) ); + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } + } + else + { + if( ssl->in_msglen < ssl->transform_in->minlen ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) ); + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } + +#if defined(MBEDTLS_SSL_PROTO_SSL3) + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 && + ssl->in_msglen > ssl->transform_in->minlen + MBEDTLS_SSL_IN_CONTENT_LEN ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) ); + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } +#endif +#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_2) + /* + * TLS encrypted messages can have up to 256 bytes of padding + */ + if( ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_1 && + ssl->in_msglen > ssl->transform_in->minlen + + MBEDTLS_SSL_IN_CONTENT_LEN + 256 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) ); + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } +#endif + } + return( 0 ); } @@ -3730,7 +3942,7 @@ static int ssl_prepare_record_content( mbedtls_ssl_context *ssl ) MBEDTLS_SSL_DEBUG_BUF( 4, "input payload after decrypt", ssl->in_msg, ssl->in_msglen ); - if( ssl->in_msglen > MBEDTLS_SSL_MAX_CONTENT_LEN ) + if( ssl->in_msglen > MBEDTLS_SSL_IN_CONTENT_LEN ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) ); return( MBEDTLS_ERR_SSL_INVALID_RECORD ); @@ -3778,7 +3990,10 @@ int mbedtls_ssl_read_record( mbedtls_ssl_context *ssl ) { do { - if( ( ret = mbedtls_ssl_read_record_layer( ssl ) ) != 0 ) + do ret = mbedtls_ssl_read_record_layer( ssl ); + while( ret == MBEDTLS_ERR_SSL_CONTINUE_PROCESSING ); + + if( ret != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, ( "mbedtls_ssl_read_record_layer" ), ret ); return( ret ); @@ -3786,11 +4001,12 @@ int mbedtls_ssl_read_record( mbedtls_ssl_context *ssl ) ret = mbedtls_ssl_handle_message_type( ssl ); - } while( MBEDTLS_ERR_SSL_NON_FATAL == ret ); + } while( MBEDTLS_ERR_SSL_NON_FATAL == ret || + MBEDTLS_ERR_SSL_CONTINUE_PROCESSING == ret ); if( 0 != ret ) { - MBEDTLS_SSL_DEBUG_RET( 1, ( "mbedtls_ssl_read_record_layer" ), ret ); + MBEDTLS_SSL_DEBUG_RET( 1, ( "mbedtls_ssl_handle_message_type" ), ret ); return( ret ); } @@ -3828,11 +4044,6 @@ int mbedtls_ssl_read_record_layer( mbedtls_ssl_context *ssl ) * (2) Alert messages: * Consume whole record content, in_msglen = 0. * - * NOTE: This needs to be fixed, since like for - * handshake messages it is allowed to have - * multiple alerts witin a single record. - * Internal reference IOTSSL-1321. - * * (3) Change cipher spec: * Consume whole record content, in_msglen = 0. * @@ -3860,12 +4071,12 @@ int mbedtls_ssl_read_record_layer( mbedtls_ssl_context *ssl ) */ /* Notes: - * (1) in_hslen is *NOT* necessarily the size of the + * (1) in_hslen is not necessarily the size of the * current handshake content: If DTLS handshake * fragmentation is used, that's the fragment * size instead. Using the total handshake message - * size here is FAULTY and should be changed at - * some point. Internal reference IOTSSL-1414. + * size here is faulty and should be changed at + * some point. * (2) While it doesn't seem to cause problems, one * has to be very careful not to assume that in_hslen * is always <= in_msglen in a sensible communication. @@ -3916,12 +4127,6 @@ int mbedtls_ssl_read_record_layer( mbedtls_ssl_context *ssl ) return( 0 ); } - /* Need to fetch a new record */ - -#if defined(MBEDTLS_SSL_PROTO_DTLS) -read_record_header: -#endif - /* Current record either fully processed or to be discarded. */ if( ( ret = mbedtls_ssl_fetch_input( ssl, mbedtls_ssl_hdr_len( ssl ) ) ) != 0 ) @@ -3956,7 +4161,7 @@ read_record_header: } /* Get next record */ - goto read_record_header; + return( MBEDTLS_ERR_SSL_CONTINUE_PROCESSING ); } #endif return( ret ); @@ -3975,7 +4180,13 @@ read_record_header: /* Done reading this record, get ready for the next one */ #if defined(MBEDTLS_SSL_PROTO_DTLS) if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { ssl->next_record_offset = ssl->in_msglen + mbedtls_ssl_hdr_len( ssl ); + if( ssl->next_record_offset < ssl->in_left ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "more than one record within datagram" ) ); + } + } else #endif ssl->in_left = 0; @@ -4022,7 +4233,7 @@ read_record_header: ssl->in_left = 0; MBEDTLS_SSL_DEBUG_MSG( 1, ( "discarding invalid record (mac)" ) ); - goto read_record_header; + return( MBEDTLS_ERR_SSL_CONTINUE_PROCESSING ); } return( ret ); @@ -4043,46 +4254,6 @@ read_record_header: } } - /* - * When we sent the last flight of the handshake, we MUST respond to a - * retransmit of the peer's previous flight with a retransmit. (In - * practice, only the Finished message will make it, other messages - * including CCS use the old transform so they're dropped as invalid.) - * - * If the record we received is not a handshake message, however, it - * means the peer received our last flight so we can clean up - * handshake info. - * - * This check needs to be done before prepare_handshake() due to an edge - * case: if the client immediately requests renegotiation, this - * finishes the current handshake first, avoiding the new ClientHello - * being mistaken for an ancient message in the current handshake. - */ -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && - ssl->handshake != NULL && - ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER ) - { - if( ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE && - ssl->in_msg[0] == MBEDTLS_SSL_HS_FINISHED ) - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "received retransmit of last flight" ) ); - - if( ( ret = mbedtls_ssl_resend( ssl ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_resend", ret ); - return( ret ); - } - - return( MBEDTLS_ERR_SSL_WANT_READ ); - } - else - { - ssl_handshake_wrapup_free_hs_transform( ssl ); - } - } -#endif - return( 0 ); } @@ -4103,6 +4274,16 @@ int mbedtls_ssl_handle_message_type( mbedtls_ssl_context *ssl ) if( ssl->in_msgtype == MBEDTLS_SSL_MSG_ALERT ) { + if( ssl->in_msglen != 2 ) + { + /* Note: Standard allows for more than one 2 byte alert + to be packed in a single message, but Mbed TLS doesn't + currently support this. */ + MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid alert message, len: %d", + ssl->in_msglen ) ); + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } + MBEDTLS_SSL_DEBUG_MSG( 2, ( "got an alert message, type: [%d:%d]", ssl->in_msg[0], ssl->in_msg[1] ) ); @@ -4127,7 +4308,7 @@ int mbedtls_ssl_handle_message_type( mbedtls_ssl_context *ssl ) if( ssl->in_msg[0] == MBEDTLS_SSL_ALERT_LEVEL_WARNING && ssl->in_msg[1] == MBEDTLS_SSL_ALERT_MSG_NO_RENEGOTIATION ) { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "is a SSLv3 no_cert" ) ); + MBEDTLS_SSL_DEBUG_MSG( 2, ( "is a SSLv3 no renegotiation alert" ) ); /* Will be handled when trying to parse ServerHello */ return( 0 ); } @@ -4149,6 +4330,15 @@ int mbedtls_ssl_handle_message_type( mbedtls_ssl_context *ssl ) return MBEDTLS_ERR_SSL_NON_FATAL; } +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ssl->handshake != NULL && + ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER ) + { + ssl_handshake_wrapup_free_hs_transform( ssl ); + } +#endif + return( 0 ); } @@ -4323,10 +4513,10 @@ int mbedtls_ssl_write_certificate( mbedtls_ssl_context *ssl ) while( crt != NULL ) { n = crt->raw.len; - if( n > MBEDTLS_SSL_MAX_CONTENT_LEN - 3 - i ) + if( n > MBEDTLS_SSL_OUT_CONTENT_LEN - 3 - i ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "certificate too large, %d > %d", - i + 3 + n, MBEDTLS_SSL_MAX_CONTENT_LEN ) ); + i + 3 + n, MBEDTLS_SSL_OUT_CONTENT_LEN ) ); return( MBEDTLS_ERR_SSL_CERTIFICATE_TOO_LARGE ); } @@ -4526,6 +4716,12 @@ int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl ) while( i < ssl->in_hslen ) { + if ( i + 3 > ssl->in_hslen ) { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE ); + } if( ssl->in_msg[i] != 0 ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate message" ) ); @@ -5026,9 +5222,9 @@ static void ssl_calc_finished_ssl( mbedtls_md5_free( &md5 ); mbedtls_sha1_free( &sha1 ); - mbedtls_zeroize( padbuf, sizeof( padbuf ) ); - mbedtls_zeroize( md5sum, sizeof( md5sum ) ); - mbedtls_zeroize( sha1sum, sizeof( sha1sum ) ); + mbedtls_platform_zeroize( padbuf, sizeof( padbuf ) ); + mbedtls_platform_zeroize( md5sum, sizeof( md5sum ) ); + mbedtls_platform_zeroize( sha1sum, sizeof( sha1sum ) ); MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= calc finished" ) ); } @@ -5087,7 +5283,7 @@ static void ssl_calc_finished_tls( mbedtls_md5_free( &md5 ); mbedtls_sha1_free( &sha1 ); - mbedtls_zeroize( padbuf, sizeof( padbuf ) ); + mbedtls_platform_zeroize( padbuf, sizeof( padbuf ) ); MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= calc finished" ) ); } @@ -5137,7 +5333,7 @@ static void ssl_calc_finished_tls_sha256( mbedtls_sha256_free( &sha256 ); - mbedtls_zeroize( padbuf, sizeof( padbuf ) ); + mbedtls_platform_zeroize( padbuf, sizeof( padbuf ) ); MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= calc finished" ) ); } @@ -5186,7 +5382,7 @@ static void ssl_calc_finished_tls_sha384( mbedtls_sha512_free( &sha512 ); - mbedtls_zeroize( padbuf, sizeof( padbuf ) ); + mbedtls_platform_zeroize( padbuf, sizeof( padbuf ) ); MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= calc finished" ) ); } @@ -5200,7 +5396,7 @@ static void ssl_handshake_wrapup_free_hs_transform( mbedtls_ssl_context *ssl ) /* * Free our handshake params */ - mbedtls_ssl_handshake_free( ssl->handshake ); + mbedtls_ssl_handshake_free( ssl ); mbedtls_free( ssl->handshake ); ssl->handshake = NULL; @@ -5555,7 +5751,7 @@ static int ssl_handshake_init( mbedtls_ssl_context *ssl ) if( ssl->session_negotiate ) mbedtls_ssl_session_free( ssl->session_negotiate ); if( ssl->handshake ) - mbedtls_ssl_handshake_free( ssl->handshake ); + mbedtls_ssl_handshake_free( ssl ); /* * Either the pointers are now NULL or cleared properly and can be freed. @@ -5660,17 +5856,23 @@ int mbedtls_ssl_setup( mbedtls_ssl_context *ssl, const mbedtls_ssl_config *conf ) { int ret; - const size_t len = MBEDTLS_SSL_BUFFER_LEN; ssl->conf = conf; /* * Prepare base structures */ - if( ( ssl-> in_buf = mbedtls_calloc( 1, len ) ) == NULL || - ( ssl->out_buf = mbedtls_calloc( 1, len ) ) == NULL ) + ssl->in_buf = mbedtls_calloc( 1, MBEDTLS_SSL_IN_BUFFER_LEN ); + if( ssl->in_buf == NULL ) { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc(%d bytes) failed", len ) ); + MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc(%d bytes) failed", MBEDTLS_SSL_IN_BUFFER_LEN) ); + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + } + + ssl->out_buf = mbedtls_calloc( 1, MBEDTLS_SSL_OUT_BUFFER_LEN ); + if( ssl->out_buf == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc(%d bytes) failed", MBEDTLS_SSL_OUT_BUFFER_LEN) ); mbedtls_free( ssl->in_buf ); ssl->in_buf = NULL; return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); @@ -5771,9 +5973,9 @@ static int ssl_session_reset_int( mbedtls_ssl_context *ssl, int partial ) ssl->transform_in = NULL; ssl->transform_out = NULL; - memset( ssl->out_buf, 0, MBEDTLS_SSL_BUFFER_LEN ); + memset( ssl->out_buf, 0, MBEDTLS_SSL_OUT_BUFFER_LEN ); if( partial == 0 ) - memset( ssl->in_buf, 0, MBEDTLS_SSL_BUFFER_LEN ); + memset( ssl->in_buf, 0, MBEDTLS_SSL_IN_BUFFER_LEN ); #if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) if( mbedtls_ssl_hw_record_reset != NULL ) @@ -5993,27 +6195,27 @@ static int ssl_append_key_cert( mbedtls_ssl_key_cert **head, mbedtls_x509_crt *cert, mbedtls_pk_context *key ) { - mbedtls_ssl_key_cert *new; + mbedtls_ssl_key_cert *new_cert; - new = mbedtls_calloc( 1, sizeof( mbedtls_ssl_key_cert ) ); - if( new == NULL ) + new_cert = mbedtls_calloc( 1, sizeof( mbedtls_ssl_key_cert ) ); + if( new_cert == NULL ) return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); - new->cert = cert; - new->key = key; - new->next = NULL; + new_cert->cert = cert; + new_cert->key = key; + new_cert->next = NULL; /* Update head is the list was null, else add to the end */ if( *head == NULL ) { - *head = new; + *head = new_cert; } else { mbedtls_ssl_key_cert *cur = *head; while( cur->next != NULL ) cur = cur->next; - cur->next = new; + cur->next = new_cert; } return( 0 ); @@ -6098,14 +6300,14 @@ int mbedtls_ssl_conf_psk( mbedtls_ssl_config *conf, /* Identity len will be encoded on two bytes */ if( ( psk_identity_len >> 16 ) != 0 || - psk_identity_len > MBEDTLS_SSL_MAX_CONTENT_LEN ) + psk_identity_len > MBEDTLS_SSL_OUT_CONTENT_LEN ) { return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); } if( conf->psk != NULL ) { - mbedtls_zeroize( conf->psk, conf->psk_len ); + mbedtls_platform_zeroize( conf->psk, conf->psk_len ); mbedtls_free( conf->psk ); conf->psk = NULL; @@ -6148,7 +6350,8 @@ int mbedtls_ssl_set_hs_psk( mbedtls_ssl_context *ssl, if( ssl->handshake->psk != NULL ) { - mbedtls_zeroize( ssl->handshake->psk, ssl->handshake->psk_len ); + mbedtls_platform_zeroize( ssl->handshake->psk, + ssl->handshake->psk_len ); mbedtls_free( ssl->handshake->psk ); ssl->handshake->psk_len = 0; } @@ -6278,7 +6481,7 @@ int mbedtls_ssl_set_hostname( mbedtls_ssl_context *ssl, const char *hostname ) if( ssl->hostname != NULL ) { - mbedtls_zeroize( ssl->hostname, strlen( ssl->hostname ) ); + mbedtls_platform_zeroize( ssl->hostname, strlen( ssl->hostname ) ); mbedtls_free( ssl->hostname ); } @@ -6398,7 +6601,7 @@ void mbedtls_ssl_conf_arc4_support( mbedtls_ssl_config *conf, char arc4 ) int mbedtls_ssl_conf_max_frag_len( mbedtls_ssl_config *conf, unsigned char mfl_code ) { if( mfl_code >= MBEDTLS_SSL_MAX_FRAG_LEN_INVALID || - mfl_code_to_length[mfl_code] > MBEDTLS_SSL_MAX_CONTENT_LEN ) + ssl_mfl_code_to_length( mfl_code ) > MBEDTLS_TLS_EXT_ADV_CONTENT_LEN ) { return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); } @@ -6477,6 +6680,43 @@ void mbedtls_ssl_conf_export_keys_cb( mbedtls_ssl_config *conf, } #endif +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) +void mbedtls_ssl_conf_async_private_cb( + mbedtls_ssl_config *conf, + mbedtls_ssl_async_sign_t *f_async_sign, + mbedtls_ssl_async_decrypt_t *f_async_decrypt, + mbedtls_ssl_async_resume_t *f_async_resume, + mbedtls_ssl_async_cancel_t *f_async_cancel, + void *async_config_data ) +{ + conf->f_async_sign_start = f_async_sign; + conf->f_async_decrypt_start = f_async_decrypt; + conf->f_async_resume = f_async_resume; + conf->f_async_cancel = f_async_cancel; + conf->p_async_config_data = async_config_data; +} + +void *mbedtls_ssl_conf_get_async_config_data( const mbedtls_ssl_config *conf ) +{ + return( conf->p_async_config_data ); +} + +void *mbedtls_ssl_get_async_operation_data( const mbedtls_ssl_context *ssl ) +{ + if( ssl->handshake == NULL ) + return( NULL ); + else + return( ssl->handshake->user_async_ctx ); +} + +void mbedtls_ssl_set_async_operation_data( mbedtls_ssl_context *ssl, + void *ctx ) +{ + if( ssl->handshake != NULL ) + ssl->handshake->user_async_ctx = ctx; +} +#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ + /* * SSL get accessors */ @@ -6485,6 +6725,61 @@ size_t mbedtls_ssl_get_bytes_avail( const mbedtls_ssl_context *ssl ) return( ssl->in_offt == NULL ? 0 : ssl->in_msglen ); } +int mbedtls_ssl_check_pending( const mbedtls_ssl_context *ssl ) +{ + /* + * Case A: We're currently holding back + * a message for further processing. + */ + + if( ssl->keep_current_message == 1 ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ssl_check_pending: record held back for processing" ) ); + return( 1 ); + } + + /* + * Case B: Further records are pending in the current datagram. + */ + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ssl->in_left > ssl->next_record_offset ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ssl_check_pending: more records within current datagram" ) ); + return( 1 ); + } +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + + /* + * Case C: A handshake message is being processed. + */ + + if( ssl->in_hslen > 0 && ssl->in_hslen < ssl->in_msglen ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ssl_check_pending: more handshake messages within current record" ) ); + return( 1 ); + } + + /* + * Case D: An application data message is being processed + */ + if( ssl->in_offt != NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ssl_check_pending: application data record is being processed" ) ); + return( 1 ); + } + + /* + * In all other cases, the rest of the message can be dropped. + * As in ssl_read_record_layer, this needs to be adapted if + * we implement support for multiple alerts in single records. + */ + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ssl_check_pending: nothing pending" ) ); + return( 0 ); +} + uint32_t mbedtls_ssl_get_verify_result( const mbedtls_ssl_context *ssl ) { if( ssl->session != NULL ) @@ -6584,15 +6879,15 @@ size_t mbedtls_ssl_get_max_frag_len( const mbedtls_ssl_context *ssl ) /* * Assume mfl_code is correct since it was checked when set */ - max_len = mfl_code_to_length[ssl->conf->mfl_code]; + max_len = ssl_mfl_code_to_length( ssl->conf->mfl_code ); /* * Check if a smaller max length was negotiated */ if( ssl->session_out != NULL && - mfl_code_to_length[ssl->session_out->mfl_code] < max_len ) + ssl_mfl_code_to_length( ssl->session_out->mfl_code ) < max_len ) { - max_len = mfl_code_to_length[ssl->session_out->mfl_code]; + max_len = ssl_mfl_code_to_length( ssl->session_out->mfl_code ); } return max_len; @@ -6892,42 +7187,8 @@ int mbedtls_ssl_read( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len ) } } - /* - * TODO - * - * The logic should be streamlined here: - * - * Instead of - * - * - Manually checking whether ssl->in_offt is NULL - * - Fetching a new record if yes - * - Setting ssl->in_offt if one finds an application record - * - Resetting keep_current_message after handling the application data - * - * one should - * - * - Adapt read_record to set ssl->in_offt automatically - * when a new application data record is processed. - * - Always call mbedtls_ssl_read_record here. - * - * This way, the logic of ssl_read would be much clearer: - * - * (1) Always call record layer and see what kind of record is on - * and have it ready for consumption (in particular, in_offt - * properly set for application data records). - * (2) If it's application data (either freshly fetched - * or something already being partially processed), - * serve the read request from it. - * (3) If it's something different from application data, - * handle it accordingly, e.g. potentially start a - * renegotiation. - * - * This will also remove the need to manually reset - * ssl->keep_current_message = 0 below. - * - */ - - if( ssl->in_offt == NULL ) + /* Loop as long as no application data record is available */ + while( ssl->in_offt == NULL ) { /* Start timer if not already running */ if( ssl->f_get_timer != NULL && @@ -6981,7 +7242,9 @@ int mbedtls_ssl_read( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len ) /* With DTLS, drop the packet (probably from last handshake) */ #if defined(MBEDTLS_SSL_PROTO_DTLS) if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) - return( MBEDTLS_ERR_SSL_WANT_READ ); + { + continue; + } #endif return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); } @@ -6996,7 +7259,9 @@ int mbedtls_ssl_read( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len ) /* With DTLS, drop the packet (probably from last handshake) */ #if defined(MBEDTLS_SSL_PROTO_DTLS) if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) - return( MBEDTLS_ERR_SSL_WANT_READ ); + { + continue; + } #endif return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); } @@ -7069,7 +7334,25 @@ int mbedtls_ssl_read( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len ) } } - return( MBEDTLS_ERR_SSL_WANT_READ ); + /* At this point, we don't know whether the renegotiation has been + * completed or not. The cases to consider are the following: + * 1) The renegotiation is complete. In this case, no new record + * has been read yet. + * 2) The renegotiation is incomplete because the client received + * an application data record while awaiting the ServerHello. + * 3) The renegotiation is incomplete because the client received + * a non-handshake, non-application data message while awaiting + * the ServerHello. + * In each of these case, looping will be the proper action: + * - For 1), the next iteration will read a new record and check + * if it's application data. + * - For 2), the loop condition isn't satisfied as application data + * is present, hence continue is the same as break + * - For 3), the loop condition is satisfied and read_record + * will re-deliver the message that was held back by the client + * when expecting the ServerHello. + */ + continue; } #if defined(MBEDTLS_SSL_RENEGOTIATION) else if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_PENDING ) @@ -7148,8 +7431,16 @@ int mbedtls_ssl_read( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len ) } /* - * Send application data to be encrypted by the SSL layer, - * taking care of max fragment length and buffer size + * Send application data to be encrypted by the SSL layer, taking care of max + * fragment length and buffer size. + * + * According to RFC 5246 Section 6.2.1: + * + * Zero-length fragments of Application data MAY be sent as they are + * potentially useful as a traffic analysis countermeasure. + * + * Therefore, it is possible that the input message length is 0 and the + * corresponding return code is 0 on success. */ static int ssl_write_real( mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len ) @@ -7158,7 +7449,7 @@ static int ssl_write_real( mbedtls_ssl_context *ssl, #if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) size_t max_len = mbedtls_ssl_get_max_frag_len( ssl ); #else - size_t max_len = MBEDTLS_SSL_MAX_CONTENT_LEN; + size_t max_len = MBEDTLS_SSL_OUT_CONTENT_LEN; #endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ if( len > max_len ) { @@ -7177,6 +7468,12 @@ static int ssl_write_real( mbedtls_ssl_context *ssl, if( ssl->out_left != 0 ) { + /* + * The user has previously tried to send the data and + * MBEDTLS_ERR_SSL_WANT_WRITE or the message was only partially + * written. In this case, we expect the high-level write function + * (e.g. mbedtls_ssl_write()) to be called with the same parameters + */ if( ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_flush_output", ret ); @@ -7185,6 +7482,11 @@ static int ssl_write_real( mbedtls_ssl_context *ssl, } else { + /* + * The user is trying to send a message the first time, so we need to + * copy the data into the internal buffers and setup the data structure + * to keep track of partial writes + */ ssl->out_msglen = len; ssl->out_msgtype = MBEDTLS_SSL_MSG_APPLICATION_DATA; memcpy( ssl->out_msg, buf, len ); @@ -7324,7 +7626,7 @@ void mbedtls_ssl_transform_free( mbedtls_ssl_transform *transform ) mbedtls_md_free( &transform->md_ctx_enc ); mbedtls_md_free( &transform->md_ctx_dec ); - mbedtls_zeroize( transform, sizeof( mbedtls_ssl_transform ) ); + mbedtls_platform_zeroize( transform, sizeof( mbedtls_ssl_transform ) ); } #if defined(MBEDTLS_X509_CRT_PARSE_C) @@ -7341,11 +7643,21 @@ static void ssl_key_cert_free( mbedtls_ssl_key_cert *key_cert ) } #endif /* MBEDTLS_X509_CRT_PARSE_C */ -void mbedtls_ssl_handshake_free( mbedtls_ssl_handshake_params *handshake ) +void mbedtls_ssl_handshake_free( mbedtls_ssl_context *ssl ) { + mbedtls_ssl_handshake_params *handshake = ssl->handshake; + if( handshake == NULL ) return; +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) + if( ssl->conf->f_async_cancel != NULL && handshake->async_in_progress != 0 ) + { + ssl->conf->f_async_cancel( ssl ); + handshake->async_in_progress = 0; + } +#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ + #if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ defined(MBEDTLS_SSL_PROTO_TLS1_1) mbedtls_md5_free( &handshake->fin_md5 ); @@ -7384,7 +7696,7 @@ void mbedtls_ssl_handshake_free( mbedtls_ssl_handshake_params *handshake ) #if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) if( handshake->psk != NULL ) { - mbedtls_zeroize( handshake->psk, handshake->psk_len ); + mbedtls_platform_zeroize( handshake->psk, handshake->psk_len ); mbedtls_free( handshake->psk ); } #endif @@ -7414,7 +7726,8 @@ void mbedtls_ssl_handshake_free( mbedtls_ssl_handshake_params *handshake ) ssl_flight_free( handshake->flight ); #endif - mbedtls_zeroize( handshake, sizeof( mbedtls_ssl_handshake_params ) ); + mbedtls_platform_zeroize( handshake, + sizeof( mbedtls_ssl_handshake_params ) ); } void mbedtls_ssl_session_free( mbedtls_ssl_session *session ) @@ -7434,7 +7747,7 @@ void mbedtls_ssl_session_free( mbedtls_ssl_session *session ) mbedtls_free( session->ticket ); #endif - mbedtls_zeroize( session, sizeof( mbedtls_ssl_session ) ); + mbedtls_platform_zeroize( session, sizeof( mbedtls_ssl_session ) ); } /* @@ -7449,20 +7762,20 @@ void mbedtls_ssl_free( mbedtls_ssl_context *ssl ) if( ssl->out_buf != NULL ) { - mbedtls_zeroize( ssl->out_buf, MBEDTLS_SSL_BUFFER_LEN ); + mbedtls_platform_zeroize( ssl->out_buf, MBEDTLS_SSL_OUT_BUFFER_LEN ); mbedtls_free( ssl->out_buf ); } if( ssl->in_buf != NULL ) { - mbedtls_zeroize( ssl->in_buf, MBEDTLS_SSL_BUFFER_LEN ); + mbedtls_platform_zeroize( ssl->in_buf, MBEDTLS_SSL_IN_BUFFER_LEN ); mbedtls_free( ssl->in_buf ); } #if defined(MBEDTLS_ZLIB_SUPPORT) if( ssl->compress_buf != NULL ) { - mbedtls_zeroize( ssl->compress_buf, MBEDTLS_SSL_BUFFER_LEN ); + mbedtls_platform_zeroize( ssl->compress_buf, MBEDTLS_SSL_COMPRESS_BUFFER_LEN ); mbedtls_free( ssl->compress_buf ); } #endif @@ -7475,7 +7788,7 @@ void mbedtls_ssl_free( mbedtls_ssl_context *ssl ) if( ssl->handshake ) { - mbedtls_ssl_handshake_free( ssl->handshake ); + mbedtls_ssl_handshake_free( ssl ); mbedtls_ssl_transform_free( ssl->transform_negotiate ); mbedtls_ssl_session_free( ssl->session_negotiate ); @@ -7493,7 +7806,7 @@ void mbedtls_ssl_free( mbedtls_ssl_context *ssl ) #if defined(MBEDTLS_X509_CRT_PARSE_C) if( ssl->hostname != NULL ) { - mbedtls_zeroize( ssl->hostname, strlen( ssl->hostname ) ); + mbedtls_platform_zeroize( ssl->hostname, strlen( ssl->hostname ) ); mbedtls_free( ssl->hostname ); } #endif @@ -7513,7 +7826,7 @@ void mbedtls_ssl_free( mbedtls_ssl_context *ssl ) MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= free" ) ); /* Actually clear after last debug message */ - mbedtls_zeroize( ssl, sizeof( mbedtls_ssl_context ) ); + mbedtls_platform_zeroize( ssl, sizeof( mbedtls_ssl_context ) ); } /* @@ -7740,11 +8053,17 @@ void mbedtls_ssl_config_free( mbedtls_ssl_config *conf ) #if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) if( conf->psk != NULL ) { - mbedtls_zeroize( conf->psk, conf->psk_len ); - mbedtls_zeroize( conf->psk_identity, conf->psk_identity_len ); + mbedtls_platform_zeroize( conf->psk, conf->psk_len ); mbedtls_free( conf->psk ); - mbedtls_free( conf->psk_identity ); + conf->psk = NULL; conf->psk_len = 0; + } + + if( conf->psk_identity != NULL ) + { + mbedtls_platform_zeroize( conf->psk_identity, conf->psk_identity_len ); + mbedtls_free( conf->psk_identity ); + conf->psk_identity = NULL; conf->psk_identity_len = 0; } #endif @@ -7753,7 +8072,7 @@ void mbedtls_ssl_config_free( mbedtls_ssl_config *conf ) ssl_key_cert_free( conf->key_cert ); #endif - mbedtls_zeroize( conf, sizeof( mbedtls_ssl_config ) ); + mbedtls_platform_zeroize( conf, sizeof( mbedtls_ssl_config ) ); } #if defined(MBEDTLS_PK_C) && \ @@ -8236,13 +8555,14 @@ exit: #if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ defined(MBEDTLS_SSL_PROTO_TLS1_2) int mbedtls_ssl_get_key_exchange_md_tls1_2( mbedtls_ssl_context *ssl, - unsigned char *output, - unsigned char *data, size_t data_len, - mbedtls_md_type_t md_alg ) + unsigned char *hash, size_t *hashlen, + unsigned char *data, size_t data_len, + mbedtls_md_type_t md_alg ) { int ret = 0; mbedtls_md_context_t ctx; const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type( md_alg ); + *hashlen = mbedtls_md_get_size( md_info ); mbedtls_md_init( &ctx ); @@ -8273,7 +8593,7 @@ int mbedtls_ssl_get_key_exchange_md_tls1_2( mbedtls_ssl_context *ssl, MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_md_update", ret ); goto exit; } - if( ( ret = mbedtls_md_finish( &ctx, output ) ) != 0 ) + if( ( ret = mbedtls_md_finish( &ctx, hash ) ) != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_md_finish", ret ); goto exit; diff --git a/thirdparty/mbedtls/library/threading.c b/thirdparty/mbedtls/library/threading.c index 07586756f2..7a32e672c7 100644 --- a/thirdparty/mbedtls/library/threading.c +++ b/thirdparty/mbedtls/library/threading.c @@ -111,8 +111,9 @@ void mbedtls_threading_set_alt( void (*mutex_init)( mbedtls_threading_mutex_t * mbedtls_mutex_lock = mutex_lock; mbedtls_mutex_unlock = mutex_unlock; +#if defined(MBEDTLS_FS_IO) mbedtls_mutex_init( &mbedtls_threading_readdir_mutex ); - mbedtls_mutex_init( &mbedtls_threading_gmtime_mutex ); +#endif } /* @@ -120,8 +121,9 @@ void mbedtls_threading_set_alt( void (*mutex_init)( mbedtls_threading_mutex_t * */ void mbedtls_threading_free_alt( void ) { +#if defined(MBEDTLS_FS_IO) mbedtls_mutex_free( &mbedtls_threading_readdir_mutex ); - mbedtls_mutex_free( &mbedtls_threading_gmtime_mutex ); +#endif } #endif /* MBEDTLS_THREADING_ALT */ @@ -131,7 +133,8 @@ void mbedtls_threading_free_alt( void ) #ifndef MUTEX_INIT #define MUTEX_INIT #endif +#if defined(MBEDTLS_FS_IO) mbedtls_threading_mutex_t mbedtls_threading_readdir_mutex MUTEX_INIT; -mbedtls_threading_mutex_t mbedtls_threading_gmtime_mutex MUTEX_INIT; +#endif #endif /* MBEDTLS_THREADING_C */ diff --git a/thirdparty/mbedtls/library/timing.c b/thirdparty/mbedtls/library/timing.c index 35d6d89e2b..3e8139f1f9 100644 --- a/thirdparty/mbedtls/library/timing.c +++ b/thirdparty/mbedtls/library/timing.c @@ -39,7 +39,8 @@ #if !defined(MBEDTLS_TIMING_ALT) #if !defined(unix) && !defined(__unix__) && !defined(__unix) && \ - !defined(__APPLE__) && !defined(_WIN32) + !defined(__APPLE__) && !defined(_WIN32) && !defined(__QNXNTO__) && \ + !defined(__HAIKU__) #error "This module only works on Unix and Windows, see MBEDTLS_TIMING_C in config.h" #endif diff --git a/thirdparty/mbedtls/library/version_features.c b/thirdparty/mbedtls/library/version_features.c index da47e3d753..777b6034c4 100644 --- a/thirdparty/mbedtls/library/version_features.c +++ b/thirdparty/mbedtls/library/version_features.c @@ -39,6 +39,9 @@ static const char *features[] = { #if defined(MBEDTLS_NO_UDBL_DIVISION) "MBEDTLS_NO_UDBL_DIVISION", #endif /* MBEDTLS_NO_UDBL_DIVISION */ +#if defined(MBEDTLS_NO_64BIT_MULTIPLICATION) + "MBEDTLS_NO_64BIT_MULTIPLICATION", +#endif /* MBEDTLS_NO_64BIT_MULTIPLICATION */ #if defined(MBEDTLS_HAVE_SSE2) "MBEDTLS_HAVE_SSE2", #endif /* MBEDTLS_HAVE_SSE2 */ @@ -90,6 +93,9 @@ static const char *features[] = { #if defined(MBEDTLS_ARC4_ALT) "MBEDTLS_ARC4_ALT", #endif /* MBEDTLS_ARC4_ALT */ +#if defined(MBEDTLS_ARIA_ALT) + "MBEDTLS_ARIA_ALT", +#endif /* MBEDTLS_ARIA_ALT */ #if defined(MBEDTLS_BLOWFISH_ALT) "MBEDTLS_BLOWFISH_ALT", #endif /* MBEDTLS_BLOWFISH_ALT */ @@ -99,6 +105,12 @@ static const char *features[] = { #if defined(MBEDTLS_CCM_ALT) "MBEDTLS_CCM_ALT", #endif /* MBEDTLS_CCM_ALT */ +#if defined(MBEDTLS_CHACHA20_ALT) + "MBEDTLS_CHACHA20_ALT", +#endif /* MBEDTLS_CHACHA20_ALT */ +#if defined(MBEDTLS_CHACHAPOLY_ALT) + "MBEDTLS_CHACHAPOLY_ALT", +#endif /* MBEDTLS_CHACHAPOLY_ALT */ #if defined(MBEDTLS_CMAC_ALT) "MBEDTLS_CMAC_ALT", #endif /* MBEDTLS_CMAC_ALT */ @@ -114,6 +126,9 @@ static const char *features[] = { #if defined(MBEDTLS_GCM_ALT) "MBEDTLS_GCM_ALT", #endif /* MBEDTLS_GCM_ALT */ +#if defined(MBEDTLS_NIST_KW_ALT) + "MBEDTLS_NIST_KW_ALT", +#endif /* MBEDTLS_NIST_KW_ALT */ #if defined(MBEDTLS_MD2_ALT) "MBEDTLS_MD2_ALT", #endif /* MBEDTLS_MD2_ALT */ @@ -123,6 +138,9 @@ static const char *features[] = { #if defined(MBEDTLS_MD5_ALT) "MBEDTLS_MD5_ALT", #endif /* MBEDTLS_MD5_ALT */ +#if defined(MBEDTLS_POLY1305_ALT) + "MBEDTLS_POLY1305_ALT", +#endif /* MBEDTLS_POLY1305_ALT */ #if defined(MBEDTLS_RIPEMD160_ALT) "MBEDTLS_RIPEMD160_ALT", #endif /* MBEDTLS_RIPEMD160_ALT */ @@ -237,6 +255,9 @@ static const char *features[] = { #if defined(MBEDTLS_AES_ROM_TABLES) "MBEDTLS_AES_ROM_TABLES", #endif /* MBEDTLS_AES_ROM_TABLES */ +#if defined(MBEDTLS_AES_FEWER_TABLES) + "MBEDTLS_AES_FEWER_TABLES", +#endif /* MBEDTLS_AES_FEWER_TABLES */ #if defined(MBEDTLS_CAMELLIA_SMALL_MEMORY) "MBEDTLS_CAMELLIA_SMALL_MEMORY", #endif /* MBEDTLS_CAMELLIA_SMALL_MEMORY */ @@ -249,6 +270,12 @@ static const char *features[] = { #if defined(MBEDTLS_CIPHER_MODE_CTR) "MBEDTLS_CIPHER_MODE_CTR", #endif /* MBEDTLS_CIPHER_MODE_CTR */ +#if defined(MBEDTLS_CIPHER_MODE_OFB) + "MBEDTLS_CIPHER_MODE_OFB", +#endif /* MBEDTLS_CIPHER_MODE_OFB */ +#if defined(MBEDTLS_CIPHER_MODE_XTS) + "MBEDTLS_CIPHER_MODE_XTS", +#endif /* MBEDTLS_CIPHER_MODE_XTS */ #if defined(MBEDTLS_CIPHER_NULL_CIPHER) "MBEDTLS_CIPHER_NULL_CIPHER", #endif /* MBEDTLS_CIPHER_NULL_CIPHER */ @@ -306,6 +333,9 @@ static const char *features[] = { #if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) "MBEDTLS_ECP_DP_CURVE25519_ENABLED", #endif /* MBEDTLS_ECP_DP_CURVE25519_ENABLED */ +#if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) + "MBEDTLS_ECP_DP_CURVE448_ENABLED", +#endif /* MBEDTLS_ECP_DP_CURVE448_ENABLED */ #if defined(MBEDTLS_ECP_NIST_OPTIM) "MBEDTLS_ECP_NIST_OPTIM", #endif /* MBEDTLS_ECP_NIST_OPTIM */ @@ -396,6 +426,9 @@ static const char *features[] = { #if defined(MBEDTLS_SSL_ALL_ALERT_MESSAGES) "MBEDTLS_SSL_ALL_ALERT_MESSAGES", #endif /* MBEDTLS_SSL_ALL_ALERT_MESSAGES */ +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) + "MBEDTLS_SSL_ASYNC_PRIVATE", +#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ #if defined(MBEDTLS_SSL_DEBUG_ALL) "MBEDTLS_SSL_DEBUG_ALL", #endif /* MBEDTLS_SSL_DEBUG_ALL */ @@ -525,12 +558,21 @@ static const char *features[] = { #if defined(MBEDTLS_CAMELLIA_C) "MBEDTLS_CAMELLIA_C", #endif /* MBEDTLS_CAMELLIA_C */ +#if defined(MBEDTLS_ARIA_C) + "MBEDTLS_ARIA_C", +#endif /* MBEDTLS_ARIA_C */ #if defined(MBEDTLS_CCM_C) "MBEDTLS_CCM_C", #endif /* MBEDTLS_CCM_C */ #if defined(MBEDTLS_CERTS_C) "MBEDTLS_CERTS_C", #endif /* MBEDTLS_CERTS_C */ +#if defined(MBEDTLS_CHACHA20_C) + "MBEDTLS_CHACHA20_C", +#endif /* MBEDTLS_CHACHA20_C */ +#if defined(MBEDTLS_CHACHAPOLY_C) + "MBEDTLS_CHACHAPOLY_C", +#endif /* MBEDTLS_CHACHAPOLY_C */ #if defined(MBEDTLS_CIPHER_C) "MBEDTLS_CIPHER_C", #endif /* MBEDTLS_CIPHER_C */ @@ -573,9 +615,15 @@ static const char *features[] = { #if defined(MBEDTLS_HAVEGE_C) "MBEDTLS_HAVEGE_C", #endif /* MBEDTLS_HAVEGE_C */ +#if defined(MBEDTLS_HKDF_C) + "MBEDTLS_HKDF_C", +#endif /* MBEDTLS_HKDF_C */ #if defined(MBEDTLS_HMAC_DRBG_C) "MBEDTLS_HMAC_DRBG_C", #endif /* MBEDTLS_HMAC_DRBG_C */ +#if defined(MBEDTLS_NIST_KW_C) + "MBEDTLS_NIST_KW_C", +#endif /* MBEDTLS_NIST_KW_C */ #if defined(MBEDTLS_MD_C) "MBEDTLS_MD_C", #endif /* MBEDTLS_MD_C */ @@ -627,6 +675,9 @@ static const char *features[] = { #if defined(MBEDTLS_PLATFORM_C) "MBEDTLS_PLATFORM_C", #endif /* MBEDTLS_PLATFORM_C */ +#if defined(MBEDTLS_POLY1305_C) + "MBEDTLS_POLY1305_C", +#endif /* MBEDTLS_POLY1305_C */ #if defined(MBEDTLS_RIPEMD160_C) "MBEDTLS_RIPEMD160_C", #endif /* MBEDTLS_RIPEMD160_C */ diff --git a/thirdparty/mbedtls/library/x509.c b/thirdparty/mbedtls/library/x509.c index 371d6da1dc..2e6795f750 100644 --- a/thirdparty/mbedtls/library/x509.c +++ b/thirdparty/mbedtls/library/x509.c @@ -29,6 +29,10 @@ * http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf */ +/* Ensure gmtime_r is available even with -std=c99; must be included before + * config.h, which pulls in glibc's features.h. Harmless on other platforms. */ +#define _POSIX_C_SOURCE 200112L + #if !defined(MBEDTLS_CONFIG_FILE) #include "mbedtls/config.h" #else @@ -59,26 +63,13 @@ #define mbedtls_snprintf snprintf #endif - #if defined(MBEDTLS_HAVE_TIME) #include "mbedtls/platform_time.h" #endif - -#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) -#include <windows.h> -#else +#if defined(MBEDTLS_HAVE_TIME_DATE) #include <time.h> #endif -#if defined(MBEDTLS_FS_IO) -#include <stdio.h> -#if !defined(_WIN32) -#include <sys/types.h> -#include <sys/stat.h> -#include <dirent.h> -#endif -#endif - #define CHECK(code) if( ( ret = code ) != 0 ){ return( ret ); } #define CHECK_RANGE(min, max, val) if( val < min || val > max ){ return( ret ); } @@ -903,36 +894,18 @@ int mbedtls_x509_key_size_helper( char *buf, size_t buf_size, const char *name ) * Set the time structure to the current time. * Return 0 on success, non-zero on failure. */ -#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) -static int x509_get_current_time( mbedtls_x509_time *now ) -{ - SYSTEMTIME st; - - GetSystemTime( &st ); - - now->year = st.wYear; - now->mon = st.wMonth; - now->day = st.wDay; - now->hour = st.wHour; - now->min = st.wMinute; - now->sec = st.wSecond; - - return( 0 ); -} -#else static int x509_get_current_time( mbedtls_x509_time *now ) { - struct tm *lt; + struct tm *lt, tm_buf; mbedtls_time_t tt; int ret = 0; -#if defined(MBEDTLS_THREADING_C) - if( mbedtls_mutex_lock( &mbedtls_threading_gmtime_mutex ) != 0 ) - return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); -#endif - tt = mbedtls_time( NULL ); - lt = gmtime( &tt ); +#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) + lt = gmtime_s( &tm_buf, &tt ) == 0 ? &tm_buf : NULL; +#else + lt = gmtime_r( &tt, &tm_buf ); +#endif if( lt == NULL ) ret = -1; @@ -946,14 +919,8 @@ static int x509_get_current_time( mbedtls_x509_time *now ) now->sec = lt->tm_sec; } -#if defined(MBEDTLS_THREADING_C) - if( mbedtls_mutex_unlock( &mbedtls_threading_gmtime_mutex ) != 0 ) - return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); -#endif - return( ret ); } -#endif /* _WIN32 && !EFIX64 && !EFI32 */ /* * Return 0 if before <= after, 1 otherwise diff --git a/thirdparty/mbedtls/library/x509_crl.c b/thirdparty/mbedtls/library/x509_crl.c index b0f39d428b..8450f87e03 100644 --- a/thirdparty/mbedtls/library/x509_crl.c +++ b/thirdparty/mbedtls/library/x509_crl.c @@ -39,6 +39,7 @@ #include "mbedtls/x509_crl.h" #include "mbedtls/oid.h" +#include "mbedtls/platform_util.h" #include <string.h> @@ -66,11 +67,6 @@ #include <stdio.h> #endif -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize( void *v, size_t n ) { - volatile unsigned char *p = v; while( n-- ) *p++ = 0; -} - /* * Version ::= INTEGER { v1(0), v2(1) } */ @@ -616,7 +612,7 @@ int mbedtls_x509_crl_parse_file( mbedtls_x509_crl *chain, const char *path ) ret = mbedtls_x509_crl_parse( chain, buf, n ); - mbedtls_zeroize( buf, n ); + mbedtls_platform_zeroize( buf, n ); mbedtls_free( buf ); return( ret ); @@ -737,7 +733,7 @@ void mbedtls_x509_crl_free( mbedtls_x509_crl *crl ) { name_prv = name_cur; name_cur = name_cur->next; - mbedtls_zeroize( name_prv, sizeof( mbedtls_x509_name ) ); + mbedtls_platform_zeroize( name_prv, sizeof( mbedtls_x509_name ) ); mbedtls_free( name_prv ); } @@ -746,13 +742,14 @@ void mbedtls_x509_crl_free( mbedtls_x509_crl *crl ) { entry_prv = entry_cur; entry_cur = entry_cur->next; - mbedtls_zeroize( entry_prv, sizeof( mbedtls_x509_crl_entry ) ); + mbedtls_platform_zeroize( entry_prv, + sizeof( mbedtls_x509_crl_entry ) ); mbedtls_free( entry_prv ); } if( crl_cur->raw.p != NULL ) { - mbedtls_zeroize( crl_cur->raw.p, crl_cur->raw.len ); + mbedtls_platform_zeroize( crl_cur->raw.p, crl_cur->raw.len ); mbedtls_free( crl_cur->raw.p ); } @@ -766,7 +763,7 @@ void mbedtls_x509_crl_free( mbedtls_x509_crl *crl ) crl_prv = crl_cur; crl_cur = crl_cur->next; - mbedtls_zeroize( crl_prv, sizeof( mbedtls_x509_crl ) ); + mbedtls_platform_zeroize( crl_prv, sizeof( mbedtls_x509_crl ) ); if( crl_prv != crl ) mbedtls_free( crl_prv ); } diff --git a/thirdparty/mbedtls/library/x509_crt.c b/thirdparty/mbedtls/library/x509_crt.c index 2a5dbb8783..3cf1743821 100644 --- a/thirdparty/mbedtls/library/x509_crt.c +++ b/thirdparty/mbedtls/library/x509_crt.c @@ -27,6 +27,8 @@ * * http://www.itu.int/ITU-T/studygroups/com17/languages/X.680-0207.pdf * http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf + * + * [SIRO] https://cabforum.org/wp-content/uploads/Chunghwatelecom201503cabforumV4.pdf */ #if !defined(MBEDTLS_CONFIG_FILE) @@ -39,6 +41,7 @@ #include "mbedtls/x509_crt.h" #include "mbedtls/oid.h" +#include "mbedtls/platform_util.h" #include <stdio.h> #include <string.h> @@ -88,10 +91,18 @@ #endif /* !_WIN32 || EFIX64 || EFI32 */ #endif -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize( void *v, size_t n ) { - volatile unsigned char *p = v; while( n-- ) *p++ = 0; -} +/* + * Item in a verification chain: cert and flags for it + */ +typedef struct { + mbedtls_x509_crt *crt; + uint32_t flags; +} x509_crt_verify_chain_item; + +/* + * Max size of verification chain: end-entity + intermediates + trusted root + */ +#define X509_MAX_VERIFY_CHAIN_SIZE ( MBEDTLS_X509_MAX_INTERMEDIATE_CA + 2 ) /* * Default profile @@ -160,7 +171,7 @@ const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_suiteb = /* * Check md_alg against profile - * Return 0 if md_alg acceptable for this profile, -1 otherwise + * Return 0 if md_alg is acceptable for this profile, -1 otherwise */ static int x509_profile_check_md_alg( const mbedtls_x509_crt_profile *profile, mbedtls_md_type_t md_alg ) @@ -173,7 +184,7 @@ static int x509_profile_check_md_alg( const mbedtls_x509_crt_profile *profile, /* * Check pk_alg against profile - * Return 0 if pk_alg acceptable for this profile, -1 otherwise + * Return 0 if pk_alg is acceptable for this profile, -1 otherwise */ static int x509_profile_check_pk_alg( const mbedtls_x509_crt_profile *profile, mbedtls_pk_type_t pk_alg ) @@ -186,12 +197,13 @@ static int x509_profile_check_pk_alg( const mbedtls_x509_crt_profile *profile, /* * Check key against profile - * Return 0 if pk_alg acceptable for this profile, -1 otherwise + * Return 0 if pk is acceptable for this profile, -1 otherwise */ static int x509_profile_check_key( const mbedtls_x509_crt_profile *profile, - mbedtls_pk_type_t pk_alg, const mbedtls_pk_context *pk ) { + const mbedtls_pk_type_t pk_alg = mbedtls_pk_get_type( pk ); + #if defined(MBEDTLS_RSA_C) if( pk_alg == MBEDTLS_PK_RSA || pk_alg == MBEDTLS_PK_RSASSA_PSS ) { @@ -207,7 +219,7 @@ static int x509_profile_check_key( const mbedtls_x509_crt_profile *profile, pk_alg == MBEDTLS_PK_ECKEY || pk_alg == MBEDTLS_PK_ECKEY_DH ) { - mbedtls_ecp_group_id gid = mbedtls_pk_ec( *pk )->grp.id; + const mbedtls_ecp_group_id gid = mbedtls_pk_ec( *pk )->grp.id; if( ( profile->allowed_curves & MBEDTLS_X509_ID_FLAG( gid ) ) != 0 ) return( 0 ); @@ -730,7 +742,7 @@ static int x509_crt_parse_der_core( mbedtls_x509_crt *crt, const unsigned char * memcpy( p, buf, crt->raw.len ); - // Direct pointers to the new buffer + // Direct pointers to the new buffer p += crt->raw.len - len; end = crt_end = p + len; @@ -1112,7 +1124,7 @@ int mbedtls_x509_crt_parse_file( mbedtls_x509_crt *chain, const char *path ) ret = mbedtls_x509_crt_parse( chain, buf, n ); - mbedtls_zeroize( buf, n ); + mbedtls_platform_zeroize( buf, n ); mbedtls_free( buf ); return( ret ); @@ -1127,7 +1139,7 @@ int mbedtls_x509_crt_parse_path( mbedtls_x509_crt *chain, const char *path ) char filename[MAX_PATH]; char *p; size_t len = strlen( path ); - int lengthAsInt = 0; + int length_as_int = 0; WIN32_FIND_DATAW file_data; HANDLE hFind; @@ -1142,7 +1154,7 @@ int mbedtls_x509_crt_parse_path( mbedtls_x509_crt *chain, const char *path ) p = filename + len; filename[len++] = '*'; - if ( FAILED ( SizeTToInt( len, &lengthAsInt ) ) ) + if ( FAILED ( SizeTToInt( len, &length_as_int ) ) ) return( MBEDTLS_ERR_X509_FILE_IO_ERROR ); /* @@ -1153,7 +1165,7 @@ int mbedtls_x509_crt_parse_path( mbedtls_x509_crt *chain, const char *path ) * incoming string are less than MAX_PATH to avoid a buffer overrun with * MultiByteToWideChar(). */ - w_ret = MultiByteToWideChar( CP_ACP, 0, filename, lengthAsInt, szDir, + w_ret = MultiByteToWideChar( CP_ACP, 0, filename, length_as_int, szDir, MAX_PATH - 3 ); if( w_ret == 0 ) return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); @@ -1170,11 +1182,11 @@ int mbedtls_x509_crt_parse_path( mbedtls_x509_crt *chain, const char *path ) if( file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) continue; - if ( FAILED( SizeTToInt( wcslen( file_data.cFileName ), &lengthAsInt ) ) ) + if ( FAILED( SizeTToInt( wcslen( file_data.cFileName ), &length_as_int ) ) ) return( MBEDTLS_ERR_X509_FILE_IO_ERROR ); w_ret = WideCharToMultiByte( CP_ACP, 0, file_data.cFileName, - lengthAsInt, + length_as_int, p, (int) len - 1, NULL, NULL ); if( w_ret == 0 ) @@ -1662,7 +1674,7 @@ int mbedtls_x509_crt_is_revoked( const mbedtls_x509_crt *crt, const mbedtls_x509 /* * Check that the given certificate is not revoked according to the CRL. - * Skip validation is no CRL for the given CA is present. + * Skip validation if no CRL for the given CA is present. */ static int x509_crt_verifycrl( mbedtls_x509_crt *crt, mbedtls_x509_crt *ca, mbedtls_x509_crl *crl_list, @@ -1707,18 +1719,14 @@ static int x509_crt_verifycrl( mbedtls_x509_crt *crt, mbedtls_x509_crt *ca, flags |= MBEDTLS_X509_BADCRL_BAD_PK; md_info = mbedtls_md_info_from_type( crl_list->sig_md ); - if( md_info == NULL ) + if( mbedtls_md( md_info, crl_list->tbs.p, crl_list->tbs.len, hash ) != 0 ) { - /* - * Cannot check 'unknown' hash - */ + /* Note: this can't happen except after an internal error */ flags |= MBEDTLS_X509_BADCRL_NOT_TRUSTED; break; } - mbedtls_md( md_info, crl_list->tbs.p, crl_list->tbs.len, hash ); - - if( x509_profile_check_key( profile, crl_list->sig_pk, &ca->pk ) != 0 ) + if( x509_profile_check_key( profile, &ca->pk ) != 0 ) flags |= MBEDTLS_X509_BADCERT_BAD_KEY; if( mbedtls_pk_verify_ext( crl_list->sig_pk, crl_list->sig_opts, &ca->pk, @@ -1786,13 +1794,14 @@ static int x509_memcasecmp( const void *s1, const void *s2, size_t len ) /* * Return 0 if name matches wildcard, -1 otherwise */ -static int x509_check_wildcard( const char *cn, mbedtls_x509_buf *name ) +static int x509_check_wildcard( const char *cn, const mbedtls_x509_buf *name ) { size_t i; size_t cn_idx = 0, cn_len = strlen( cn ); + /* We can't have a match if there is no wildcard to match */ if( name->len < 3 || name->p[0] != '*' || name->p[1] != '.' ) - return( 0 ); + return( -1 ); for( i = 0; i < cn_len; ++i ) { @@ -1884,15 +1893,40 @@ static int x509_name_cmp( const mbedtls_x509_name *a, const mbedtls_x509_name *b } /* + * Check the signature of a certificate by its parent + */ +static int x509_crt_check_signature( const mbedtls_x509_crt *child, + mbedtls_x509_crt *parent ) +{ + const mbedtls_md_info_t *md_info; + unsigned char hash[MBEDTLS_MD_MAX_SIZE]; + + md_info = mbedtls_md_info_from_type( child->sig_md ); + if( mbedtls_md( md_info, child->tbs.p, child->tbs.len, hash ) != 0 ) + { + /* Note: this can't happen except after an internal error */ + return( -1 ); + } + + if( mbedtls_pk_verify_ext( child->sig_pk, child->sig_opts, &parent->pk, + child->sig_md, hash, mbedtls_md_get_size( md_info ), + child->sig.p, child->sig.len ) != 0 ) + { + return( -1 ); + } + + return( 0 ); +} + +/* * Check if 'parent' is a suitable parent (signing CA) for 'child'. * Return 0 if yes, -1 if not. * * top means parent is a locally-trusted certificate - * bottom means child is the end entity cert */ static int x509_crt_check_parent( const mbedtls_x509_crt *child, const mbedtls_x509_crt *parent, - int top, int bottom ) + int top ) { int need_ca_bit; @@ -1907,14 +1941,6 @@ static int x509_crt_check_parent( const mbedtls_x509_crt *child, if( top && parent->version < 3 ) need_ca_bit = 0; - /* Exception: self-signed end-entity certs that are locally trusted. */ - if( top && bottom && - child->raw.len == parent->raw.len && - memcmp( child->raw.p, parent->raw.p, child->raw.len ) == 0 ) - { - need_ca_bit = 0; - } - if( need_ca_bit && ! parent->ca_istrue ) return( -1 ); @@ -1929,86 +1955,78 @@ static int x509_crt_check_parent( const mbedtls_x509_crt *child, return( 0 ); } -static int x509_crt_verify_top( - mbedtls_x509_crt *child, mbedtls_x509_crt *trust_ca, - mbedtls_x509_crl *ca_crl, - const mbedtls_x509_crt_profile *profile, - int path_cnt, int self_cnt, uint32_t *flags, - int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), - void *p_vrfy ) +/* + * Find a suitable parent for child in candidates, or return NULL. + * + * Here suitable is defined as: + * 1. subject name matches child's issuer + * 2. if necessary, the CA bit is set and key usage allows signing certs + * 3. for trusted roots, the signature is correct + * 4. pathlen constraints are satisfied + * + * If there's a suitable candidate which is also time-valid, return the first + * such. Otherwise, return the first suitable candidate (or NULL if there is + * none). + * + * The rationale for this rule is that someone could have a list of trusted + * roots with two versions on the same root with different validity periods. + * (At least one user reported having such a list and wanted it to just work.) + * The reason we don't just require time-validity is that generally there is + * only one version, and if it's expired we want the flags to state that + * rather than NOT_TRUSTED, as would be the case if we required it here. + * + * The rationale for rule 3 (signature for trusted roots) is that users might + * have two versions of the same CA with different keys in their list, and the + * way we select the correct one is by checking the signature (as we don't + * rely on key identifier extensions). (This is one way users might choose to + * handle key rollover, another relies on self-issued certs, see [SIRO].) + * + * Arguments: + * - [in] child: certificate for which we're looking for a parent + * - [in] candidates: chained list of potential parents + * - [in] top: 1 if candidates consists of trusted roots, ie we're at the top + * of the chain, 0 otherwise + * - [in] path_cnt: number of intermediates seen so far + * - [in] self_cnt: number of self-signed intermediates seen so far + * (will never be greater than path_cnt) + * + * Return value: + * - the first suitable parent found (see above regarding time-validity) + * - NULL if no suitable parent was found + */ +static mbedtls_x509_crt *x509_crt_find_parent_in( mbedtls_x509_crt *child, + mbedtls_x509_crt *candidates, + int top, + size_t path_cnt, + size_t self_cnt ) { - int ret; - uint32_t ca_flags = 0; - int check_path_cnt; - unsigned char hash[MBEDTLS_MD_MAX_SIZE]; - const mbedtls_md_info_t *md_info; - mbedtls_x509_crt *future_past_ca = NULL; + mbedtls_x509_crt *parent, *badtime_parent = NULL; - if( mbedtls_x509_time_is_past( &child->valid_to ) ) - *flags |= MBEDTLS_X509_BADCERT_EXPIRED; - - if( mbedtls_x509_time_is_future( &child->valid_from ) ) - *flags |= MBEDTLS_X509_BADCERT_FUTURE; - - if( x509_profile_check_md_alg( profile, child->sig_md ) != 0 ) - *flags |= MBEDTLS_X509_BADCERT_BAD_MD; - - if( x509_profile_check_pk_alg( profile, child->sig_pk ) != 0 ) - *flags |= MBEDTLS_X509_BADCERT_BAD_PK; - - /* - * Child is the top of the chain. Check against the trust_ca list. - */ - *flags |= MBEDTLS_X509_BADCERT_NOT_TRUSTED; - - md_info = mbedtls_md_info_from_type( child->sig_md ); - if( md_info == NULL ) + for( parent = candidates; parent != NULL; parent = parent->next ) { - /* - * Cannot check 'unknown', no need to try any CA - */ - trust_ca = NULL; - } - else - mbedtls_md( md_info, child->tbs.p, child->tbs.len, hash ); - - for( /* trust_ca */ ; trust_ca != NULL; trust_ca = trust_ca->next ) - { - if( x509_crt_check_parent( child, trust_ca, 1, path_cnt == 0 ) != 0 ) + /* basic parenting skills (name, CA bit, key usage) */ + if( x509_crt_check_parent( child, parent, top ) != 0 ) continue; - check_path_cnt = path_cnt + 1; - - /* - * Reduce check_path_cnt to check against if top of the chain is - * the same as the trusted CA - */ - if( child->subject_raw.len == trust_ca->subject_raw.len && - memcmp( child->subject_raw.p, trust_ca->subject_raw.p, - child->issuer_raw.len ) == 0 ) - { - check_path_cnt--; - } - - /* Self signed certificates do not count towards the limit */ - if( trust_ca->max_pathlen > 0 && - trust_ca->max_pathlen < check_path_cnt - self_cnt ) + /* +1 because stored max_pathlen is 1 higher that the actual value */ + if( parent->max_pathlen > 0 && + (size_t) parent->max_pathlen < 1 + path_cnt - self_cnt ) { continue; } - if( mbedtls_pk_verify_ext( child->sig_pk, child->sig_opts, &trust_ca->pk, - child->sig_md, hash, mbedtls_md_get_size( md_info ), - child->sig.p, child->sig.len ) != 0 ) + /* Signature */ + if( top && x509_crt_check_signature( child, parent ) != 0 ) { continue; } - if( mbedtls_x509_time_is_past( &trust_ca->valid_to ) || - mbedtls_x509_time_is_future( &trust_ca->valid_from ) ) + /* optional time check */ + if( mbedtls_x509_time_is_past( &parent->valid_to ) || + mbedtls_x509_time_is_future( &parent->valid_from ) ) { - if ( future_past_ca == NULL ) - future_past_ca = trust_ca; + if( badtime_parent == NULL ) + badtime_parent = parent; continue; } @@ -2016,190 +2034,292 @@ static int x509_crt_verify_top( break; } - if( trust_ca != NULL || ( trust_ca = future_past_ca ) != NULL ) - { - /* - * Top of chain is signed by a trusted CA - */ - *flags &= ~MBEDTLS_X509_BADCERT_NOT_TRUSTED; + if( parent == NULL ) + parent = badtime_parent; - if( x509_profile_check_key( profile, child->sig_pk, &trust_ca->pk ) != 0 ) - *flags |= MBEDTLS_X509_BADCERT_BAD_KEY; - } + return( parent ); +} - /* - * If top of chain is not the same as the trusted CA send a verify request - * to the callback for any issues with validity and CRL presence for the - * trusted CA certificate. - */ - if( trust_ca != NULL && - ( child->subject_raw.len != trust_ca->subject_raw.len || - memcmp( child->subject_raw.p, trust_ca->subject_raw.p, - child->issuer_raw.len ) != 0 ) ) - { -#if defined(MBEDTLS_X509_CRL_PARSE_C) - /* Check trusted CA's CRL for the chain's top crt */ - *flags |= x509_crt_verifycrl( child, trust_ca, ca_crl, profile ); -#else - ((void) ca_crl); -#endif +/* + * Find a parent in trusted CAs or the provided chain, or return NULL. + * + * Searches in trusted CAs first, and return the first suitable parent found + * (see find_parent_in() for definition of suitable). + * + * Arguments: + * - [in] child: certificate for which we're looking for a parent, followed + * by a chain of possible intermediates + * - [in] trust_ca: locally trusted CAs + * - [out] 1 if parent was found in trust_ca, 0 if found in provided chain + * - [in] path_cnt: number of intermediates seen so far + * - [in] self_cnt: number of self-signed intermediates seen so far + * (will always be no greater than path_cnt) + * + * Return value: + * - the first suitable parent found (see find_parent_in() for "suitable") + * - NULL if no suitable parent was found + */ +static mbedtls_x509_crt *x509_crt_find_parent( mbedtls_x509_crt *child, + mbedtls_x509_crt *trust_ca, + int *parent_is_trusted, + size_t path_cnt, + size_t self_cnt ) +{ + mbedtls_x509_crt *parent; - if( mbedtls_x509_time_is_past( &trust_ca->valid_to ) ) - ca_flags |= MBEDTLS_X509_BADCERT_EXPIRED; + /* Look for a parent in trusted CAs */ + *parent_is_trusted = 1; + parent = x509_crt_find_parent_in( child, trust_ca, 1, path_cnt, self_cnt ); - if( mbedtls_x509_time_is_future( &trust_ca->valid_from ) ) - ca_flags |= MBEDTLS_X509_BADCERT_FUTURE; + if( parent != NULL ) + return( parent ); - if( NULL != f_vrfy ) - { - if( ( ret = f_vrfy( p_vrfy, trust_ca, path_cnt + 1, - &ca_flags ) ) != 0 ) - { - return( ret ); - } - } - } + /* Look for a parent upwards the chain */ + *parent_is_trusted = 0; + return( x509_crt_find_parent_in( child, child->next, 0, path_cnt, self_cnt ) ); +} - /* Call callback on top cert */ - if( NULL != f_vrfy ) +/* + * Check if an end-entity certificate is locally trusted + * + * Currently we require such certificates to be self-signed (actually only + * check for self-issued as self-signatures are not checked) + */ +static int x509_crt_check_ee_locally_trusted( + mbedtls_x509_crt *crt, + mbedtls_x509_crt *trust_ca ) +{ + mbedtls_x509_crt *cur; + + /* must be self-issued */ + if( x509_name_cmp( &crt->issuer, &crt->subject ) != 0 ) + return( -1 ); + + /* look for an exact match with trusted cert */ + for( cur = trust_ca; cur != NULL; cur = cur->next ) { - if( ( ret = f_vrfy( p_vrfy, child, path_cnt, flags ) ) != 0 ) - return( ret ); + if( crt->raw.len == cur->raw.len && + memcmp( crt->raw.p, cur->raw.p, crt->raw.len ) == 0 ) + { + return( 0 ); + } } - *flags |= ca_flags; - - return( 0 ); + /* too bad */ + return( -1 ); } -static int x509_crt_verify_child( - mbedtls_x509_crt *child, mbedtls_x509_crt *parent, - mbedtls_x509_crt *trust_ca, mbedtls_x509_crl *ca_crl, +/* + * Build and verify a certificate chain + * + * Given a peer-provided list of certificates EE, C1, ..., Cn and + * a list of trusted certs R1, ... Rp, try to build and verify a chain + * EE, Ci1, ... Ciq [, Rj] + * such that every cert in the chain is a child of the next one, + * jumping to a trusted root as early as possible. + * + * Verify that chain and return it with flags for all issues found. + * + * Special cases: + * - EE == Rj -> return a one-element list containing it + * - EE, Ci1, ..., Ciq cannot be continued with a trusted root + * -> return that chain with NOT_TRUSTED set on Ciq + * + * Arguments: + * - [in] crt: the cert list EE, C1, ..., Cn + * - [in] trust_ca: the trusted list R1, ..., Rp + * - [in] ca_crl, profile: as in verify_with_profile() + * - [out] ver_chain, chain_len: the built and verified chain + * + * Return value: + * - non-zero if the chain could not be fully built and examined + * - 0 is the chain was successfully built and examined, + * even if it was found to be invalid + */ +static int x509_crt_verify_chain( + mbedtls_x509_crt *crt, + mbedtls_x509_crt *trust_ca, + mbedtls_x509_crl *ca_crl, const mbedtls_x509_crt_profile *profile, - int path_cnt, int self_cnt, uint32_t *flags, - int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), - void *p_vrfy ) + x509_crt_verify_chain_item ver_chain[X509_MAX_VERIFY_CHAIN_SIZE], + size_t *chain_len ) { - int ret; - uint32_t parent_flags = 0; - unsigned char hash[MBEDTLS_MD_MAX_SIZE]; - mbedtls_x509_crt *grandparent; - const mbedtls_md_info_t *md_info; + uint32_t *flags; + mbedtls_x509_crt *child; + mbedtls_x509_crt *parent; + int parent_is_trusted = 0; + int child_is_trusted = 0; + size_t self_cnt = 0; - /* Counting intermediate self signed certificates */ - if( ( path_cnt != 0 ) && x509_name_cmp( &child->issuer, &child->subject ) == 0 ) - self_cnt++; + child = crt; + *chain_len = 0; - /* path_cnt is 0 for the first intermediate CA */ - if( 1 + path_cnt > MBEDTLS_X509_MAX_INTERMEDIATE_CA ) - { - /* return immediately as the goal is to avoid unbounded recursion */ - return( MBEDTLS_ERR_X509_FATAL_ERROR ); - } + while( 1 ) { + /* Add certificate to the verification chain */ + ver_chain[*chain_len].crt = child; + flags = &ver_chain[*chain_len].flags; + ++*chain_len; - if( mbedtls_x509_time_is_past( &child->valid_to ) ) - *flags |= MBEDTLS_X509_BADCERT_EXPIRED; + /* Check time-validity (all certificates) */ + if( mbedtls_x509_time_is_past( &child->valid_to ) ) + *flags |= MBEDTLS_X509_BADCERT_EXPIRED; - if( mbedtls_x509_time_is_future( &child->valid_from ) ) - *flags |= MBEDTLS_X509_BADCERT_FUTURE; + if( mbedtls_x509_time_is_future( &child->valid_from ) ) + *flags |= MBEDTLS_X509_BADCERT_FUTURE; - if( x509_profile_check_md_alg( profile, child->sig_md ) != 0 ) - *flags |= MBEDTLS_X509_BADCERT_BAD_MD; + /* Stop here for trusted roots (but not for trusted EE certs) */ + if( child_is_trusted ) + return( 0 ); - if( x509_profile_check_pk_alg( profile, child->sig_pk ) != 0 ) - *flags |= MBEDTLS_X509_BADCERT_BAD_PK; + /* Check signature algorithm: MD & PK algs */ + if( x509_profile_check_md_alg( profile, child->sig_md ) != 0 ) + *flags |= MBEDTLS_X509_BADCERT_BAD_MD; - md_info = mbedtls_md_info_from_type( child->sig_md ); - if( md_info == NULL ) - { - /* - * Cannot check 'unknown' hash - */ - *flags |= MBEDTLS_X509_BADCERT_NOT_TRUSTED; - } - else - { - mbedtls_md( md_info, child->tbs.p, child->tbs.len, hash ); + if( x509_profile_check_pk_alg( profile, child->sig_pk ) != 0 ) + *flags |= MBEDTLS_X509_BADCERT_BAD_PK; - if( x509_profile_check_key( profile, child->sig_pk, &parent->pk ) != 0 ) - *flags |= MBEDTLS_X509_BADCERT_BAD_KEY; + /* Special case: EE certs that are locally trusted */ + if( *chain_len == 1 && + x509_crt_check_ee_locally_trusted( child, trust_ca ) == 0 ) + { + return( 0 ); + } - if( mbedtls_pk_verify_ext( child->sig_pk, child->sig_opts, &parent->pk, - child->sig_md, hash, mbedtls_md_get_size( md_info ), - child->sig.p, child->sig.len ) != 0 ) + /* Look for a parent in trusted CAs or up the chain */ + parent = x509_crt_find_parent( child, trust_ca, &parent_is_trusted, + *chain_len - 1, self_cnt ); + + /* No parent? We're done here */ + if( parent == NULL ) { *flags |= MBEDTLS_X509_BADCERT_NOT_TRUSTED; + return( 0 ); + } + + /* Count intermediate self-issued (not necessarily self-signed) certs. + * These can occur with some strategies for key rollover, see [SIRO], + * and should be excluded from max_pathlen checks. */ + if( *chain_len != 1 && + x509_name_cmp( &child->issuer, &child->subject ) == 0 ) + { + self_cnt++; } - } + + /* path_cnt is 0 for the first intermediate CA, + * and if parent is trusted it's not an intermediate CA */ + if( ! parent_is_trusted && + *chain_len > MBEDTLS_X509_MAX_INTERMEDIATE_CA ) + { + /* return immediately to avoid overflow the chain array */ + return( MBEDTLS_ERR_X509_FATAL_ERROR ); + } + + /* if parent is trusted, the signature was checked by find_parent() */ + if( ! parent_is_trusted && x509_crt_check_signature( child, parent ) != 0 ) + *flags |= MBEDTLS_X509_BADCERT_NOT_TRUSTED; + + /* check size of signing key */ + if( x509_profile_check_key( profile, &parent->pk ) != 0 ) + *flags |= MBEDTLS_X509_BADCERT_BAD_KEY; #if defined(MBEDTLS_X509_CRL_PARSE_C) - /* Check trusted CA's CRL for the given crt */ - *flags |= x509_crt_verifycrl(child, parent, ca_crl, profile ); + /* Check trusted CA's CRL for the given crt */ + *flags |= x509_crt_verifycrl( child, parent, ca_crl, profile ); +#else + (void) ca_crl; #endif - /* Look for a grandparent in trusted CAs */ - for( grandparent = trust_ca; - grandparent != NULL; - grandparent = grandparent->next ) + /* prepare for next iteration */ + child = parent; + parent = NULL; + child_is_trusted = parent_is_trusted; + } +} + +/* + * Check for CN match + */ +static int x509_crt_check_cn( const mbedtls_x509_buf *name, + const char *cn, size_t cn_len ) +{ + /* try exact match */ + if( name->len == cn_len && + x509_memcasecmp( cn, name->p, cn_len ) == 0 ) { - if( x509_crt_check_parent( parent, grandparent, - 0, path_cnt == 0 ) == 0 ) - break; + return( 0 ); } - if( grandparent != NULL ) + /* try wildcard match */ + if( x509_check_wildcard( cn, name ) == 0 ) { - ret = x509_crt_verify_top( parent, grandparent, ca_crl, profile, - path_cnt + 1, self_cnt, &parent_flags, f_vrfy, p_vrfy ); - if( ret != 0 ) - return( ret ); + return( 0 ); } - else + + return( -1 ); +} + +/* + * Verify the requested CN - only call this if cn is not NULL! + */ +static void x509_crt_verify_name( const mbedtls_x509_crt *crt, + const char *cn, + uint32_t *flags ) +{ + const mbedtls_x509_name *name; + const mbedtls_x509_sequence *cur; + size_t cn_len = strlen( cn ); + + if( crt->ext_types & MBEDTLS_X509_EXT_SUBJECT_ALT_NAME ) { - /* Look for a grandparent upwards the chain */ - for( grandparent = parent->next; - grandparent != NULL; - grandparent = grandparent->next ) + for( cur = &crt->subject_alt_names; cur != NULL; cur = cur->next ) { - /* +2 because the current step is not yet accounted for - * and because max_pathlen is one higher than it should be. - * Also self signed certificates do not count to the limit. */ - if( grandparent->max_pathlen > 0 && - grandparent->max_pathlen < 2 + path_cnt - self_cnt ) - { - continue; - } - - if( x509_crt_check_parent( parent, grandparent, - 0, path_cnt == 0 ) == 0 ) + if( x509_crt_check_cn( &cur->buf, cn, cn_len ) == 0 ) break; } - /* Is our parent part of the chain or at the top? */ - if( grandparent != NULL ) - { - ret = x509_crt_verify_child( parent, grandparent, trust_ca, ca_crl, - profile, path_cnt + 1, self_cnt, &parent_flags, - f_vrfy, p_vrfy ); - if( ret != 0 ) - return( ret ); - } - else + if( cur == NULL ) + *flags |= MBEDTLS_X509_BADCERT_CN_MISMATCH; + } + else + { + for( name = &crt->subject; name != NULL; name = name->next ) { - ret = x509_crt_verify_top( parent, trust_ca, ca_crl, profile, - path_cnt + 1, self_cnt, &parent_flags, - f_vrfy, p_vrfy ); - if( ret != 0 ) - return( ret ); + if( MBEDTLS_OID_CMP( MBEDTLS_OID_AT_CN, &name->oid ) == 0 && + x509_crt_check_cn( &name->val, cn, cn_len ) == 0 ) + { + break; + } } + + if( name == NULL ) + *flags |= MBEDTLS_X509_BADCERT_CN_MISMATCH; } +} - /* child is verified to be a child of the parent, call verify callback */ - if( NULL != f_vrfy ) - if( ( ret = f_vrfy( p_vrfy, child, path_cnt, flags ) ) != 0 ) - return( ret ); +/* + * Merge the flags for all certs in the chain, after calling callback + */ +static int x509_crt_merge_flags_with_cb( + uint32_t *flags, + x509_crt_verify_chain_item ver_chain[X509_MAX_VERIFY_CHAIN_SIZE], + size_t chain_len, + int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), + void *p_vrfy ) +{ + int ret; + size_t i; + uint32_t cur_flags; + + for( i = chain_len; i != 0; --i ) + { + cur_flags = ver_chain[i-1].flags; + + if( NULL != f_vrfy ) + if( ( ret = f_vrfy( p_vrfy, ver_chain[i-1].crt, (int) i-1, &cur_flags ) ) != 0 ) + return( ret ); - *flags |= parent_flags; + *flags |= cur_flags; + } return( 0 ); } @@ -2218,9 +2338,15 @@ int mbedtls_x509_crt_verify( mbedtls_x509_crt *crt, &mbedtls_x509_crt_profile_default, cn, flags, f_vrfy, p_vrfy ) ); } - /* * Verify the certificate validity, with profile + * + * This function: + * - checks the requested CN (if any) + * - checks the type and size of the EE cert's key, + * as that isn't done as part of chain building/verification currently + * - builds and verifies the chain + * - then calls the callback and merges the flags */ int mbedtls_x509_crt_verify_with_profile( mbedtls_x509_crt *crt, mbedtls_x509_crt *trust_ca, @@ -2230,15 +2356,15 @@ int mbedtls_x509_crt_verify_with_profile( mbedtls_x509_crt *crt, int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), void *p_vrfy ) { - size_t cn_len; int ret; - int pathlen = 0, selfsigned = 0; - mbedtls_x509_crt *parent; - mbedtls_x509_name *name; - mbedtls_x509_sequence *cur = NULL; mbedtls_pk_type_t pk_type; + x509_crt_verify_chain_item ver_chain[X509_MAX_VERIFY_CHAIN_SIZE]; + size_t chain_len; + uint32_t *ee_flags = &ver_chain[0].flags; *flags = 0; + memset( ver_chain, 0, sizeof( ver_chain ) ); + chain_len = 0; if( profile == NULL ) { @@ -2246,104 +2372,28 @@ int mbedtls_x509_crt_verify_with_profile( mbedtls_x509_crt *crt, goto exit; } + /* check name if requested */ if( cn != NULL ) - { - name = &crt->subject; - cn_len = strlen( cn ); - - if( crt->ext_types & MBEDTLS_X509_EXT_SUBJECT_ALT_NAME ) - { - cur = &crt->subject_alt_names; - - while( cur != NULL ) - { - if( cur->buf.len == cn_len && - x509_memcasecmp( cn, cur->buf.p, cn_len ) == 0 ) - break; - - if( cur->buf.len > 2 && - memcmp( cur->buf.p, "*.", 2 ) == 0 && - x509_check_wildcard( cn, &cur->buf ) == 0 ) - { - break; - } - - cur = cur->next; - } - - if( cur == NULL ) - *flags |= MBEDTLS_X509_BADCERT_CN_MISMATCH; - } - else - { - while( name != NULL ) - { - if( MBEDTLS_OID_CMP( MBEDTLS_OID_AT_CN, &name->oid ) == 0 ) - { - if( name->val.len == cn_len && - x509_memcasecmp( name->val.p, cn, cn_len ) == 0 ) - break; - - if( name->val.len > 2 && - memcmp( name->val.p, "*.", 2 ) == 0 && - x509_check_wildcard( cn, &name->val ) == 0 ) - break; - } - - name = name->next; - } - - if( name == NULL ) - *flags |= MBEDTLS_X509_BADCERT_CN_MISMATCH; - } - } + x509_crt_verify_name( crt, cn, ee_flags ); /* Check the type and size of the key */ pk_type = mbedtls_pk_get_type( &crt->pk ); if( x509_profile_check_pk_alg( profile, pk_type ) != 0 ) - *flags |= MBEDTLS_X509_BADCERT_BAD_PK; + *ee_flags |= MBEDTLS_X509_BADCERT_BAD_PK; - if( x509_profile_check_key( profile, pk_type, &crt->pk ) != 0 ) - *flags |= MBEDTLS_X509_BADCERT_BAD_KEY; + if( x509_profile_check_key( profile, &crt->pk ) != 0 ) + *ee_flags |= MBEDTLS_X509_BADCERT_BAD_KEY; - /* Look for a parent in trusted CAs */ - for( parent = trust_ca; parent != NULL; parent = parent->next ) - { - if( x509_crt_check_parent( crt, parent, 0, pathlen == 0 ) == 0 ) - break; - } - - if( parent != NULL ) - { - ret = x509_crt_verify_top( crt, parent, ca_crl, profile, - pathlen, selfsigned, flags, f_vrfy, p_vrfy ); - if( ret != 0 ) - goto exit; - } - else - { - /* Look for a parent upwards the chain */ - for( parent = crt->next; parent != NULL; parent = parent->next ) - if( x509_crt_check_parent( crt, parent, 0, pathlen == 0 ) == 0 ) - break; + /* Check the chain */ + ret = x509_crt_verify_chain( crt, trust_ca, ca_crl, profile, + ver_chain, &chain_len ); + if( ret != 0 ) + goto exit; - /* Are we part of the chain or at the top? */ - if( parent != NULL ) - { - ret = x509_crt_verify_child( crt, parent, trust_ca, ca_crl, profile, - pathlen, selfsigned, flags, f_vrfy, p_vrfy ); - if( ret != 0 ) - goto exit; - } - else - { - ret = x509_crt_verify_top( crt, trust_ca, ca_crl, profile, - pathlen, selfsigned, flags, f_vrfy, p_vrfy ); - if( ret != 0 ) - goto exit; - } - } + /* Build final flags, calling callback on the way if any */ + ret = x509_crt_merge_flags_with_cb( flags, + ver_chain, chain_len, f_vrfy, p_vrfy ); exit: /* prevent misuse of the vrfy callback - VERIFY_FAILED would be ignored by @@ -2400,7 +2450,7 @@ void mbedtls_x509_crt_free( mbedtls_x509_crt *crt ) { name_prv = name_cur; name_cur = name_cur->next; - mbedtls_zeroize( name_prv, sizeof( mbedtls_x509_name ) ); + mbedtls_platform_zeroize( name_prv, sizeof( mbedtls_x509_name ) ); mbedtls_free( name_prv ); } @@ -2409,7 +2459,7 @@ void mbedtls_x509_crt_free( mbedtls_x509_crt *crt ) { name_prv = name_cur; name_cur = name_cur->next; - mbedtls_zeroize( name_prv, sizeof( mbedtls_x509_name ) ); + mbedtls_platform_zeroize( name_prv, sizeof( mbedtls_x509_name ) ); mbedtls_free( name_prv ); } @@ -2418,7 +2468,8 @@ void mbedtls_x509_crt_free( mbedtls_x509_crt *crt ) { seq_prv = seq_cur; seq_cur = seq_cur->next; - mbedtls_zeroize( seq_prv, sizeof( mbedtls_x509_sequence ) ); + mbedtls_platform_zeroize( seq_prv, + sizeof( mbedtls_x509_sequence ) ); mbedtls_free( seq_prv ); } @@ -2427,13 +2478,14 @@ void mbedtls_x509_crt_free( mbedtls_x509_crt *crt ) { seq_prv = seq_cur; seq_cur = seq_cur->next; - mbedtls_zeroize( seq_prv, sizeof( mbedtls_x509_sequence ) ); + mbedtls_platform_zeroize( seq_prv, + sizeof( mbedtls_x509_sequence ) ); mbedtls_free( seq_prv ); } if( cert_cur->raw.p != NULL ) { - mbedtls_zeroize( cert_cur->raw.p, cert_cur->raw.len ); + mbedtls_platform_zeroize( cert_cur->raw.p, cert_cur->raw.len ); mbedtls_free( cert_cur->raw.p ); } @@ -2447,7 +2499,7 @@ void mbedtls_x509_crt_free( mbedtls_x509_crt *crt ) cert_prv = cert_cur; cert_cur = cert_cur->next; - mbedtls_zeroize( cert_prv, sizeof( mbedtls_x509_crt ) ); + mbedtls_platform_zeroize( cert_prv, sizeof( mbedtls_x509_crt ) ); if( cert_prv != crt ) mbedtls_free( cert_prv ); } diff --git a/thirdparty/mbedtls/library/x509_csr.c b/thirdparty/mbedtls/library/x509_csr.c index 26a06db4f6..f84425728a 100644 --- a/thirdparty/mbedtls/library/x509_csr.c +++ b/thirdparty/mbedtls/library/x509_csr.c @@ -39,6 +39,7 @@ #include "mbedtls/x509_csr.h" #include "mbedtls/oid.h" +#include "mbedtls/platform_util.h" #include <string.h> @@ -60,11 +61,6 @@ #include <stdio.h> #endif -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize( void *v, size_t n ) { - volatile unsigned char *p = v; while( n-- ) *p++ = 0; -} - /* * Version ::= INTEGER { v1(0) } */ @@ -278,34 +274,25 @@ int mbedtls_x509_csr_parse( mbedtls_x509_csr *csr, const unsigned char *buf, siz return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); #if defined(MBEDTLS_PEM_PARSE_C) - mbedtls_pem_init( &pem ); - /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ - if( buf[buflen - 1] != '\0' ) - ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; - else + if( buf[buflen - 1] == '\0' ) + { + mbedtls_pem_init( &pem ); ret = mbedtls_pem_read_buffer( &pem, "-----BEGIN CERTIFICATE REQUEST-----", "-----END CERTIFICATE REQUEST-----", buf, NULL, 0, &use_len ); - if( ret == 0 ) - { - /* - * Was PEM encoded, parse the result - */ - if( ( ret = mbedtls_x509_csr_parse_der( csr, pem.buf, pem.buflen ) ) != 0 ) - return( ret ); + if( ret == 0 ) + /* + * Was PEM encoded, parse the result + */ + ret = mbedtls_x509_csr_parse_der( csr, pem.buf, pem.buflen ); mbedtls_pem_free( &pem ); - return( 0 ); - } - else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) - { - mbedtls_pem_free( &pem ); - return( ret ); + if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) + return( ret ); } - else #endif /* MBEDTLS_PEM_PARSE_C */ return( mbedtls_x509_csr_parse_der( csr, buf, buflen ) ); } @@ -325,7 +312,7 @@ int mbedtls_x509_csr_parse_file( mbedtls_x509_csr *csr, const char *path ) ret = mbedtls_x509_csr_parse( csr, buf, n ); - mbedtls_zeroize( buf, n ); + mbedtls_platform_zeroize( buf, n ); mbedtls_free( buf ); return( ret ); @@ -407,17 +394,17 @@ void mbedtls_x509_csr_free( mbedtls_x509_csr *csr ) { name_prv = name_cur; name_cur = name_cur->next; - mbedtls_zeroize( name_prv, sizeof( mbedtls_x509_name ) ); + mbedtls_platform_zeroize( name_prv, sizeof( mbedtls_x509_name ) ); mbedtls_free( name_prv ); } if( csr->raw.p != NULL ) { - mbedtls_zeroize( csr->raw.p, csr->raw.len ); + mbedtls_platform_zeroize( csr->raw.p, csr->raw.len ); mbedtls_free( csr->raw.p ); } - mbedtls_zeroize( csr, sizeof( mbedtls_x509_csr ) ); + mbedtls_platform_zeroize( csr, sizeof( mbedtls_x509_csr ) ); } #endif /* MBEDTLS_X509_CSR_PARSE_C */ diff --git a/thirdparty/mbedtls/library/x509write_crt.c b/thirdparty/mbedtls/library/x509write_crt.c index 41dfe87b75..b1ef216c95 100644 --- a/thirdparty/mbedtls/library/x509write_crt.c +++ b/thirdparty/mbedtls/library/x509write_crt.c @@ -37,6 +37,7 @@ #include "mbedtls/oid.h" #include "mbedtls/asn1write.h" #include "mbedtls/sha1.h" +#include "mbedtls/platform_util.h" #include <string.h> @@ -44,11 +45,6 @@ #include "mbedtls/pem.h" #endif /* MBEDTLS_PEM_WRITE_C */ -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize( void *v, size_t n ) { - volatile unsigned char *p = v; while( n-- ) *p++ = 0; -} - void mbedtls_x509write_crt_init( mbedtls_x509write_cert *ctx ) { memset( ctx, 0, sizeof( mbedtls_x509write_cert ) ); @@ -65,7 +61,7 @@ void mbedtls_x509write_crt_free( mbedtls_x509write_cert *ctx ) mbedtls_asn1_free_named_data_list( &ctx->issuer ); mbedtls_asn1_free_named_data_list( &ctx->extensions ); - mbedtls_zeroize( ctx, sizeof( mbedtls_x509write_cert ) ); + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_x509write_cert ) ); } void mbedtls_x509write_crt_set_version( mbedtls_x509write_cert *ctx, int version ) diff --git a/thirdparty/mbedtls/library/x509write_csr.c b/thirdparty/mbedtls/library/x509write_csr.c index e80053828f..66cee56014 100644 --- a/thirdparty/mbedtls/library/x509write_csr.c +++ b/thirdparty/mbedtls/library/x509write_csr.c @@ -35,6 +35,7 @@ #include "mbedtls/x509_csr.h" #include "mbedtls/oid.h" #include "mbedtls/asn1write.h" +#include "mbedtls/platform_util.h" #include <string.h> #include <stdlib.h> @@ -43,11 +44,6 @@ #include "mbedtls/pem.h" #endif -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize( void *v, size_t n ) { - volatile unsigned char *p = v; while( n-- ) *p++ = 0; -} - void mbedtls_x509write_csr_init( mbedtls_x509write_csr *ctx ) { memset( ctx, 0, sizeof( mbedtls_x509write_csr ) ); @@ -58,7 +54,7 @@ void mbedtls_x509write_csr_free( mbedtls_x509write_csr *ctx ) mbedtls_asn1_free_named_data_list( &ctx->subject ); mbedtls_asn1_free_named_data_list( &ctx->extensions ); - mbedtls_zeroize( ctx, sizeof( mbedtls_x509write_csr ) ); + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_x509write_csr ) ); } void mbedtls_x509write_csr_set_md_alg( mbedtls_x509write_csr *ctx, mbedtls_md_type_t md_alg ) diff --git a/thirdparty/mbedtls/library/xtea.c b/thirdparty/mbedtls/library/xtea.c index fe0a3509f6..a33707bc17 100644 --- a/thirdparty/mbedtls/library/xtea.c +++ b/thirdparty/mbedtls/library/xtea.c @@ -28,6 +28,7 @@ #if defined(MBEDTLS_XTEA_C) #include "mbedtls/xtea.h" +#include "mbedtls/platform_util.h" #include <string.h> @@ -42,11 +43,6 @@ #if !defined(MBEDTLS_XTEA_ALT) -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize( void *v, size_t n ) { - volatile unsigned char *p = v; while( n-- ) *p++ = 0; -} - /* * 32-bit integer manipulation macros (big endian) */ @@ -80,7 +76,7 @@ void mbedtls_xtea_free( mbedtls_xtea_context *ctx ) if( ctx == NULL ) return; - mbedtls_zeroize( ctx, sizeof( mbedtls_xtea_context ) ); + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_xtea_context ) ); } /* diff --git a/thirdparty/misc/triangulator.h b/thirdparty/misc/triangulator.h index b6dd7e8236..d1538cfae5 100644 --- a/thirdparty/misc/triangulator.h +++ b/thirdparty/misc/triangulator.h @@ -21,9 +21,9 @@ #ifndef TRIANGULATOR_H #define TRIANGULATOR_H -#include "math_2d.h" #include "list.h" #include "set.h" +#include "vector2.h" //2D point structure diff --git a/thirdparty/pcre2/AUTHORS b/thirdparty/pcre2/AUTHORS index e056ad6868..d5592bbc5b 100644 --- a/thirdparty/pcre2/AUTHORS +++ b/thirdparty/pcre2/AUTHORS @@ -8,7 +8,7 @@ Email domain: cam.ac.uk University of Cambridge Computing Service, Cambridge, England. -Copyright (c) 1997-2017 University of Cambridge +Copyright (c) 1997-2018 University of Cambridge All rights reserved @@ -19,7 +19,7 @@ Written by: Zoltan Herczeg Email local part: hzmester Emain domain: freemail.hu -Copyright(c) 2010-2017 Zoltan Herczeg +Copyright(c) 2010-2018 Zoltan Herczeg All rights reserved. @@ -30,7 +30,7 @@ Written by: Zoltan Herczeg Email local part: hzmester Emain domain: freemail.hu -Copyright(c) 2009-2017 Zoltan Herczeg +Copyright(c) 2009-2018 Zoltan Herczeg All rights reserved. #### diff --git a/thirdparty/pcre2/LICENCE b/thirdparty/pcre2/LICENCE index 402fe2435c..bfe3c8d528 100644 --- a/thirdparty/pcre2/LICENCE +++ b/thirdparty/pcre2/LICENCE @@ -5,9 +5,10 @@ PCRE2 is a library of functions to support regular expressions whose syntax and semantics are as close as possible to those of the Perl 5 language. Release 10 of PCRE2 is distributed under the terms of the "BSD" licence, as -specified below. The documentation for PCRE2, supplied in the "doc" -directory, is distributed under the same terms as the software itself. The data -in the testdata directory is not copyrighted and is in the public domain. +specified below, with one exemption for certain binary redistributions. The +documentation for PCRE2, supplied in the "doc" directory, is distributed under +the same terms as the software itself. The data in the testdata directory is +not copyrighted and is in the public domain. The basic library functions are written in C and are freestanding. Also included in the distribution is a just-in-time compiler that can be used to @@ -25,7 +26,7 @@ Email domain: cam.ac.uk University of Cambridge Computing Service, Cambridge, England. -Copyright (c) 1997-2017 University of Cambridge +Copyright (c) 1997-2018 University of Cambridge All rights reserved. @@ -36,7 +37,7 @@ Written by: Zoltan Herczeg Email local part: hzmester Emain domain: freemail.hu -Copyright(c) 2010-2017 Zoltan Herczeg +Copyright(c) 2010-2018 Zoltan Herczeg All rights reserved. @@ -47,7 +48,7 @@ Written by: Zoltan Herczeg Email local part: hzmester Emain domain: freemail.hu -Copyright(c) 2009-2017 Zoltan Herczeg +Copyright(c) 2009-2018 Zoltan Herczeg All rights reserved. @@ -57,11 +58,11 @@ THE "BSD" LICENCE Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright notice, + * Redistributions of source code must retain the above copyright notices, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the + notices, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the University of Cambridge nor the names of any @@ -80,4 +81,14 @@ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +EXEMPTION FOR BINARY LIBRARY-LIKE PACKAGES +------------------------------------------ + +The second condition in the BSD licence (covering binary redistributions) does +not apply all the way down a chain of software. If binary package A includes +PCRE2, it must respect the condition, but if package B is software that +includes package A, the condition is not imposed on package B unless it uses +PCRE2 independently. + End diff --git a/thirdparty/pcre2/src/config.h b/thirdparty/pcre2/src/config.h index 3315b7770e..f738616714 100644 --- a/thirdparty/pcre2/src/config.h +++ b/thirdparty/pcre2/src/config.h @@ -132,13 +132,11 @@ sure both macros are undefined; an emulation function will then be used. */ /* Define to 1 if you have the <zlib.h> header file. */ /* #undef HAVE_ZLIB_H */ -/* PCRE2 uses recursive function calls to handle backtracking while matching. - This can sometimes be a problem on systems that have stacks of limited - size. Define HEAP_MATCH_RECURSE to any value to get a version that doesn't - use recursion in the match() function; instead it creates its own stack by - steam using memory from the heap. For more detail, see the comments and - other stuff just above the match() function. */ -/* #undef HEAP_MATCH_RECURSE */ +/* This limits the amount of memory that pcre2_match() may use while matching + a pattern. The value is in kilobytes. */ +#ifndef HEAP_LIMIT +#define HEAP_LIMIT 20000000 +#endif /* The value of LINK_SIZE determines the number of bytes used to store links as offsets within the compiled regex. The default is 2, which allows for @@ -156,25 +154,25 @@ sure both macros are undefined; an emulation function will then be used. */ #endif /* The value of MATCH_LIMIT determines the default number of times the - internal match() function can be called during a single execution of - pcre2_match(). There is a runtime interface for setting a different limit. - The limit exists in order to catch runaway regular expressions that take - for ever to determine that they do not match. The default is set very large - so that it does not accidentally catch legitimate cases. */ + pcre2_match() function can record a backtrack position during a single + matching attempt. There is a runtime interface for setting a different + limit. The limit exists in order to catch runaway regular expressions that + take for ever to determine that they do not match. The default is set very + large so that it does not accidentally catch legitimate cases. */ #ifndef MATCH_LIMIT #define MATCH_LIMIT 10000000 #endif -/* The above limit applies to all calls of match(), whether or not they - increase the recursion depth. In some environments it is desirable to limit - the depth of recursive calls of match() more strictly, in order to restrict - the maximum amount of stack (or heap, if HEAP_MATCH_RECURSE is defined) - that is used. The value of MATCH_LIMIT_RECURSION applies only to recursive - calls of match(). To have any useful effect, it must be less than the value - of MATCH_LIMIT. The default is to use the same value as MATCH_LIMIT. There - is a runtime method for setting a different limit. */ -#ifndef MATCH_LIMIT_RECURSION -#define MATCH_LIMIT_RECURSION MATCH_LIMIT +/* The above limit applies to all backtracks, whether or not they are nested. + In some environments it is desirable to limit the nesting of backtracking + (that is, the depth of tree that is searched) more strictly, in order to + restrict the maximum amount of heap memory that is used. The value of + MATCH_LIMIT_DEPTH provides this facility. To have any useful effect, it + must be less than the value of MATCH_LIMIT. The default is to use the same + value as MATCH_LIMIT. There is a runtime method for setting a different + limit. */ +#ifndef MATCH_LIMIT_DEPTH +#define MATCH_LIMIT_DEPTH MATCH_LIMIT #endif /* This limit is parameterized just in case anybody ever wants to change it. @@ -196,8 +194,8 @@ sure both macros are undefined; an emulation function will then be used. */ /* The value of NEWLINE_DEFAULT determines the default newline character sequence. PCRE2 client programs can override this by selecting other values - at run time. The valid values are 1 (CR), 2 (LF), 3 (CRLF), 4 (ANY), and 5 - (ANYCRLF). */ + at run time. The valid values are 1 (CR), 2 (LF), 3 (CRLF), 4 (ANY), 5 + (ANYCRLF), and 6 (NUL). */ #ifndef NEWLINE_DEFAULT #define NEWLINE_DEFAULT 2 #endif @@ -212,7 +210,7 @@ sure both macros are undefined; an emulation function will then be used. */ #define PACKAGE_NAME "PCRE2" /* Define to the full name and version of this package. */ -#define PACKAGE_STRING "PCRE2 10.23" +#define PACKAGE_STRING "PCRE2 10.31" /* Define to the one symbol short name of this package. */ #define PACKAGE_TARNAME "pcre2" @@ -221,7 +219,7 @@ sure both macros are undefined; an emulation function will then be used. */ #define PACKAGE_URL "" /* Define to the version of this package. */ -#define PACKAGE_VERSION "10.23" +#define PACKAGE_VERSION "10.31" /* The value of PARENS_NEST_LIMIT specifies the maximum depth of nested parentheses (of any kind) in a pattern. This limits the amount of system @@ -269,6 +267,11 @@ sure both macros are undefined; an emulation function will then be used. */ your system. */ /* #undef PTHREAD_CREATE_JOINABLE */ +/* Define to any non-zero number to enable support for SELinux compatible + executable memory allocator in JIT. Note that this will have no effect + unless SUPPORT_JIT is also defined. */ +/* #undef SLJIT_PROT_EXECUTABLE_ALLOCATOR */ + /* Define to 1 if you have the ANSI C header files. */ /* #undef STDC_HEADERS */ @@ -336,7 +339,7 @@ sure both macros are undefined; an emulation function will then be used. */ #endif /* Version number of package */ -#define VERSION "10.23" +#define VERSION "10.31" /* Define to 1 if on MINIX. */ /* #undef _MINIX */ diff --git a/thirdparty/pcre2/src/pcre2.h b/thirdparty/pcre2/src/pcre2.h index 86503208e8..fffcc307d0 100644 --- a/thirdparty/pcre2/src/pcre2.h +++ b/thirdparty/pcre2/src/pcre2.h @@ -5,7 +5,7 @@ /* This is the public header file for the PCRE library, second API, to be #included by applications that call PCRE2 functions. - Copyright (c) 2016 University of Cambridge + Copyright (c) 2016-2017 University of Cambridge ----------------------------------------------------------------------------- Redistribution and use in source and binary forms, with or without @@ -42,9 +42,9 @@ POSSIBILITY OF SUCH DAMAGE. /* The current PCRE version information. */ #define PCRE2_MAJOR 10 -#define PCRE2_MINOR 23 +#define PCRE2_MINOR 31 #define PCRE2_PRERELEASE -#define PCRE2_DATE 2017-02-14 +#define PCRE2_DATE 2018-02-12 /* When an application links to a PCRE DLL in Windows, the symbols that are imported have to be identified as such. When building PCRE2, the appropriate @@ -101,6 +101,7 @@ others can be added next to them */ #define PCRE2_ANCHORED 0x80000000u #define PCRE2_NO_UTF_CHECK 0x40000000u +#define PCRE2_ENDANCHORED 0x20000000u /* The following option bits can be passed only to pcre2_compile(). However, they may affect compilation, JIT compilation, and/or interpretive execution. @@ -136,6 +137,15 @@ D is inspected during pcre2_dfa_match() execution #define PCRE2_ALT_CIRCUMFLEX 0x00200000u /* J M D */ #define PCRE2_ALT_VERBNAMES 0x00400000u /* C */ #define PCRE2_USE_OFFSET_LIMIT 0x00800000u /* J M D */ +#define PCRE2_EXTENDED_MORE 0x01000000u /* C */ +#define PCRE2_LITERAL 0x02000000u /* C */ + +/* An additional compile options word is available in the compile context. */ + +#define PCRE2_EXTRA_ALLOW_SURROGATE_ESCAPES 0x00000001u /* C */ +#define PCRE2_EXTRA_BAD_ESCAPE_IS_LITERAL 0x00000002u /* C */ +#define PCRE2_EXTRA_MATCH_WORD 0x00000004u /* C */ +#define PCRE2_EXTRA_MATCH_LINE 0x00000008u /* C */ /* These are for pcre2_jit_compile(). */ @@ -174,6 +184,16 @@ ignored for pcre2_jit_match(). */ #define PCRE2_NO_JIT 0x00002000u +/* Options for pcre2_pattern_convert(). */ + +#define PCRE2_CONVERT_UTF 0x00000001u +#define PCRE2_CONVERT_NO_UTF_CHECK 0x00000002u +#define PCRE2_CONVERT_POSIX_BASIC 0x00000004u +#define PCRE2_CONVERT_POSIX_EXTENDED 0x00000008u +#define PCRE2_CONVERT_GLOB 0x00000010u +#define PCRE2_CONVERT_GLOB_NO_WILD_SEPARATOR 0x00000030u +#define PCRE2_CONVERT_GLOB_NO_STARSTAR 0x00000050u + /* Newline and \R settings, for use in compile contexts. The newline values must be kept in step with values set in config.h and both sets must all be greater than zero. */ @@ -183,11 +203,109 @@ greater than zero. */ #define PCRE2_NEWLINE_CRLF 3 #define PCRE2_NEWLINE_ANY 4 #define PCRE2_NEWLINE_ANYCRLF 5 +#define PCRE2_NEWLINE_NUL 6 #define PCRE2_BSR_UNICODE 1 #define PCRE2_BSR_ANYCRLF 2 -/* Error codes: no match and partial match are "expected" errors. */ +/* Error codes for pcre2_compile(). Some of these are also used by +pcre2_pattern_convert(). */ + +#define PCRE2_ERROR_END_BACKSLASH 101 +#define PCRE2_ERROR_END_BACKSLASH_C 102 +#define PCRE2_ERROR_UNKNOWN_ESCAPE 103 +#define PCRE2_ERROR_QUANTIFIER_OUT_OF_ORDER 104 +#define PCRE2_ERROR_QUANTIFIER_TOO_BIG 105 +#define PCRE2_ERROR_MISSING_SQUARE_BRACKET 106 +#define PCRE2_ERROR_ESCAPE_INVALID_IN_CLASS 107 +#define PCRE2_ERROR_CLASS_RANGE_ORDER 108 +#define PCRE2_ERROR_QUANTIFIER_INVALID 109 +#define PCRE2_ERROR_INTERNAL_UNEXPECTED_REPEAT 110 +#define PCRE2_ERROR_INVALID_AFTER_PARENS_QUERY 111 +#define PCRE2_ERROR_POSIX_CLASS_NOT_IN_CLASS 112 +#define PCRE2_ERROR_POSIX_NO_SUPPORT_COLLATING 113 +#define PCRE2_ERROR_MISSING_CLOSING_PARENTHESIS 114 +#define PCRE2_ERROR_BAD_SUBPATTERN_REFERENCE 115 +#define PCRE2_ERROR_NULL_PATTERN 116 +#define PCRE2_ERROR_BAD_OPTIONS 117 +#define PCRE2_ERROR_MISSING_COMMENT_CLOSING 118 +#define PCRE2_ERROR_PARENTHESES_NEST_TOO_DEEP 119 +#define PCRE2_ERROR_PATTERN_TOO_LARGE 120 +#define PCRE2_ERROR_HEAP_FAILED 121 +#define PCRE2_ERROR_UNMATCHED_CLOSING_PARENTHESIS 122 +#define PCRE2_ERROR_INTERNAL_CODE_OVERFLOW 123 +#define PCRE2_ERROR_MISSING_CONDITION_CLOSING 124 +#define PCRE2_ERROR_LOOKBEHIND_NOT_FIXED_LENGTH 125 +#define PCRE2_ERROR_ZERO_RELATIVE_REFERENCE 126 +#define PCRE2_ERROR_TOO_MANY_CONDITION_BRANCHES 127 +#define PCRE2_ERROR_CONDITION_ASSERTION_EXPECTED 128 +#define PCRE2_ERROR_BAD_RELATIVE_REFERENCE 129 +#define PCRE2_ERROR_UNKNOWN_POSIX_CLASS 130 +#define PCRE2_ERROR_INTERNAL_STUDY_ERROR 131 +#define PCRE2_ERROR_UNICODE_NOT_SUPPORTED 132 +#define PCRE2_ERROR_PARENTHESES_STACK_CHECK 133 +#define PCRE2_ERROR_CODE_POINT_TOO_BIG 134 +#define PCRE2_ERROR_LOOKBEHIND_TOO_COMPLICATED 135 +#define PCRE2_ERROR_LOOKBEHIND_INVALID_BACKSLASH_C 136 +#define PCRE2_ERROR_UNSUPPORTED_ESCAPE_SEQUENCE 137 +#define PCRE2_ERROR_CALLOUT_NUMBER_TOO_BIG 138 +#define PCRE2_ERROR_MISSING_CALLOUT_CLOSING 139 +#define PCRE2_ERROR_ESCAPE_INVALID_IN_VERB 140 +#define PCRE2_ERROR_UNRECOGNIZED_AFTER_QUERY_P 141 +#define PCRE2_ERROR_MISSING_NAME_TERMINATOR 142 +#define PCRE2_ERROR_DUPLICATE_SUBPATTERN_NAME 143 +#define PCRE2_ERROR_INVALID_SUBPATTERN_NAME 144 +#define PCRE2_ERROR_UNICODE_PROPERTIES_UNAVAILABLE 145 +#define PCRE2_ERROR_MALFORMED_UNICODE_PROPERTY 146 +#define PCRE2_ERROR_UNKNOWN_UNICODE_PROPERTY 147 +#define PCRE2_ERROR_SUBPATTERN_NAME_TOO_LONG 148 +#define PCRE2_ERROR_TOO_MANY_NAMED_SUBPATTERNS 149 +#define PCRE2_ERROR_CLASS_INVALID_RANGE 150 +#define PCRE2_ERROR_OCTAL_BYTE_TOO_BIG 151 +#define PCRE2_ERROR_INTERNAL_OVERRAN_WORKSPACE 152 +#define PCRE2_ERROR_INTERNAL_MISSING_SUBPATTERN 153 +#define PCRE2_ERROR_DEFINE_TOO_MANY_BRANCHES 154 +#define PCRE2_ERROR_BACKSLASH_O_MISSING_BRACE 155 +#define PCRE2_ERROR_INTERNAL_UNKNOWN_NEWLINE 156 +#define PCRE2_ERROR_BACKSLASH_G_SYNTAX 157 +#define PCRE2_ERROR_PARENS_QUERY_R_MISSING_CLOSING 158 +#define PCRE2_ERROR_VERB_ARGUMENT_NOT_ALLOWED 159 +#define PCRE2_ERROR_VERB_UNKNOWN 160 +#define PCRE2_ERROR_SUBPATTERN_NUMBER_TOO_BIG 161 +#define PCRE2_ERROR_SUBPATTERN_NAME_EXPECTED 162 +#define PCRE2_ERROR_INTERNAL_PARSED_OVERFLOW 163 +#define PCRE2_ERROR_INVALID_OCTAL 164 +#define PCRE2_ERROR_SUBPATTERN_NAMES_MISMATCH 165 +#define PCRE2_ERROR_MARK_MISSING_ARGUMENT 166 +#define PCRE2_ERROR_INVALID_HEXADECIMAL 167 +#define PCRE2_ERROR_BACKSLASH_C_SYNTAX 168 +#define PCRE2_ERROR_BACKSLASH_K_SYNTAX 169 +#define PCRE2_ERROR_INTERNAL_BAD_CODE_LOOKBEHINDS 170 +#define PCRE2_ERROR_BACKSLASH_N_IN_CLASS 171 +#define PCRE2_ERROR_CALLOUT_STRING_TOO_LONG 172 +#define PCRE2_ERROR_UNICODE_DISALLOWED_CODE_POINT 173 +#define PCRE2_ERROR_UTF_IS_DISABLED 174 +#define PCRE2_ERROR_UCP_IS_DISABLED 175 +#define PCRE2_ERROR_VERB_NAME_TOO_LONG 176 +#define PCRE2_ERROR_BACKSLASH_U_CODE_POINT_TOO_BIG 177 +#define PCRE2_ERROR_MISSING_OCTAL_OR_HEX_DIGITS 178 +#define PCRE2_ERROR_VERSION_CONDITION_SYNTAX 179 +#define PCRE2_ERROR_INTERNAL_BAD_CODE_AUTO_POSSESS 180 +#define PCRE2_ERROR_CALLOUT_NO_STRING_DELIMITER 181 +#define PCRE2_ERROR_CALLOUT_BAD_STRING_DELIMITER 182 +#define PCRE2_ERROR_BACKSLASH_C_CALLER_DISABLED 183 +#define PCRE2_ERROR_QUERY_BARJX_NEST_TOO_DEEP 184 +#define PCRE2_ERROR_BACKSLASH_C_LIBRARY_DISABLED 185 +#define PCRE2_ERROR_PATTERN_TOO_COMPLICATED 186 +#define PCRE2_ERROR_LOOKBEHIND_TOO_LONG 187 +#define PCRE2_ERROR_PATTERN_STRING_TOO_LONG 188 +#define PCRE2_ERROR_INTERNAL_BAD_CODE 189 +#define PCRE2_ERROR_INTERNAL_BAD_CODE_IN_SKIP 190 +#define PCRE2_ERROR_NO_SURROGATES_IN_UTF16 191 +#define PCRE2_ERROR_BAD_LITERAL_OPTIONS 192 + + +/* "Expected" matching error codes: no match and partial match. */ #define PCRE2_ERROR_NOMATCH (-1) #define PCRE2_ERROR_PARTIAL (-2) @@ -227,10 +345,10 @@ greater than zero. */ #define PCRE2_ERROR_UTF32_ERR1 (-27) #define PCRE2_ERROR_UTF32_ERR2 (-28) -/* Error codes for pcre2[_dfa]_match(), substring extraction functions, context -functions, and serializing functions. They are in numerical order. Originally -they were in alphabetical order too, but now that PCRE2 is released, the -numbers must not be changed. */ +/* Miscellaneous error codes for pcre2[_dfa]_match(), substring extraction +functions, context functions, and serializing functions. They are in numerical +order. Originally they were in alphabetical order too, but now that PCRE2 is +released, the numbers must not be changed. */ #define PCRE2_ERROR_BADDATA (-29) #define PCRE2_ERROR_MIXEDTABLES (-30) /* Name was changed */ @@ -256,7 +374,8 @@ numbers must not be changed. */ #define PCRE2_ERROR_NOUNIQUESUBSTRING (-50) #define PCRE2_ERROR_NULL (-51) #define PCRE2_ERROR_RECURSELOOP (-52) -#define PCRE2_ERROR_RECURSIONLIMIT (-53) +#define PCRE2_ERROR_DEPTHLIMIT (-53) +#define PCRE2_ERROR_RECURSIONLIMIT (-53) /* Obsolete synonym */ #define PCRE2_ERROR_UNAVAILABLE (-54) #define PCRE2_ERROR_UNSET (-55) #define PCRE2_ERROR_BADOFFSETLIMIT (-56) @@ -266,6 +385,9 @@ numbers must not be changed. */ #define PCRE2_ERROR_BADSUBSPATTERN (-60) #define PCRE2_ERROR_TOOMANYREPLACE (-61) #define PCRE2_ERROR_BADSERIALIZEDDATA (-62) +#define PCRE2_ERROR_HEAPLIMIT (-63) +#define PCRE2_ERROR_CONVERT_SYNTAX (-64) + /* Request types for pcre2_pattern_info() */ @@ -290,9 +412,13 @@ numbers must not be changed. */ #define PCRE2_INFO_NAMEENTRYSIZE 18 #define PCRE2_INFO_NAMETABLE 19 #define PCRE2_INFO_NEWLINE 20 -#define PCRE2_INFO_RECURSIONLIMIT 21 +#define PCRE2_INFO_DEPTHLIMIT 21 +#define PCRE2_INFO_RECURSIONLIMIT 21 /* Obsolete synonym */ #define PCRE2_INFO_SIZE 22 #define PCRE2_INFO_HASBACKSLASHC 23 +#define PCRE2_INFO_FRAMESIZE 24 +#define PCRE2_INFO_HEAPLIMIT 25 +#define PCRE2_INFO_EXTRAOPTIONS 26 /* Request types for pcre2_config(). */ @@ -303,11 +429,16 @@ numbers must not be changed. */ #define PCRE2_CONFIG_MATCHLIMIT 4 #define PCRE2_CONFIG_NEWLINE 5 #define PCRE2_CONFIG_PARENSLIMIT 6 -#define PCRE2_CONFIG_RECURSIONLIMIT 7 -#define PCRE2_CONFIG_STACKRECURSE 8 +#define PCRE2_CONFIG_DEPTHLIMIT 7 +#define PCRE2_CONFIG_RECURSIONLIMIT 7 /* Obsolete synonym */ +#define PCRE2_CONFIG_STACKRECURSE 8 /* Obsolete */ #define PCRE2_CONFIG_UNICODE 9 #define PCRE2_CONFIG_UNICODE_VERSION 10 #define PCRE2_CONFIG_VERSION 11 +#define PCRE2_CONFIG_HEAPLIMIT 12 +#define PCRE2_CONFIG_NEVER_BACKSLASH_C 13 +#define PCRE2_CONFIG_COMPILED_WIDTHS 14 + /* Types for code units in patterns and subject strings. */ @@ -342,6 +473,9 @@ typedef struct pcre2_real_compile_context pcre2_compile_context; \ struct pcre2_real_match_context; \ typedef struct pcre2_real_match_context pcre2_match_context; \ \ +struct pcre2_real_convert_context; \ +typedef struct pcre2_real_convert_context pcre2_convert_context; \ +\ struct pcre2_real_code; \ typedef struct pcre2_real_code pcre2_code; \ \ @@ -360,6 +494,11 @@ without changing the API of the function, thereby allowing old clients to work without modification. Define the generic version in a macro; the width-specific versions are generated from this macro below. */ +/* Flags for the callout_flags field. These are cleared after a callout. */ + +#define PCRE2_CALLOUT_STARTMATCH 0x00000001u /* Set for each bumpalong */ +#define PCRE2_CALLOUT_BACKTRACK 0x00000002u /* Set after a backtrack */ + #define PCRE2_STRUCTURE_LIST \ typedef struct pcre2_callout_block { \ uint32_t version; /* Identifies version of block */ \ @@ -379,6 +518,8 @@ typedef struct pcre2_callout_block { \ PCRE2_SIZE callout_string_offset; /* Offset to string within pattern */ \ PCRE2_SIZE callout_string_length; /* Length of string compiled into pattern */ \ PCRE2_SPTR callout_string; /* String compiled into pattern */ \ + /* ------------------- Added for Version 2 -------------------------- */ \ + uint32_t callout_flags; /* See above for list */ \ /* ------------------------------------------------------------------ */ \ } pcre2_callout_block; \ \ @@ -426,6 +567,8 @@ PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \ PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \ pcre2_set_character_tables(pcre2_compile_context *, const unsigned char *); \ PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \ + pcre2_set_compile_extra_options(pcre2_compile_context *, uint32_t); \ +PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \ pcre2_set_max_pattern_length(pcre2_compile_context *, PCRE2_SIZE); \ PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \ pcre2_set_newline(pcre2_compile_context *, uint32_t); \ @@ -446,6 +589,10 @@ PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \ pcre2_set_callout(pcre2_match_context *, \ int (*)(pcre2_callout_block *, void *), void *); \ PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \ + pcre2_set_depth_limit(pcre2_match_context *, uint32_t); \ +PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \ + pcre2_set_heap_limit(pcre2_match_context *, uint32_t); \ +PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \ pcre2_set_match_limit(pcre2_match_context *, uint32_t); \ PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \ pcre2_set_offset_limit(pcre2_match_context *, PCRE2_SIZE); \ @@ -455,6 +602,18 @@ PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \ pcre2_set_recursion_memory_management(pcre2_match_context *, \ void *(*)(PCRE2_SIZE, void *), void (*)(void *, void *), void *); +#define PCRE2_CONVERT_CONTEXT_FUNCTIONS \ +PCRE2_EXP_DECL pcre2_convert_context PCRE2_CALL_CONVENTION \ + *pcre2_convert_context_copy(pcre2_convert_context *); \ +PCRE2_EXP_DECL pcre2_convert_context PCRE2_CALL_CONVENTION \ + *pcre2_convert_context_create(pcre2_general_context *); \ +PCRE2_EXP_DECL void PCRE2_CALL_CONVENTION \ + pcre2_convert_context_free(pcre2_convert_context *); \ +PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \ + pcre2_set_glob_escape(pcre2_convert_context *, uint32_t); \ +PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \ + pcre2_set_glob_separator(pcre2_convert_context *, uint32_t); + /* Functions concerned with compiling a pattern to PCRE internal code. */ @@ -561,6 +720,16 @@ PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \ PCRE2_SIZE, PCRE2_UCHAR *, PCRE2_SIZE *); +/* Functions for converting pattern source strings. */ + +#define PCRE2_CONVERT_FUNCTIONS \ +PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \ + pcre2_pattern_convert(PCRE2_SPTR, PCRE2_SIZE, uint32_t, PCRE2_UCHAR **, \ + PCRE2_SIZE *, pcre2_convert_context *); \ +PCRE2_EXP_DECL void PCRE2_CALL_CONVENTION \ + pcre2_converted_pattern_free(PCRE2_UCHAR *); + + /* Functions for JIT processing */ #define PCRE2_JIT_FUNCTIONS \ @@ -612,6 +781,7 @@ pcre2_compile are called by application code. */ #define pcre2_real_code PCRE2_SUFFIX(pcre2_real_code_) #define pcre2_real_general_context PCRE2_SUFFIX(pcre2_real_general_context_) #define pcre2_real_compile_context PCRE2_SUFFIX(pcre2_real_compile_context_) +#define pcre2_real_convert_context PCRE2_SUFFIX(pcre2_real_convert_context_) #define pcre2_real_match_context PCRE2_SUFFIX(pcre2_real_match_context_) #define pcre2_real_jit_stack PCRE2_SUFFIX(pcre2_real_jit_stack_) #define pcre2_real_match_data PCRE2_SUFFIX(pcre2_real_match_data_) @@ -623,6 +793,7 @@ pcre2_compile are called by application code. */ #define pcre2_callout_enumerate_block PCRE2_SUFFIX(pcre2_callout_enumerate_block_) #define pcre2_general_context PCRE2_SUFFIX(pcre2_general_context_) #define pcre2_compile_context PCRE2_SUFFIX(pcre2_compile_context_) +#define pcre2_convert_context PCRE2_SUFFIX(pcre2_convert_context_) #define pcre2_match_context PCRE2_SUFFIX(pcre2_match_context_) #define pcre2_match_data PCRE2_SUFFIX(pcre2_match_data_) @@ -638,6 +809,10 @@ pcre2_compile are called by application code. */ #define pcre2_compile_context_create PCRE2_SUFFIX(pcre2_compile_context_create_) #define pcre2_compile_context_free PCRE2_SUFFIX(pcre2_compile_context_free_) #define pcre2_config PCRE2_SUFFIX(pcre2_config_) +#define pcre2_convert_context_copy PCRE2_SUFFIX(pcre2_convert_context_copy_) +#define pcre2_convert_context_create PCRE2_SUFFIX(pcre2_convert_context_create_) +#define pcre2_convert_context_free PCRE2_SUFFIX(pcre2_convert_context_free_) +#define pcre2_converted_pattern_free PCRE2_SUFFIX(pcre2_converted_pattern_free_) #define pcre2_dfa_match PCRE2_SUFFIX(pcre2_dfa_match_) #define pcre2_general_context_copy PCRE2_SUFFIX(pcre2_general_context_copy_) #define pcre2_general_context_create PCRE2_SUFFIX(pcre2_general_context_create_) @@ -661,6 +836,7 @@ pcre2_compile are called by application code. */ #define pcre2_match_data_create PCRE2_SUFFIX(pcre2_match_data_create_) #define pcre2_match_data_create_from_pattern PCRE2_SUFFIX(pcre2_match_data_create_from_pattern_) #define pcre2_match_data_free PCRE2_SUFFIX(pcre2_match_data_free_) +#define pcre2_pattern_convert PCRE2_SUFFIX(pcre2_pattern_convert_) #define pcre2_pattern_info PCRE2_SUFFIX(pcre2_pattern_info_) #define pcre2_serialize_decode PCRE2_SUFFIX(pcre2_serialize_decode_) #define pcre2_serialize_encode PCRE2_SUFFIX(pcre2_serialize_encode_) @@ -669,14 +845,17 @@ pcre2_compile are called by application code. */ #define pcre2_set_bsr PCRE2_SUFFIX(pcre2_set_bsr_) #define pcre2_set_callout PCRE2_SUFFIX(pcre2_set_callout_) #define pcre2_set_character_tables PCRE2_SUFFIX(pcre2_set_character_tables_) +#define pcre2_set_compile_extra_options PCRE2_SUFFIX(pcre2_set_compile_extra_options_) #define pcre2_set_compile_recursion_guard PCRE2_SUFFIX(pcre2_set_compile_recursion_guard_) +#define pcre2_set_depth_limit PCRE2_SUFFIX(pcre2_set_depth_limit_) +#define pcre2_set_glob_escape PCRE2_SUFFIX(pcre2_set_glob_escape_) +#define pcre2_set_glob_separator PCRE2_SUFFIX(pcre2_set_glob_separator_) +#define pcre2_set_heap_limit PCRE2_SUFFIX(pcre2_set_heap_limit_) #define pcre2_set_match_limit PCRE2_SUFFIX(pcre2_set_match_limit_) #define pcre2_set_max_pattern_length PCRE2_SUFFIX(pcre2_set_max_pattern_length_) #define pcre2_set_newline PCRE2_SUFFIX(pcre2_set_newline_) #define pcre2_set_parens_nest_limit PCRE2_SUFFIX(pcre2_set_parens_nest_limit_) #define pcre2_set_offset_limit PCRE2_SUFFIX(pcre2_set_offset_limit_) -#define pcre2_set_recursion_limit PCRE2_SUFFIX(pcre2_set_recursion_limit_) -#define pcre2_set_recursion_memory_management PCRE2_SUFFIX(pcre2_set_recursion_memory_management_) #define pcre2_substitute PCRE2_SUFFIX(pcre2_substitute_) #define pcre2_substring_copy_byname PCRE2_SUFFIX(pcre2_substring_copy_byname_) #define pcre2_substring_copy_bynumber PCRE2_SUFFIX(pcre2_substring_copy_bynumber_) @@ -690,6 +869,11 @@ pcre2_compile are called by application code. */ #define pcre2_substring_nametable_scan PCRE2_SUFFIX(pcre2_substring_nametable_scan_) #define pcre2_substring_number_from_name PCRE2_SUFFIX(pcre2_substring_number_from_name_) +/* Keep this old function name for backwards compatibility */ +#define pcre2_set_recursion_limit PCRE2_SUFFIX(pcre2_set_recursion_limit_) + +/* Keep this obsolete function for backwards compatibility: it is now a noop. */ +#define pcre2_set_recursion_memory_management PCRE2_SUFFIX(pcre2_set_recursion_memory_management_) /* Now generate all three sets of width-specific structures and function prototypes. */ @@ -700,6 +884,8 @@ PCRE2_STRUCTURE_LIST \ PCRE2_GENERAL_INFO_FUNCTIONS \ PCRE2_GENERAL_CONTEXT_FUNCTIONS \ PCRE2_COMPILE_CONTEXT_FUNCTIONS \ +PCRE2_CONVERT_CONTEXT_FUNCTIONS \ +PCRE2_CONVERT_FUNCTIONS \ PCRE2_MATCH_CONTEXT_FUNCTIONS \ PCRE2_COMPILE_FUNCTIONS \ PCRE2_PATTERN_INFO_FUNCTIONS \ @@ -729,6 +915,7 @@ PCRE2_TYPES_STRUCTURES_AND_FUNCTIONS #undef PCRE2_GENERAL_INFO_FUNCTIONS #undef PCRE2_GENERAL_CONTEXT_FUNCTIONS #undef PCRE2_COMPILE_CONTEXT_FUNCTIONS +#undef PCRE2_CONVERT_CONTEXT_FUNCTIONS #undef PCRE2_MATCH_CONTEXT_FUNCTIONS #undef PCRE2_COMPILE_FUNCTIONS #undef PCRE2_PATTERN_INFO_FUNCTIONS diff --git a/thirdparty/pcre2/src/pcre2_auto_possess.c b/thirdparty/pcre2/src/pcre2_auto_possess.c index 64ec6dfbbc..23275a2e39 100644 --- a/thirdparty/pcre2/src/pcre2_auto_possess.c +++ b/thirdparty/pcre2/src/pcre2_auto_possess.c @@ -7,7 +7,7 @@ and semantics are as close as possible to those of the Perl 5 language. Written by Philip Hazel Original API code Copyright (c) 1997-2012 University of Cambridge - New API code Copyright (c) 2016 University of Cambridge + New API code Copyright (c) 2016-2017 University of Cambridge ----------------------------------------------------------------------------- Redistribution and use in source and binary forms, with or without @@ -558,50 +558,74 @@ for(;;) continue; } + /* At the end of a branch, skip to the end of the group. */ + if (c == OP_ALT) { do code += GET(code, 1); while (*code == OP_ALT); c = *code; } + /* Inspect the next opcode. */ + switch(c) { - case OP_END: - case OP_KETRPOS: - /* TRUE only in greedy case. The non-greedy case could be replaced by - an OP_EXACT, but it is probably not worth it. (And note that OP_EXACT - uses more memory, which we cannot get at this stage.) */ + /* We can always possessify a greedy iterator at the end of the pattern, + which is reached after skipping over the final OP_KET. A non-greedy + iterator must never be possessified. */ + case OP_END: return base_list[1] != 0; + /* When an iterator is at the end of certain kinds of group we can inspect + what follows the group by skipping over the closing ket. Note that this + does not apply to OP_KETRMAX or OP_KETRMIN because what follows any given + iteration is variable (could be another iteration or could be the next + item). As these two opcodes are not listed in the next switch, they will + end up as the next code to inspect, and return FALSE by virtue of being + unsupported. */ + case OP_KET: - /* If the bracket is capturing, and referenced by an OP_RECURSE, or - it is an atomic sub-pattern (assert, once, etc.) the non-greedy case - cannot be converted to a possessive form. */ + case OP_KETRPOS: + /* The non-greedy case cannot be converted to a possessive form. */ if (base_list[1] == 0) return FALSE; + /* If the bracket is capturing it might be referenced by an OP_RECURSE + so its last iterator can never be possessified if the pattern contains + recursions. (This could be improved by keeping a list of group numbers that + are called by recursion.) */ + switch(*(code - GET(code, 1))) { + case OP_CBRA: + case OP_SCBRA: + case OP_CBRAPOS: + case OP_SCBRAPOS: + if (cb->had_recurse) return FALSE; + break; + + /* Atomic sub-patterns and assertions can always auto-possessify their + last iterator. However, if the group was entered as a result of checking + a previous iterator, this is not possible. */ + case OP_ASSERT: case OP_ASSERT_NOT: case OP_ASSERTBACK: case OP_ASSERTBACK_NOT: case OP_ONCE: - case OP_ONCE_NC: - - /* Atomic sub-patterns and assertions can always auto-possessify their - last iterator. However, if the group was entered as a result of checking - a previous iterator, this is not possible. */ return !entered_a_group; } + /* Skip over the bracket and inspect what comes next. */ + code += PRIV(OP_lengths)[c]; continue; + /* Handle cases where the next item is a group. */ + case OP_ONCE: - case OP_ONCE_NC: case OP_BRA: case OP_CBRA: next_code = code + GET(code, 1); @@ -625,8 +649,8 @@ for(;;) case OP_BRAMINZERO: next_code = code + 1; - if (*next_code != OP_BRA && *next_code != OP_CBRA - && *next_code != OP_ONCE && *next_code != OP_ONCE_NC) return FALSE; + if (*next_code != OP_BRA && *next_code != OP_CBRA && + *next_code != OP_ONCE) return FALSE; do next_code += GET(next_code, 1); while (*next_code == OP_ALT); @@ -639,11 +663,15 @@ for(;;) code += PRIV(OP_lengths)[c]; continue; + /* The next opcode does not need special handling; fall through and use it + to see if the base can be possessified. */ + default: break; } - /* Check for a supported opcode, and load its properties. */ + /* We now have the next appropriate opcode to compare with the base. Check + for a supported opcode, and load its properties. */ code = get_chr_property_list(code, utf, cb->fcc, list); if (code == NULL) return FALSE; /* Unsupported */ @@ -1077,7 +1105,7 @@ for (;;) { c = *code; - if (c > OP_TABLE_LENGTH) return -1; /* Something gone wrong */ + if (c >= OP_TABLE_LENGTH) return -1; /* Something gone wrong */ if (c >= OP_STAR && c <= OP_TYPEPOSUPTO) { diff --git a/thirdparty/pcre2/src/pcre2_compile.c b/thirdparty/pcre2/src/pcre2_compile.c index 6d98a68caa..87530fb584 100644 --- a/thirdparty/pcre2/src/pcre2_compile.c +++ b/thirdparty/pcre2/src/pcre2_compile.c @@ -7,7 +7,7 @@ and semantics are as close as possible to those of the Perl 5 language. Written by Philip Hazel Original API code Copyright (c) 1997-2012 University of Cambridge - New API code Copyright (c) 2016 University of Cambridge + New API code Copyright (c) 2016-2017 University of Cambridge ----------------------------------------------------------------------------- Redistribution and use in source and binary forms, with or without @@ -160,7 +160,7 @@ the length of compiled items varies with this. In the real compile phase, this workspace is not currently used. */ -#define COMPILE_WORK_SIZE (2048*LINK_SIZE) /* Size in code units */ +#define COMPILE_WORK_SIZE (3000*LINK_SIZE) /* Size in code units */ #define C16_WORK_SIZE \ ((COMPILE_WORK_SIZE * sizeof(PCRE2_UCHAR))/sizeof(uint16_t)) @@ -690,17 +690,29 @@ static int posix_substitutes[] = { #define POSIX_SUBSIZE (sizeof(posix_substitutes) / (2*sizeof(uint32_t))) #endif /* SUPPORT_UNICODE */ -/* Masks for checking option settings. */ +/* Masks for checking option settings. When PCRE2_LITERAL is set, only a subset +are allowed. */ + +#define PUBLIC_LITERAL_COMPILE_OPTIONS \ + (PCRE2_ANCHORED|PCRE2_AUTO_CALLOUT|PCRE2_CASELESS|PCRE2_ENDANCHORED| \ + PCRE2_FIRSTLINE|PCRE2_LITERAL|PCRE2_NO_START_OPTIMIZE| \ + PCRE2_NO_UTF_CHECK|PCRE2_USE_OFFSET_LIMIT|PCRE2_UTF) #define PUBLIC_COMPILE_OPTIONS \ - (PCRE2_ANCHORED|PCRE2_ALLOW_EMPTY_CLASS|PCRE2_ALT_BSUX|PCRE2_ALT_CIRCUMFLEX| \ - PCRE2_ALT_VERBNAMES|PCRE2_AUTO_CALLOUT|PCRE2_CASELESS|PCRE2_DOLLAR_ENDONLY| \ - PCRE2_DOTALL|PCRE2_DUPNAMES|PCRE2_EXTENDED|PCRE2_FIRSTLINE| \ - PCRE2_MATCH_UNSET_BACKREF|PCRE2_MULTILINE|PCRE2_NEVER_BACKSLASH_C| \ - PCRE2_NEVER_UCP|PCRE2_NEVER_UTF|PCRE2_NO_AUTO_CAPTURE| \ - PCRE2_NO_AUTO_POSSESS|PCRE2_NO_DOTSTAR_ANCHOR|PCRE2_NO_START_OPTIMIZE| \ - PCRE2_NO_UTF_CHECK|PCRE2_UCP|PCRE2_UNGREEDY|PCRE2_USE_OFFSET_LIMIT| \ - PCRE2_UTF) + (PUBLIC_LITERAL_COMPILE_OPTIONS| \ + PCRE2_ALLOW_EMPTY_CLASS|PCRE2_ALT_BSUX|PCRE2_ALT_CIRCUMFLEX| \ + PCRE2_ALT_VERBNAMES|PCRE2_DOLLAR_ENDONLY|PCRE2_DOTALL|PCRE2_DUPNAMES| \ + PCRE2_EXTENDED|PCRE2_EXTENDED_MORE|PCRE2_MATCH_UNSET_BACKREF| \ + PCRE2_MULTILINE|PCRE2_NEVER_BACKSLASH_C|PCRE2_NEVER_UCP| \ + PCRE2_NEVER_UTF|PCRE2_NO_AUTO_CAPTURE|PCRE2_NO_AUTO_POSSESS| \ + PCRE2_NO_DOTSTAR_ANCHOR|PCRE2_UCP|PCRE2_UNGREEDY) + +#define PUBLIC_LITERAL_COMPILE_EXTRA_OPTIONS \ + (PCRE2_EXTRA_MATCH_LINE|PCRE2_EXTRA_MATCH_WORD) + +#define PUBLIC_COMPILE_EXTRA_OPTIONS \ + (PUBLIC_LITERAL_COMPILE_EXTRA_OPTIONS| \ + PCRE2_EXTRA_ALLOW_SURROGATE_ESCAPES|PCRE2_EXTRA_BAD_ESCAPE_IS_LITERAL) /* Compile time error code numbers. They are given names so that they can more easily be tracked. When a new number is added, the tables called eint1 and @@ -716,7 +728,8 @@ enum { ERR0 = COMPILE_ERROR_BASE, ERR51, ERR52, ERR53, ERR54, ERR55, ERR56, ERR57, ERR58, ERR59, ERR60, ERR61, ERR62, ERR63, ERR64, ERR65, ERR66, ERR67, ERR68, ERR69, ERR70, ERR71, ERR72, ERR73, ERR74, ERR75, ERR76, ERR77, ERR78, ERR79, ERR80, - ERR81, ERR82, ERR83, ERR84, ERR85, ERR86, ERR87, ERR88, ERR89, ERR90 }; + ERR81, ERR82, ERR83, ERR84, ERR85, ERR86, ERR87, ERR88, ERR89, ERR90, + ERR91, ERR92}; /* This is a table of start-of-pattern options such as (*UTF) and settings such as (*LIMIT_MATCH=nnnn) and (*CRLF). For completeness and backward @@ -727,8 +740,9 @@ enum { PSO_OPT, /* Value is an option bit */ PSO_FLG, /* Value is a flag bit */ PSO_NL, /* Value is a newline type */ PSO_BSR, /* Value is a \R type */ + PSO_LIMH, /* Read integer value for heap limit */ PSO_LIMM, /* Read integer value for match limit */ - PSO_LIMR }; /* Read integer value for recursion limit */ + PSO_LIMD }; /* Read integer value for depth limit */ typedef struct pso { const uint8_t *name; @@ -749,12 +763,15 @@ static pso pso_list[] = { { (uint8_t *)STRING_NO_DOTSTAR_ANCHOR_RIGHTPAR, 18, PSO_OPT, PCRE2_NO_DOTSTAR_ANCHOR }, { (uint8_t *)STRING_NO_JIT_RIGHTPAR, 7, PSO_FLG, PCRE2_NOJIT }, { (uint8_t *)STRING_NO_START_OPT_RIGHTPAR, 13, PSO_OPT, PCRE2_NO_START_OPTIMIZE }, + { (uint8_t *)STRING_LIMIT_HEAP_EQ, 11, PSO_LIMH, 0 }, { (uint8_t *)STRING_LIMIT_MATCH_EQ, 12, PSO_LIMM, 0 }, - { (uint8_t *)STRING_LIMIT_RECURSION_EQ, 16, PSO_LIMR, 0 }, + { (uint8_t *)STRING_LIMIT_DEPTH_EQ, 12, PSO_LIMD, 0 }, + { (uint8_t *)STRING_LIMIT_RECURSION_EQ, 16, PSO_LIMD, 0 }, { (uint8_t *)STRING_CR_RIGHTPAR, 3, PSO_NL, PCRE2_NEWLINE_CR }, { (uint8_t *)STRING_LF_RIGHTPAR, 3, PSO_NL, PCRE2_NEWLINE_LF }, { (uint8_t *)STRING_CRLF_RIGHTPAR, 5, PSO_NL, PCRE2_NEWLINE_CRLF }, { (uint8_t *)STRING_ANY_RIGHTPAR, 4, PSO_NL, PCRE2_NEWLINE_ANY }, + { (uint8_t *)STRING_NUL_RIGHTPAR, 4, PSO_NL, PCRE2_NEWLINE_NUL }, { (uint8_t *)STRING_ANYCRLF_RIGHTPAR, 8, PSO_NL, PCRE2_NEWLINE_ANYCRLF }, { (uint8_t *)STRING_BSR_ANYCRLF_RIGHTPAR, 12, PSO_BSR, PCRE2_BSR_ANYCRLF }, { (uint8_t *)STRING_BSR_UNICODE_RIGHTPAR, 12, PSO_BSR, PCRE2_BSR_UNICODE } @@ -1470,7 +1487,10 @@ else if (utf) { if (c > 0x10ffffU) *errorcodeptr = ERR77; - else if (c >= 0xd800 && c <= 0xdfff) *errorcodeptr = ERR73; + else + if (c >= 0xd800 && c <= 0xdfff && + (cb->cx->extra_options & PCRE2_EXTRA_ALLOW_SURROGATE_ESCAPES) == 0) + *errorcodeptr = ERR73; } else if (c > MAX_NON_UTF_CHAR) *errorcodeptr = ERR77; } @@ -1604,7 +1624,7 @@ else if (c >= CHAR_8) break; - /* Fall through with a digit less than 8 */ + /* Fall through */ /* \0 always starts an octal number, but we may drop through to here with a larger first octal digit. The original code used just to take the least @@ -1659,7 +1679,8 @@ else } else if (ptr < ptrend && *ptr++ == CHAR_RIGHT_CURLY_BRACKET) { - if (utf && c >= 0xd800 && c <= 0xdfff) + if (utf && c >= 0xd800 && c <= 0xdfff && (cb == NULL || + (cb->cx->extra_options & PCRE2_EXTRA_ALLOW_SURROGATE_ESCAPES) == 0)) { ptr--; *errorcodeptr = ERR73; @@ -1728,7 +1749,8 @@ else } else if (ptr < ptrend && *ptr++ == CHAR_RIGHT_CURLY_BRACKET) { - if (utf && c >= 0xd800 && c <= 0xdfff) + if (utf && c >= 0xd800 && c <= 0xdfff && (cb == NULL || + (cb->cx->extra_options & PCRE2_EXTRA_ALLOW_SURROGATE_ESCAPES) == 0)) { ptr--; *errorcodeptr = ERR73; @@ -1901,7 +1923,7 @@ if (c == CHAR_LEFT_CURLY_BRACKET) { if (ptr >= cb->end_pattern) goto ERROR_RETURN; c = *ptr++; - if (c == CHAR_NULL) goto ERROR_RETURN; + if (c == CHAR_NUL) goto ERROR_RETURN; if (c == CHAR_RIGHT_CURLY_BRACKET) break; name[i] = c; } @@ -2159,7 +2181,7 @@ the parsed pattern. Arguments: ptr current pattern pointer pcalloutptr points to a pointer to previous callout, or NULL - options the compiling options + auto_callout TRUE if auto_callouts are enabled parsed_pattern the parsed pattern pointer cb compile block @@ -2167,15 +2189,15 @@ Returns: possibly updated parsed_pattern pointer. */ static uint32_t * -manage_callouts(PCRE2_SPTR ptr, uint32_t **pcalloutptr, uint32_t options, +manage_callouts(PCRE2_SPTR ptr, uint32_t **pcalloutptr, BOOL auto_callout, uint32_t *parsed_pattern, compile_block *cb) { uint32_t *previous_callout = *pcalloutptr; -if (previous_callout != NULL) previous_callout[2] = ptr - cb->start_pattern - - (PCRE2_SIZE)previous_callout[1]; +if (previous_callout != NULL) previous_callout[2] = (uint32_t)(ptr - + cb->start_pattern - (PCRE2_SIZE)previous_callout[1]); -if ((options & PCRE2_AUTO_CALLOUT) == 0) previous_callout = NULL; else +if (!auto_callout) previous_callout = NULL; else { if (previous_callout == NULL || previous_callout != parsed_pattern - 4 || @@ -2223,12 +2245,17 @@ typedef struct nest_save { uint16_t reset_group; uint16_t max_group; uint16_t flags; + uint32_t options; } nest_save; -#define NSF_RESET 0x0001u -#define NSF_EXTENDED 0x0002u -#define NSF_DUPNAMES 0x0004u -#define NSF_CONDASSERT 0x0008u +#define NSF_RESET 0x0001u +#define NSF_CONDASSERT 0x0002u + +/* Of the options that are changeable within the pattern, these are tracked +during parsing. The rest are used from META_OPTIONS items when compiling. */ + +#define PARSE_TRACKED_OPTIONS \ + (PCRE2_DUPNAMES|PCRE2_EXTENDED|PCRE2_EXTENDED_MORE|PCRE2_NO_AUTO_CAPTURE) /* States used for analyzing ranges in character classes. The two OK values must be last. */ @@ -2272,15 +2299,57 @@ int i; BOOL inescq = FALSE; BOOL inverbname = FALSE; BOOL utf = (options & PCRE2_UTF) != 0; +BOOL auto_callout = (options & PCRE2_AUTO_CALLOUT) != 0; BOOL isdupname; BOOL negate_class; BOOL okquantifier = FALSE; +PCRE2_SPTR thisptr; PCRE2_SPTR name; PCRE2_SPTR ptrend = cb->end_pattern; PCRE2_SPTR verbnamestart = NULL; /* Value avoids compiler warning */ named_group *ng; -nest_save *top_nest = NULL; -nest_save *end_nests = (nest_save *)(cb->start_workspace + cb->workspace_size); +nest_save *top_nest, *end_nests; + +/* Insert leading items for word and line matching (features provided for the +benefit of pcre2grep). */ + +if ((cb->cx->extra_options & PCRE2_EXTRA_MATCH_LINE) != 0) + { + *parsed_pattern++ = META_CIRCUMFLEX; + *parsed_pattern++ = META_NOCAPTURE; + } +else if ((cb->cx->extra_options & PCRE2_EXTRA_MATCH_WORD) != 0) + { + *parsed_pattern++ = META_ESCAPE + ESC_b; + *parsed_pattern++ = META_NOCAPTURE; + } + +/* If the pattern is actually a literal string, process it separately to avoid +cluttering up the main loop. */ + +if ((options & PCRE2_LITERAL) != 0) + { + while (ptr < ptrend) + { + if (parsed_pattern >= parsed_pattern_end) + { + errorcode = ERR63; /* Internal error (parsed pattern overflow) */ + goto FAILED; + } + thisptr = ptr; + GETCHARINCTEST(c, ptr); + if (auto_callout) + parsed_pattern = manage_callouts(thisptr, &previous_callout, + auto_callout, parsed_pattern, cb); + PARSED_LITERAL(c, parsed_pattern); + } + goto PARSED_END; + } + +/* Process a real regex which may contain meta-characters. */ + +top_nest = NULL; +end_nests = (nest_save *)(cb->start_workspace + cb->workspace_size); /* The size of the nest_save structure might not be a factor of the size of the workspace. Therefore we must round down end_nests so as to correctly avoid @@ -2289,9 +2358,11 @@ creating a nest_save that spans the end of the workspace. */ end_nests = (nest_save *)((char *)end_nests - ((cb->workspace_size * sizeof(PCRE2_UCHAR)) % sizeof(nest_save))); -/* Now scan the pattern */ +/* PCRE2_EXTENDED_MORE implies PCRE2_EXTENDED */ -*has_lookbehind = FALSE; +if ((options & PCRE2_EXTENDED_MORE) != 0) options |= PCRE2_EXTENDED; + +/* Now scan the pattern */ while (ptr < ptrend) { @@ -2302,7 +2373,6 @@ while (ptr < ptrend) uint32_t prev_meta_quantifier; BOOL prev_okquantifier; PCRE2_SPTR tempptr; - PCRE2_SPTR thisptr; PCRE2_SIZE offset; if (parsed_pattern >= parsed_pattern_end) @@ -2314,7 +2384,7 @@ while (ptr < ptrend) if (nest_depth > cb->cx->parens_nest_limit) { errorcode = ERR19; - goto FAILED; + goto FAILED; /* Parentheses too deeply nested */ } /* Get next input character, save its position for callout handling. */ @@ -2341,8 +2411,8 @@ while (ptr < ptrend) goto FAILED; } if (!inverbname && after_manual_callout-- <= 0) - parsed_pattern = manage_callouts(thisptr, &previous_callout, options, - parsed_pattern, cb); + parsed_pattern = manage_callouts(thisptr, &previous_callout, + auto_callout, parsed_pattern, cb); PARSED_LITERAL(c, parsed_pattern); meta_quantifier = 0; } @@ -2487,7 +2557,7 @@ while (ptr < ptrend) !read_repeat_counts(&tempptr, ptrend, NULL, NULL, &errorcode)))) { if (after_manual_callout-- <= 0) - parsed_pattern = manage_callouts(thisptr, &previous_callout, options, + parsed_pattern = manage_callouts(thisptr, &previous_callout, auto_callout, parsed_pattern, cb); } @@ -2571,11 +2641,23 @@ while (ptr < ptrend) /* ---- Escape sequence ---- */ case CHAR_BACKSLASH: + tempptr = ptr; escape = PRIV(check_escape)(&ptr, ptrend, &c, &errorcode, options, FALSE, cb); - if (errorcode != 0) goto FAILED; + if (errorcode != 0) + { + ESCAPE_FAILED: + if ((cb->cx->extra_options & PCRE2_EXTRA_BAD_ESCAPE_IS_LITERAL) == 0) + goto FAILED; + ptr = tempptr; + if (ptr >= ptrend) c = CHAR_BACKSLASH; else + { + GETCHARINCTEST(c, ptr); /* Get character value, increment pointer */ + } + escape = 0; /* Treat as literal character */ + } - /* The escape was a data character. */ + /* The escape was a data escape or literal character. */ if (escape == 0) { @@ -2627,12 +2709,12 @@ while (ptr < ptrend) case ESC_C: #ifdef NEVER_BACKSLASH_C errorcode = ERR85; - goto FAILED; + goto ESCAPE_FAILED; #else if ((options & PCRE2_NEVER_BACKSLASH_C) != 0) { errorcode = ERR83; - goto FAILED; + goto ESCAPE_FAILED; } #endif okquantifier = TRUE; @@ -2642,7 +2724,7 @@ while (ptr < ptrend) case ESC_X: #ifndef SUPPORT_UNICODE errorcode = ERR45; /* Supported only with Unicode support */ - goto FAILED; + goto ESCAPE_FAILED; #endif case ESC_H: case ESC_h: @@ -2707,7 +2789,7 @@ while (ptr < ptrend) BOOL negated; uint16_t ptype = 0, pdata = 0; if (!get_ucp(&ptr, &negated, &ptype, &pdata, &errorcode, cb)) - goto FAILED; + goto ESCAPE_FAILED; if (negated) escape = (escape == ESC_P)? ESC_p : ESC_P; *parsed_pattern++ = META_ESCAPE + escape; *parsed_pattern++ = (ptype << 16) | pdata; @@ -2715,7 +2797,7 @@ while (ptr < ptrend) } #else errorcode = ERR45; - goto FAILED; + goto ESCAPE_FAILED; #endif break; /* End \P and \p */ @@ -2731,7 +2813,7 @@ while (ptr < ptrend) *ptr != CHAR_LESS_THAN_SIGN && *ptr != CHAR_APOSTROPHE)) { errorcode = (escape == ESC_g)? ERR57 : ERR69; - goto FAILED; + goto ESCAPE_FAILED; } terminator = (*ptr == CHAR_LESS_THAN_SIGN)? CHAR_GREATER_THAN_SIGN : (*ptr == CHAR_APOSTROPHE)? @@ -2749,18 +2831,18 @@ while (ptr < ptrend) if (p >= ptrend || *p != terminator) { errorcode = ERR57; - goto FAILED; + goto ESCAPE_FAILED; } ptr = p; goto SET_RECURSION; } - if (errorcode != 0) goto FAILED; + if (errorcode != 0) goto ESCAPE_FAILED; } /* Not a numerical recursion */ if (!read_name(&ptr, ptrend, terminator, &offset, &name, &namelen, - &errorcode, cb)) goto FAILED; + &errorcode, cb)) goto ESCAPE_FAILED; /* \k and \g when used with braces are back references, whereas \g used with quotes or angle brackets is a recursion */ @@ -2772,7 +2854,7 @@ while (ptr < ptrend) PUTOFFSET(offset, parsed_pattern); okquantifier = TRUE; - break; + break; /* End special escape processing */ } break; /* End escape sequence processing */ @@ -2904,7 +2986,8 @@ while (ptr < ptrend) /* Process a regular character class. If the first character is '^', set the negation flag. If the first few characters (either before or after ^) - are \Q\E or \E we skip them too. This makes for compatibility with Perl. */ + are \Q\E or \E or space or tab in extended-more mode, we skip them too. + This makes for compatibility with Perl. */ negate_class = FALSE; while (ptr < ptrend) @@ -2919,6 +3002,9 @@ while (ptr < ptrend) else break; } + else if ((options & PCRE2_EXTENDED_MORE) != 0 && + (c == CHAR_SPACE || c == CHAR_HT)) /* Note: just these two */ + continue; else if (!negate_class && c == CHAR_CIRCUMFLEX_ACCENT) negate_class = TRUE; else break; @@ -2966,6 +3052,12 @@ while (ptr < ptrend) goto CLASS_LITERAL; } + /* Skip over space and tab (only) in extended-more mode. */ + + if ((options & PCRE2_EXTENDED_MORE) != 0 && + (c == CHAR_SPACE || c == CHAR_HT)) + goto CLASS_CONTINUE; + /* Handle POSIX class names. Perl allows a negation extension of the form [:^name:]. A square bracket that doesn't match the syntax is treated as a literal. We also recognize the POSIX constructions @@ -3013,21 +3105,23 @@ while (ptr < ptrend) ptr = tempptr + 2; /* Perl treats a hyphen after a POSIX class as a literal, not the - start of a range. However, it gives a warning in its warning mode. PCRE - does not have a warning mode, so we give an error, because this is - likely an error on the user's part. */ + start of a range. However, it gives a warning in its warning mode + unless the hyphen is the last character in the class. PCRE does not + have a warning mode, so we give an error, because this is likely an + error on the user's part. */ - if (ptr < ptrend && *ptr == CHAR_MINUS) + if (ptr < ptrend - 1 && *ptr == CHAR_MINUS && + ptr[1] != CHAR_RIGHT_SQUARE_BRACKET) { errorcode = ERR50; goto FAILED; } - /* Set "a hyphen is not the start of a range" just in case the POSIX - class is followed by \E or \Q\E (possibly repeated - fuzzers do that - kind of thing) and *then* a hyphen. This causes that hyphen to be - treated as a literal. I don't think it's worth setting up special - apparatus to do otherwise. */ + /* Set "a hyphen is not the start of a range" for the -] case, and also + in case the POSIX class is followed by \E or \Q\E (possibly repeated - + fuzzers do that kind of thing) and *then* a hyphen. This causes that + hyphen to be treated as a literal. I don't think it's worth setting up + special apparatus to do otherwise. */ class_range_state = RANGE_NO; @@ -3109,10 +3203,23 @@ while (ptr < ptrend) else { + tempptr = ptr; escape = PRIV(check_escape)(&ptr, ptrend, &c, &errorcode, options, TRUE, cb); - if (errorcode != 0) goto FAILED; + if (errorcode != 0) + { + CLASS_ESCAPE_FAILED: + if ((cb->cx->extra_options & PCRE2_EXTRA_BAD_ESCAPE_IS_LITERAL) == 0) + goto FAILED; + ptr = tempptr; + if (ptr >= ptrend) c = CHAR_BACKSLASH; else + { + GETCHARINCTEST(c, ptr); /* Get character value, increment pointer */ + } + escape = 0; /* Treat as literal character */ + } + if (escape == 0) /* Escaped character code point is in c */ { char_is_literal = FALSE; @@ -3146,7 +3253,7 @@ while (ptr < ptrend) if (class_range_state == RANGE_STARTED) { errorcode = ERR50; - goto FAILED; + goto CLASS_ESCAPE_FAILED; } /* Of the remaining escapes, only those that define characters are @@ -3157,7 +3264,7 @@ while (ptr < ptrend) { case ESC_N: errorcode = ERR71; /* Not supported in a class */ - goto FAILED; + goto CLASS_ESCAPE_FAILED; case ESC_H: case ESC_h: @@ -3220,13 +3327,24 @@ while (ptr < ptrend) } #else errorcode = ERR45; - goto FAILED; + goto CLASS_ESCAPE_FAILED; #endif break; /* End \P and \p */ default: /* All others are not allowed in a class */ errorcode = ERR7; - goto FAILED_BACK; + ptr--; + goto CLASS_ESCAPE_FAILED; + } + + /* Perl gives a warning unless a following hyphen is the last character + in the class. PCRE throws an error. */ + + if (ptr < ptrend - 1 && *ptr == CHAR_MINUS && + ptr[1] != CHAR_RIGHT_SQUARE_BRACKET) + { + errorcode = ERR50; + goto FAILED; } } @@ -3384,8 +3502,7 @@ while (ptr < ptrend) } top_nest->nest_depth = nest_depth; top_nest->flags = 0; - if ((options & PCRE2_EXTENDED) != 0) top_nest->flags |= NSF_EXTENDED; - if ((options & PCRE2_DUPNAMES) != 0) top_nest->flags |= NSF_DUPNAMES; + top_nest->options = options & PARSE_TRACKED_OPTIONS; /* Start of non-capturing group that resets the capture count for each branch. */ @@ -3400,9 +3517,7 @@ while (ptr < ptrend) ptr++; } - /* Scan for options imsxJU. We need to keep track of (?x) and (?J) for - use while scanning. The other options are used during the compiling - phases. */ + /* Scan for options imnsxJU to be set or unset. */ else { @@ -3425,16 +3540,36 @@ while (ptr < ptrend) case CHAR_i: *optset |= PCRE2_CASELESS; break; case CHAR_m: *optset |= PCRE2_MULTILINE; break; + case CHAR_n: *optset |= PCRE2_NO_AUTO_CAPTURE; break; case CHAR_s: *optset |= PCRE2_DOTALL; break; - case CHAR_x: *optset |= PCRE2_EXTENDED; break; case CHAR_U: *optset |= PCRE2_UNGREEDY; break; + /* If x appears twice it sets the extended extended option. */ + + case CHAR_x: + *optset |= PCRE2_EXTENDED; + if (ptr < ptrend && *ptr == CHAR_x) + { + *optset |= PCRE2_EXTENDED_MORE; + ptr++; + } + break; + default: errorcode = ERR11; ptr--; /* Correct the offset */ goto FAILED; } } + + /* If we are setting extended without extended-more, ensure that any + existing extended-more gets unset. Also, unsetting extended must also + unset extended-more. */ + + if ((set & (PCRE2_EXTENDED|PCRE2_EXTENDED_MORE)) == PCRE2_EXTENDED || + (unset & PCRE2_EXTENDED) != 0) + unset |= PCRE2_EXTENDED_MORE; + options = (options | set) & (~unset); /* If the options ended with ')' this is not the start of a nested @@ -3671,7 +3806,7 @@ while (ptr < ptrend) /* Remember the offset to the next item in the pattern, and set a default length. This should get updated after the next item is read. */ - previous_callout[1] = ptr - cb->start_pattern; + previous_callout[1] = (uint32_t)(ptr - cb->start_pattern); previous_callout[2] = 0; break; /* End callout */ @@ -3913,8 +4048,7 @@ while (ptr < ptrend) } top_nest->nest_depth = nest_depth; top_nest->flags = NSF_CONDASSERT; - if ((options & PCRE2_EXTENDED) != 0) top_nest->flags |= NSF_EXTENDED; - if ((options & PCRE2_DUPNAMES) != 0) top_nest->flags |= NSF_DUPNAMES; + top_nest->options = options & PARSE_TRACKED_OPTIONS; } break; @@ -4035,20 +4169,17 @@ while (ptr < ptrend) break; /* End of group; reset the capture count to the maximum if we are in a (?| - group and/or reset the extended and dupnames options. Disallow quantifier - for a condition that is an assertion. */ + group and/or reset the options that are tracked during parsing. Disallow + quantifier for a condition that is an assertion. */ case CHAR_RIGHT_PARENTHESIS: okquantifier = TRUE; if (top_nest != NULL && top_nest->nest_depth == nest_depth) { + options = (options & ~PARSE_TRACKED_OPTIONS) | top_nest->options; if ((top_nest->flags & NSF_RESET) != 0 && top_nest->max_group > cb->bracount) cb->bracount = top_nest->max_group; - if ((top_nest->flags & NSF_EXTENDED) != 0) options |= PCRE2_EXTENDED; - else options &= ~PCRE2_EXTENDED; - if ((top_nest->flags & NSF_DUPNAMES) != 0) options |= PCRE2_DUPNAMES; - else options &= ~PCRE2_DUPNAMES; if ((top_nest->flags & NSF_CONDASSERT) != 0) okquantifier = FALSE; if (top_nest == (nest_save *)(cb->start_workspace)) top_nest = NULL; @@ -4075,9 +4206,24 @@ if (inverbname && ptr >= ptrend) /* Manage callout for the final item */ -parsed_pattern = manage_callouts(ptr, &previous_callout, options, +PARSED_END: +parsed_pattern = manage_callouts(ptr, &previous_callout, auto_callout, parsed_pattern, cb); +/* Insert trailing items for word and line matching (features provided for the +benefit of pcre2grep). */ + +if ((cb->cx->extra_options & PCRE2_EXTRA_MATCH_LINE) != 0) + { + *parsed_pattern++ = META_KET; + *parsed_pattern++ = META_DOLLAR; + } +else if ((cb->cx->extra_options & PCRE2_EXTRA_MATCH_WORD) != 0) + { + *parsed_pattern++ = META_KET; + *parsed_pattern++ = META_ESCAPE + ESC_b; + } + /* Terminate the parsed pattern, then return success if all groups are closed. Otherwise we have unclosed parentheses. */ @@ -4086,6 +4232,7 @@ if (parsed_pattern >= parsed_pattern_end) errorcode = ERR63; /* Internal error (parsed pattern overflow) */ goto FAILED; } + *parsed_pattern = META_END; if (nest_depth == 0) return 0; @@ -4164,6 +4311,18 @@ for (;;) code += GET(code, 1 + 2*LINK_SIZE); break; + case OP_SKIPZERO: + code += 2 + GET(code, 2) + LINK_SIZE; + break; + + case OP_COND: + case OP_SCOND: + if (code[1+LINK_SIZE] != OP_FALSE || /* Not DEFINE */ + code[GET(code, 1)] != OP_KET) /* More than one branch */ + return code; + code += GET(code, 1) + 1 + LINK_SIZE; + break; + default: return code; } @@ -4746,7 +4905,6 @@ for (;; pptr++) int class_has_8bitchar; int i; uint32_t mclength; - uint32_t templastcapture; uint32_t skipunits; uint32_t subreqcu, subfirstcu; uint32_t groupnumber; @@ -5198,6 +5356,10 @@ for (;; pptr++) options & ~PCRE2_CASELESS, cb, PRIV(vspace_list)); break; + /* If Unicode is not supported, \P and \p are not allowed and are + faulted at parse time, so will never appear here. */ + +#ifdef SUPPORT_UNICODE case ESC_p: case ESC_P: { @@ -5206,12 +5368,11 @@ for (;; pptr++) *class_uchardata++ = (escape == ESC_p)? XCL_PROP : XCL_NOTPROP; *class_uchardata++ = ptype; *class_uchardata++ = pdata; -#ifdef SUPPORT_WIDE_CHARS xclass_has_prop = TRUE; -#endif class_has_8bitchar--; /* Undo! */ } break; +#endif } goto CONTINUE_CLASS; @@ -5438,14 +5599,17 @@ for (;; pptr++) /* ===================================================================*/ /* Deal with (*VERB)s. */ - /* Check for open captures before ACCEPT and convert it to ASSERT_ACCEPT if - in an assertion. In the first pass, just accumulate the length required; + /* Check for open captures before ACCEPT and close those that are within + the same assertion level, also converting ACCEPT to ASSERT_ACCEPT in an + assertion. In the first pass, just accumulate the length required; otherwise hitting (*ACCEPT) inside many nested parentheses can cause workspace overflow. Do not set firstcu after *ACCEPT. */ case META_ACCEPT: cb->had_accept = TRUE; - for (oc = cb->open_caps; oc != NULL; oc = oc->next) + for (oc = cb->open_caps; + oc != NULL && oc->assert_depth >= cb->assert_depth; + oc = oc->next) { if (lengthptr != NULL) { @@ -5753,7 +5917,6 @@ for (;; pptr++) pptr++; tempcode = code; tempreqvary = cb->req_varyopt; /* Save value before group */ - templastcapture = cb->lastcapture; /* Save value before group */ length_prevgroup = 0; /* Initialize for pre-compile phase */ if ((group_return = @@ -5783,12 +5946,6 @@ for (;; pptr++) if (note_group_empty && bravalue != OP_COND && group_return > 0) matched_char = TRUE; - /* If that was an atomic group and there are no capturing groups within it, - generate OP_ONCE_NC instead of OP_ONCE. */ - - if (bravalue == OP_ONCE && cb->lastcapture <= templastcapture) - *code = OP_ONCE_NC; - /* If we've just compiled an assertion, pop the assert depth. */ if (bravalue >= OP_ASSERT && bravalue <= OP_ASSERTBACK_NOT) @@ -6113,7 +6270,7 @@ for (;; pptr++) } else *callout_string++ = *pp++; } - *callout_string++ = CHAR_NULL; + *callout_string++ = CHAR_NUL; /* Set the length of the entire item, the advance to its end. */ @@ -6209,24 +6366,6 @@ for (;; pptr++) tempcode = previous; op_previous = *previous; - /* If previous was a recursion call, wrap it in atomic brackets so that - previous becomes the atomic group. All recursions were so wrapped in the - past, but it no longer happens for non-repeated recursions. In fact, the - repeated ones could be re-implemented independently so as not to need this, - but for the moment we rely on the code for repeating groups. */ - - if (op_previous == OP_RECURSE) - { - memmove(previous + 1 + LINK_SIZE, previous, CU2BYTES(1 + LINK_SIZE)); - op_previous = *previous = OP_ONCE; - PUT(previous, 1, 2 + 2*LINK_SIZE); - previous[2 + 2*LINK_SIZE] = OP_KET; - PUT(previous, 3 + 2*LINK_SIZE, 2 + 2*LINK_SIZE); - code += 2 + 2 * LINK_SIZE; - length_prevgroup = 3 + 3*LINK_SIZE; - group_return = -1; /* Set "may match empty string" */ - } - /* Now handle repetition for the different types of item. */ switch (op_previous) @@ -6311,6 +6450,77 @@ for (;; pptr++) case OP_FAIL: goto END_REPEAT; + /* Prior to 10.30, repeated recursions were wrapped in OP_ONCE brackets + because pcre2_match() could not handle backtracking into recursively + called groups. Now that this backtracking is available, we no longer need + to do this. However, we still need to replicate recursions as we do for + groups so as to have independent backtracking points. We can replicate + for the minimum number of repeats directly. For optional repeats we now + wrap the recursion in OP_BRA brackets and make use of the bracket + repetition. */ + + case OP_RECURSE: + + /* Generate unwrapped repeats for a non-zero minimum, except when the + minimum is 1 and the maximum unlimited, because that can be handled with + OP_BRA terminated by OP_KETRMAX/MIN. When the maximum is equal to the + minimum, we just need to generate the appropriate additional copies. + Otherwise we need to generate one more, to simulate the situation when + the minimum is zero. */ + + if (repeat_min > 0 && (repeat_min != 1 || repeat_max != REPEAT_UNLIMITED)) + { + int replicate = repeat_min; + if (repeat_min == repeat_max) replicate--; + + /* In the pre-compile phase, we don't actually do the replication. We + just adjust the length as if we had. Do some paranoid checks for + potential integer overflow. The INT64_OR_DOUBLE type is a 64-bit + integer type when available, otherwise double. */ + + if (lengthptr != NULL) + { + PCRE2_SIZE delta = replicate*(1 + LINK_SIZE); + if ((INT64_OR_DOUBLE)replicate* + (INT64_OR_DOUBLE)(1 + LINK_SIZE) > + (INT64_OR_DOUBLE)INT_MAX || + OFLOW_MAX - *lengthptr < delta) + { + *errorcodeptr = ERR20; + return 0; + } + *lengthptr += delta; + } + + else for (i = 0; i < replicate; i++) + { + memcpy(code, previous, CU2BYTES(1 + LINK_SIZE)); + previous = code; + code += 1 + LINK_SIZE; + } + + /* If the number of repeats is fixed, we are done. Otherwise, adjust + the counts and fall through. */ + + if (repeat_min == repeat_max) break; + if (repeat_max != REPEAT_UNLIMITED) repeat_max -= repeat_min; + repeat_min = 0; + } + + /* Wrap the recursion call in OP_BRA brackets. */ + + memmove(previous + 1 + LINK_SIZE, previous, CU2BYTES(1 + LINK_SIZE)); + op_previous = *previous = OP_BRA; + PUT(previous, 1, 2 + 2*LINK_SIZE); + previous[2 + 2*LINK_SIZE] = OP_KET; + PUT(previous, 3 + 2*LINK_SIZE, 2 + 2*LINK_SIZE); + code += 2 + 2 * LINK_SIZE; + length_prevgroup = 3 + 3*LINK_SIZE; + group_return = -1; /* Set "may match empty string" */ + + /* Now treat as a repeated OP_BRA. */ + /* Fall through */ + /* If previous was a bracket group, we may have to replicate it in certain cases. Note that at this point we can encounter only the "basic" bracket opcodes such as BRA and CBRA, as this is the place where they get @@ -6323,7 +6533,6 @@ for (;; pptr++) case OP_ASSERTBACK: case OP_ASSERTBACK_NOT: case OP_ONCE: - case OP_ONCE_NC: case OP_BRA: case OP_CBRA: case OP_COND: @@ -6340,10 +6549,10 @@ for (;; pptr++) previous[GET(previous, 1)] != OP_ALT) goto END_REPEAT; - /* There is no sense in actually repeating assertions. The only potential - use of repetition is in cases when the assertion is optional. Therefore, - if the minimum is greater than zero, just ignore the repeat. If the - maximum is not zero or one, set it to 1. */ + /* There is no sense in actually repeating assertions. The only + potential use of repetition is in cases when the assertion is optional. + Therefore, if the minimum is greater than zero, just ignore the repeat. + If the maximum is not zero or one, set it to 1. */ if (op_previous < OP_ONCE) /* Assertion */ { @@ -6567,14 +6776,12 @@ for (;; pptr++) /* Convert possessive ONCE brackets to non-capturing */ - if ((*bracode == OP_ONCE || *bracode == OP_ONCE_NC) && - possessive_quantifier) *bracode = OP_BRA; + if (*bracode == OP_ONCE && possessive_quantifier) *bracode = OP_BRA; /* For non-possessive ONCE brackets, all we need to do is to set the KET. */ - if (*bracode == OP_ONCE || *bracode == OP_ONCE_NC) - *ketcode = OP_KETRMAX + repeat_type; + if (*bracode == OP_ONCE) *ketcode = OP_KETRMAX + repeat_type; /* Handle non-ONCE brackets and possessive ONCEs (which have been converted to non-capturing above). */ @@ -6928,7 +7135,7 @@ for (;; pptr++) later. */ HANDLE_SINGLE_REFERENCE: - if (firstcuflags == REQ_UNSET) firstcuflags = REQ_NONE; + if (firstcuflags == REQ_UNSET) zerofirstcuflags = firstcuflags = REQ_NONE; *code++ = ((options & PCRE2_CASELESS) != 0)? OP_REFI : OP_REF; PUT2INC(code, 0, meta_arg); @@ -7143,7 +7350,6 @@ for (;; pptr++) if (mclength == 1 || req_caseopt == 0) { - firstcu = mcbuffer[0] | req_caseopt; firstcu = mcbuffer[0]; firstcuflags = req_caseopt; if (mclength != 1) @@ -7280,6 +7486,7 @@ if (*code == OP_CBRA) capitem.number = capnumber; capitem.next = cb->open_caps; capitem.flag = FALSE; + capitem.assert_depth = cb->assert_depth; cb->open_caps = &capitem; } @@ -7568,7 +7775,7 @@ do { /* Atomic groups */ - else if (op == OP_ONCE || op == OP_ONCE_NC) + else if (op == OP_ONCE) { if (!is_anchored(scode, bracket_map, cb, atomcount + 1, inassert)) return FALSE; @@ -7698,7 +7905,7 @@ do { /* Atomic brackets */ - else if (op == OP_ONCE || op == OP_ONCE_NC) + else if (op == OP_ONCE) { if (!is_startline(scode, bracket_map, cb, atomcount + 1, inassert)) return FALSE; @@ -7720,9 +7927,8 @@ do { } /* Check for explicit circumflex; anything else gives a FALSE result. Note - in particular that this includes atomic brackets OP_ONCE and OP_ONCE_NC - because the number of characters matched by .* cannot be adjusted inside - them. */ + in particular that this includes atomic brackets OP_ONCE because the number + of characters matched by .* cannot be adjusted inside them. */ else if (op != OP_CIRC && op != OP_CIRCM) return FALSE; @@ -7900,13 +8106,13 @@ REQ_NONE in the flags. Arguments: code points to start of compiled pattern flags points to the first code unit flags - inassert TRUE if in an assertion + inassert non-zero if in an assertion Returns: the fixed first code unit, or 0 with REQ_NONE in flags */ static uint32_t -find_firstassertedcu(PCRE2_SPTR code, int32_t *flags, BOOL inassert) +find_firstassertedcu(PCRE2_SPTR code, int32_t *flags, uint32_t inassert) { uint32_t c = 0; int cflags = REQ_NONE; @@ -7933,8 +8139,7 @@ do { case OP_SCBRAPOS: case OP_ASSERT: case OP_ONCE: - case OP_ONCE_NC: - d = find_firstassertedcu(scode, &dflags, op == OP_ASSERT); + d = find_firstassertedcu(scode, &dflags, inassert + ((op==OP_ASSERT)?1:0)); if (dflags < 0) return 0; if (cflags < 0) { c = d; cflags = dflags; } @@ -7949,7 +8154,7 @@ do { case OP_PLUS: case OP_MINPLUS: case OP_POSPLUS: - if (!inassert) return 0; + if (inassert == 0) return 0; if (cflags < 0) { c = scode[1]; cflags = 0; } else if (c != scode[1]) return 0; break; @@ -7962,7 +8167,7 @@ do { case OP_PLUSI: case OP_MINPLUSI: case OP_POSPLUSI: - if (!inassert) return 0; + if (inassert == 0) return 0; if (cflags < 0) { c = scode[1]; cflags = REQ_CASELESS; } else if (c != scode[1]) return 0; break; @@ -8049,6 +8254,10 @@ the end of the branch, it is called to skip over an internal lookaround, and it is also called to skip to the end of a class, during which it will never encounter nested groups (but there's no need to have special code for that). +When called to find the end of a branch or group, pptr must point to the first +meta code inside the branch, not the branch-starting code. In other cases it +can point to the item that causes the function to be called. + Arguments: pptr current pointer to skip from skiptype PSKIP_CLASS when skipping to end of class @@ -8065,7 +8274,7 @@ parsed_skip(uint32_t *pptr, uint32_t skiptype) { uint32_t nestlevel = 0; -for (pptr += 1;; pptr++) +for (;; pptr++) { uint32_t meta = META_CODE(*pptr); @@ -8160,11 +8369,12 @@ return pptr; /* This is called for nested groups within a branch of a lookbehind whose length is being computed. If all the branches in the nested group have the same length, that is OK. On entry, the pointer must be at the first element after -the group initializing code. Caching is used to improve processing speed when -the same capturing group occurs many times. +the group initializing code. On exit it points to OP_KET. Caching is used to +improve processing speed when the same capturing group occurs many times. Arguments: pptrptr pointer to pointer in the parsed pattern + isinline FALSE if a reference or recursion; TRUE for inline group errcodeptr pointer to the errorcode lcptr pointer to the loop counter group number of captured group or -1 for a non-capturing group @@ -8175,27 +8385,29 @@ Returns: the group length or a negative number */ static int -get_grouplength(uint32_t **pptrptr, int *errcodeptr, int *lcptr, +get_grouplength(uint32_t **pptrptr, BOOL isinline, int *errcodeptr, int *lcptr, int group, parsed_recurse_check *recurses, compile_block *cb) { int branchlength; int grouplength = -1; /* The cache can be used only if there is no possibility of there being two -groups with the same number. */ +groups with the same number. We do not need to set the end pointer for a group +that is being processed as a back reference or recursion, but we must do so for +an inline group. */ -if (group > 0) +if (group > 0 && (cb->external_flags & PCRE2_DUPCAPUSED) == 0) { uint32_t groupinfo = cb->groupinfo[group]; - if ((cb->external_flags & PCRE2_DUPCAPUSED) == 0) + if ((groupinfo & GI_NOT_FIXED_LENGTH) != 0) return -1; + if ((groupinfo & GI_SET_FIXED_LENGTH) != 0) { - if ((groupinfo & GI_NOT_FIXED_LENGTH) != 0) return -1; - if ((groupinfo & GI_SET_FIXED_LENGTH) != 0) - return groupinfo & GI_FIXED_LENGTH_MASK; + if (isinline) *pptrptr = parsed_skip(*pptrptr, PSKIP_KET); + return groupinfo & GI_FIXED_LENGTH_MASK; } } -/* Scan the group */ +/* Scan the group. In this case we find the end pointer of necessity. */ for(;;) { @@ -8353,11 +8565,12 @@ for (;; pptr++) } break; - /* Lookaheads can be ignored. */ + /* Lookaheads can be ignored, but we must start the skip inside the group + so that it isn't treated as a group within the branch. */ case META_LOOKAHEAD: case META_LOOKAHEADNOT: - pptr = parsed_skip(pptr, PSKIP_KET); + pptr = parsed_skip(pptr + 1, PSKIP_KET); if (pptr == NULL) goto PARSED_SKIP_FAILED; break; @@ -8378,6 +8591,7 @@ for (;; pptr++) case META_BACKREF_BYNAME: if ((cb->external_options & PCRE2_MATCH_UNSET_BACKREF) != 0) goto ISNOTFIXED; + /* Fall through */ case META_RECURSE_BYNAME: { @@ -8432,7 +8646,8 @@ for (;; pptr++) goto RECURSE_OR_BACKREF_LENGTH; } - /* Fall through for groups >= 10 - picking up group twice does no harm. */ + /* Fall through */ + /* For groups >= 10 - picking up group twice does no harm. */ /* A true recursion implies not fixed length, but a subroutine call may be OK. Back reference "recursions" are also failed. */ @@ -8455,15 +8670,24 @@ for (;; pptr++) else if (*gptr == (META_CAPTURE | group)) break; } - gptrend = parsed_skip(gptr, PSKIP_KET); + /* We must start the search for the end of the group at the first meta code + inside the group. Otherwise it will be treated as an enclosed group. */ + + gptrend = parsed_skip(gptr + 1, PSKIP_KET); if (gptrend == NULL) goto PARSED_SKIP_FAILED; if (pptr > gptr && pptr < gptrend) goto ISNOTFIXED; /* Local recursion */ for (r = recurses; r != NULL; r = r->prev) if (r->groupptr == gptr) break; if (r != NULL) goto ISNOTFIXED; /* Mutual recursion */ this_recurse.prev = recurses; this_recurse.groupptr = gptr; + + /* We do not need to know the position of the end of the group, that is, + gptr is not used after the call to get_grouplength(). Setting the second + argument FALSE stops it scanning for the end when the length can be found + in the cache. */ + gptr++; - grouplength = get_grouplength(&gptr, errcodeptr, lcptr, group, + grouplength = get_grouplength(&gptr, FALSE, errcodeptr, lcptr, group, &this_recurse, cb); if (grouplength < 0) { @@ -8500,7 +8724,8 @@ for (;; pptr++) case META_NOCAPTURE: pptr++; CHECK_GROUP: - grouplength = get_grouplength(&pptr, errcodeptr, lcptr, group, recurses, cb); + grouplength = get_grouplength(&pptr, TRUE, errcodeptr, lcptr, group, + recurses, cb); if (grouplength < 0) return -1; itemlength = grouplength; break; @@ -8760,7 +8985,7 @@ pcre2_compile(PCRE2_SPTR pattern, PCRE2_SIZE patlen, uint32_t options, int *errorptr, PCRE2_SIZE *erroroffset, pcre2_compile_context *ccontext) { BOOL utf; /* Set TRUE for UTF mode */ -BOOL has_lookbehind; /* Set TRUE if a lookbehind is found */ +BOOL has_lookbehind = FALSE; /* Set TRUE if a lookbehind is found */ BOOL zero_terminated; /* Set TRUE for zero-terminated pattern */ pcre2_real_code *re = NULL; /* What we will return */ compile_block cb; /* "Static" compile-time data */ @@ -8782,8 +9007,9 @@ uint32_t firstcu, reqcu; /* Value of first/req code unit */ uint32_t setflags = 0; /* NL and BSR set flags */ uint32_t skipatstart; /* When checking (*UTF) etc */ +uint32_t limit_heap = UINT32_MAX; uint32_t limit_match = UINT32_MAX; /* Unset match limits */ -uint32_t limit_recursion = UINT32_MAX; +uint32_t limit_depth = UINT32_MAX; int newline = 0; /* Unset; can be set by the pattern */ int bsr = 0; /* Unset; can be set by the pattern */ @@ -8821,18 +9047,27 @@ if (pattern == NULL) return NULL; } +/* A NULL compile context means "use a default context" */ + +if (ccontext == NULL) + ccontext = (pcre2_compile_context *)(&PRIV(default_compile_context)); + /* Check that all undefined public option bits are zero. */ -if ((options & ~PUBLIC_COMPILE_OPTIONS) != 0) +if ((options & ~PUBLIC_COMPILE_OPTIONS) != 0 || + (ccontext->extra_options & ~PUBLIC_COMPILE_EXTRA_OPTIONS) != 0) { *errorptr = ERR17; return NULL; } -/* A NULL compile context means "use a default context" */ - -if (ccontext == NULL) - ccontext = (pcre2_compile_context *)(&PRIV(default_compile_context)); +if ((options & PCRE2_LITERAL) != 0 && + ((options & ~PUBLIC_LITERAL_COMPILE_OPTIONS) != 0 || + (ccontext->extra_options & ~PUBLIC_LITERAL_COMPILE_EXTRA_OPTIONS) != 0)) + { + *errorptr = ERR92; + return NULL; + } /* A zero-terminated pattern is indicated by the special length value PCRE2_ZERO_TERMINATED. Check for an overlong pattern. */ @@ -8907,10 +9142,11 @@ for (i = 0; i < 10; i++) cb.small_ref_offset[i] = PCRE2_UNSET; /* --------------- Start looking at the pattern --------------- */ -/* Check for global one-time option settings at the start of the pattern, and -remember the offset to the actual regex. With valgrind support, make the -terminator of a zero-terminated pattern inaccessible. This catches bugs that -would otherwise only show up for non-zero-terminated patterns. */ +/* Unless PCRE2_LITERAL is set, check for global one-time option settings at +the start of the pattern, and remember the offset to the actual regex. With +valgrind support, make the terminator of a zero-terminated pattern +inaccessible. This catches bugs that would otherwise only show up for +non-zero-terminated patterns. */ #ifdef SUPPORT_VALGRIND if (zero_terminated) VALGRIND_MAKE_MEM_NOACCESS(pattern + patlen, CU2BYTES(1)); @@ -8919,70 +9155,75 @@ if (zero_terminated) VALGRIND_MAKE_MEM_NOACCESS(pattern + patlen, CU2BYTES(1)); ptr = pattern; skipatstart = 0; -while (patlen - skipatstart >= 2 && - ptr[skipatstart] == CHAR_LEFT_PARENTHESIS && - ptr[skipatstart+1] == CHAR_ASTERISK) +if ((options & PCRE2_LITERAL) == 0) { - for (i = 0; i < sizeof(pso_list)/sizeof(pso); i++) + while (patlen - skipatstart >= 2 && + ptr[skipatstart] == CHAR_LEFT_PARENTHESIS && + ptr[skipatstart+1] == CHAR_ASTERISK) { - pso *p = pso_list + i; - - if (patlen - skipatstart - 2 >= p->length && - PRIV(strncmp_c8)(ptr+skipatstart+2, (char *)(p->name), p->length) == 0) + for (i = 0; i < sizeof(pso_list)/sizeof(pso); i++) { uint32_t c, pp; + pso *p = pso_list + i; - skipatstart += p->length + 2; - switch(p->type) + if (patlen - skipatstart - 2 >= p->length && + PRIV(strncmp_c8)(ptr + skipatstart + 2, (char *)(p->name), + p->length) == 0) { - case PSO_OPT: - cb.external_options |= p->value; - break; + skipatstart += p->length + 2; + switch(p->type) + { + case PSO_OPT: + cb.external_options |= p->value; + break; - case PSO_FLG: - setflags |= p->value; - break; + case PSO_FLG: + setflags |= p->value; + break; - case PSO_NL: - newline = p->value; - setflags |= PCRE2_NL_SET; - break; + case PSO_NL: + newline = p->value; + setflags |= PCRE2_NL_SET; + break; - case PSO_BSR: - bsr = p->value; - setflags |= PCRE2_BSR_SET; - break; + case PSO_BSR: + bsr = p->value; + setflags |= PCRE2_BSR_SET; + break; - case PSO_LIMM: - case PSO_LIMR: - c = 0; - pp = skipatstart; - if (!IS_DIGIT(ptr[pp])) - { - errorcode = ERR60; - ptr += pp; - goto HAD_EARLY_ERROR; - } - while (IS_DIGIT(ptr[pp])) - { - if (c > UINT32_MAX / 10 - 1) break; /* Integer overflow */ - c = c*10 + (ptr[pp++] - CHAR_0); - } - if (ptr[pp++] != CHAR_RIGHT_PARENTHESIS) - { - errorcode = ERR60; - ptr += pp; - goto HAD_EARLY_ERROR; + case PSO_LIMM: + case PSO_LIMD: + case PSO_LIMH: + c = 0; + pp = skipatstart; + if (!IS_DIGIT(ptr[pp])) + { + errorcode = ERR60; + ptr += pp; + goto HAD_EARLY_ERROR; + } + while (IS_DIGIT(ptr[pp])) + { + if (c > UINT32_MAX / 10 - 1) break; /* Integer overflow */ + c = c*10 + (ptr[pp++] - CHAR_0); + } + if (ptr[pp++] != CHAR_RIGHT_PARENTHESIS) + { + errorcode = ERR60; + ptr += pp; + goto HAD_EARLY_ERROR; + } + if (p->type == PSO_LIMH) limit_heap = c; + else if (p->type == PSO_LIMM) limit_match = c; + else limit_depth = c; + skipatstart += pp - skipatstart; + break; } - if (p->type == PSO_LIMM) limit_match = c; - else limit_recursion = c; - skipatstart += pp - skipatstart; - break; + break; /* Out of the table scan loop */ } - break; /* Out of the table scan loop */ } + if (i >= sizeof(pso_list)/sizeof(pso)) break; /* Out of pso loop */ } - if (i >= sizeof(pso_list)/sizeof(pso)) break; /* Out of pso loop */ } /* End of pattern-start options; advance to start of real regex. */ @@ -9000,7 +9241,9 @@ if ((cb.external_options & (PCRE2_UTF|PCRE2_UCP)) != 0) #endif /* Check UTF. We have the original options in 'options', with that value as -modified by (*UTF) etc in cb->external_options. */ +modified by (*UTF) etc in cb->external_options. The extra option +PCRE2_EXTRA_ALLOW_SURROGATE_ESCAPES is not permitted in UTF-16 mode because the +surrogate code points cannot be represented in UTF-16. */ utf = (cb.external_options & PCRE2_UTF) != 0; if (utf) @@ -9013,6 +9256,14 @@ if (utf) if ((options & PCRE2_NO_UTF_CHECK) == 0 && (errorcode = PRIV(valid_utf)(pattern, patlen, erroroffset)) != 0) goto HAD_ERROR; /* Offset was set by valid_utf() */ + +#if PCRE2_CODE_UNIT_WIDTH == 16 + if ((ccontext->extra_options & PCRE2_EXTRA_ALLOW_SURROGATE_ESCAPES) != 0) + { + errorcode = ERR91; + goto HAD_EARLY_ERROR; + } +#endif } /* Check UCP lockout. */ @@ -9044,6 +9295,11 @@ switch(newline) cb.nl[0] = CHAR_NL; break; + case PCRE2_NEWLINE_NUL: + cb.nllen = 1; + cb.nl[0] = CHAR_NUL; + break; + case PCRE2_NEWLINE_CRLF: cb.nllen = 2; cb.nl[0] = CHAR_CR; @@ -9071,10 +9327,10 @@ and comments removed (amongst other things). In all but one case, when PCRE2_AUTO_CALLOUT is not set, the number of unsigned 32-bit ints in the parsed pattern is bounded by the length of the pattern plus -one (for the terminator). The exceptional case is when running in 32-bit, -non-UTF mode, when literal characters greater than META_END (0x80000000) have -to be coded as two units. In this case, therefore, we scan the pattern to check -for such values. */ +one (for the terminator) plus four if PCRE2_EXTRA_WORD or PCRE2_EXTRA_LINE is +set. The exceptional case is when running in 32-bit, non-UTF mode, when literal +characters greater than META_END (0x80000000) have to be coded as two units. In +this case, therefore, we scan the pattern to check for such values. */ #if PCRE2_CODE_UNIT_WIDTH == 32 if (!utf) @@ -9091,6 +9347,11 @@ many smaller patterns the vector on the stack (which was set up above) can be used. */ parsed_size_needed = patlen - skipatstart + big32count; + +if ((ccontext->extra_options & + (PCRE2_EXTRA_MATCH_WORD|PCRE2_EXTRA_MATCH_LINE)) != 0) + parsed_size_needed += 4; + if ((options & PCRE2_AUTO_CALLOUT) != 0) parsed_size_needed = (parsed_size_needed + 1) * 5; @@ -9199,7 +9460,8 @@ possible because nowadays we limit the maximum value of cb.names_found and cb.name_entry_size. */ re_blocksize = sizeof(pcre2_real_code) + - CU2BYTES(length + cb.names_found * cb.name_entry_size); + CU2BYTES(length + + (PCRE2_SIZE)cb.names_found * (PCRE2_SIZE)cb.name_entry_size); re = (pcre2_real_code *) ccontext->memctl.malloc(re_blocksize, ccontext->memctl.memory_data); if (re == NULL) @@ -9208,6 +9470,13 @@ if (re == NULL) goto HAD_CB_ERROR; } +/* The compiler may put padding at the end of the pcre2_real_code structure in +order to round it up to a multiple of 4 or 8 bytes. This means that when a +compiled pattern is copied (for example, when serialized) undefined bytes are +read, and this annoys debuggers such as valgrind. To avoid this, we explicitly +write to the last 8 bytes of the structure before setting the fields. */ + +memset((char *)re + sizeof(pcre2_real_code) - 8, 0, 8); re->memctl = ccontext->memctl; re->tables = tables; re->executable_jit = NULL; @@ -9216,9 +9485,11 @@ re->blocksize = re_blocksize; re->magic_number = MAGIC_NUMBER; re->compile_options = options; re->overall_options = cb.external_options; +re->extra_options = ccontext->extra_options; re->flags = PCRE2_CODE_UNIT_WIDTH/8 | cb.external_flags | setflags; +re->limit_heap = limit_heap; re->limit_match = limit_match; -re->limit_recursion = limit_recursion; +re->limit_depth = limit_depth; re->first_codeunit = 0; re->last_codeunit = 0; re->bsr_convention = bsr; @@ -9390,16 +9661,21 @@ if ((re->overall_options & PCRE2_ANCHORED) == 0 && is_anchored(codestart, 0, &cb, 0, FALSE)) re->overall_options |= PCRE2_ANCHORED; -/* If the pattern is still not anchored and we do not have a first code unit, -see if there is one that is asserted (these are not saved during the compile -because they can cause conflicts with actual literals that follow). This code -need not be obeyed if PCRE2_NO_START_OPTIMIZE is set, as the data it would -create will not be used. */ +/* Set up the first code unit or startline flag, the required code unit, and +then study the pattern. This code need not be obeyed if PCRE2_NO_START_OPTIMIZE +is set, as the data it would create will not be used. Note that a first code +unit (but not the startline flag) is useful for anchored patterns because it +can still give a quick "no match" and also avoid searching for a last code +unit. */ -if ((re->overall_options & (PCRE2_ANCHORED|PCRE2_NO_START_OPTIMIZE)) == 0) +if ((re->overall_options & PCRE2_NO_START_OPTIMIZE) == 0) { + /* If we do not have a first code unit, see if there is one that is asserted + (these are not saved during the compile because they can cause conflicts with + actual literals that follow). */ + if (firstcuflags < 0) - firstcu = find_firstassertedcu(codestart, &firstcuflags, FALSE); + firstcu = find_firstassertedcu(codestart, &firstcuflags, 0); /* Save the data for a first code unit. */ @@ -9430,52 +9706,50 @@ if ((re->overall_options & (PCRE2_ANCHORED|PCRE2_NO_START_OPTIMIZE)) == 0) } } - /* When there is no first code unit, see if we can set the PCRE2_STARTLINE - flag. This is helpful for multiline matches when all branches start with ^ - and also when all branches start with non-atomic .* for non-DOTALL matches - when *PRUNE and SKIP are not present. (There is an option that disables this - case.) */ + /* When there is no first code unit, for non-anchored patterns, see if we can + set the PCRE2_STARTLINE flag. This is helpful for multiline matches when all + branches start with ^ and also when all branches start with non-atomic .* for + non-DOTALL matches when *PRUNE and SKIP are not present. (There is an option + that disables this case.) */ - else if (is_startline(codestart, 0, &cb, 0, FALSE)) + else if ((re->overall_options & PCRE2_ANCHORED) == 0 && + is_startline(codestart, 0, &cb, 0, FALSE)) re->flags |= PCRE2_STARTLINE; - } -/* Handle the "required code unit", if one is set. In the case of an anchored -pattern, do this only if it follows a variable length item in the pattern. -Again, skip this if PCRE2_NO_START_OPTIMIZE is set. */ + /* Handle the "required code unit", if one is set. In the case of an anchored + pattern, do this only if it follows a variable length item in the pattern. */ -if (reqcuflags >= 0 && - ((re->overall_options & (PCRE2_ANCHORED|PCRE2_NO_START_OPTIMIZE)) == 0 || - (reqcuflags & REQ_VARY) != 0)) - { - re->last_codeunit = reqcu; - re->flags |= PCRE2_LASTSET; + if (reqcuflags >= 0 && + ((re->overall_options & PCRE2_ANCHORED) == 0 || + (reqcuflags & REQ_VARY) != 0)) + { + re->last_codeunit = reqcu; + re->flags |= PCRE2_LASTSET; - /* Handle caseless required code units as for first code units (above). */ + /* Handle caseless required code units as for first code units (above). */ - if ((reqcuflags & REQ_CASELESS) != 0) - { - if (reqcu < 128 || (!utf && reqcu < 255)) + if ((reqcuflags & REQ_CASELESS) != 0) { - if (cb.fcc[reqcu] != reqcu) re->flags |= PCRE2_LASTCASELESS; - } + if (reqcu < 128 || (!utf && reqcu < 255)) + { + if (cb.fcc[reqcu] != reqcu) re->flags |= PCRE2_LASTCASELESS; + } #if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 8 - else if (reqcu <= MAX_UTF_CODE_POINT && UCD_OTHERCASE(reqcu) != reqcu) - re->flags |= PCRE2_LASTCASELESS; + else if (reqcu <= MAX_UTF_CODE_POINT && UCD_OTHERCASE(reqcu) != reqcu) + re->flags |= PCRE2_LASTCASELESS; #endif + } } - } -/* Finally, unless PCRE2_NO_START_OPTIMIZE is set, study the compiled pattern -to set up information such as a bitmap of starting code units and a minimum -matching length. */ + /* Finally, study the compiled pattern to set up information such as a bitmap + of starting code units and a minimum matching length. */ -if ((re->overall_options & PCRE2_NO_START_OPTIMIZE) == 0 && - PRIV(study)(re) != 0) - { - errorcode = ERR31; - goto HAD_CB_ERROR; - } + if (PRIV(study)(re) != 0) + { + errorcode = ERR31; + goto HAD_CB_ERROR; + } + } /* End of start-of-match optimizations. */ /* Control ends up here in all cases. When running under valgrind, make a pattern's terminating zero defined again. If memory was obtained for the parsed diff --git a/thirdparty/pcre2/src/pcre2_config.c b/thirdparty/pcre2/src/pcre2_config.c index e99272f577..e487b10220 100644 --- a/thirdparty/pcre2/src/pcre2_config.c +++ b/thirdparty/pcre2/src/pcre2_config.c @@ -7,7 +7,7 @@ and semantics are as close as possible to those of the Perl 5 language. Written by Philip Hazel Original API code Copyright (c) 1997-2012 University of Cambridge - New API code Copyright (c) 2016 University of Cambridge + New API code Copyright (c) 2016-2017 University of Cambridge ----------------------------------------------------------------------------- Redistribution and use in source and binary forms, with or without @@ -84,13 +84,16 @@ if (where == NULL) /* Requests a length */ return PCRE2_ERROR_BADOPTION; case PCRE2_CONFIG_BSR: + case PCRE2_CONFIG_COMPILED_WIDTHS: + case PCRE2_CONFIG_DEPTHLIMIT: + case PCRE2_CONFIG_HEAPLIMIT: case PCRE2_CONFIG_JIT: case PCRE2_CONFIG_LINKSIZE: case PCRE2_CONFIG_MATCHLIMIT: + case PCRE2_CONFIG_NEVER_BACKSLASH_C: case PCRE2_CONFIG_NEWLINE: case PCRE2_CONFIG_PARENSLIMIT: - case PCRE2_CONFIG_RECURSIONLIMIT: - case PCRE2_CONFIG_STACKRECURSE: + case PCRE2_CONFIG_STACKRECURSE: /* Obsolete */ case PCRE2_CONFIG_UNICODE: return sizeof(uint32_t); @@ -116,6 +119,28 @@ switch (what) #endif break; + case PCRE2_CONFIG_COMPILED_WIDTHS: + *((uint32_t *)where) = 0 +#ifdef SUPPORT_PCRE2_8 + + 1 +#endif +#ifdef SUPPORT_PCRE2_16 + + 2 +#endif +#ifdef SUPPORT_PCRE2_32 + + 4 +#endif + ; + break; + + case PCRE2_CONFIG_DEPTHLIMIT: + *((uint32_t *)where) = MATCH_LIMIT_DEPTH; + break; + + case PCRE2_CONFIG_HEAPLIMIT: + *((uint32_t *)where) = HEAP_LIMIT; + break; + case PCRE2_CONFIG_JIT: #ifdef SUPPORT_JIT *((uint32_t *)where) = 1; @@ -147,20 +172,23 @@ switch (what) *((uint32_t *)where) = NEWLINE_DEFAULT; break; + case PCRE2_CONFIG_NEVER_BACKSLASH_C: +#ifdef NEVER_BACKSLASH_C + *((uint32_t *)where) = 1; +#else + *((uint32_t *)where) = 0; +#endif + break; + case PCRE2_CONFIG_PARENSLIMIT: *((uint32_t *)where) = PARENS_NEST_LIMIT; break; - case PCRE2_CONFIG_RECURSIONLIMIT: - *((uint32_t *)where) = MATCH_LIMIT_RECURSION; - break; + /* This is now obsolete. The stack is no longer used via recursion for + handling backtracking in pcre2_match(). */ case PCRE2_CONFIG_STACKRECURSE: -#ifdef HEAP_MATCH_RECURSE *((uint32_t *)where) = 0; -#else - *((uint32_t *)where) = 1; -#endif break; case PCRE2_CONFIG_UNICODE_VERSION: diff --git a/thirdparty/pcre2/src/pcre2_context.c b/thirdparty/pcre2/src/pcre2_context.c index ae050fe92c..2c14df0080 100644 --- a/thirdparty/pcre2/src/pcre2_context.c +++ b/thirdparty/pcre2/src/pcre2_context.c @@ -7,7 +7,7 @@ and semantics are as close as possible to those of the Perl 5 language. Written by Philip Hazel Original API code Copyright (c) 1997-2012 University of Cambridge - New API code Copyright (c) 2016 University of Cambridge + New API code Copyright (c) 2016-2017 University of Cambridge ----------------------------------------------------------------------------- Redistribution and use in source and binary forms, with or without @@ -138,7 +138,8 @@ const pcre2_compile_context PRIV(default_compile_context) = { PCRE2_UNSET, /* Max pattern length */ BSR_DEFAULT, /* Backslash R default */ NEWLINE_DEFAULT, /* Newline convention */ - PARENS_NEST_LIMIT }; /* As it says */ + PARENS_NEST_LIMIT, /* As it says */ + 0 }; /* Extra options */ /* The create function copies the default into the new memory, but must override the default memory handling functions if a gcontext was provided. */ @@ -161,9 +162,6 @@ when no context is supplied to a match function. */ const pcre2_match_context PRIV(default_match_context) = { { default_malloc, default_free, NULL }, -#ifdef HEAP_MATCH_RECURSE - { default_malloc, default_free, NULL }, -#endif #ifdef SUPPORT_JIT NULL, NULL, @@ -171,8 +169,9 @@ const pcre2_match_context PRIV(default_match_context) = { NULL, NULL, PCRE2_UNSET, /* Offset limit */ + HEAP_LIMIT, MATCH_LIMIT, - MATCH_LIMIT_RECURSION }; + MATCH_LIMIT_DEPTH }; /* The create function copies the default into the new memory, but must override the default memory handling functions if a gcontext was provided. */ @@ -190,6 +189,36 @@ return mcontext; } +/* A default convert context is set up to save having to initialize at run time +when no context is supplied to the convert function. */ + +const pcre2_convert_context PRIV(default_convert_context) = { + { default_malloc, default_free, NULL }, /* Default memory handling */ +#ifdef _WIN32 + CHAR_BACKSLASH, /* Default path separator */ + CHAR_GRAVE_ACCENT /* Default escape character */ +#else /* Not Windows */ + CHAR_SLASH, /* Default path separator */ + CHAR_BACKSLASH /* Default escape character */ +#endif + }; + +/* The create function copies the default into the new memory, but must +override the default memory handling functions if a gcontext was provided. */ + +PCRE2_EXP_DEFN pcre2_convert_context * PCRE2_CALL_CONVENTION +pcre2_convert_context_create(pcre2_general_context *gcontext) +{ +pcre2_convert_context *ccontext = PRIV(memctl_malloc)( + sizeof(pcre2_real_convert_context), (pcre2_memctl *)gcontext); +if (ccontext == NULL) return NULL; +*ccontext = PRIV(default_convert_context); +if (gcontext != NULL) + *((pcre2_memctl *)ccontext) = *((pcre2_memctl *)gcontext); +return ccontext; +} + + /************************************************* * Context copy functions * *************************************************/ @@ -231,11 +260,22 @@ return new; +PCRE2_EXP_DEFN pcre2_convert_context * PCRE2_CALL_CONVENTION +pcre2_convert_context_copy(pcre2_convert_context *ccontext) +{ +pcre2_convert_context *new = + ccontext->memctl.malloc(sizeof(pcre2_real_convert_context), + ccontext->memctl.memory_data); +if (new == NULL) return NULL; +memcpy(new, ccontext, sizeof(pcre2_real_convert_context)); +return new; +} + + /************************************************* * Context free functions * *************************************************/ - PCRE2_EXP_DEFN void PCRE2_CALL_CONVENTION pcre2_general_context_free(pcre2_general_context *gcontext) { @@ -260,6 +300,12 @@ if (mcontext != NULL) } +PCRE2_EXP_DEFN void PCRE2_CALL_CONVENTION +pcre2_convert_context_free(pcre2_convert_context *ccontext) +{ +if (ccontext != NULL) + ccontext->memctl.free(ccontext, ccontext->memctl.memory_data); +} /************************************************* @@ -271,7 +317,7 @@ data is given. Only some of the functions are able to test the validity of the data. */ -/* ------------ Compile contexts ------------ */ +/* ------------ Compile context ------------ */ PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION pcre2_set_character_tables(pcre2_compile_context *ccontext, @@ -313,6 +359,7 @@ switch(newline) case PCRE2_NEWLINE_CRLF: case PCRE2_NEWLINE_ANY: case PCRE2_NEWLINE_ANYCRLF: + case PCRE2_NEWLINE_NUL: ccontext->newline_convention = newline; return 0; @@ -329,6 +376,13 @@ return 0; } PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION +pcre2_set_compile_extra_options(pcre2_compile_context *ccontext, uint32_t options) +{ +ccontext->extra_options = options; +return 0; +} + +PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION pcre2_set_compile_recursion_guard(pcre2_compile_context *ccontext, int (*guard)(uint32_t, void *), void *user_data) { @@ -338,7 +392,7 @@ return 0; } -/* ------------ Match contexts ------------ */ +/* ------------ Match context ------------ */ PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION pcre2_set_callout(pcre2_match_context *mcontext, @@ -350,6 +404,13 @@ return 0; } PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION +pcre2_set_heap_limit(pcre2_match_context *mcontext, uint32_t limit) +{ +mcontext->heap_limit = limit; +return 0; +} + +PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION pcre2_set_match_limit(pcre2_match_context *mcontext, uint32_t limit) { mcontext->match_limit = limit; @@ -357,17 +418,26 @@ return 0; } PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION +pcre2_set_depth_limit(pcre2_match_context *mcontext, uint32_t limit) +{ +mcontext->depth_limit = limit; +return 0; +} + +PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION pcre2_set_offset_limit(pcre2_match_context *mcontext, PCRE2_SIZE limit) { mcontext->offset_limit = limit; return 0; } +/* This function became obsolete at release 10.30. It is kept as a synonym for +backwards compatibility. */ + PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION pcre2_set_recursion_limit(pcre2_match_context *mcontext, uint32_t limit) { -mcontext->recursion_limit = limit; -return 0; +return pcre2_set_depth_limit(mcontext, limit); } PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION @@ -375,17 +445,32 @@ pcre2_set_recursion_memory_management(pcre2_match_context *mcontext, void *(*mymalloc)(size_t, void *), void (*myfree)(void *, void *), void *mydata) { -#ifdef HEAP_MATCH_RECURSE -mcontext->stack_memctl.malloc = mymalloc; -mcontext->stack_memctl.free = myfree; -mcontext->stack_memctl.memory_data = mydata; -#else (void)mcontext; (void)mymalloc; (void)myfree; (void)mydata; -#endif +return 0; +} + +/* ------------ Convert context ------------ */ + +PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION +pcre2_set_glob_separator(pcre2_convert_context *ccontext, uint32_t separator) +{ +if (separator != CHAR_SLASH && separator != CHAR_BACKSLASH && + separator != CHAR_DOT) return PCRE2_ERROR_BADDATA; +ccontext->glob_separator = separator; +return 0; +} + +PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION +pcre2_set_glob_escape(pcre2_convert_context *ccontext, uint32_t escape) +{ +if (escape > 255 || (escape != 0 && !ispunct(escape))) + return PCRE2_ERROR_BADDATA; +ccontext->glob_escape = escape; return 0; } /* End of pcre2_context.c */ + diff --git a/thirdparty/pcre2/src/pcre2_convert.c b/thirdparty/pcre2/src/pcre2_convert.c new file mode 100644 index 0000000000..bdf9b86df6 --- /dev/null +++ b/thirdparty/pcre2/src/pcre2_convert.c @@ -0,0 +1,1176 @@ +/************************************************* +* Perl-Compatible Regular Expressions * +*************************************************/ + +/* PCRE is a library of functions to support regular expressions whose syntax +and semantics are as close as possible to those of the Perl 5 language. + + Written by Philip Hazel + Original API code Copyright (c) 1997-2012 University of Cambridge + New API code Copyright (c) 2016-2017 University of Cambridge + +----------------------------------------------------------------------------- +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of the University of Cambridge nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +----------------------------------------------------------------------------- +*/ + + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "pcre2_internal.h" + +#define TYPE_OPTIONS (PCRE2_CONVERT_GLOB| \ + PCRE2_CONVERT_POSIX_BASIC|PCRE2_CONVERT_POSIX_EXTENDED) + +#define ALL_OPTIONS (PCRE2_CONVERT_UTF|PCRE2_CONVERT_NO_UTF_CHECK| \ + PCRE2_CONVERT_GLOB_NO_WILD_SEPARATOR| \ + PCRE2_CONVERT_GLOB_NO_STARSTAR| \ + TYPE_OPTIONS) + +#define DUMMY_BUFFER_SIZE 100 + +/* Generated pattern fragments */ + +#define STR_BACKSLASH_A STR_BACKSLASH STR_A +#define STR_BACKSLASH_z STR_BACKSLASH STR_z +#define STR_COLON_RIGHT_SQUARE_BRACKET STR_COLON STR_RIGHT_SQUARE_BRACKET +#define STR_DOT_STAR_LOOKBEHIND STR_DOT STR_ASTERISK STR_LEFT_PARENTHESIS STR_QUESTION_MARK STR_LESS_THAN_SIGN STR_EQUALS_SIGN +#define STR_LOOKAHEAD_NOT_DOT STR_LEFT_PARENTHESIS STR_QUESTION_MARK STR_EXCLAMATION_MARK STR_BACKSLASH STR_DOT STR_RIGHT_PARENTHESIS +#define STR_QUERY_s STR_LEFT_PARENTHESIS STR_QUESTION_MARK STR_s STR_RIGHT_PARENTHESIS +#define STR_STAR_NUL STR_LEFT_PARENTHESIS STR_ASTERISK STR_N STR_U STR_L STR_RIGHT_PARENTHESIS + +/* States for range and POSIX processing */ + +enum { RANGE_NOT_STARTED, RANGE_STARTING, RANGE_STARTED }; +enum { POSIX_START_REGEX, POSIX_ANCHORED, POSIX_NOT_BRACKET, + POSIX_CLASS_NOT_STARTED, POSIX_CLASS_STARTING, POSIX_CLASS_STARTED }; + +/* Macro to add a character string to the output buffer, checking for overflow. */ + +#define PUTCHARS(string) \ + { \ + for (s = (char *)(string); *s != 0; s++) \ + { \ + if (p >= endp) return PCRE2_ERROR_NOMEMORY; \ + *p++ = *s; \ + } \ + } + +/* Literals that must be escaped: \ ? * + | . ^ $ { } [ ] ( ) */ + +static const char *pcre2_escaped_literals = + STR_BACKSLASH STR_QUESTION_MARK STR_ASTERISK STR_PLUS + STR_VERTICAL_LINE STR_DOT STR_CIRCUMFLEX_ACCENT STR_DOLLAR_SIGN + STR_LEFT_CURLY_BRACKET STR_RIGHT_CURLY_BRACKET + STR_LEFT_SQUARE_BRACKET STR_RIGHT_SQUARE_BRACKET + STR_LEFT_PARENTHESIS STR_RIGHT_PARENTHESIS; + +/* Recognized escaped metacharacters in POSIX basic patterns. */ + +static const char *posix_meta_escapes = + STR_LEFT_PARENTHESIS STR_RIGHT_PARENTHESIS + STR_LEFT_CURLY_BRACKET STR_RIGHT_CURLY_BRACKET + STR_1 STR_2 STR_3 STR_4 STR_5 STR_6 STR_7 STR_8 STR_9; + + + +/************************************************* +* Convert a POSIX pattern * +*************************************************/ + +/* This function handles both basic and extended POSIX patterns. + +Arguments: + pattype the pattern type + pattern the pattern + plength length in code units + utf TRUE if UTF + use_buffer where to put the output + use_length length of use_buffer + bufflenptr where to put the used length + dummyrun TRUE if a dummy run + ccontext the convert context + +Returns: 0 => success + !0 => error code +*/ + +static int +convert_posix(uint32_t pattype, PCRE2_SPTR pattern, PCRE2_SIZE plength, + BOOL utf, PCRE2_UCHAR *use_buffer, PCRE2_SIZE use_length, + PCRE2_SIZE *bufflenptr, BOOL dummyrun, pcre2_convert_context *ccontext) +{ +char *s; +PCRE2_SPTR posix = pattern; +PCRE2_UCHAR *p = use_buffer; +PCRE2_UCHAR *pp = p; +PCRE2_UCHAR *endp = p + use_length - 1; /* Allow for trailing zero */ +PCRE2_SIZE convlength = 0; + +uint32_t bracount = 0; +uint32_t posix_state = POSIX_START_REGEX; +uint32_t lastspecial = 0; +BOOL extended = (pattype & PCRE2_CONVERT_POSIX_EXTENDED) != 0; +BOOL nextisliteral = FALSE; + +(void)utf; /* Not used when Unicode not supported */ +(void)ccontext; /* Not currently used */ + +/* Initialize default for error offset as end of input. */ + +*bufflenptr = plength; +PUTCHARS(STR_STAR_NUL); + +/* Now scan the input. */ + +while (plength > 0) + { + uint32_t c, sc; + int clength = 1; + + /* Add in the length of the last item, then, if in the dummy run, pull the + pointer back to the start of the (temporary) buffer and then remember the + start of the next item. */ + + convlength += p - pp; + if (dummyrun) p = use_buffer; + pp = p; + + /* Pick up the next character */ + +#ifndef SUPPORT_UNICODE + c = *posix; +#else + GETCHARLENTEST(c, posix, clength); +#endif + posix += clength; + plength -= clength; + + sc = nextisliteral? 0 : c; + nextisliteral = FALSE; + + /* Handle a character within a class. */ + + if (posix_state >= POSIX_CLASS_NOT_STARTED) + { + if (c == CHAR_RIGHT_SQUARE_BRACKET) + { + PUTCHARS(STR_RIGHT_SQUARE_BRACKET); + posix_state = POSIX_NOT_BRACKET; + } + + /* Not the end of the class */ + + else + { + switch (posix_state) + { + case POSIX_CLASS_STARTED: + if (c <= 127 && islower(c)) break; /* Remain in started state */ + posix_state = POSIX_CLASS_NOT_STARTED; + if (c == CHAR_COLON && plength > 0 && + *posix == CHAR_RIGHT_SQUARE_BRACKET) + { + PUTCHARS(STR_COLON_RIGHT_SQUARE_BRACKET); + plength--; + posix++; + continue; /* With next character after :] */ + } + /* Fall through */ + + case POSIX_CLASS_NOT_STARTED: + if (c == CHAR_LEFT_SQUARE_BRACKET) + posix_state = POSIX_CLASS_STARTING; + break; + + case POSIX_CLASS_STARTING: + if (c == CHAR_COLON) posix_state = POSIX_CLASS_STARTED; + break; + } + + if (c == CHAR_BACKSLASH) PUTCHARS(STR_BACKSLASH); + if (p + clength > endp) return PCRE2_ERROR_NOMEMORY; + memcpy(p, posix - clength, CU2BYTES(clength)); + p += clength; + } + } + + /* Handle a character not within a class. */ + + else switch(sc) + { + case CHAR_LEFT_SQUARE_BRACKET: + PUTCHARS(STR_LEFT_SQUARE_BRACKET); + +#ifdef NEVER + /* We could handle special cases [[:<:]] and [[:>:]] (which PCRE does + support) but they are not part of POSIX 1003.1. */ + + if (plength >= 6) + { + if (posix[0] == CHAR_LEFT_SQUARE_BRACKET && + posix[1] == CHAR_COLON && + (posix[2] == CHAR_LESS_THAN_SIGN || + posix[2] == CHAR_GREATER_THAN_SIGN) && + posix[3] == CHAR_COLON && + posix[4] == CHAR_RIGHT_SQUARE_BRACKET && + posix[5] == CHAR_RIGHT_SQUARE_BRACKET) + { + if (p + 6 > endp) return PCRE2_ERROR_NOMEMORY; + memcpy(p, posix, CU2BYTES(6)); + p += 6; + posix += 6; + plength -= 6; + continue; /* With next character */ + } + } +#endif + + /* Handle start of "normal" character classes */ + + posix_state = POSIX_CLASS_NOT_STARTED; + + /* Handle ^ and ] as first characters */ + + if (plength > 0) + { + if (*posix == CHAR_CIRCUMFLEX_ACCENT) + { + posix++; + plength--; + PUTCHARS(STR_CIRCUMFLEX_ACCENT); + } + if (plength > 0 && *posix == CHAR_RIGHT_SQUARE_BRACKET) + { + posix++; + plength--; + PUTCHARS(STR_RIGHT_SQUARE_BRACKET); + } + } + break; + + case CHAR_BACKSLASH: + if (plength <= 0) return PCRE2_ERROR_END_BACKSLASH; + if (extended) nextisliteral = TRUE; else + { + if (*posix < 127 && strchr(posix_meta_escapes, *posix) != NULL) + { + if (isdigit(*posix)) PUTCHARS(STR_BACKSLASH); + if (p + 1 > endp) return PCRE2_ERROR_NOMEMORY; + lastspecial = *p++ = *posix++; + plength--; + } + else nextisliteral = TRUE; + } + break; + + case CHAR_RIGHT_PARENTHESIS: + if (!extended || bracount == 0) goto ESCAPE_LITERAL; + bracount--; + goto COPY_SPECIAL; + + case CHAR_LEFT_PARENTHESIS: + bracount++; + /* Fall through */ + + case CHAR_QUESTION_MARK: + case CHAR_PLUS: + case CHAR_LEFT_CURLY_BRACKET: + case CHAR_RIGHT_CURLY_BRACKET: + case CHAR_VERTICAL_LINE: + if (!extended) goto ESCAPE_LITERAL; + /* Fall through */ + + case CHAR_DOT: + case CHAR_DOLLAR_SIGN: + posix_state = POSIX_NOT_BRACKET; + COPY_SPECIAL: + lastspecial = c; + if (p + 1 > endp) return PCRE2_ERROR_NOMEMORY; + *p++ = c; + break; + + case CHAR_ASTERISK: + if (lastspecial != CHAR_ASTERISK) + { + if (!extended && (posix_state < POSIX_NOT_BRACKET || + lastspecial == CHAR_LEFT_PARENTHESIS)) + goto ESCAPE_LITERAL; + goto COPY_SPECIAL; + } + break; /* Ignore second and subsequent asterisks */ + + case CHAR_CIRCUMFLEX_ACCENT: + if (extended) goto COPY_SPECIAL; + if (posix_state == POSIX_START_REGEX || + lastspecial == CHAR_LEFT_PARENTHESIS) + { + posix_state = POSIX_ANCHORED; + goto COPY_SPECIAL; + } + /* Fall through */ + + default: + if (c < 128 && strchr(pcre2_escaped_literals, c) != NULL) + { + ESCAPE_LITERAL: + PUTCHARS(STR_BACKSLASH); + } + lastspecial = 0xff; /* Indicates nothing special */ + if (p + clength > endp) return PCRE2_ERROR_NOMEMORY; + memcpy(p, posix - clength, CU2BYTES(clength)); + p += clength; + posix_state = POSIX_NOT_BRACKET; + break; + } + } + +if (posix_state >= POSIX_CLASS_NOT_STARTED) + return PCRE2_ERROR_MISSING_SQUARE_BRACKET; +convlength += p - pp; /* Final segment */ +*bufflenptr = convlength; +*p++ = 0; +return 0; +} + + +/************************************************* +* Convert a glob pattern * +*************************************************/ + +/* Context for writing the output into a buffer. */ + +typedef struct pcre2_output_context { + PCRE2_UCHAR *output; /* current output position */ + PCRE2_SPTR output_end; /* output end */ + PCRE2_SIZE output_size; /* size of the output */ + uint8_t out_str[8]; /* string copied to the output */ +} pcre2_output_context; + + +/* Write a character into the output. + +Arguments: + out output context + chr the next character +*/ + +static void +convert_glob_write(pcre2_output_context *out, PCRE2_UCHAR chr) +{ +out->output_size++; + +if (out->output < out->output_end) + *out->output++ = chr; +} + + +/* Write a string into the output. + +Arguments: + out output context + length length of out->out_str +*/ + +static void +convert_glob_write_str(pcre2_output_context *out, PCRE2_SIZE length) +{ +uint8_t *out_str = out->out_str; +PCRE2_UCHAR *output = out->output; +PCRE2_SPTR output_end = out->output_end; +PCRE2_SIZE output_size = out->output_size; + +do + { + output_size++; + + if (output < output_end) + *output++ = *out_str++; + } +while (--length != 0); + +out->output = output; +out->output_size = output_size; +} + + +/* Prints the separator into the output. + +Arguments: + out output context + separator glob separator + with_escape backslash is needed before separator +*/ + +static void +convert_glob_print_separator(pcre2_output_context *out, + PCRE2_UCHAR separator, BOOL with_escape) +{ +if (with_escape) + convert_glob_write(out, CHAR_BACKSLASH); + +convert_glob_write(out, separator); +} + + +/* Prints a wildcard into the output. + +Arguments: + out output context + separator glob separator + with_escape backslash is needed before separator +*/ + +static void +convert_glob_print_wildcard(pcre2_output_context *out, + PCRE2_UCHAR separator, BOOL with_escape) +{ +out->out_str[0] = CHAR_LEFT_SQUARE_BRACKET; +out->out_str[1] = CHAR_CIRCUMFLEX_ACCENT; +convert_glob_write_str(out, 2); + +convert_glob_print_separator(out, separator, with_escape); + +convert_glob_write(out, CHAR_RIGHT_SQUARE_BRACKET); +} + + +/* Parse a posix class. + +Arguments: + from starting point of scanning the range + pattern_end end of pattern + out output context + +Returns: >0 => class index + 0 => malformed class +*/ + +static int +convert_glob_parse_class(PCRE2_SPTR *from, PCRE2_SPTR pattern_end, + pcre2_output_context *out) +{ +static const char *posix_classes = "alnum:alpha:ascii:blank:cntrl:digit:" + "graph:lower:print:punct:space:upper:word:xdigit:"; +PCRE2_SPTR start = *from + 1; +PCRE2_SPTR pattern = start; +const char *class_ptr; +PCRE2_UCHAR c; +int class_index; + +while (TRUE) + { + if (pattern >= pattern_end) return 0; + + c = *pattern++; + + if (c < CHAR_a || c > CHAR_z) break; + } + +if (c != CHAR_COLON || pattern >= pattern_end || + *pattern != CHAR_RIGHT_SQUARE_BRACKET) + return 0; + +class_ptr = posix_classes; +class_index = 1; + +while (TRUE) + { + if (*class_ptr == CHAR_NUL) return 0; + + pattern = start; + + while (*pattern == (PCRE2_UCHAR) *class_ptr) + { + if (*pattern == CHAR_COLON) + { + pattern += 2; + start -= 2; + + do convert_glob_write(out, *start++); while (start < pattern); + + *from = pattern; + return class_index; + } + pattern++; + class_ptr++; + } + + while (*class_ptr != CHAR_COLON) class_ptr++; + class_ptr++; + class_index++; + } +} + +/* Checks whether the character is in the class. + +Arguments: + class_index class index + c character + +Returns: !0 => character is found in the class + 0 => otherwise +*/ + +static BOOL +convert_glob_char_in_class(int class_index, PCRE2_UCHAR c) +{ +switch (class_index) + { + case 1: return isalnum(c); + case 2: return isalpha(c); + case 3: return 1; + case 4: return c == CHAR_HT || c == CHAR_SPACE; + case 5: return iscntrl(c); + case 6: return isdigit(c); + case 7: return isgraph(c); + case 8: return islower(c); + case 9: return isprint(c); + case 10: return ispunct(c); + case 11: return isspace(c); + case 12: return isupper(c); + case 13: return isalnum(c) || c == CHAR_UNDERSCORE; + default: return isxdigit(c); + } +} + +/* Parse a range of characters. + +Arguments: + from starting point of scanning the range + pattern_end end of pattern + out output context + separator glob separator + with_escape backslash is needed before separator + +Returns: 0 => success + !0 => error code +*/ + +static int +convert_glob_parse_range(PCRE2_SPTR *from, PCRE2_SPTR pattern_end, + pcre2_output_context *out, BOOL utf, PCRE2_UCHAR separator, + BOOL with_escape, PCRE2_UCHAR escape, BOOL no_wildsep) +{ +BOOL is_negative = FALSE; +BOOL separator_seen = FALSE; +BOOL has_prev_c; +PCRE2_SPTR pattern = *from; +PCRE2_SPTR char_start = NULL; +uint32_t c, prev_c; +int len, class_index; + +(void)utf; /* Avoid compiler warning. */ + +if (pattern >= pattern_end) + { + *from = pattern; + return PCRE2_ERROR_MISSING_SQUARE_BRACKET; + } + +if (*pattern == CHAR_EXCLAMATION_MARK + || *pattern == CHAR_CIRCUMFLEX_ACCENT) + { + pattern++; + + if (pattern >= pattern_end) + { + *from = pattern; + return PCRE2_ERROR_MISSING_SQUARE_BRACKET; + } + + is_negative = TRUE; + + out->out_str[0] = CHAR_LEFT_SQUARE_BRACKET; + out->out_str[1] = CHAR_CIRCUMFLEX_ACCENT; + len = 2; + + if (!no_wildsep) + { + if (with_escape) + { + out->out_str[len] = CHAR_BACKSLASH; + len++; + } + out->out_str[len] = (uint8_t) separator; + } + + convert_glob_write_str(out, len + 1); + } +else + convert_glob_write(out, CHAR_LEFT_SQUARE_BRACKET); + +has_prev_c = FALSE; +prev_c = 0; + +if (*pattern == CHAR_RIGHT_SQUARE_BRACKET) + { + out->out_str[0] = CHAR_BACKSLASH; + out->out_str[1] = CHAR_RIGHT_SQUARE_BRACKET; + convert_glob_write_str(out, 2); + has_prev_c = TRUE; + prev_c = CHAR_RIGHT_SQUARE_BRACKET; + pattern++; + } + +while (pattern < pattern_end) + { + char_start = pattern; + GETCHARINCTEST(c, pattern); + + if (c == CHAR_RIGHT_SQUARE_BRACKET) + { + convert_glob_write(out, c); + + if (!is_negative && !no_wildsep && separator_seen) + { + out->out_str[0] = CHAR_LEFT_PARENTHESIS; + out->out_str[1] = CHAR_QUESTION_MARK; + out->out_str[2] = CHAR_LESS_THAN_SIGN; + out->out_str[3] = CHAR_EXCLAMATION_MARK; + convert_glob_write_str(out, 4); + + convert_glob_print_separator(out, separator, with_escape); + convert_glob_write(out, CHAR_RIGHT_PARENTHESIS); + } + + *from = pattern; + return 0; + } + + if (pattern >= pattern_end) break; + + if (c == CHAR_LEFT_SQUARE_BRACKET && *pattern == CHAR_COLON) + { + *from = pattern; + class_index = convert_glob_parse_class(from, pattern_end, out); + + if (class_index != 0) + { + pattern = *from; + + has_prev_c = FALSE; + prev_c = 0; + + if (!is_negative && + convert_glob_char_in_class (class_index, separator)) + separator_seen = TRUE; + continue; + } + } + else if (c == CHAR_MINUS && has_prev_c && + *pattern != CHAR_RIGHT_SQUARE_BRACKET) + { + convert_glob_write(out, CHAR_MINUS); + + char_start = pattern; + GETCHARINCTEST(c, pattern); + + if (pattern >= pattern_end) break; + + if (escape != 0 && c == escape) + { + char_start = pattern; + GETCHARINCTEST(c, pattern); + } + else if (c == CHAR_LEFT_SQUARE_BRACKET && *pattern == CHAR_COLON) + { + *from = pattern; + return PCRE2_ERROR_CONVERT_SYNTAX; + } + + if (prev_c > c) + { + *from = pattern; + return PCRE2_ERROR_CONVERT_SYNTAX; + } + + if (prev_c < separator && separator < c) separator_seen = TRUE; + + has_prev_c = FALSE; + prev_c = 0; + } + else + { + if (escape != 0 && c == escape) + { + char_start = pattern; + GETCHARINCTEST(c, pattern); + + if (pattern >= pattern_end) break; + } + + has_prev_c = TRUE; + prev_c = c; + } + + if (c == CHAR_LEFT_SQUARE_BRACKET || c == CHAR_RIGHT_SQUARE_BRACKET || + c == CHAR_BACKSLASH || c == CHAR_MINUS) + convert_glob_write(out, CHAR_BACKSLASH); + + if (c == separator) separator_seen = TRUE; + + do convert_glob_write(out, *char_start++); while (char_start < pattern); + } + +*from = pattern; +return PCRE2_ERROR_MISSING_SQUARE_BRACKET; +} + + +/* Prints a (*COMMIT) into the output. + +Arguments: + out output context +*/ + +static void +convert_glob_print_commit(pcre2_output_context *out) +{ +out->out_str[0] = CHAR_LEFT_PARENTHESIS; +out->out_str[1] = CHAR_ASTERISK; +out->out_str[2] = CHAR_C; +out->out_str[3] = CHAR_O; +out->out_str[4] = CHAR_M; +out->out_str[5] = CHAR_M; +out->out_str[6] = CHAR_I; +out->out_str[7] = CHAR_T; +convert_glob_write_str(out, 8); +convert_glob_write(out, CHAR_RIGHT_PARENTHESIS); +} + + +/* Bash glob converter. + +Arguments: + pattype the pattern type + pattern the pattern + plength length in code units + utf TRUE if UTF + use_buffer where to put the output + use_length length of use_buffer + bufflenptr where to put the used length + dummyrun TRUE if a dummy run + ccontext the convert context + +Returns: 0 => success + !0 => error code +*/ + +static int +convert_glob(uint32_t options, PCRE2_SPTR pattern, PCRE2_SIZE plength, + BOOL utf, PCRE2_UCHAR *use_buffer, PCRE2_SIZE use_length, + PCRE2_SIZE *bufflenptr, BOOL dummyrun, pcre2_convert_context *ccontext) +{ +pcre2_output_context out; +PCRE2_SPTR pattern_start = pattern; +PCRE2_SPTR pattern_end = pattern + plength; +PCRE2_UCHAR separator = ccontext->glob_separator; +PCRE2_UCHAR escape = ccontext->glob_escape; +PCRE2_UCHAR c; +BOOL no_wildsep = (options & PCRE2_CONVERT_GLOB_NO_WILD_SEPARATOR) != 0; +BOOL no_starstar = (options & PCRE2_CONVERT_GLOB_NO_STARSTAR) != 0; +BOOL in_atomic = FALSE; +BOOL after_starstar = FALSE; +BOOL no_slash_z = FALSE; +BOOL with_escape, is_start, after_separator; +int result = 0; + +(void)utf; /* Avoid compiler warning. */ + +#ifdef SUPPORT_UNICODE +if (utf && (separator >= 128 || escape >= 128)) + { + /* Currently only ASCII characters are supported. */ + *bufflenptr = 0; + return PCRE2_ERROR_CONVERT_SYNTAX; + } +#endif + +with_escape = strchr(pcre2_escaped_literals, separator) != NULL; + +/* Initialize default for error offset as end of input. */ +out.output = use_buffer; +out.output_end = use_buffer + use_length; +out.output_size = 0; + +out.out_str[0] = CHAR_LEFT_PARENTHESIS; +out.out_str[1] = CHAR_QUESTION_MARK; +out.out_str[2] = CHAR_s; +out.out_str[3] = CHAR_RIGHT_PARENTHESIS; +convert_glob_write_str(&out, 4); + +is_start = TRUE; + +if (pattern < pattern_end && pattern[0] == CHAR_ASTERISK) + { + if (no_wildsep) + is_start = FALSE; + else if (!no_starstar && pattern + 1 < pattern_end && + pattern[1] == CHAR_ASTERISK) + is_start = FALSE; + } + +if (is_start) + { + out.out_str[0] = CHAR_BACKSLASH; + out.out_str[1] = CHAR_A; + convert_glob_write_str(&out, 2); + } + +while (pattern < pattern_end) + { + c = *pattern++; + + if (c == CHAR_ASTERISK) + { + is_start = pattern == pattern_start + 1; + + if (in_atomic) + { + convert_glob_write(&out, CHAR_RIGHT_PARENTHESIS); + in_atomic = FALSE; + } + + if (!no_starstar && pattern < pattern_end && *pattern == CHAR_ASTERISK) + { + after_separator = is_start || (pattern[-2] == separator); + + do pattern++; while (pattern < pattern_end && + *pattern == CHAR_ASTERISK); + + if (pattern >= pattern_end) + { + no_slash_z = TRUE; + break; + } + + after_starstar = TRUE; + + if (after_separator && escape != 0 && *pattern == escape && + pattern + 1 < pattern_end && pattern[1] == separator) + pattern++; + + if (is_start) + { + if (*pattern != separator) continue; + + out.out_str[0] = CHAR_LEFT_PARENTHESIS; + out.out_str[1] = CHAR_QUESTION_MARK; + out.out_str[2] = CHAR_COLON; + out.out_str[3] = CHAR_BACKSLASH; + out.out_str[4] = CHAR_A; + out.out_str[5] = CHAR_VERTICAL_LINE; + convert_glob_write_str(&out, 6); + + convert_glob_print_separator(&out, separator, with_escape); + convert_glob_write(&out, CHAR_RIGHT_PARENTHESIS); + + pattern++; + continue; + } + + convert_glob_print_commit(&out); + + if (!after_separator || *pattern != separator) + { + out.out_str[0] = CHAR_DOT; + out.out_str[1] = CHAR_ASTERISK; + out.out_str[2] = CHAR_QUESTION_MARK; + convert_glob_write_str(&out, 3); + continue; + } + + out.out_str[0] = CHAR_LEFT_PARENTHESIS; + out.out_str[1] = CHAR_QUESTION_MARK; + out.out_str[2] = CHAR_COLON; + out.out_str[3] = CHAR_DOT; + out.out_str[4] = CHAR_ASTERISK; + out.out_str[5] = CHAR_QUESTION_MARK; + + convert_glob_write_str(&out, 6); + + convert_glob_print_separator(&out, separator, with_escape); + + out.out_str[0] = CHAR_RIGHT_PARENTHESIS; + out.out_str[1] = CHAR_QUESTION_MARK; + out.out_str[2] = CHAR_QUESTION_MARK; + convert_glob_write_str(&out, 3); + + pattern++; + continue; + } + + if (pattern < pattern_end && *pattern == CHAR_ASTERISK) + { + do pattern++; while (pattern < pattern_end && + *pattern == CHAR_ASTERISK); + } + + if (no_wildsep) + { + if (pattern >= pattern_end) + { + no_slash_z = TRUE; + break; + } + + /* Start check must be after the end check. */ + if (is_start) continue; + } + + if (!is_start) + { + if (after_starstar) + { + out.out_str[0] = CHAR_LEFT_PARENTHESIS; + out.out_str[1] = CHAR_QUESTION_MARK; + out.out_str[2] = CHAR_GREATER_THAN_SIGN; + convert_glob_write_str(&out, 3); + in_atomic = TRUE; + } + else + convert_glob_print_commit(&out); + } + + if (no_wildsep) + convert_glob_write(&out, CHAR_DOT); + else + convert_glob_print_wildcard(&out, separator, with_escape); + + out.out_str[0] = CHAR_ASTERISK; + out.out_str[1] = CHAR_QUESTION_MARK; + if (pattern >= pattern_end) + out.out_str[1] = CHAR_PLUS; + convert_glob_write_str(&out, 2); + continue; + } + + if (c == CHAR_QUESTION_MARK) + { + if (no_wildsep) + convert_glob_write(&out, CHAR_DOT); + else + convert_glob_print_wildcard(&out, separator, with_escape); + continue; + } + + if (c == CHAR_LEFT_SQUARE_BRACKET) + { + result = convert_glob_parse_range(&pattern, pattern_end, + &out, utf, separator, with_escape, escape, no_wildsep); + if (result != 0) break; + continue; + } + + if (escape != 0 && c == escape) + { + if (pattern >= pattern_end) + { + result = PCRE2_ERROR_CONVERT_SYNTAX; + break; + } + c = *pattern++; + } + + if (c < 128 && strchr(pcre2_escaped_literals, c) != NULL) + convert_glob_write(&out, CHAR_BACKSLASH); + + convert_glob_write(&out, c); + } + +if (result == 0) + { + if (!no_slash_z) + { + out.out_str[0] = CHAR_BACKSLASH; + out.out_str[1] = CHAR_z; + convert_glob_write_str(&out, 2); + } + + if (in_atomic) + convert_glob_write(&out, CHAR_RIGHT_PARENTHESIS); + + convert_glob_write(&out, CHAR_NUL); + + if (!dummyrun && out.output_size != (PCRE2_SIZE) (out.output - use_buffer)) + result = PCRE2_ERROR_NOMEMORY; + } + +if (result != 0) + { + *bufflenptr = pattern - pattern_start; + return result; + } + +*bufflenptr = out.output_size - 1; +return 0; +} + + +/************************************************* +* Convert pattern * +*************************************************/ + +/* This is the external-facing function for converting other forms of pattern +into PCRE2 regular expression patterns. On error, the bufflenptr argument is +used to return an offset in the original pattern. + +Arguments: + pattern the input pattern + plength length of input, or PCRE2_ZERO_TERMINATED + options options bits + buffptr pointer to pointer to output buffer + bufflenptr pointer to length of output buffer + ccontext convert context or NULL + +Returns: 0 for success, else an error code (+ve or -ve) +*/ + +PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION +pcre2_pattern_convert(PCRE2_SPTR pattern, PCRE2_SIZE plength, uint32_t options, + PCRE2_UCHAR **buffptr, PCRE2_SIZE *bufflenptr, + pcre2_convert_context *ccontext) +{ +int i, rc; +PCRE2_UCHAR dummy_buffer[DUMMY_BUFFER_SIZE]; +PCRE2_UCHAR *use_buffer = dummy_buffer; +PCRE2_SIZE use_length = DUMMY_BUFFER_SIZE; +BOOL utf = (options & PCRE2_CONVERT_UTF) != 0; +uint32_t pattype = options & TYPE_OPTIONS; + +if (pattern == NULL || bufflenptr == NULL) return PCRE2_ERROR_NULL; +if ((options & ~ALL_OPTIONS) != 0 || /* Undefined bit set */ + (pattype & (~pattype+1)) != pattype || /* More than one type set */ + pattype == 0) /* No type set */ + { + *bufflenptr = 0; /* Error offset */ + return PCRE2_ERROR_BADOPTION; + } + +if (plength == PCRE2_ZERO_TERMINATED) plength = PRIV(strlen)(pattern); +if (ccontext == NULL) ccontext = + (pcre2_convert_context *)(&PRIV(default_convert_context)); + +/* Check UTF if required. */ + +#ifndef SUPPORT_UNICODE +if (utf) return PCRE2_ERROR_UNICODE_NOT_SUPPORTED; +#else +if (utf && (options & PCRE2_CONVERT_NO_UTF_CHECK) == 0) + { + PCRE2_SIZE erroroffset; + rc = PRIV(valid_utf)(pattern, plength, &erroroffset); + if (rc != 0) + { + *bufflenptr = erroroffset; + return rc; + } + } +#endif + +/* If buffptr is not NULL, and what it points to is not NULL, we are being +provided with a buffer and a length, so set them as the buffer to use. */ + +if (buffptr != NULL && *buffptr != NULL) + { + use_buffer = *buffptr; + use_length = *bufflenptr; + } + +/* Call an individual converter, either just once (if a buffer was provided or +just the length is needed), or twice (if a memory allocation is required). */ + +for (i = 0; i < 2; i++) + { + PCRE2_UCHAR *allocated; + BOOL dummyrun = buffptr == NULL || *buffptr == NULL; + + switch(pattype) + { + case PCRE2_CONVERT_GLOB: + rc = convert_glob(options & ~PCRE2_CONVERT_GLOB, pattern, plength, utf, + use_buffer, use_length, bufflenptr, dummyrun, ccontext); + break; + + case PCRE2_CONVERT_POSIX_BASIC: + case PCRE2_CONVERT_POSIX_EXTENDED: + rc = convert_posix(pattype, pattern, plength, utf, use_buffer, use_length, + bufflenptr, dummyrun, ccontext); + break; + + default: + return PCRE2_ERROR_INTERNAL; + } + + if (rc != 0 || /* Error */ + buffptr == NULL || /* Just the length is required */ + *buffptr != NULL) /* Buffer was provided or allocated */ + return rc; + + /* Allocate memory for the buffer, with hidden space for an allocator at + the start. The next time round the loop runs the conversion for real. */ + + allocated = PRIV(memctl_malloc)(sizeof(pcre2_memctl) + + (*bufflenptr + 1)*PCRE2_CODE_UNIT_WIDTH, (pcre2_memctl *)ccontext); + if (allocated == NULL) return PCRE2_ERROR_NOMEMORY; + *buffptr = (PCRE2_UCHAR *)(((char *)allocated) + sizeof(pcre2_memctl)); + + use_buffer = *buffptr; + use_length = *bufflenptr + 1; + } + +/* Control should never get here. */ + +return PCRE2_ERROR_INTERNAL; +} + + +/************************************************* +* Free converted pattern * +*************************************************/ + +/* This frees a converted pattern that was put in newly-allocated memory. + +Argument: the converted pattern +Returns: nothing +*/ + +PCRE2_EXP_DEFN void PCRE2_CALL_CONVENTION +pcre2_converted_pattern_free(PCRE2_UCHAR *converted) +{ +if (converted != NULL) + { + pcre2_memctl *memctl = + (pcre2_memctl *)((char *)converted - sizeof(pcre2_memctl)); + memctl->free(memctl, memctl->memory_data); + } +} + +/* End of pcre2_convert.c */ diff --git a/thirdparty/pcre2/src/pcre2_dfa_match.c b/thirdparty/pcre2/src/pcre2_dfa_match.c index c909d61285..c6184ff5e9 100644 --- a/thirdparty/pcre2/src/pcre2_dfa_match.c +++ b/thirdparty/pcre2/src/pcre2_dfa_match.c @@ -7,7 +7,7 @@ and semantics are as close as possible to those of the Perl 5 language. Written by Philip Hazel Original API code Copyright (c) 1997-2012 University of Cambridge - New API code Copyright (c) 2016 University of Cambridge + New API code Copyright (c) 2016-2018 University of Cambridge ----------------------------------------------------------------------------- Redistribution and use in source and binary forms, with or without @@ -83,7 +83,7 @@ in others, so I abandoned this code. */ #include "pcre2_internal.h" #define PUBLIC_DFA_MATCH_OPTIONS \ - (PCRE2_ANCHORED|PCRE2_NOTBOL|PCRE2_NOTEOL|PCRE2_NOTEMPTY| \ + (PCRE2_ANCHORED|PCRE2_ENDANCHORED|PCRE2_NOTBOL|PCRE2_NOTEOL|PCRE2_NOTEMPTY| \ PCRE2_NOTEMPTY_ATSTART|PCRE2_NO_UTF_CHECK|PCRE2_PARTIAL_HARD| \ PCRE2_PARTIAL_SOFT|PCRE2_DFA_SHORTEST|PCRE2_DFA_RESTART) @@ -172,7 +172,7 @@ static const uint8_t coptable[] = { 0, /* Assert not */ 0, /* Assert behind */ 0, /* Assert behind not */ - 0, 0, /* ONCE, ONCE_NC */ + 0, /* ONCE */ 0, 0, 0, 0, 0, /* BRA, BRAPOS, CBRA, CBRAPOS, COND */ 0, 0, 0, 0, 0, /* SBRA, SBRAPOS, SCBRA, SCBRAPOS, SCOND */ 0, 0, /* CREF, DNCREF */ @@ -245,7 +245,7 @@ static const uint8_t poptable[] = { 0, /* Assert not */ 0, /* Assert behind */ 0, /* Assert behind not */ - 0, 0, /* ONCE, ONCE_NC */ + 0, /* ONCE */ 0, 0, 0, 0, 0, /* BRA, BRAPOS, CBRA, CBRAPOS, COND */ 0, 0, 0, 0, 0, /* SBRA, SBRAPOS, SCBRA, SCBRAPOS, SCOND */ 0, 0, /* CREF, DNCREF */ @@ -294,6 +294,66 @@ typedef struct stateblock { /************************************************* +* Process a callout * +*************************************************/ + +/* This function is called to perform a callout. + +Arguments: + code current code pointer + offsets points to current capture offsets + current_subject start of current subject match + ptr current position in subject + mb the match block + extracode extra code offset when called from condition + lengthptr where to return the callout length + +Returns: the return from the callout +*/ + +static int +do_callout(PCRE2_SPTR code, PCRE2_SIZE *offsets, PCRE2_SPTR current_subject, + PCRE2_SPTR ptr, dfa_match_block *mb, PCRE2_SIZE extracode, + PCRE2_SIZE *lengthptr) +{ +pcre2_callout_block *cb = mb->cb; + +*lengthptr = (code[extracode] == OP_CALLOUT)? + (PCRE2_SIZE)PRIV(OP_lengths)[OP_CALLOUT] : + (PCRE2_SIZE)GET(code, 1 + 2*LINK_SIZE + extracode); + +if (mb->callout == NULL) return 0; /* No callout provided */ + +/* Fixed fields in the callout block are set once and for all at the start of +matching. */ + +cb->offset_vector = offsets; +cb->start_match = (PCRE2_SIZE)(current_subject - mb->start_subject); +cb->current_position = (PCRE2_SIZE)(ptr - mb->start_subject); +cb->pattern_position = GET(code, 1 + extracode); +cb->next_item_length = GET(code, 1 + LINK_SIZE + extracode); + +if (code[extracode] == OP_CALLOUT) + { + cb->callout_number = code[1 + 2*LINK_SIZE + extracode]; + cb->callout_string_offset = 0; + cb->callout_string = NULL; + cb->callout_string_length = 0; + } +else + { + cb->callout_number = 0; + cb->callout_string_offset = GET(code, 1 + 3*LINK_SIZE + extracode); + cb->callout_string = code + (1 + 4*LINK_SIZE + extracode) + 1; + cb->callout_string_length = *lengthptr - (1 + 4*LINK_SIZE) - 2; + } + +return (mb->callout)(cb, mb->callout_data); +} + + + +/************************************************* * Match a Regular Expression - DFA engine * *************************************************/ @@ -375,14 +435,10 @@ internal_dfa_match( { stateblock *active_states, *new_states, *temp_states; stateblock *next_active_state, *next_new_state; - const uint8_t *ctypes, *lcc, *fcc; PCRE2_SPTR ptr; PCRE2_SPTR end_code; -PCRE2_SPTR first_op; - dfa_recursion_info new_recursive; - int active_count, new_count, match_count; /* Some fields in the mb block are frequently referenced, so we load them into @@ -400,7 +456,8 @@ BOOL utf = FALSE; BOOL reset_could_continue = FALSE; -if (rlevel++ > mb->match_limit_recursion) return PCRE2_ERROR_RECURSIONLIMIT; +if (mb->match_call_count++ >= mb->match_limit) return PCRE2_ERROR_MATCHLIMIT; +if (rlevel++ > mb->match_limit_depth) return PCRE2_ERROR_DEPTHLIMIT; offsetcount &= (uint32_t)(-2); /* Round down */ wscount -= 2; @@ -417,21 +474,15 @@ active_states = (stateblock *)(workspace + 2); next_new_state = new_states = active_states + wscount; new_count = 0; -first_op = this_start_code + 1 + LINK_SIZE + - ((*this_start_code == OP_CBRA || *this_start_code == OP_SCBRA || - *this_start_code == OP_CBRAPOS || *this_start_code == OP_SCBRAPOS) - ? IMM2_SIZE:0); - /* The first thing in any (sub) pattern is a bracket of some sort. Push all the alternative states onto the list, and find out where the end is. This makes is possible to use this function recursively, when we want to stop at a matching internal ket rather than at the end. -If the first opcode in the first alternative is OP_REVERSE, we are dealing with -a backward assertion. In that case, we have to find out the maximum amount to -move back, and set up each alternative appropriately. */ +If we are dealing with a backward assertion we have to find out the maximum +amount to move back, and set up each alternative appropriately. */ -if (*first_op == OP_REVERSE) +if (*this_start_code == OP_ASSERTBACK || *this_start_code == OP_ASSERTBACK_NOT) { size_t max_back = 0; size_t gone_back; @@ -457,7 +508,8 @@ if (*first_op == OP_REVERSE) { if (current_subject <= start_subject) break; current_subject--; - ACROSSCHAR(current_subject > start_subject, *current_subject, current_subject--); + ACROSSCHAR(current_subject > start_subject, current_subject, + current_subject--); } } else @@ -476,15 +528,17 @@ if (*first_op == OP_REVERSE) if (current_subject < mb->start_used_ptr) mb->start_used_ptr = current_subject; - /* Now we can process the individual branches. */ + /* Now we can process the individual branches. There will be an OP_REVERSE at + the start of each branch, except when the length of the branch is zero. */ end_code = this_start_code; do { - size_t back = (size_t)GET(end_code, 2+LINK_SIZE); + uint32_t revlen = (end_code[1+LINK_SIZE] == OP_REVERSE)? 1 + LINK_SIZE : 0; + size_t back = (revlen == 0)? 0 : (size_t)GET(end_code, 2+LINK_SIZE); if (back <= gone_back) { - int bstate = (int)(end_code - start_code + 2 + 2*LINK_SIZE); + int bstate = (int)(end_code - start_code + 1 + LINK_SIZE + revlen); ADD_NEW_DATA(-bstate, 0, (int)(gone_back - back)); } end_code += GET(end_code, 1); @@ -697,7 +751,7 @@ for (;;) case OP_TABLE_LENGTH + ((sizeof(coptable) == OP_TABLE_LENGTH) && (sizeof(poptable) == OP_TABLE_LENGTH)): - break; + return 0; /* ========================================================================== */ /* Reached a closing bracket. If not at the end of the pattern, carry @@ -1371,25 +1425,14 @@ for (;;) if (count > 0) { ADD_ACTIVE(state_offset + 2, 0); } if (clen > 0) { - uint32_t lgb, rgb; - PCRE2_SPTR nptr = ptr + clen; int ncount = 0; if (count > 0 && codevalue == OP_EXTUNI_EXTRA + OP_TYPEPOSPLUS) { active_count--; /* Remove non-match possibility */ next_active_state--; } - lgb = UCD_GRAPHBREAK(c); - while (nptr < end_subject) - { - dlen = 1; - if (!utf) d = *nptr; else { GETCHARLEN(d, nptr, dlen); } - rgb = UCD_GRAPHBREAK(d); - if ((PRIV(ucp_gbtable)[lgb] & (1u << rgb)) == 0) break; - ncount++; - lgb = rgb; - nptr += dlen; - } + (void)PRIV(extuni)(c, ptr + clen, mb->start_subject, end_subject, utf, + &ncount); count++; ADD_NEW_DATA(-state_offset, count, ncount); } @@ -1632,8 +1675,6 @@ for (;;) ADD_ACTIVE(state_offset + 2, 0); if (clen > 0) { - uint32_t lgb, rgb; - PCRE2_SPTR nptr = ptr + clen; int ncount = 0; if (codevalue == OP_EXTUNI_EXTRA + OP_TYPEPOSSTAR || codevalue == OP_EXTUNI_EXTRA + OP_TYPEPOSQUERY) @@ -1641,17 +1682,8 @@ for (;;) active_count--; /* Remove non-match possibility */ next_active_state--; } - lgb = UCD_GRAPHBREAK(c); - while (nptr < end_subject) - { - dlen = 1; - if (!utf) d = *nptr; else { GETCHARLEN(d, nptr, dlen); } - rgb = UCD_GRAPHBREAK(d); - if ((PRIV(ucp_gbtable)[lgb] & (1u << rgb)) == 0) break; - ncount++; - lgb = rgb; - nptr += dlen; - } + (void)PRIV(extuni)(c, ptr + clen, mb->start_subject, end_subject, utf, + &ncount); ADD_NEW_DATA(-(state_offset + count), 0, ncount); } break; @@ -1904,25 +1936,15 @@ for (;;) count = current_state->count; /* Number already matched */ if (clen > 0) { - uint32_t lgb, rgb; - PCRE2_SPTR nptr = ptr + clen; + PCRE2_SPTR nptr; int ncount = 0; if (codevalue == OP_EXTUNI_EXTRA + OP_TYPEPOSUPTO) { active_count--; /* Remove non-match possibility */ next_active_state--; } - lgb = UCD_GRAPHBREAK(c); - while (nptr < end_subject) - { - dlen = 1; - if (!utf) d = *nptr; else { GETCHARLEN(d, nptr, dlen); } - rgb = UCD_GRAPHBREAK(d); - if ((PRIV(ucp_gbtable)[lgb] & (1u << rgb)) == 0) break; - ncount++; - lgb = rgb; - nptr += dlen; - } + nptr = PRIV(extuni)(c, ptr + clen, mb->start_subject, end_subject, utf, + &ncount); if (nptr >= end_subject && (mb->moptions & PCRE2_PARTIAL_HARD) != 0) reset_could_continue = TRUE; if (++count >= (int)GET2(code, 1)) @@ -2099,20 +2121,9 @@ for (;;) case OP_EXTUNI: if (clen > 0) { - uint32_t lgb, rgb; - PCRE2_SPTR nptr = ptr + clen; int ncount = 0; - lgb = UCD_GRAPHBREAK(c); - while (nptr < end_subject) - { - dlen = 1; - if (!utf) d = *nptr; else { GETCHARLEN(d, nptr, dlen); } - rgb = UCD_GRAPHBREAK(d); - if ((PRIV(ucp_gbtable)[lgb] & (1u << rgb)) == 0) break; - ncount++; - lgb = rgb; - nptr += dlen; - } + PCRE2_SPTR nptr = PRIV(extuni)(c, ptr + clen, mb->start_subject, + end_subject, utf, &ncount); if (nptr >= end_subject && (mb->moptions & PCRE2_PARTIAL_HARD) != 0) reset_could_continue = TRUE; ADD_NEW_DATA(-(state_offset + 1), 0, ncount); @@ -2136,6 +2147,7 @@ for (;;) case 0x2029: #endif /* Not EBCDIC */ if (mb->bsr_convention == PCRE2_BSR_ANYCRLF) break; + /* Fall through */ case CHAR_LF: ADD_NEW(state_offset + 1, 0); @@ -2225,7 +2237,7 @@ for (;;) case OP_NOTI: if (clen > 0) { - unsigned int otherd; + uint32_t otherd; #ifdef SUPPORT_UNICODE if (utf && d >= 128) otherd = UCD_OTHERCASE(d); @@ -2539,11 +2551,13 @@ for (;;) if (isinclass) { int max = (int)GET2(ecode, 1 + IMM2_SIZE); - if (*ecode == OP_CRPOSRANGE) + + if (*ecode == OP_CRPOSRANGE && count >= (int)GET2(ecode, 1)) { active_count--; /* Remove non-match possibility */ next_active_state--; } + if (++count >= max && max != 0) /* Max 0 => no limit */ { ADD_NEW(next_state_offset + 1 + 2 * IMM2_SIZE, 0); } else @@ -2613,45 +2627,10 @@ for (;;) if (code[LINK_SIZE + 1] == OP_CALLOUT || code[LINK_SIZE + 1] == OP_CALLOUT_STR) { - PCRE2_SIZE callout_length = (code[LINK_SIZE + 1] == OP_CALLOUT)? - (PCRE2_SIZE)PRIV(OP_lengths)[OP_CALLOUT] : - (PCRE2_SIZE)GET(code, 2 + 3*LINK_SIZE); - - rrc = 0; - if (mb->callout != NULL) - { - pcre2_callout_block cb; - cb.version = 1; - cb.capture_top = 1; - cb.capture_last = 0; - cb.offset_vector = offsets; - cb.mark = NULL; /* No (*MARK) support */ - cb.subject = start_subject; - cb.subject_length = (PCRE2_SIZE)(end_subject - start_subject); - cb.start_match = (PCRE2_SIZE)(current_subject - start_subject); - cb.current_position = (PCRE2_SIZE)(ptr - start_subject); - cb.pattern_position = GET(code, LINK_SIZE + 2); - cb.next_item_length = GET(code, LINK_SIZE + 2 + LINK_SIZE); - - if (code[LINK_SIZE + 1] == OP_CALLOUT) - { - cb.callout_number = code[2 + 3*LINK_SIZE]; - cb.callout_string_offset = 0; - cb.callout_string = NULL; - cb.callout_string_length = 0; - } - else - { - cb.callout_number = 0; - cb.callout_string_offset = GET(code, 2 + 4*LINK_SIZE); - cb.callout_string = code + (2 + 5*LINK_SIZE) + 1; - cb.callout_string_length = - callout_length - (1 + 4*LINK_SIZE) - 2; - } - - if ((rrc = (mb->callout)(&cb, mb->callout_data)) < 0) - return rrc; /* Abandon */ - } + PCRE2_SIZE callout_length; + rrc = do_callout(code, offsets, current_subject, ptr, mb, + 1 + LINK_SIZE, &callout_length); + if (rrc < 0) return rrc; /* Abandon */ if (rrc > 0) break; /* Fail this thread */ code += callout_length; /* Skip callout data */ } @@ -2889,7 +2868,6 @@ for (;;) /*-----------------------------------------------------------------*/ case OP_ONCE: - case OP_ONCE_NC: { PCRE2_SIZE local_offsets[2]; int local_workspace[1000]; @@ -2984,44 +2962,10 @@ for (;;) case OP_CALLOUT: case OP_CALLOUT_STR: { - unsigned int callout_length = (*code == OP_CALLOUT) - ? PRIV(OP_lengths)[OP_CALLOUT] : GET(code, 1 + 2*LINK_SIZE); - rrc = 0; - - if (mb->callout != NULL) - { - pcre2_callout_block cb; - cb.version = 1; - cb.capture_top = 1; - cb.capture_last = 0; - cb.offset_vector = offsets; - cb.mark = NULL; /* No (*MARK) support */ - cb.subject = start_subject; - cb.subject_length = (PCRE2_SIZE)(end_subject - start_subject); - cb.start_match = (PCRE2_SIZE)(current_subject - start_subject); - cb.current_position = (PCRE2_SIZE)(ptr - start_subject); - cb.pattern_position = GET(code, 1); - cb.next_item_length = GET(code, 1 + LINK_SIZE); - - if (*code == OP_CALLOUT) - { - cb.callout_number = code[1 + 2*LINK_SIZE]; - cb.callout_string_offset = 0; - cb.callout_string = NULL; - cb.callout_string_length = 0; - } - else - { - cb.callout_number = 0; - cb.callout_string_offset = GET(code, 1 + 3*LINK_SIZE); - cb.callout_string = code + (1 + 4*LINK_SIZE) + 1; - cb.callout_string_length = - callout_length - (1 + 4*LINK_SIZE) - 2; - } - - if ((rrc = (mb->callout)(&cb, mb->callout_data)) < 0) - return rrc; /* Abandon */ - } + PCRE2_SIZE callout_length; + rrc = do_callout(code, offsets, current_subject, ptr, mb, 0, + &callout_length); + if (rrc < 0) return rrc; /* Abandon */ if (rrc == 0) { ADD_ACTIVE(state_offset + (int)callout_length, 0); } } @@ -3069,7 +3013,7 @@ for (;;) ) ) match_count = PCRE2_ERROR_PARTIAL; - break; /* In effect, "return", but see the comment below */ + break; /* Exit from loop along the subject string */ } /* One or more states are active for the next character. */ @@ -3077,11 +3021,13 @@ for (;;) ptr += clen; /* Advance to next subject character */ } /* Loop to move along the subject string */ -/* Control gets here from "break" a few lines above. We do it this way because -if we use "return" above, we have compiler trouble. Some compilers warn if -there's nothing here because they think the function doesn't return a value. On -the other hand, if we put a dummy statement here, some more clever compilers -complain that it can't be reached. Sigh. */ +/* Control gets here from "break" a few lines above. If we have a match and +PCRE2_ENDANCHORED is set, the match fails. */ + +if (match_count >= 0 && + ((mb->moptions | mb->poptions) & PCRE2_ENDANCHORED) != 0 && + ptr < end_subject) + match_count = PCRE2_ERROR_NOMATCH; return match_count; } @@ -3138,6 +3084,7 @@ const uint8_t *start_bits = NULL; /* We need to have mb pointing to a match block, because the IS_NEWLINE macro is used below, and it expects NLBLOCK to be defined as a pointer. */ +pcre2_callout_block cb; dfa_match_block actual_match_block; dfa_match_block *mb = &actual_match_block; @@ -3154,6 +3101,13 @@ if (re == NULL || subject == NULL || workspace == NULL || match_data == NULL) if (wscount < 20) return PCRE2_ERROR_DFA_WSSIZE; if (start_offset > length) return PCRE2_ERROR_BADOFFSET; +/* Partial matching and PCRE2_ENDANCHORED are currently not allowed at the same +time. */ + +if ((options & (PCRE2_PARTIAL_HARD|PCRE2_PARTIAL_SOFT)) != 0 && + ((re->overall_options | options) & PCRE2_ENDANCHORED) != 0) + return PCRE2_ERROR_BADOPTION; + /* Check that the first field in the block is the magic number. If it is not, return with PCRE2_ERROR_BADMAGIC. */ @@ -3208,15 +3162,28 @@ startline = (re->flags & PCRE2_STARTLINE) != 0; firstline = (re->overall_options & PCRE2_FIRSTLINE) != 0; bumpalong_limit = end_subject; -/* Get data from the match context, if present, and fill in the fields in the -match block. It is an error to set an offset limit without setting the flag at -compile time. */ +/* Initialize and set up the fixed fields in the callout block, with a pointer +in the match block. */ + +mb->cb = &cb; +cb.version = 2; +cb.subject = subject; +cb.subject_length = (PCRE2_SIZE)(end_subject - subject); +cb.callout_flags = 0; +cb.capture_top = 1; /* No capture support */ +cb.capture_last = 0; +cb.mark = NULL; /* No (*MARK) support */ + +/* Get data from the match context, if present, and fill in the remaining +fields in the match block. It is an error to set an offset limit without +setting the flag at compile time. */ if (mcontext == NULL) { mb->callout = NULL; mb->memctl = re->memctl; - mb->match_limit_recursion = PRIV(default_match_context).recursion_limit; + mb->match_limit = PRIV(default_match_context).match_limit; + mb->match_limit_depth = PRIV(default_match_context).depth_limit; } else { @@ -3229,10 +3196,15 @@ else mb->callout = mcontext->callout; mb->callout_data = mcontext->callout_data; mb->memctl = mcontext->memctl; - mb->match_limit_recursion = mcontext->recursion_limit; + mb->match_limit = mcontext->match_limit; + mb->match_limit_depth = mcontext->depth_limit; } -if (mb->match_limit_recursion > re->limit_recursion) - mb->match_limit_recursion = re->limit_recursion; + +if (mb->match_limit > re->limit_match) + mb->match_limit = re->limit_match; + +if (mb->match_limit_depth > re->limit_depth) + mb->match_limit_depth = re->limit_depth; mb->start_code = (PCRE2_UCHAR *)((uint8_t *)re + sizeof(pcre2_real_code)) + re->name_count * re->name_entry_size; @@ -3242,6 +3214,7 @@ mb->end_subject = end_subject; mb->start_offset = start_offset; mb->moptions = options; mb->poptions = re->overall_options; +mb->match_call_count = 0; /* Process the \R and newline settings. */ @@ -3259,6 +3232,11 @@ switch(re->newline_convention) mb->nl[0] = CHAR_NL; break; + case PCRE2_NEWLINE_NUL: + mb->nllen = 1; + mb->nl[0] = CHAR_NUL; + break; + case PCRE2_NEWLINE_CRLF: mb->nllen = 2; mb->nl[0] = CHAR_CR; @@ -3325,34 +3303,27 @@ if (utf && (options & PCRE2_NO_UTF_CHECK) == 0) } #endif /* SUPPORT_UNICODE */ -/* Set up the first code unit to match, if available. The first_codeunit value -is never set for an anchored regular expression, but the anchoring may be -forced at run time, so we have to test for anchoring. The first code unit may -be unset for an unanchored pattern, of course. If there's no first code unit -there may be a bitmap of possible first characters. */ +/* Set up the first code unit to match, if available. If there's no first code +unit there may be a bitmap of possible first characters. */ -if (!anchored) +if ((re->flags & PCRE2_FIRSTSET) != 0) { - if ((re->flags & PCRE2_FIRSTSET) != 0) + has_first_cu = TRUE; + first_cu = first_cu2 = (PCRE2_UCHAR)(re->first_codeunit); + if ((re->flags & PCRE2_FIRSTCASELESS) != 0) { - has_first_cu = TRUE; - first_cu = first_cu2 = (PCRE2_UCHAR)(re->first_codeunit); - if ((re->flags & PCRE2_FIRSTCASELESS) != 0) - { - first_cu2 = TABLE_GET(first_cu, mb->tables + fcc_offset, first_cu); + first_cu2 = TABLE_GET(first_cu, mb->tables + fcc_offset, first_cu); #if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 8 - if (utf && first_cu > 127) - first_cu2 = (PCRE2_UCHAR)UCD_OTHERCASE(first_cu); + if (utf && first_cu > 127) + first_cu2 = (PCRE2_UCHAR)UCD_OTHERCASE(first_cu); #endif - } } - else - if (!startline && (re->flags & PCRE2_FIRSTMAPSET) != 0) - start_bits = re->start_bitmap; } +else + if (!startline && (re->flags & PCRE2_FIRSTMAPSET) != 0) + start_bits = re->start_bitmap; -/* For anchored or unanchored matches, there may be a "last known required -character" set. */ +/* There may be a "last known required code unit" set. */ if ((re->flags & PCRE2_LASTSET) != 0) { @@ -3393,13 +3364,13 @@ for (;;) if ((re->overall_options & PCRE2_NO_START_OPTIMIZE) == 0 && (options & PCRE2_DFA_RESTART) == 0) { - PCRE2_SPTR save_end_subject = end_subject; - /* If firstline is TRUE, the start of the match is constrained to the first line of a multiline string. That is, the match must be before or at the - first newline. Implement this by temporarily adjusting end_subject so that - we stop the optimization scans at a newline. If the match fails at the - newline, later code breaks this loop. */ + first newline following the start of matching. Temporarily adjust + end_subject so that we stop the optimization scans for a first code unit + immediately after the first character of a newline (the first code unit can + legitimately be a newline). If the match fails at the newline, later code + breaks this loop. */ if (firstline) { @@ -3407,85 +3378,162 @@ for (;;) #ifdef SUPPORT_UNICODE if (utf) { - while (t < mb->end_subject && !IS_NEWLINE(t)) + while (t < end_subject && !IS_NEWLINE(t)) { t++; - ACROSSCHAR(t < end_subject, *t, t++); + ACROSSCHAR(t < end_subject, t, t++); } } else #endif - while (t < mb->end_subject && !IS_NEWLINE(t)) t++; + while (t < end_subject && !IS_NEWLINE(t)) t++; end_subject = t; } - /* Advance to a unique first code unit if there is one. */ + /* Anchored: check the first code unit if one is recorded. This may seem + pointless but it can help in detecting a no match case without scanning for + the required code unit. */ - if (has_first_cu) + if (anchored) { - PCRE2_UCHAR smc; - if (first_cu != first_cu2) - while (start_match < end_subject && - (smc = UCHAR21TEST(start_match)) != first_cu && smc != first_cu2) - start_match++; - else - while (start_match < end_subject && UCHAR21TEST(start_match) != first_cu) - start_match++; + if (has_first_cu || start_bits != NULL) + { + BOOL ok = start_match < end_subject; + if (ok) + { + PCRE2_UCHAR c = UCHAR21TEST(start_match); + ok = has_first_cu && (c == first_cu || c == first_cu2); + if (!ok && start_bits != NULL) + { +#if PCRE2_CODE_UNIT_WIDTH != 8 + if (c > 255) c = 255; +#endif + ok = (start_bits[c/8] & (1 << (c&7))) != 0; + } + } + if (!ok) break; + } } - /* Or to just after a linebreak for a multiline match */ + /* Not anchored. Advance to a unique first code unit if there is one. In + 8-bit mode, the use of memchr() gives a big speed up, even though we have + to call it twice in caseless mode, in order to find the earliest occurrence + of the character in either of its cases. */ - else if (startline) + else { - if (start_match > mb->start_subject + start_offset) + if (has_first_cu) { -#ifdef SUPPORT_UNICODE - if (utf) + if (first_cu != first_cu2) /* Caseless */ { - while (start_match < end_subject && !WAS_NEWLINE(start_match)) - { +#if PCRE2_CODE_UNIT_WIDTH != 8 + PCRE2_UCHAR smc; + while (start_match < end_subject && + (smc = UCHAR21TEST(start_match)) != first_cu && + smc != first_cu2) start_match++; - ACROSSCHAR(start_match < end_subject, *start_match, - start_match++); - } +#else /* 8-bit code units */ + PCRE2_SPTR pp1 = + memchr(start_match, first_cu, end_subject-start_match); + PCRE2_SPTR pp2 = + memchr(start_match, first_cu2, end_subject-start_match); + if (pp1 == NULL) + start_match = (pp2 == NULL)? end_subject : pp2; + else + start_match = (pp2 == NULL || pp1 < pp2)? pp1 : pp2; +#endif } + + /* The caseful case */ + else + { +#if PCRE2_CODE_UNIT_WIDTH != 8 + while (start_match < end_subject && UCHAR21TEST(start_match) != + first_cu) + start_match++; +#else + start_match = memchr(start_match, first_cu, end_subject - start_match); + if (start_match == NULL) start_match = end_subject; #endif - while (start_match < end_subject && !WAS_NEWLINE(start_match)) - start_match++; + } - /* If we have just passed a CR and the newline option is ANY or - ANYCRLF, and we are now at a LF, advance the match position by one more - code unit. */ + /* If we can't find the required code unit, having reached the true end + of the subject, break the bumpalong loop, to force a match failure, + except when doing partial matching, when we let the next cycle run at + the end of the subject. To see why, consider the pattern /(?<=abc)def/, + which partially matches "abc", even though the string does not contain + the starting character "d". If we have not reached the true end of the + subject (PCRE2_FIRSTLINE caused end_subject to be temporarily modified) + we also let the cycle run, because the matching string is legitimately + allowed to start with the first code unit of a newline. */ - if (start_match[-1] == CHAR_CR && - (mb->nltype == NLTYPE_ANY || mb->nltype == NLTYPE_ANYCRLF) && - start_match < end_subject && - UCHAR21TEST(start_match) == CHAR_NL) - start_match++; + if ((mb->moptions & (PCRE2_PARTIAL_HARD|PCRE2_PARTIAL_SOFT)) == 0 && + start_match >= mb->end_subject) + break; } - } - /* Or to a non-unique first code unit if any have been identified. The - bitmap contains only 256 bits. When code units are 16 or 32 bits wide, all - code units greater than 254 set the 255 bit. */ + /* If there's no first code unit, advance to just after a linebreak for a + multiline match if required. */ - else if (start_bits != NULL) - { - while (start_match < end_subject) + else if (startline) { - uint32_t c = UCHAR21TEST(start_match); + if (start_match > mb->start_subject + start_offset) + { +#ifdef SUPPORT_UNICODE + if (utf) + { + while (start_match < end_subject && !WAS_NEWLINE(start_match)) + { + start_match++; + ACROSSCHAR(start_match < end_subject, start_match, start_match++); + } + } + else +#endif + while (start_match < end_subject && !WAS_NEWLINE(start_match)) + start_match++; + + /* If we have just passed a CR and the newline option is ANY or + ANYCRLF, and we are now at a LF, advance the match position by one + more code unit. */ + + if (start_match[-1] == CHAR_CR && + (mb->nltype == NLTYPE_ANY || mb->nltype == NLTYPE_ANYCRLF) && + start_match < end_subject && + UCHAR21TEST(start_match) == CHAR_NL) + start_match++; + } + } + + /* If there's no first code unit or a requirement for a multiline line + start, advance to a non-unique first code unit if any have been + identified. The bitmap contains only 256 bits. When code units are 16 or + 32 bits wide, all code units greater than 254 set the 255 bit. */ + + else if (start_bits != NULL) + { + while (start_match < end_subject) + { + uint32_t c = UCHAR21TEST(start_match); #if PCRE2_CODE_UNIT_WIDTH != 8 - if (c > 255) c = 255; + if (c > 255) c = 255; #endif - if ((start_bits[c/8] & (1 << (c&7))) != 0) break; - start_match++; + if ((start_bits[c/8] & (1 << (c&7))) != 0) break; + start_match++; + } + + /* See comment above in first_cu checking about the next line. */ + + if ((mb->moptions & (PCRE2_PARTIAL_HARD|PCRE2_PARTIAL_SOFT)) == 0 && + start_match >= mb->end_subject) + break; } - } + } /* End of first code unit handling */ /* Restore fudged end_subject */ - end_subject = save_end_subject; + end_subject = mb->end_subject; /* The following two optimizations are disabled for partial matching. */ @@ -3600,8 +3648,7 @@ for (;;) #ifdef SUPPORT_UNICODE if (utf) { - ACROSSCHAR(start_match < end_subject, *start_match, - start_match++); + ACROSSCHAR(start_match < end_subject, start_match, start_match++); } #endif if (start_match > end_subject) break; diff --git a/thirdparty/pcre2/src/pcre2_error.c b/thirdparty/pcre2/src/pcre2_error.c index 437bdfd202..d98cae9963 100644 --- a/thirdparty/pcre2/src/pcre2_error.c +++ b/thirdparty/pcre2/src/pcre2_error.c @@ -7,7 +7,7 @@ and semantics are as close as possible to those of the Perl 5 language. Written by Philip Hazel Original API code Copyright (c) 1997-2012 University of Cambridge - New API code Copyright (c) 2016 University of Cambridge + New API code Copyright (c) 2016-2017 University of Cambridge ----------------------------------------------------------------------------- Redistribution and use in source and binary forms, with or without @@ -176,6 +176,8 @@ static const unsigned char compile_error_texts[] = "internal error: unknown code in parsed pattern\0" /* 90 */ "internal error: bad code value in parsed_skip()\0" + "PCRE2_EXTRA_ALLOW_SURROGATE_ESCAPES is not allowed in UTF-16 mode\0" + "invalid option bits with PCRE2_LITERAL\0" ; /* Match-time and UTF error texts are in the same format. */ @@ -244,7 +246,7 @@ static const unsigned char match_error_texts[] = "non-unique substring name\0" "NULL argument passed\0" "nested recursion at the same subject position\0" - "recursion limit exceeded\0" + "matching depth limit exceeded\0" "requested value is not available\0" /* 55 */ "requested value is not set\0" @@ -256,6 +258,8 @@ static const unsigned char match_error_texts[] = "match with end before start is not supported\0" "too many replacements (more than INT_MAX)\0" "bad serialized data\0" + "heap limit exceeded\0" + "invalid syntax\0" ; @@ -271,7 +275,7 @@ distinct. Arguments: enumber error number buffer where to put the message (zero terminated) - size size of the buffer + size size of the buffer in code units Returns: length of message if all is well negative on error @@ -304,8 +308,8 @@ else /* Invalid error number */ for (; n > 0; n--) { - while (*message++ != CHAR_NULL) {}; - if (*message == CHAR_NULL) return PCRE2_ERROR_BADDATA; + while (*message++ != CHAR_NUL) {}; + if (*message == CHAR_NUL) return PCRE2_ERROR_BADDATA; } for (i = 0; *message != 0; i++) diff --git a/thirdparty/pcre2/src/pcre2_extuni.c b/thirdparty/pcre2/src/pcre2_extuni.c new file mode 100644 index 0000000000..11a0bfbdd6 --- /dev/null +++ b/thirdparty/pcre2/src/pcre2_extuni.c @@ -0,0 +1,148 @@ +/************************************************* +* Perl-Compatible Regular Expressions * +*************************************************/ + +/* PCRE is a library of functions to support regular expressions whose syntax +and semantics are as close as possible to those of the Perl 5 language. + + Written by Philip Hazel + Original API code Copyright (c) 1997-2012 University of Cambridge + New API code Copyright (c) 2016-2018 University of Cambridge + +----------------------------------------------------------------------------- +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of the University of Cambridge nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +----------------------------------------------------------------------------- +*/ + +/* This module contains an internal function that is used to match a Unicode +extended grapheme sequence. It is used by both pcre2_match() and +pcre2_def_match(). However, it is called only when Unicode support is being +compiled. Nevertheless, we provide a dummy function when there is no Unicode +support, because some compilers do not like functionless source files. */ + + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + + +#include "pcre2_internal.h" + + +/* Dummy function */ + +#ifndef SUPPORT_UNICODE +PCRE2_SPTR +PRIV(extuni)(uint32_t c, PCRE2_SPTR eptr, PCRE2_SPTR start_subject, + PCRE2_SPTR end_subject, BOOL utf, int *xcount) +{ +(void)c; +(void)eptr; +(void)start_subject; +(void)end_subject; +(void)utf; +(void)xcount; +return NULL; +} +#else + + +/************************************************* +* Match an extended grapheme sequence * +*************************************************/ + +/* +Arguments: + c the first character + eptr pointer to next character + start_subject pointer to start of subject + end_subject pointer to end of subject + utf TRUE if in UTF mode + xcount pointer to count of additional characters, + or NULL if count not needed + +Returns: pointer after the end of the sequence +*/ + +PCRE2_SPTR +PRIV(extuni)(uint32_t c, PCRE2_SPTR eptr, PCRE2_SPTR start_subject, + PCRE2_SPTR end_subject, BOOL utf, int *xcount) +{ +int lgb = UCD_GRAPHBREAK(c); + +while (eptr < end_subject) + { + int rgb; + int len = 1; + if (!utf) c = *eptr; else { GETCHARLEN(c, eptr, len); } + rgb = UCD_GRAPHBREAK(c); + if ((PRIV(ucp_gbtable)[lgb] & (1 << rgb)) == 0) break; + + /* Not breaking between Regional Indicators is allowed only if there + are an even number of preceding RIs. */ + + if (lgb == ucp_gbRegionalIndicator && rgb == ucp_gbRegionalIndicator) + { + int ricount = 0; + PCRE2_SPTR bptr = eptr - 1; + if (utf) BACKCHAR(bptr); + + /* bptr is pointing to the left-hand character */ + + while (bptr > start_subject) + { + bptr--; + if (utf) + { + BACKCHAR(bptr); + GETCHAR(c, bptr); + } + else + c = *bptr; + if (UCD_GRAPHBREAK(c) != ucp_gbRegionalIndicator) break; + ricount++; + } + if ((ricount & 1) != 0) break; /* Grapheme break required */ + } + + /* If Extend follows E_Base[_GAZ] do not update lgb; this allows + any number of Extend before a following E_Modifier. */ + + if (rgb != ucp_gbExtend || + (lgb != ucp_gbE_Base && lgb != ucp_gbE_Base_GAZ)) + lgb = rgb; + + eptr += len; + if (xcount != NULL) *xcount += 1; + } + +return eptr; +} + +#endif /* SUPPORT_UNICODE */ + +/* End of pcre2_extuni.c */ diff --git a/thirdparty/pcre2/src/pcre2_internal.h b/thirdparty/pcre2/src/pcre2_internal.h index 6a8774ce8c..3db9d604f4 100644 --- a/thirdparty/pcre2/src/pcre2_internal.h +++ b/thirdparty/pcre2/src/pcre2_internal.h @@ -7,7 +7,7 @@ and semantics are as close as possible to those of the Perl 5 language. Written by Philip Hazel Original API code Copyright (c) 1997-2012 University of Cambridge - New API code Copyright (c) 2016 University of Cambridge + New API code Copyright (c) 2016-2017 University of Cambridge ----------------------------------------------------------------------------- Redistribution and use in source and binary forms, with or without @@ -38,6 +38,9 @@ POSSIBILITY OF SUCH DAMAGE. ----------------------------------------------------------------------------- */ +#ifndef PCRE2_INTERNAL_H_IDEMPOTENT_GUARD +#define PCRE2_INTERNAL_H_IDEMPOTENT_GUARD + /* We do not support both EBCDIC and Unicode at the same time. The "configure" script prevents both being selected, but not everybody uses "configure". EBCDIC is only supported for the 8-bit library, but the check for this has to be later @@ -240,6 +243,16 @@ not rely on this. */ #define COMPILE_ERROR_BASE 100 +/* The initial frames vector for remembering backtracking points in +pcre2_match() is allocated on the system stack, of this size (bytes). The size +must be a multiple of sizeof(PCRE2_SPTR) in all environments, so making it a +multiple of 8 is best. Typical frame sizes are a few hundred bytes (it depends +on the number of capturing parentheses) so 20K handles quite a few frames. A +larger vector on the heap is obtained for patterns that need more frames. The +maximum size of this can be limited. */ + +#define START_FRAMES_SIZE 20480 + /* Define the default BSR convention. */ #ifdef BSR_ANYCRLF @@ -547,9 +560,14 @@ enum { PCRE2_MATCHEDBY_INTERPRETER, /* pcre2_match() */ #define MAGIC_NUMBER 0x50435245UL /* 'PCRE' */ /* The maximum remaining length of subject we are prepared to search for a -req_unit match. */ +req_unit match. In 8-bit mode, memchr() is used and is much faster than the +search loop that has to be used in 16-bit and 32-bit modes. */ +#if PCRE2_CODE_UNIT_WIDTH == 8 +#define REQ_CU_MAX 2000 +#else #define REQ_CU_MAX 1000 +#endif /* Offsets for the bitmap tables in the cbits set of tables. Each table contains a set of bits for a class map. Some classes are built by combining @@ -668,7 +686,7 @@ a positive value. */ /* The remaining definitions work in both environments. */ -#define CHAR_NULL '\0' +#define CHAR_NUL '\0' #define CHAR_HT '\t' #define CHAR_VT '\v' #define CHAR_FF '\f' @@ -909,6 +927,7 @@ a positive value. */ #define STRING_CRLF_RIGHTPAR "CRLF)" #define STRING_ANY_RIGHTPAR "ANY)" #define STRING_ANYCRLF_RIGHTPAR "ANYCRLF)" +#define STRING_NUL_RIGHTPAR "NUL)" #define STRING_BSR_ANYCRLF_RIGHTPAR "BSR_ANYCRLF)" #define STRING_BSR_UNICODE_RIGHTPAR "BSR_UNICODE)" #define STRING_UTF8_RIGHTPAR "UTF8)" @@ -922,7 +941,9 @@ a positive value. */ #define STRING_NO_START_OPT_RIGHTPAR "NO_START_OPT)" #define STRING_NOTEMPTY_RIGHTPAR "NOTEMPTY)" #define STRING_NOTEMPTY_ATSTART_RIGHTPAR "NOTEMPTY_ATSTART)" +#define STRING_LIMIT_HEAP_EQ "LIMIT_HEAP=" #define STRING_LIMIT_MATCH_EQ "LIMIT_MATCH=" +#define STRING_LIMIT_DEPTH_EQ "LIMIT_DEPTH=" #define STRING_LIMIT_RECURSION_EQ "LIMIT_RECURSION=" #define STRING_MARK "MARK" @@ -944,7 +965,7 @@ only. */ #define CHAR_ESC '\033' #define CHAR_DEL '\177' -#define CHAR_NULL '\0' +#define CHAR_NUL '\0' #define CHAR_SPACE '\040' #define CHAR_EXCLAMATION_MARK '\041' #define CHAR_QUOTATION_MARK '\042' @@ -1182,6 +1203,7 @@ only. */ #define STRING_CRLF_RIGHTPAR STR_C STR_R STR_L STR_F STR_RIGHT_PARENTHESIS #define STRING_ANY_RIGHTPAR STR_A STR_N STR_Y STR_RIGHT_PARENTHESIS #define STRING_ANYCRLF_RIGHTPAR STR_A STR_N STR_Y STR_C STR_R STR_L STR_F STR_RIGHT_PARENTHESIS +#define STRING_NUL_RIGHTPAR STR_N STR_U STR_L STR_RIGHT_PARENTHESIS #define STRING_BSR_ANYCRLF_RIGHTPAR STR_B STR_S STR_R STR_UNDERSCORE STR_A STR_N STR_Y STR_C STR_R STR_L STR_F STR_RIGHT_PARENTHESIS #define STRING_BSR_UNICODE_RIGHTPAR STR_B STR_S STR_R STR_UNDERSCORE STR_U STR_N STR_I STR_C STR_O STR_D STR_E STR_RIGHT_PARENTHESIS #define STRING_UTF8_RIGHTPAR STR_U STR_T STR_F STR_8 STR_RIGHT_PARENTHESIS @@ -1195,7 +1217,9 @@ only. */ #define STRING_NO_START_OPT_RIGHTPAR STR_N STR_O STR_UNDERSCORE STR_S STR_T STR_A STR_R STR_T STR_UNDERSCORE STR_O STR_P STR_T STR_RIGHT_PARENTHESIS #define STRING_NOTEMPTY_RIGHTPAR STR_N STR_O STR_T STR_E STR_M STR_P STR_T STR_Y STR_RIGHT_PARENTHESIS #define STRING_NOTEMPTY_ATSTART_RIGHTPAR STR_N STR_O STR_T STR_E STR_M STR_P STR_T STR_Y STR_UNDERSCORE STR_A STR_T STR_S STR_T STR_A STR_R STR_T STR_RIGHT_PARENTHESIS +#define STRING_LIMIT_HEAP_EQ STR_L STR_I STR_M STR_I STR_T STR_UNDERSCORE STR_H STR_E STR_A STR_P STR_EQUALS_SIGN #define STRING_LIMIT_MATCH_EQ STR_L STR_I STR_M STR_I STR_T STR_UNDERSCORE STR_M STR_A STR_T STR_C STR_H STR_EQUALS_SIGN +#define STRING_LIMIT_DEPTH_EQ STR_L STR_I STR_M STR_I STR_T STR_UNDERSCORE STR_D STR_E STR_P STR_T STR_H STR_EQUALS_SIGN #define STRING_LIMIT_RECURSION_EQ STR_L STR_I STR_M STR_I STR_T STR_UNDERSCORE STR_R STR_E STR_C STR_U STR_R STR_S STR_I STR_O STR_N STR_EQUALS_SIGN #define STRING_MARK STR_M STR_A STR_R STR_K @@ -1510,68 +1534,67 @@ enum { OP_ASSERTBACK, /* 128 Positive lookbehind */ OP_ASSERTBACK_NOT, /* 129 Negative lookbehind */ - /* ONCE, ONCE_NC, BRA, BRAPOS, CBRA, CBRAPOS, and COND must come immediately - after the assertions, with ONCE first, as there's a test for >= ONCE for a - subpattern that isn't an assertion. The POS versions must immediately follow - the non-POS versions in each case. */ + /* ONCE, BRA, BRAPOS, CBRA, CBRAPOS, and COND must come immediately after the + assertions, with ONCE first, as there's a test for >= ONCE for a subpattern + that isn't an assertion. The POS versions must immediately follow the non-POS + versions in each case. */ OP_ONCE, /* 130 Atomic group, contains captures */ - OP_ONCE_NC, /* 131 Atomic group containing no captures */ - OP_BRA, /* 132 Start of non-capturing bracket */ - OP_BRAPOS, /* 133 Ditto, with unlimited, possessive repeat */ - OP_CBRA, /* 134 Start of capturing bracket */ - OP_CBRAPOS, /* 135 Ditto, with unlimited, possessive repeat */ - OP_COND, /* 136 Conditional group */ + OP_BRA, /* 131 Start of non-capturing bracket */ + OP_BRAPOS, /* 132 Ditto, with unlimited, possessive repeat */ + OP_CBRA, /* 133 Start of capturing bracket */ + OP_CBRAPOS, /* 134 Ditto, with unlimited, possessive repeat */ + OP_COND, /* 135 Conditional group */ /* These five must follow the previous five, in the same order. There's a check for >= SBRA to distinguish the two sets. */ - OP_SBRA, /* 137 Start of non-capturing bracket, check empty */ - OP_SBRAPOS, /* 138 Ditto, with unlimited, possessive repeat */ - OP_SCBRA, /* 139 Start of capturing bracket, check empty */ - OP_SCBRAPOS, /* 140 Ditto, with unlimited, possessive repeat */ - OP_SCOND, /* 141 Conditional group, check empty */ + OP_SBRA, /* 136 Start of non-capturing bracket, check empty */ + OP_SBRAPOS, /* 137 Ditto, with unlimited, possessive repeat */ + OP_SCBRA, /* 138 Start of capturing bracket, check empty */ + OP_SCBRAPOS, /* 139 Ditto, with unlimited, possessive repeat */ + OP_SCOND, /* 140 Conditional group, check empty */ /* The next two pairs must (respectively) be kept together. */ - OP_CREF, /* 142 Used to hold a capture number as condition */ - OP_DNCREF, /* 143 Used to point to duplicate names as a condition */ - OP_RREF, /* 144 Used to hold a recursion number as condition */ - OP_DNRREF, /* 145 Used to point to duplicate names as a condition */ - OP_FALSE, /* 146 Always false (used by DEFINE and VERSION) */ - OP_TRUE, /* 147 Always true (used by VERSION) */ + OP_CREF, /* 141 Used to hold a capture number as condition */ + OP_DNCREF, /* 142 Used to point to duplicate names as a condition */ + OP_RREF, /* 143 Used to hold a recursion number as condition */ + OP_DNRREF, /* 144 Used to point to duplicate names as a condition */ + OP_FALSE, /* 145 Always false (used by DEFINE and VERSION) */ + OP_TRUE, /* 146 Always true (used by VERSION) */ - OP_BRAZERO, /* 148 These two must remain together and in this */ - OP_BRAMINZERO, /* 149 order. */ - OP_BRAPOSZERO, /* 150 */ + OP_BRAZERO, /* 147 These two must remain together and in this */ + OP_BRAMINZERO, /* 148 order. */ + OP_BRAPOSZERO, /* 149 */ /* These are backtracking control verbs */ - OP_MARK, /* 151 always has an argument */ - OP_PRUNE, /* 152 */ - OP_PRUNE_ARG, /* 153 same, but with argument */ - OP_SKIP, /* 154 */ - OP_SKIP_ARG, /* 155 same, but with argument */ - OP_THEN, /* 156 */ - OP_THEN_ARG, /* 157 same, but with argument */ - OP_COMMIT, /* 158 */ + OP_MARK, /* 150 always has an argument */ + OP_PRUNE, /* 151 */ + OP_PRUNE_ARG, /* 152 same, but with argument */ + OP_SKIP, /* 153 */ + OP_SKIP_ARG, /* 154 same, but with argument */ + OP_THEN, /* 155 */ + OP_THEN_ARG, /* 156 same, but with argument */ + OP_COMMIT, /* 157 */ /* These are forced failure and success verbs */ - OP_FAIL, /* 159 */ - OP_ACCEPT, /* 160 */ - OP_ASSERT_ACCEPT, /* 161 Used inside assertions */ - OP_CLOSE, /* 162 Used before OP_ACCEPT to close open captures */ + OP_FAIL, /* 158 */ + OP_ACCEPT, /* 159 */ + OP_ASSERT_ACCEPT, /* 160 Used inside assertions */ + OP_CLOSE, /* 161 Used before OP_ACCEPT to close open captures */ /* This is used to skip a subpattern with a {0} quantifier */ - OP_SKIPZERO, /* 163 */ + OP_SKIPZERO, /* 162 */ /* This is used to identify a DEFINE group during compilation so that it can be checked for having only one branch. It is changed to OP_FALSE before compilation finishes. */ - OP_DEFINE, /* 164 */ + OP_DEFINE, /* 163 */ /* This is not an opcode, but is used to check that tables indexed by opcode are the correct length, in order to catch updating errors - there have been @@ -1618,7 +1641,7 @@ some cases doesn't actually use these names at all). */ "Recurse", "Callout", "CalloutStr", \ "Alt", "Ket", "KetRmax", "KetRmin", "KetRpos", \ "Reverse", "Assert", "Assert not", "AssertB", "AssertB not", \ - "Once", "Once_NC", \ + "Once", \ "Bra", "BraPos", "CBra", "CBraPos", \ "Cond", \ "SBra", "SBraPos", "SCBra", "SCBraPos", \ @@ -1702,7 +1725,6 @@ in UTF-8 mode. The code that uses this table must know about such things. */ 1+LINK_SIZE, /* Assert behind */ \ 1+LINK_SIZE, /* Assert behind not */ \ 1+LINK_SIZE, /* ONCE */ \ - 1+LINK_SIZE, /* ONCE_NC */ \ 1+LINK_SIZE, /* BRA */ \ 1+LINK_SIZE, /* BRAPOS */ \ 1+LINK_SIZE+IMM2_SIZE, /* CBRA */ \ @@ -1748,6 +1770,7 @@ typedef struct open_capitem { struct open_capitem *next; /* Chain link */ uint16_t number; /* Capture number */ uint16_t flag; /* Set TRUE if recursive back ref */ + uint16_t assert_depth; /* Assertion depth when opened */ } open_capitem; /* Layout of the UCP type table that translates property names into types and @@ -1774,10 +1797,17 @@ typedef struct { /* UCD access macros */ #define UCD_BLOCK_SIZE 128 -#define GET_UCD(ch) (PRIV(ucd_records) + \ +#define REAL_GET_UCD(ch) (PRIV(ucd_records) + \ PRIV(ucd_stage2)[PRIV(ucd_stage1)[(int)(ch) / UCD_BLOCK_SIZE] * \ UCD_BLOCK_SIZE + (int)(ch) % UCD_BLOCK_SIZE]) +#if PCRE2_CODE_UNIT_WIDTH == 32 +#define GET_UCD(ch) ((ch > MAX_UTF_CODE_POINT)? \ + PRIV(dummy_ucd_record) : REAL_GET_UCD(ch)) +#else +#define GET_UCD(ch) REAL_GET_UCD(ch) +#endif + #define UCD_CHARTYPE(ch) GET_UCD(ch)->chartype #define UCD_SCRIPT(ch) GET_UCD(ch)->script #define UCD_CATEGORY(ch) PRIV(ucp_gentype)[UCD_CHARTYPE(ch)] @@ -1832,8 +1862,12 @@ extern const uint8_t PRIV(utf8_table4)[]; #define _pcre2_callout_end_delims PCRE2_SUFFIX(_pcre2_callout_end_delims_) #define _pcre2_callout_start_delims PCRE2_SUFFIX(_pcre2_callout_start_delims_) #define _pcre2_default_compile_context PCRE2_SUFFIX(_pcre2_default_compile_context_) +#define _pcre2_default_convert_context PCRE2_SUFFIX(_pcre2_default_convert_context_) #define _pcre2_default_match_context PCRE2_SUFFIX(_pcre2_default_match_context_) #define _pcre2_default_tables PCRE2_SUFFIX(_pcre2_default_tables_) +#if PCRE2_CODE_UNIT_WIDTH == 32 +#define _pcre2_dummy_ucd_record PCRE2_SUFFIX(_pcre2_dummy_ucd_record_) +#endif #define _pcre2_hspace_list PCRE2_SUFFIX(_pcre2_hspace_list_) #define _pcre2_vspace_list PCRE2_SUFFIX(_pcre2_vspace_list_) #define _pcre2_ucd_caseless_sets PCRE2_SUFFIX(_pcre2_ucd_caseless_sets_) @@ -1852,12 +1886,16 @@ extern const uint8_t PRIV(OP_lengths)[]; extern const uint32_t PRIV(callout_end_delims)[]; extern const uint32_t PRIV(callout_start_delims)[]; extern const pcre2_compile_context PRIV(default_compile_context); +extern const pcre2_convert_context PRIV(default_convert_context); extern const pcre2_match_context PRIV(default_match_context); extern const uint8_t PRIV(default_tables)[]; extern const uint32_t PRIV(hspace_list)[]; extern const uint32_t PRIV(vspace_list)[]; extern const uint32_t PRIV(ucd_caseless_sets)[]; extern const ucd_record PRIV(ucd_records)[]; +#if PCRE2_CODE_UNIT_WIDTH == 32 +extern const ucd_record PRIV(dummy_ucd_record)[]; +#endif extern const uint8_t PRIV(ucd_stage1)[]; extern const uint16_t PRIV(ucd_stage2)[]; extern const uint32_t PRIV(ucp_gbtable)[]; @@ -1892,6 +1930,7 @@ is available. */ #define _pcre2_auto_possessify PCRE2_SUFFIX(_pcre2_auto_possessify_) #define _pcre2_check_escape PCRE2_SUFFIX(_pcre2_check_escape_) +#define _pcre2_extuni PCRE2_SUFFIX(_pcre2_extuni_) #define _pcre2_find_bracket PCRE2_SUFFIX(_pcre2_find_bracket_) #define _pcre2_is_newline PCRE2_SUFFIX(_pcre2_is_newline_) #define _pcre2_jit_free_rodata PCRE2_SUFFIX(_pcre2_jit_free_rodata_) @@ -1915,6 +1954,8 @@ extern int _pcre2_auto_possessify(PCRE2_UCHAR *, BOOL, const compile_block *); extern int _pcre2_check_escape(PCRE2_SPTR *, PCRE2_SPTR, uint32_t *, int *, uint32_t, BOOL, compile_block *); +extern PCRE2_SPTR _pcre2_extuni(uint32_t, PCRE2_SPTR, PCRE2_SPTR, PCRE2_SPTR, + BOOL, int *); extern PCRE2_SPTR _pcre2_find_bracket(PCRE2_SPTR, BOOL, int); extern BOOL _pcre2_is_newline(PCRE2_SPTR, uint32_t, PCRE2_SPTR, uint32_t *, BOOL); @@ -1936,5 +1977,6 @@ extern BOOL _pcre2_was_newline(PCRE2_SPTR, uint32_t, PCRE2_SPTR, uint32_t *, BOOL); extern BOOL _pcre2_xclass(uint32_t, PCRE2_SPTR, BOOL); #endif /* PCRE2_CODE_UNIT_WIDTH */ +#endif /* PCRE2_INTERNAL_H_IDEMPOTENT_GUARD */ /* End of pcre2_internal.h */ diff --git a/thirdparty/pcre2/src/pcre2_intmodedep.h b/thirdparty/pcre2/src/pcre2_intmodedep.h index ebff7e3066..c4c4c3adb9 100644 --- a/thirdparty/pcre2/src/pcre2_intmodedep.h +++ b/thirdparty/pcre2/src/pcre2_intmodedep.h @@ -7,7 +7,7 @@ and semantics are as close as possible to those of the Perl 5 language. Written by Philip Hazel Original API code Copyright (c) 1997-2012 University of Cambridge - New API code Copyright (c) 2016 University of Cambridge + New API code Copyright (c) 2016-2018 University of Cambridge ----------------------------------------------------------------------------- Redistribution and use in source and binary forms, with or without @@ -54,6 +54,7 @@ just to undefine them all. */ #undef ACROSSCHAR #undef BACKCHAR #undef BYTES2CU +#undef CHMAX_255 #undef CU2BYTES #undef FORWARDCHAR #undef FORWARDCHARTEST @@ -201,20 +202,25 @@ arithmetic results in a signed value. Hence the cast. */ /* Other macros that are different for 8-bit mode. The MAX_255 macro checks whether its argument, which is assumed to be one code unit, is less than 256. -The maximum length of a MARK name must fit in one code unit; currently it is -set to 255 or 65535. The TABLE_GET macro is used to access elements of tables -containing exactly 256 items. When code points can be greater than 255, a check -is needed before accessing these tables. */ +The CHMAX_255 macro does not assume one code unit. The maximum length of a MARK +name must fit in one code unit; currently it is set to 255 or 65535. The +TABLE_GET macro is used to access elements of tables containing exactly 256 +items. When code points can be greater than 255, a check is needed before +accessing these tables. */ #if PCRE2_CODE_UNIT_WIDTH == 8 #define MAX_255(c) TRUE #define MAX_MARK ((1u << 8) - 1) #ifdef SUPPORT_UNICODE #define SUPPORT_WIDE_CHARS +#define CHMAX_255(c) ((c) <= 255u) +#else +#define CHMAX_255(c) TRUE #endif /* SUPPORT_UNICODE */ #define TABLE_GET(c, table, default) ((table)[c]) #else /* Code units are 16 or 32 bits */ +#define CHMAX_255(c) ((c) <= 255u) #define MAX_255(c) ((c) <= 255u) #define MAX_MARK ((1u << 16) - 1) #define SUPPORT_WIDE_CHARS @@ -345,7 +351,7 @@ because almost all calls are already within a block of UTF-8 only code. */ /* Same as above, but it allows a fully customizable form. */ #define ACROSSCHAR(condition, eptr, action) \ - while((condition) && ((eptr) & 0xc0u) == 0x80u) action + while((condition) && ((*eptr) & 0xc0u) == 0x80u) action /* Deposit a character into memory, returning the number of code units. */ @@ -451,7 +457,7 @@ code. */ /* Same as above, but it allows a fully customizable form. */ #define ACROSSCHAR(condition, eptr, action) \ - if ((condition) && ((eptr) & 0xfc00u) == 0xdc00u) action + if ((condition) && ((*eptr) & 0xfc00u) == 0xdc00u) action /* Deposit a character into memory, returning the number of code units. */ @@ -566,15 +572,13 @@ typedef struct pcre2_real_compile_context { uint16_t bsr_convention; uint16_t newline_convention; uint32_t parens_nest_limit; + uint32_t extra_options; } pcre2_real_compile_context; /* The real match context structure. */ typedef struct pcre2_real_match_context { pcre2_memctl memctl; -#ifdef HEAP_MATCH_RECURSE - pcre2_memctl stack_memctl; -#endif #ifdef SUPPORT_JIT pcre2_jit_callback jit_callback; void *jit_callback_data; @@ -582,10 +586,19 @@ typedef struct pcre2_real_match_context { int (*callout)(pcre2_callout_block *, void *); void *callout_data; PCRE2_SIZE offset_limit; + uint32_t heap_limit; uint32_t match_limit; - uint32_t recursion_limit; + uint32_t depth_limit; } pcre2_real_match_context; +/* The real convert context structure. */ + +typedef struct pcre2_real_convert_context { + pcre2_memctl memctl; + uint32_t glob_separator; + uint32_t glob_escape; +} pcre2_real_convert_context; + /* The real compiled code structure. The type for the blocksize field is defined specially because it is required in pcre2_serialize_decode() when copying the size from possibly unaligned memory into a variable of the same @@ -610,9 +623,11 @@ typedef struct pcre2_real_code { uint32_t magic_number; /* Paranoid and endianness check */ uint32_t compile_options; /* Options passed to pcre2_compile() */ uint32_t overall_options; /* Options after processing the pattern */ + uint32_t extra_options; /* Taken from compile_context */ uint32_t flags; /* Various state flags */ + uint32_t limit_heap; /* Limit set in the pattern */ uint32_t limit_match; /* Limit set in the pattern */ - uint32_t limit_recursion; /* Limit set in the pattern */ + uint32_t limit_depth; /* Limit set in the pattern */ uint32_t first_codeunit; /* Starting code unit */ uint32_t last_codeunit; /* This codeunit must be seen */ uint16_t bsr_convention; /* What \R matches */ @@ -625,7 +640,13 @@ typedef struct pcre2_real_code { uint16_t name_count; /* Number of name entries in the table */ } pcre2_real_code; -/* The real match data structure. */ +/* The real match data structure. Define ovector as large as it can ever +actually be so that array bound checkers don't grumble. Memory for this +structure is obtained by calling pcre2_match_data_create(), which sets the size +as the offset of ovector plus a pair of elements for each capturable string, so +the size varies from call to call. As the maximum number of capturing +subpatterns is 65535 we must allow for 65536 strings to include the overall +match. (See also the heapframe structure below.) */ typedef struct pcre2_real_match_data { pcre2_memctl memctl; @@ -638,7 +659,7 @@ typedef struct pcre2_real_match_data { uint16_t matchedby; /* Type of match (normal, JIT, DFA) */ uint16_t oveccount; /* Number of pairs */ int rc; /* The return code from the match */ - PCRE2_SIZE ovector[1]; /* The first field */ + PCRE2_SIZE ovector[131072]; /* Must be last in the structure */ } pcre2_real_match_data; @@ -705,6 +726,8 @@ typedef struct compile_block { PCRE2_SIZE erroroffset; /* Offset of error in pattern */ uint16_t names_found; /* Number of entries so far */ uint16_t name_entry_size; /* Size of each entry */ + uint16_t parens_depth; /* Depth of nested parentheses */ + uint16_t assert_depth; /* Depth of nested assertions */ open_capitem *open_caps; /* Chain of open capture items */ named_group *named_groups; /* Points to vector in pre-compile */ uint32_t named_group_list_size; /* Number of entries in the list */ @@ -723,8 +746,6 @@ typedef struct compile_block { uint32_t class_range_end; /* Overall class range end */ PCRE2_UCHAR nl[4]; /* Newline string when fixed length */ int max_lookbehind; /* Maximum lookbehind (characters) */ - int parens_depth; /* Depth of nested parentheses */ - int assert_depth; /* Depth of nested assertions */ int req_varyopt; /* "After variable item" flag for reqbyte */ BOOL had_accept; /* (*ACCEPT) encountered */ BOOL had_pruneorskip; /* (*PRUNE) or (*SKIP) encountered */ @@ -740,27 +761,8 @@ typedef struct pcre2_real_jit_stack { void* stack; } pcre2_real_jit_stack; -/* Structure for keeping a chain of heap blocks used for saving ovectors -during pattern recursion when the ovector is larger than can be saved on -the system stack. */ - -typedef struct ovecsave_frame { - struct ovecsave_frame *next; /* Next frame on free chain */ - PCRE2_SIZE saved_ovec[1]; /* First vector element */ -} ovecsave_frame; - /* Structure for items in a linked list that represents an explicit recursive -call within the pattern; used by pcre_match(). */ - -typedef struct recursion_info { - struct recursion_info *prevrec; /* Previous recursion record (or NULL) */ - unsigned int group_num; /* Number of group that was called */ - PCRE2_SIZE *ovec_save; /* Pointer to saved ovector frame */ - uint32_t saved_capture_last; /* Last capture number */ - PCRE2_SPTR subject_position; /* Position at start of recursion */ -} recursion_info; - -/* A similar structure for pcre_dfa_match(). */ +call within the pattern when running pcre_dfa_match(). */ typedef struct dfa_recursion_info { struct dfa_recursion_info *prevrec; @@ -768,35 +770,75 @@ typedef struct dfa_recursion_info { uint32_t group_num; } dfa_recursion_info; -/* Structure for building a chain of data for holding the values of the subject -pointer at the start of each subpattern, so as to detect when an empty string -has been matched by a subpattern - to break infinite loops; used by -pcre2_match(). */ +/* Structure for "stack" frames that are used for remembering backtracking +positions during matching. As these are used in a vector, with the ovector item +being extended, the size of the structure must be a multiple of PCRE2_SIZE. The +only way to check this at compile time is to force an error by generating an +array with a negative size. By putting this in a typedef (which is never used), +we don't generate any code when all is well. */ + +typedef struct heapframe { + + /* The first set of fields are variables that have to be preserved over calls + to RRMATCH(), but which do not need to be copied to new frames. */ + + PCRE2_SPTR ecode; /* The current position in the pattern */ + PCRE2_SPTR temp_sptr[2]; /* Used for short-term PCRE_SPTR values */ + PCRE2_SIZE length; /* Used for character, string, or code lengths */ + PCRE2_SIZE back_frame; /* Amount to subtract on RRETURN */ + PCRE2_SIZE temp_size; /* Used for short-term PCRE2_SIZE values */ + uint32_t rdepth; /* "Recursion" depth */ + uint32_t group_frame_type; /* Type information for group frames */ + uint32_t temp_32[4]; /* Used for short-term 32-bit or BOOL values */ + uint8_t return_id; /* Where to go on in internal "return" */ + uint8_t op; /* Processing opcode */ -typedef struct eptrblock { - struct eptrblock *epb_prev; - PCRE2_SPTR epb_saved_eptr; -} eptrblock; +#if PCRE2_CODE_UNIT_WIDTH == 8 + PCRE2_UCHAR occu[6]; /* Used for other case code units */ +#elif PCRE2_CODE_UNIT_WIDTH == 16 + PCRE2_UCHAR occu[2]; /* Used for other case code units */ +#else + PCRE2_UCHAR occu[1]; /* Used for other case code units */ +#endif + + /* The rest have to be copied from the previous frame whenever a new frame + becomes current. The final field is specified as a large vector so that + runtime array bound checks don't catch references to it. However, for any + specific call to pcre2_match() the memory allocated for each frame structure + allows for exactly the right size ovector for the number of capturing + parentheses. (See also the comment for pcre2_real_match_data above.) */ + + PCRE2_SPTR eptr; /* MUST BE FIRST */ + PCRE2_SPTR start_match; /* Can be adjusted by \K */ + PCRE2_SPTR mark; /* Most recent mark on the success path */ + uint32_t current_recurse; /* Current (deepest) recursion number */ + uint32_t capture_last; /* Most recent capture */ + PCRE2_SIZE last_group_offset; /* Saved offset to most recent group frame */ + PCRE2_SIZE offset_top; /* Offset after highest capture */ + PCRE2_SIZE ovector[131072]; /* Must be last in the structure */ +} heapframe; + +typedef char check_heapframe_size[ + ((sizeof(heapframe) % sizeof(PCRE2_SIZE)) == 0)? (+1):(-1)]; /* Structure for passing "static" information around between the functions doing traditional NFA matching (pcre2_match() and friends). */ typedef struct match_block { pcre2_memctl memctl; /* For general use */ -#ifdef HEAP_MATCH_RECURSE - pcre2_memctl stack_memctl; /* For "stack" frames */ -#endif - uint32_t match_call_count; /* As it says */ + PCRE2_SIZE frame_vector_size; /* Size of a backtracking frame */ + heapframe *match_frames; /* Points to vector of frames */ + heapframe *match_frames_top; /* Points after the end of the vector */ + heapframe *stack_frames; /* The original vector on the stack */ + PCRE2_SIZE heap_limit; /* As it says */ uint32_t match_limit; /* As it says */ - uint32_t match_limit_recursion; /* As it says */ + uint32_t match_limit_depth; /* As it says */ + uint32_t match_call_count; /* Number of times a new frame is created */ BOOL hitend; /* Hit the end of the subject at some point */ BOOL hasthen; /* Pattern contains (*THEN) */ const uint8_t *lcc; /* Points to lower casing table */ const uint8_t *fcc; /* Points to case-flipping table */ const uint8_t *ctypes; /* Points to table of type maps */ - PCRE2_SIZE *ovector; /* Pointer to the offset vector */ - PCRE2_SIZE offset_end; /* One past the end */ - PCRE2_SIZE offset_max; /* The maximum usable for return data */ PCRE2_SIZE start_offset; /* The start offset value */ PCRE2_SIZE end_offset_top; /* Highwater mark at end of match */ uint16_t partial; /* PARTIAL options */ @@ -807,30 +849,24 @@ typedef struct match_block { PCRE2_SPTR start_code; /* For use when recursing */ PCRE2_SPTR start_subject; /* Start of the subject string */ PCRE2_SPTR end_subject; /* End of the subject string */ - PCRE2_SPTR start_match_ptr; /* Start of matched string */ PCRE2_SPTR end_match_ptr; /* Subject position at end match */ PCRE2_SPTR start_used_ptr; /* Earliest consulted character */ PCRE2_SPTR last_used_ptr; /* Latest consulted character */ PCRE2_SPTR mark; /* Mark pointer to pass back on success */ PCRE2_SPTR nomatch_mark; /* Mark pointer to pass back on failure */ - PCRE2_SPTR once_target; /* Where to back up to for atomic groups */ + PCRE2_SPTR verb_ecode_ptr; /* For passing back info */ + PCRE2_SPTR verb_skip_ptr; /* For passing back a (*SKIP) name */ + uint32_t verb_current_recurse; /* Current recurse when (*VERB) happens */ uint32_t moptions; /* Match options */ uint32_t poptions; /* Pattern options */ - uint32_t capture_last; /* Most recent capture number + overflow flag */ uint32_t skip_arg_count; /* For counting SKIP_ARGs */ uint32_t ignore_skip_arg; /* For re-run when SKIP arg name not found */ - uint32_t match_function_type; /* Set for certain special calls of match() */ uint32_t nltype; /* Newline type */ uint32_t nllen; /* Newline string length */ PCRE2_UCHAR nl[4]; /* Newline string when fixed */ - eptrblock *eptrchain; /* Chain of eptrblocks for tail recursions */ - recursion_info *recursive; /* Linked list of recursion data */ - ovecsave_frame *ovecsave_chain; /* Linked list of free ovecsave blocks */ + pcre2_callout_block *cb; /* Points to a callout block */ void *callout_data; /* To pass back to callouts */ int (*callout)(pcre2_callout_block *,void *); /* Callout function or NULL */ -#ifdef HEAP_MATCH_RECURSE - void *match_frames_base; /* For remembering malloc'd frames */ -#endif } match_block; /* A similar structure is used for the same purpose by the DFA matching @@ -845,13 +881,16 @@ typedef struct dfa_match_block { PCRE2_SPTR last_used_ptr; /* Latest consulted character */ const uint8_t *tables; /* Character tables */ PCRE2_SIZE start_offset; /* The start offset value */ - uint32_t match_limit_recursion; /* As it says */ + uint32_t match_limit; /* As it says */ + uint32_t match_limit_depth; /* As it says */ + uint32_t match_call_count; /* Number of calls of internal function */ uint32_t moptions; /* Match options */ uint32_t poptions; /* Pattern options */ uint32_t nltype; /* Newline type */ uint32_t nllen; /* Newline string length */ PCRE2_UCHAR nl[4]; /* Newline string when fixed */ uint16_t bsr_convention; /* \R interpretation */ + pcre2_callout_block *cb; /* Points to a callout block */ void *callout_data; /* To pass back to callouts */ int (*callout)(pcre2_callout_block *,void *); /* Callout function or NULL */ dfa_recursion_info *recursive; /* Linked list of recursion data */ diff --git a/thirdparty/pcre2/src/pcre2_jit_compile.c b/thirdparty/pcre2/src/pcre2_jit_compile.c index 8dea90a1c5..80ed1c4ca6 100644 --- a/thirdparty/pcre2/src/pcre2_jit_compile.c +++ b/thirdparty/pcre2/src/pcre2_jit_compile.c @@ -7,7 +7,7 @@ and semantics are as close as possible to those of the Perl 5 language. Written by Philip Hazel Original API code Copyright (c) 1997-2012 University of Cambridge - New API code Copyright (c) 2016 University of Cambridge + New API code Copyright (c) 2016-2017 University of Cambridge ----------------------------------------------------------------------------- Redistribution and use in source and binary forms, with or without @@ -228,7 +228,7 @@ enum control_types { type_then_trap = 1 }; -typedef int (SLJIT_CALL *jit_function)(jit_arguments *args); +typedef int (SLJIT_FUNC *jit_function)(jit_arguments *args); /* The following structure is the key data type for the recursive code generator. It is allocated by compile_matchingpath, and contains @@ -313,16 +313,25 @@ typedef struct ref_iterator_backtrack { typedef struct recurse_entry { struct recurse_entry *next; - /* Contains the function entry. */ - struct sljit_label *entry; - /* Collects the calls until the function is not created. */ - jump_list *calls; + /* Contains the function entry label. */ + struct sljit_label *entry_label; + /* Contains the function entry label. */ + struct sljit_label *backtrack_label; + /* Collects the entry calls until the function is not created. */ + jump_list *entry_calls; + /* Collects the backtrack calls until the function is not created. */ + jump_list *backtrack_calls; /* Points to the starting opcode. */ sljit_sw start; } recurse_entry; typedef struct recurse_backtrack { backtrack_common common; + /* Return to the matching path. */ + struct sljit_label *matchingpath; + /* Recursive pattern. */ + recurse_entry *entry; + /* Pattern is inlined. */ BOOL inlined_pattern; } recurse_backtrack; @@ -341,11 +350,26 @@ typedef struct then_trap_backtrack { int framesize; } then_trap_backtrack; -#define MAX_RANGE_SIZE 4 +#define MAX_N_CHARS 12 +#define MAX_DIFF_CHARS 5 + +typedef struct fast_forward_char_data { + /* Number of characters in the chars array, 255 for any character. */ + sljit_u8 count; + /* Number of last UTF-8 characters in the chars array. */ + sljit_u8 last_count; + /* Available characters in the current position. */ + PCRE2_UCHAR chars[MAX_DIFF_CHARS]; +} fast_forward_char_data; + +#define MAX_CLASS_RANGE_SIZE 4 +#define MAX_CLASS_CHARS_SIZE 3 typedef struct compiler_common { /* The sljit ceneric compiler. */ struct sljit_compiler *compiler; + /* Compiled regular expression. */ + pcre2_real_code *re; /* First byte code. */ PCRE2_SPTR start; /* Maps private data offset to each opcode. */ @@ -402,10 +426,10 @@ typedef struct compiler_common { BOOL has_then; /* (*SKIP) or (*SKIP:arg) is found in lookbehind assertion. */ BOOL has_skip_in_assert_back; - /* Currently in recurse or negative assert. */ - BOOL local_exit; - /* Currently in a positive assert. */ - BOOL positive_assert; + /* Quit is redirected by recurse, negative assertion, or positive assertion in conditional block. */ + BOOL local_quit_available; + /* Currently in a positive assertion. */ + BOOL in_positive_assertion; /* Newline control. */ int nltype; sljit_u32 nlmax; @@ -426,7 +450,7 @@ typedef struct compiler_common { /* Labels and jump lists. */ struct sljit_label *partialmatchlabel; struct sljit_label *quit_label; - struct sljit_label *forced_quit_label; + struct sljit_label *abort_label; struct sljit_label *accept_label; struct sljit_label *ff_newline_shortcut; stub_list *stubs; @@ -435,8 +459,9 @@ typedef struct compiler_common { recurse_entry *currententry; jump_list *partialmatch; jump_list *quit; - jump_list *positive_assert_quit; - jump_list *forced_quit; + jump_list *positive_assertion_quit; + jump_list *abort; + jump_list *failed_match; jump_list *accept; jump_list *calllimit; jump_list *stackalloc; @@ -500,14 +525,29 @@ typedef struct compare_context { #undef CMP /* Used for accessing the elements of the stack. */ -#define STACK(i) ((-(i) - 1) * (int)sizeof(sljit_sw)) +#define STACK(i) ((i) * (int)sizeof(sljit_sw)) + +#ifdef SLJIT_PREF_SHIFT_REG +#if SLJIT_PREF_SHIFT_REG == SLJIT_R2 +/* Nothing. */ +#elif SLJIT_PREF_SHIFT_REG == SLJIT_R3 +#define SHIFT_REG_IS_R3 +#else +#error "Unsupported shift register" +#endif +#endif #define TMP1 SLJIT_R0 +#ifdef SHIFT_REG_IS_R3 +#define TMP2 SLJIT_R3 +#define TMP3 SLJIT_R2 +#else #define TMP2 SLJIT_R2 #define TMP3 SLJIT_R3 -#define STR_PTR SLJIT_S0 -#define STR_END SLJIT_S1 -#define STACK_TOP SLJIT_R1 +#endif +#define STR_PTR SLJIT_R1 +#define STR_END SLJIT_S0 +#define STACK_TOP SLJIT_S1 #define STACK_LIMIT SLJIT_S2 #define COUNT_MATCH SLJIT_S3 #define ARGUMENTS SLJIT_S4 @@ -533,16 +573,13 @@ the start pointers when the end of the capturing group has not yet reached. */ #if PCRE2_CODE_UNIT_WIDTH == 8 #define MOV_UCHAR SLJIT_MOV_U8 -#define MOVU_UCHAR SLJIT_MOVU_U8 #define IN_UCHARS(x) (x) #elif PCRE2_CODE_UNIT_WIDTH == 16 #define MOV_UCHAR SLJIT_MOV_U16 -#define MOVU_UCHAR SLJIT_MOVU_U16 #define UCHAR_SHIFT (1) #define IN_UCHARS(x) ((x) * 2) #elif PCRE2_CODE_UNIT_WIDTH == 32 #define MOV_UCHAR SLJIT_MOV_U32 -#define MOVU_UCHAR SLJIT_MOVU_U32 #define UCHAR_SHIFT (2) #define IN_UCHARS(x) ((x) * 4) #else @@ -570,13 +607,17 @@ the start pointers when the end of the capturing group has not yet reached. */ sljit_emit_cmp(compiler, (type), (src1), (src1w), (src2), (src2w)) #define CMPTO(type, src1, src1w, src2, src2w, label) \ sljit_set_label(sljit_emit_cmp(compiler, (type), (src1), (src1w), (src2), (src2w)), (label)) -#define OP_FLAGS(op, dst, dstw, src, srcw, type) \ - sljit_emit_op_flags(compiler, (op), (dst), (dstw), (src), (srcw), (type)) +#define OP_FLAGS(op, dst, dstw, type) \ + sljit_emit_op_flags(compiler, (op), (dst), (dstw), (type)) +#define CMOV(type, dst_reg, src, srcw) \ + sljit_emit_cmov(compiler, (type), (dst_reg), (src), (srcw)) #define GET_LOCAL_BASE(dst, dstw, offset) \ sljit_get_local_base(compiler, (dst), (dstw), (offset)) #define READ_CHAR_MAX 0x7fffffff +#define INVALID_UTF_CHAR 888 + static PCRE2_SPTR bracketend(PCRE2_SPTR cc) { SLJIT_ASSERT((*cc >= OP_ASSERT && *cc <= OP_ASSERTBACK_NOT) || (*cc >= OP_ONCE && *cc <= OP_SCOND)); @@ -606,8 +647,8 @@ return count; set_private_data_ptrs get_framesize init_frame - get_private_data_copy_length - copy_private_data + get_recurse_data_length + copy_recurse_data compile_matchingpath compile_backtrackingpath */ @@ -675,7 +716,6 @@ switch(*cc) case OP_ASSERTBACK: case OP_ASSERTBACK_NOT: case OP_ONCE: - case OP_ONCE_NC: case OP_BRA: case OP_BRAPOS: case OP_CBRA: @@ -806,7 +846,7 @@ switch(*cc) default: /* All opcodes are supported now! */ - SLJIT_ASSERT_STOP(); + SLJIT_UNREACHABLE(); return NULL; } } @@ -1304,7 +1344,7 @@ while (cc < ccend) if (private_data_ptr > SLJIT_MAX_LOCAL_SIZE) break; - if (repeat_check && (*cc == OP_ONCE || *cc == OP_ONCE_NC || *cc == OP_BRA || *cc == OP_CBRA || *cc == OP_COND)) + if (repeat_check && (*cc == OP_ONCE || *cc == OP_BRA || *cc == OP_CBRA || *cc == OP_COND)) { if (detect_repeat(common, cc)) { @@ -1333,7 +1373,6 @@ while (cc < ccend) case OP_ASSERTBACK: case OP_ASSERTBACK_NOT: case OP_ONCE: - case OP_ONCE_NC: case OP_BRAPOS: case OP_SBRA: case OP_SBRAPOS: @@ -1654,11 +1693,11 @@ if (length > 0) return stack_restore ? no_frame : no_stack; } -static void init_frame(compiler_common *common, PCRE2_SPTR cc, PCRE2_SPTR ccend, int stackpos, int stacktop, BOOL recursive) +static void init_frame(compiler_common *common, PCRE2_SPTR cc, PCRE2_SPTR ccend, int stackpos, int stacktop) { DEFINE_COMPILER; -BOOL setsom_found = recursive; -BOOL setmark_found = recursive; +BOOL setsom_found = FALSE; +BOOL setmark_found = FALSE; /* The last capture is a local variable even for recursions. */ BOOL capture_last_found = FALSE; int offset; @@ -1671,7 +1710,7 @@ stackpos = STACK(stackpos); if (ccend == NULL) { ccend = bracketend(cc) - (1 + LINK_SIZE); - if (recursive || (*cc != OP_CBRAPOS && *cc != OP_SCBRAPOS)) + if (*cc != OP_CBRAPOS && *cc != OP_SCBRAPOS) cc = next_opcode(common, cc); } @@ -1685,9 +1724,9 @@ while (cc < ccend) { OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(0)); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, -OVECTOR(0)); - stackpos += (int)sizeof(sljit_sw); + stackpos -= (int)sizeof(sljit_sw); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP1, 0); - stackpos += (int)sizeof(sljit_sw); + stackpos -= (int)sizeof(sljit_sw); setsom_found = TRUE; } cc += 1; @@ -1701,9 +1740,9 @@ while (cc < ccend) { OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->mark_ptr); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, -common->mark_ptr); - stackpos += (int)sizeof(sljit_sw); + stackpos -= (int)sizeof(sljit_sw); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP1, 0); - stackpos += (int)sizeof(sljit_sw); + stackpos -= (int)sizeof(sljit_sw); setmark_found = TRUE; } cc += 1 + 2 + cc[1]; @@ -1714,27 +1753,27 @@ while (cc < ccend) { OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(0)); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, -OVECTOR(0)); - stackpos += (int)sizeof(sljit_sw); + stackpos -= (int)sizeof(sljit_sw); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP1, 0); - stackpos += (int)sizeof(sljit_sw); + stackpos -= (int)sizeof(sljit_sw); setsom_found = TRUE; } if (common->mark_ptr != 0 && !setmark_found) { OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->mark_ptr); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, -common->mark_ptr); - stackpos += (int)sizeof(sljit_sw); + stackpos -= (int)sizeof(sljit_sw); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP1, 0); - stackpos += (int)sizeof(sljit_sw); + stackpos -= (int)sizeof(sljit_sw); setmark_found = TRUE; } if (common->capture_last_ptr != 0 && !capture_last_found) { OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->capture_last_ptr); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, -common->capture_last_ptr); - stackpos += (int)sizeof(sljit_sw); + stackpos -= (int)sizeof(sljit_sw); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP1, 0); - stackpos += (int)sizeof(sljit_sw); + stackpos -= (int)sizeof(sljit_sw); capture_last_found = TRUE; } cc += 1 + LINK_SIZE; @@ -1748,20 +1787,20 @@ while (cc < ccend) { OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->capture_last_ptr); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, -common->capture_last_ptr); - stackpos += (int)sizeof(sljit_sw); + stackpos -= (int)sizeof(sljit_sw); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP1, 0); - stackpos += (int)sizeof(sljit_sw); + stackpos -= (int)sizeof(sljit_sw); capture_last_found = TRUE; } offset = (GET2(cc, 1 + LINK_SIZE)) << 1; OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, OVECTOR(offset)); - stackpos += (int)sizeof(sljit_sw); + stackpos -= (int)sizeof(sljit_sw); OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset)); OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset + 1)); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP1, 0); - stackpos += (int)sizeof(sljit_sw); + stackpos -= (int)sizeof(sljit_sw); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP2, 0); - stackpos += (int)sizeof(sljit_sw); + stackpos -= (int)sizeof(sljit_sw); cc += 1 + LINK_SIZE + IMM2_SIZE; break; @@ -1776,21 +1815,127 @@ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, 0); SLJIT_ASSERT(stackpos == STACK(stacktop)); } -static SLJIT_INLINE int get_private_data_copy_length(compiler_common *common, PCRE2_SPTR cc, PCRE2_SPTR ccend, BOOL needs_control_head) +#define RECURSE_TMP_REG_COUNT 3 + +typedef struct delayed_mem_copy_status { + struct sljit_compiler *compiler; + int store_bases[RECURSE_TMP_REG_COUNT]; + int store_offsets[RECURSE_TMP_REG_COUNT]; + int tmp_regs[RECURSE_TMP_REG_COUNT]; + int saved_tmp_regs[RECURSE_TMP_REG_COUNT]; + int next_tmp_reg; +} delayed_mem_copy_status; + +static void delayed_mem_copy_init(delayed_mem_copy_status *status, compiler_common *common) +{ +int i; + +for (i = 0; i < RECURSE_TMP_REG_COUNT; i++) + { + SLJIT_ASSERT(status->tmp_regs[i] >= 0); + SLJIT_ASSERT(sljit_get_register_index(status->saved_tmp_regs[i]) < 0 || status->tmp_regs[i] == status->saved_tmp_regs[i]); + + status->store_bases[i] = -1; + } +status->next_tmp_reg = 0; +status->compiler = common->compiler; +} + +static void delayed_mem_copy_move(delayed_mem_copy_status *status, int load_base, sljit_sw load_offset, + int store_base, sljit_sw store_offset) +{ +struct sljit_compiler *compiler = status->compiler; +int next_tmp_reg = status->next_tmp_reg; +int tmp_reg = status->tmp_regs[next_tmp_reg]; + +SLJIT_ASSERT(load_base > 0 && store_base > 0); + +if (status->store_bases[next_tmp_reg] == -1) + { + /* Preserve virtual registers. */ + if (sljit_get_register_index(status->saved_tmp_regs[next_tmp_reg]) < 0) + OP1(SLJIT_MOV, status->saved_tmp_regs[next_tmp_reg], 0, tmp_reg, 0); + } +else + OP1(SLJIT_MOV, SLJIT_MEM1(status->store_bases[next_tmp_reg]), status->store_offsets[next_tmp_reg], tmp_reg, 0); + +OP1(SLJIT_MOV, tmp_reg, 0, SLJIT_MEM1(load_base), load_offset); +status->store_bases[next_tmp_reg] = store_base; +status->store_offsets[next_tmp_reg] = store_offset; + +status->next_tmp_reg = (next_tmp_reg + 1) % RECURSE_TMP_REG_COUNT; +} + +static void delayed_mem_copy_finish(delayed_mem_copy_status *status) +{ +struct sljit_compiler *compiler = status->compiler; +int next_tmp_reg = status->next_tmp_reg; +int tmp_reg, saved_tmp_reg, i; + +for (i = 0; i < RECURSE_TMP_REG_COUNT; i++) + { + if (status->store_bases[next_tmp_reg] != -1) + { + tmp_reg = status->tmp_regs[next_tmp_reg]; + saved_tmp_reg = status->saved_tmp_regs[next_tmp_reg]; + + OP1(SLJIT_MOV, SLJIT_MEM1(status->store_bases[next_tmp_reg]), status->store_offsets[next_tmp_reg], tmp_reg, 0); + + /* Restore virtual registers. */ + if (sljit_get_register_index(saved_tmp_reg) < 0) + OP1(SLJIT_MOV, tmp_reg, 0, saved_tmp_reg, 0); + } + + next_tmp_reg = (next_tmp_reg + 1) % RECURSE_TMP_REG_COUNT; + } +} + +#undef RECURSE_TMP_REG_COUNT + +static int get_recurse_data_length(compiler_common *common, PCRE2_SPTR cc, PCRE2_SPTR ccend, + BOOL *needs_control_head, BOOL *has_quit, BOOL *has_accept) { -int private_data_length = needs_control_head ? 3 : 2; +int length = 1; int size; PCRE2_SPTR alternative; +BOOL quit_found = FALSE; +BOOL accept_found = FALSE; +BOOL setsom_found = FALSE; +BOOL setmark_found = FALSE; +BOOL capture_last_found = FALSE; +BOOL control_head_found = FALSE; + +#if defined DEBUG_FORCE_CONTROL_HEAD && DEBUG_FORCE_CONTROL_HEAD +SLJIT_ASSERT(common->control_head_ptr != 0); +control_head_found = TRUE; +#endif + /* Calculate the sum of the private machine words. */ while (cc < ccend) { size = 0; switch(*cc) { + case OP_SET_SOM: + SLJIT_ASSERT(common->has_set_som); + setsom_found = TRUE; + cc += 1; + break; + + case OP_RECURSE: + if (common->has_set_som) + setsom_found = TRUE; + if (common->mark_ptr != 0) + setmark_found = TRUE; + if (common->capture_last_ptr != 0) + capture_last_found = TRUE; + cc += 1 + LINK_SIZE; + break; + case OP_KET: if (PRIVATE_DATA(cc) != 0) { - private_data_length++; + length++; SLJIT_ASSERT(PRIVATE_DATA(cc + 1) != 0); cc += PRIVATE_DATA(cc + 1); } @@ -1802,26 +1947,30 @@ while (cc < ccend) case OP_ASSERTBACK: case OP_ASSERTBACK_NOT: case OP_ONCE: - case OP_ONCE_NC: case OP_BRAPOS: case OP_SBRA: case OP_SBRAPOS: case OP_SCOND: - private_data_length++; + length++; SLJIT_ASSERT(PRIVATE_DATA(cc) != 0); cc += 1 + LINK_SIZE; break; case OP_CBRA: case OP_SCBRA: + length += 2; + if (common->capture_last_ptr != 0) + capture_last_found = TRUE; if (common->optimized_cbracket[GET2(cc, 1 + LINK_SIZE)] == 0) - private_data_length++; + length++; cc += 1 + LINK_SIZE + IMM2_SIZE; break; case OP_CBRAPOS: case OP_SCBRAPOS: - private_data_length += 2; + length += 2 + 2; + if (common->capture_last_ptr != 0) + capture_last_found = TRUE; cc += 1 + LINK_SIZE + IMM2_SIZE; break; @@ -1829,13 +1978,13 @@ while (cc < ccend) /* Might be a hidden SCOND. */ alternative = cc + GET(cc, 1); if (*alternative == OP_KETRMAX || *alternative == OP_KETRMIN) - private_data_length++; + length++; cc += 1 + LINK_SIZE; break; CASE_ITERATOR_PRIVATE_DATA_1 - if (PRIVATE_DATA(cc)) - private_data_length++; + if (PRIVATE_DATA(cc) != 0) + length++; cc += 2; #ifdef SUPPORT_UNICODE if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]); @@ -1843,8 +1992,8 @@ while (cc < ccend) break; CASE_ITERATOR_PRIVATE_DATA_2A - if (PRIVATE_DATA(cc)) - private_data_length += 2; + if (PRIVATE_DATA(cc) != 0) + length += 2; cc += 2; #ifdef SUPPORT_UNICODE if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]); @@ -1852,8 +2001,8 @@ while (cc < ccend) break; CASE_ITERATOR_PRIVATE_DATA_2B - if (PRIVATE_DATA(cc)) - private_data_length += 2; + if (PRIVATE_DATA(cc) != 0) + length += 2; cc += 2 + IMM2_SIZE; #ifdef SUPPORT_UNICODE if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]); @@ -1861,20 +2010,20 @@ while (cc < ccend) break; CASE_ITERATOR_TYPE_PRIVATE_DATA_1 - if (PRIVATE_DATA(cc)) - private_data_length++; + if (PRIVATE_DATA(cc) != 0) + length++; cc += 1; break; CASE_ITERATOR_TYPE_PRIVATE_DATA_2A - if (PRIVATE_DATA(cc)) - private_data_length += 2; + if (PRIVATE_DATA(cc) != 0) + length += 2; cc += 1; break; CASE_ITERATOR_TYPE_PRIVATE_DATA_2B - if (PRIVATE_DATA(cc)) - private_data_length += 2; + if (PRIVATE_DATA(cc) != 0) + length += 2; cc += 1 + IMM2_SIZE; break; @@ -1886,11 +2035,51 @@ while (cc < ccend) #else size = 1 + 32 / (int)sizeof(PCRE2_UCHAR); #endif - if (PRIVATE_DATA(cc)) - private_data_length += get_class_iterator_size(cc + size); + if (PRIVATE_DATA(cc) != 0) + length += get_class_iterator_size(cc + size); cc += size; break; + case OP_MARK: + case OP_PRUNE_ARG: + case OP_THEN_ARG: + SLJIT_ASSERT(common->mark_ptr != 0); + if (!setmark_found) + setmark_found = TRUE; + if (common->control_head_ptr != 0) + control_head_found = TRUE; + if (*cc != OP_MARK) + quit_found = TRUE; + + cc += 1 + 2 + cc[1]; + break; + + case OP_PRUNE: + case OP_SKIP: + case OP_COMMIT: + quit_found = TRUE; + cc++; + break; + + case OP_SKIP_ARG: + quit_found = TRUE; + cc += 1 + 2 + cc[1]; + break; + + case OP_THEN: + SLJIT_ASSERT(common->control_head_ptr != 0); + quit_found = TRUE; + if (!control_head_found) + control_head_found = TRUE; + cc++; + break; + + case OP_ACCEPT: + case OP_ASSERT_ACCEPT: + accept_found = TRUE; + cc++; + break; + default: cc = next_opcode(common, cc); SLJIT_ASSERT(cc != NULL); @@ -1898,329 +2087,446 @@ while (cc < ccend) } } SLJIT_ASSERT(cc == ccend); -return private_data_length; + +if (control_head_found) + length++; +if (capture_last_found) + length++; +if (quit_found) + { + if (setsom_found) + length++; + if (setmark_found) + length++; + } + +*needs_control_head = control_head_found; +*has_quit = quit_found; +*has_accept = accept_found; +return length; } -static void copy_private_data(compiler_common *common, PCRE2_SPTR cc, PCRE2_SPTR ccend, - BOOL save, int stackptr, int stacktop, BOOL needs_control_head) +enum copy_recurse_data_types { + recurse_copy_from_global, + recurse_copy_private_to_global, + recurse_copy_shared_to_global, + recurse_copy_kept_shared_to_global, + recurse_swap_global +}; + +static void copy_recurse_data(compiler_common *common, PCRE2_SPTR cc, PCRE2_SPTR ccend, + int type, int stackptr, int stacktop, BOOL has_quit) { -DEFINE_COMPILER; -int srcw[2]; -int count, size; -BOOL tmp1next = TRUE; -BOOL tmp1empty = TRUE; -BOOL tmp2empty = TRUE; +delayed_mem_copy_status status; PCRE2_SPTR alternative; -enum { - start, - loop, - end -} status; +sljit_sw private_srcw[2]; +sljit_sw shared_srcw[3]; +sljit_sw kept_shared_srcw[2]; +int private_count, shared_count, kept_shared_count; +int from_sp, base_reg, offset, i; +BOOL setsom_found = FALSE; +BOOL setmark_found = FALSE; +BOOL capture_last_found = FALSE; +BOOL control_head_found = FALSE; -status = save ? start : loop; -stackptr = STACK(stackptr - 2); -stacktop = STACK(stacktop - 1); +#if defined DEBUG_FORCE_CONTROL_HEAD && DEBUG_FORCE_CONTROL_HEAD +SLJIT_ASSERT(common->control_head_ptr != 0); +control_head_found = TRUE; +#endif -if (!save) +switch (type) { - stackptr += (needs_control_head ? 2 : 1) * sizeof(sljit_sw); - if (stackptr < stacktop) - { - OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), stackptr); - stackptr += sizeof(sljit_sw); - tmp1empty = FALSE; - } - if (stackptr < stacktop) - { - OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), stackptr); - stackptr += sizeof(sljit_sw); - tmp2empty = FALSE; - } - /* The tmp1next must be TRUE in either way. */ + case recurse_copy_from_global: + from_sp = TRUE; + base_reg = STACK_TOP; + break; + + case recurse_copy_private_to_global: + case recurse_copy_shared_to_global: + case recurse_copy_kept_shared_to_global: + from_sp = FALSE; + base_reg = STACK_TOP; + break; + + default: + SLJIT_ASSERT(type == recurse_swap_global); + from_sp = FALSE; + base_reg = TMP2; + break; } -do +stackptr = STACK(stackptr); +stacktop = STACK(stacktop); + +status.tmp_regs[0] = TMP1; +status.saved_tmp_regs[0] = TMP1; + +if (base_reg != TMP2) { - count = 0; - switch(status) + status.tmp_regs[1] = TMP2; + status.saved_tmp_regs[1] = TMP2; + } +else + { + status.saved_tmp_regs[1] = RETURN_ADDR; + if (sljit_get_register_index (RETURN_ADDR) == -1) + status.tmp_regs[1] = STR_PTR; + else + status.tmp_regs[1] = RETURN_ADDR; + } + +status.saved_tmp_regs[2] = TMP3; +if (sljit_get_register_index (TMP3) == -1) + status.tmp_regs[2] = STR_END; +else + status.tmp_regs[2] = TMP3; + +delayed_mem_copy_init(&status, common); + +if (type != recurse_copy_shared_to_global && type != recurse_copy_kept_shared_to_global) + { + SLJIT_ASSERT(type == recurse_copy_from_global || type == recurse_copy_private_to_global || type == recurse_swap_global); + + if (!from_sp) + delayed_mem_copy_move(&status, base_reg, stackptr, SLJIT_SP, common->recursive_head_ptr); + + if (from_sp || type == recurse_swap_global) + delayed_mem_copy_move(&status, SLJIT_SP, common->recursive_head_ptr, base_reg, stackptr); + } + +stackptr += sizeof(sljit_sw); + +#if defined DEBUG_FORCE_CONTROL_HEAD && DEBUG_FORCE_CONTROL_HEAD +if (type != recurse_copy_shared_to_global) + { + if (!from_sp) + delayed_mem_copy_move(&status, base_reg, stackptr, SLJIT_SP, common->control_head_ptr); + + if (from_sp || type == recurse_swap_global) + delayed_mem_copy_move(&status, SLJIT_SP, common->control_head_ptr, base_reg, stackptr); + } + +stackptr += sizeof(sljit_sw); +#endif + +while (cc < ccend) + { + private_count = 0; + shared_count = 0; + kept_shared_count = 0; + + switch(*cc) { - case start: - SLJIT_ASSERT(save && common->recursive_head_ptr != 0); - count = 1; - srcw[0] = common->recursive_head_ptr; - if (needs_control_head) + case OP_SET_SOM: + SLJIT_ASSERT(common->has_set_som); + if (has_quit && !setsom_found) { - SLJIT_ASSERT(common->control_head_ptr != 0); - count = 2; - srcw[1] = common->control_head_ptr; + kept_shared_srcw[0] = OVECTOR(0); + kept_shared_count = 1; + setsom_found = TRUE; } - status = loop; + cc += 1; break; - case loop: - if (cc >= ccend) + case OP_RECURSE: + if (has_quit) { - status = end; - break; + if (common->has_set_som && !setsom_found) + { + kept_shared_srcw[0] = OVECTOR(0); + kept_shared_count = 1; + setsom_found = TRUE; + } + if (common->mark_ptr != 0 && !setmark_found) + { + kept_shared_srcw[kept_shared_count] = common->mark_ptr; + kept_shared_count++; + setmark_found = TRUE; + } + } + if (common->capture_last_ptr != 0 && !capture_last_found) + { + shared_srcw[0] = common->capture_last_ptr; + shared_count = 1; + capture_last_found = TRUE; } + cc += 1 + LINK_SIZE; + break; - switch(*cc) + case OP_KET: + if (PRIVATE_DATA(cc) != 0) { - case OP_KET: - if (PRIVATE_DATA(cc) != 0) - { - count = 1; - srcw[0] = PRIVATE_DATA(cc); - SLJIT_ASSERT(PRIVATE_DATA(cc + 1) != 0); - cc += PRIVATE_DATA(cc + 1); - } - cc += 1 + LINK_SIZE; - break; + private_count = 1; + private_srcw[0] = PRIVATE_DATA(cc); + SLJIT_ASSERT(PRIVATE_DATA(cc + 1) != 0); + cc += PRIVATE_DATA(cc + 1); + } + cc += 1 + LINK_SIZE; + break; - case OP_ASSERT: - case OP_ASSERT_NOT: - case OP_ASSERTBACK: - case OP_ASSERTBACK_NOT: - case OP_ONCE: - case OP_ONCE_NC: - case OP_BRAPOS: - case OP_SBRA: - case OP_SBRAPOS: - case OP_SCOND: - count = 1; - srcw[0] = PRIVATE_DATA(cc); - SLJIT_ASSERT(srcw[0] != 0); - cc += 1 + LINK_SIZE; - break; + case OP_ASSERT: + case OP_ASSERT_NOT: + case OP_ASSERTBACK: + case OP_ASSERTBACK_NOT: + case OP_ONCE: + case OP_BRAPOS: + case OP_SBRA: + case OP_SBRAPOS: + case OP_SCOND: + private_count = 1; + private_srcw[0] = PRIVATE_DATA(cc); + cc += 1 + LINK_SIZE; + break; - case OP_CBRA: - case OP_SCBRA: - if (common->optimized_cbracket[GET2(cc, 1 + LINK_SIZE)] == 0) - { - count = 1; - srcw[0] = OVECTOR_PRIV(GET2(cc, 1 + LINK_SIZE)); - } - cc += 1 + LINK_SIZE + IMM2_SIZE; - break; + case OP_CBRA: + case OP_SCBRA: + offset = (GET2(cc, 1 + LINK_SIZE)) << 1; + shared_srcw[0] = OVECTOR(offset); + shared_srcw[1] = OVECTOR(offset + 1); + shared_count = 2; - case OP_CBRAPOS: - case OP_SCBRAPOS: - count = 2; - srcw[0] = PRIVATE_DATA(cc); - srcw[1] = OVECTOR_PRIV(GET2(cc, 1 + LINK_SIZE)); - SLJIT_ASSERT(srcw[0] != 0 && srcw[1] != 0); - cc += 1 + LINK_SIZE + IMM2_SIZE; - break; + if (common->capture_last_ptr != 0 && !capture_last_found) + { + shared_srcw[2] = common->capture_last_ptr; + shared_count = 3; + capture_last_found = TRUE; + } - case OP_COND: - /* Might be a hidden SCOND. */ - alternative = cc + GET(cc, 1); - if (*alternative == OP_KETRMAX || *alternative == OP_KETRMIN) - { - count = 1; - srcw[0] = PRIVATE_DATA(cc); - SLJIT_ASSERT(srcw[0] != 0); - } - cc += 1 + LINK_SIZE; - break; + if (common->optimized_cbracket[GET2(cc, 1 + LINK_SIZE)] == 0) + { + private_count = 1; + private_srcw[0] = OVECTOR_PRIV(GET2(cc, 1 + LINK_SIZE)); + } + cc += 1 + LINK_SIZE + IMM2_SIZE; + break; - CASE_ITERATOR_PRIVATE_DATA_1 - if (PRIVATE_DATA(cc)) - { - count = 1; - srcw[0] = PRIVATE_DATA(cc); - } - cc += 2; + case OP_CBRAPOS: + case OP_SCBRAPOS: + offset = (GET2(cc, 1 + LINK_SIZE)) << 1; + shared_srcw[0] = OVECTOR(offset); + shared_srcw[1] = OVECTOR(offset + 1); + shared_count = 2; + + if (common->capture_last_ptr != 0 && !capture_last_found) + { + shared_srcw[2] = common->capture_last_ptr; + shared_count = 3; + capture_last_found = TRUE; + } + + private_count = 2; + private_srcw[0] = PRIVATE_DATA(cc); + private_srcw[1] = OVECTOR_PRIV(GET2(cc, 1 + LINK_SIZE)); + cc += 1 + LINK_SIZE + IMM2_SIZE; + break; + + case OP_COND: + /* Might be a hidden SCOND. */ + alternative = cc + GET(cc, 1); + if (*alternative == OP_KETRMAX || *alternative == OP_KETRMIN) + { + private_count = 1; + private_srcw[0] = PRIVATE_DATA(cc); + } + cc += 1 + LINK_SIZE; + break; + + CASE_ITERATOR_PRIVATE_DATA_1 + if (PRIVATE_DATA(cc)) + { + private_count = 1; + private_srcw[0] = PRIVATE_DATA(cc); + } + cc += 2; #ifdef SUPPORT_UNICODE - if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]); + if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]); #endif - break; + break; - CASE_ITERATOR_PRIVATE_DATA_2A - if (PRIVATE_DATA(cc)) - { - count = 2; - srcw[0] = PRIVATE_DATA(cc); - srcw[1] = PRIVATE_DATA(cc) + sizeof(sljit_sw); - } - cc += 2; + CASE_ITERATOR_PRIVATE_DATA_2A + if (PRIVATE_DATA(cc)) + { + private_count = 2; + private_srcw[0] = PRIVATE_DATA(cc); + private_srcw[1] = PRIVATE_DATA(cc) + sizeof(sljit_sw); + } + cc += 2; #ifdef SUPPORT_UNICODE - if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]); + if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]); #endif - break; + break; - CASE_ITERATOR_PRIVATE_DATA_2B - if (PRIVATE_DATA(cc)) - { - count = 2; - srcw[0] = PRIVATE_DATA(cc); - srcw[1] = PRIVATE_DATA(cc) + sizeof(sljit_sw); - } - cc += 2 + IMM2_SIZE; + CASE_ITERATOR_PRIVATE_DATA_2B + if (PRIVATE_DATA(cc)) + { + private_count = 2; + private_srcw[0] = PRIVATE_DATA(cc); + private_srcw[1] = PRIVATE_DATA(cc) + sizeof(sljit_sw); + } + cc += 2 + IMM2_SIZE; #ifdef SUPPORT_UNICODE - if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]); + if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]); #endif - break; + break; - CASE_ITERATOR_TYPE_PRIVATE_DATA_1 - if (PRIVATE_DATA(cc)) - { - count = 1; - srcw[0] = PRIVATE_DATA(cc); - } - cc += 1; - break; + CASE_ITERATOR_TYPE_PRIVATE_DATA_1 + if (PRIVATE_DATA(cc)) + { + private_count = 1; + private_srcw[0] = PRIVATE_DATA(cc); + } + cc += 1; + break; - CASE_ITERATOR_TYPE_PRIVATE_DATA_2A - if (PRIVATE_DATA(cc)) - { - count = 2; - srcw[0] = PRIVATE_DATA(cc); - srcw[1] = srcw[0] + sizeof(sljit_sw); - } - cc += 1; - break; + CASE_ITERATOR_TYPE_PRIVATE_DATA_2A + if (PRIVATE_DATA(cc)) + { + private_count = 2; + private_srcw[0] = PRIVATE_DATA(cc); + private_srcw[1] = private_srcw[0] + sizeof(sljit_sw); + } + cc += 1; + break; - CASE_ITERATOR_TYPE_PRIVATE_DATA_2B - if (PRIVATE_DATA(cc)) - { - count = 2; - srcw[0] = PRIVATE_DATA(cc); - srcw[1] = srcw[0] + sizeof(sljit_sw); - } - cc += 1 + IMM2_SIZE; - break; + CASE_ITERATOR_TYPE_PRIVATE_DATA_2B + if (PRIVATE_DATA(cc)) + { + private_count = 2; + private_srcw[0] = PRIVATE_DATA(cc); + private_srcw[1] = private_srcw[0] + sizeof(sljit_sw); + } + cc += 1 + IMM2_SIZE; + break; - case OP_CLASS: - case OP_NCLASS: + case OP_CLASS: + case OP_NCLASS: #if defined SUPPORT_UNICODE || PCRE2_CODE_UNIT_WIDTH != 8 - case OP_XCLASS: - size = (*cc == OP_XCLASS) ? GET(cc, 1) : 1 + 32 / (int)sizeof(PCRE2_UCHAR); + case OP_XCLASS: + i = (*cc == OP_XCLASS) ? GET(cc, 1) : 1 + 32 / (int)sizeof(PCRE2_UCHAR); #else - size = 1 + 32 / (int)sizeof(PCRE2_UCHAR); + i = 1 + 32 / (int)sizeof(PCRE2_UCHAR); #endif - if (PRIVATE_DATA(cc)) - switch(get_class_iterator_size(cc + size)) - { - case 1: - count = 1; - srcw[0] = PRIVATE_DATA(cc); - break; - - case 2: - count = 2; - srcw[0] = PRIVATE_DATA(cc); - srcw[1] = srcw[0] + sizeof(sljit_sw); - break; + if (PRIVATE_DATA(cc) != 0) + switch(get_class_iterator_size(cc + i)) + { + case 1: + private_count = 1; + private_srcw[0] = PRIVATE_DATA(cc); + break; + + case 2: + private_count = 2; + private_srcw[0] = PRIVATE_DATA(cc); + private_srcw[1] = private_srcw[0] + sizeof(sljit_sw); + break; + + default: + SLJIT_UNREACHABLE(); + break; + } + cc += i; + break; - default: - SLJIT_ASSERT_STOP(); - break; - } - cc += size; - break; + case OP_MARK: + case OP_PRUNE_ARG: + case OP_THEN_ARG: + SLJIT_ASSERT(common->mark_ptr != 0); + if (has_quit && !setmark_found) + { + kept_shared_srcw[0] = common->mark_ptr; + kept_shared_count = 1; + setmark_found = TRUE; + } + if (common->control_head_ptr != 0 && !control_head_found) + { + shared_srcw[0] = common->control_head_ptr; + shared_count = 1; + control_head_found = TRUE; + } + cc += 1 + 2 + cc[1]; + break; - default: - cc = next_opcode(common, cc); - SLJIT_ASSERT(cc != NULL); - break; + case OP_THEN: + SLJIT_ASSERT(common->control_head_ptr != 0); + if (!control_head_found) + { + shared_srcw[0] = common->control_head_ptr; + shared_count = 1; + control_head_found = TRUE; } + cc++; break; - case end: - SLJIT_ASSERT_STOP(); + default: + cc = next_opcode(common, cc); + SLJIT_ASSERT(cc != NULL); break; } - while (count > 0) + if (type != recurse_copy_shared_to_global && type != recurse_copy_kept_shared_to_global) { - count--; - if (save) - { - if (tmp1next) - { - if (!tmp1empty) - { - OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackptr, TMP1, 0); - stackptr += sizeof(sljit_sw); - } - OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), srcw[count]); - tmp1empty = FALSE; - tmp1next = FALSE; - } - else - { - if (!tmp2empty) - { - OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackptr, TMP2, 0); - stackptr += sizeof(sljit_sw); - } - OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), srcw[count]); - tmp2empty = FALSE; - tmp1next = TRUE; - } - } - else + SLJIT_ASSERT(type == recurse_copy_from_global || type == recurse_copy_private_to_global || type == recurse_swap_global); + + for (i = 0; i < private_count; i++) { - if (tmp1next) - { - SLJIT_ASSERT(!tmp1empty); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), srcw[count], TMP1, 0); - tmp1empty = stackptr >= stacktop; - if (!tmp1empty) - { - OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), stackptr); - stackptr += sizeof(sljit_sw); - } - tmp1next = FALSE; - } - else - { - SLJIT_ASSERT(!tmp2empty); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), srcw[count], TMP2, 0); - tmp2empty = stackptr >= stacktop; - if (!tmp2empty) - { - OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), stackptr); - stackptr += sizeof(sljit_sw); - } - tmp1next = TRUE; - } + SLJIT_ASSERT(private_srcw[i] != 0); + + if (!from_sp) + delayed_mem_copy_move(&status, base_reg, stackptr, SLJIT_SP, private_srcw[i]); + + if (from_sp || type == recurse_swap_global) + delayed_mem_copy_move(&status, SLJIT_SP, private_srcw[i], base_reg, stackptr); + + stackptr += sizeof(sljit_sw); } } - } -while (status != end); + else + stackptr += sizeof(sljit_sw) * private_count; -if (save) - { - if (tmp1next) + if (type != recurse_copy_private_to_global && type != recurse_copy_kept_shared_to_global) { - if (!tmp1empty) - { - OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackptr, TMP1, 0); - stackptr += sizeof(sljit_sw); - } - if (!tmp2empty) + SLJIT_ASSERT(type == recurse_copy_from_global || type == recurse_copy_shared_to_global || type == recurse_swap_global); + + for (i = 0; i < shared_count; i++) { - OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackptr, TMP2, 0); + SLJIT_ASSERT(shared_srcw[i] != 0); + + if (!from_sp) + delayed_mem_copy_move(&status, base_reg, stackptr, SLJIT_SP, shared_srcw[i]); + + if (from_sp || type == recurse_swap_global) + delayed_mem_copy_move(&status, SLJIT_SP, shared_srcw[i], base_reg, stackptr); + stackptr += sizeof(sljit_sw); } } else + stackptr += sizeof(sljit_sw) * shared_count; + + if (type != recurse_copy_private_to_global && type != recurse_swap_global) { - if (!tmp2empty) - { - OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackptr, TMP2, 0); - stackptr += sizeof(sljit_sw); - } - if (!tmp1empty) + SLJIT_ASSERT(type == recurse_copy_from_global || type == recurse_copy_shared_to_global || type == recurse_copy_kept_shared_to_global); + + for (i = 0; i < kept_shared_count; i++) { - OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackptr, TMP1, 0); + SLJIT_ASSERT(kept_shared_srcw[i] != 0); + + if (!from_sp) + delayed_mem_copy_move(&status, base_reg, stackptr, SLJIT_SP, kept_shared_srcw[i]); + + if (from_sp || type == recurse_swap_global) + delayed_mem_copy_move(&status, SLJIT_SP, kept_shared_srcw[i], base_reg, stackptr); + stackptr += sizeof(sljit_sw); } } + else + stackptr += sizeof(sljit_sw) * kept_shared_count; } -SLJIT_ASSERT(cc == ccend && stackptr == stacktop && (save || (tmp1empty && tmp2empty))); + +SLJIT_ASSERT(cc == ccend && stackptr == stacktop); + +delayed_mem_copy_finish(&status); } static SLJIT_INLINE PCRE2_SPTR set_then_offsets(compiler_common *common, PCRE2_SPTR cc, sljit_u8 *current_offset) @@ -2337,7 +2643,7 @@ static SLJIT_INLINE void count_match(compiler_common *common) { DEFINE_COMPILER; -OP2(SLJIT_SUB | SLJIT_SET_E, COUNT_MATCH, 0, COUNT_MATCH, 0, SLJIT_IMM, 1); +OP2(SLJIT_SUB | SLJIT_SET_Z, COUNT_MATCH, 0, COUNT_MATCH, 0, SLJIT_IMM, 1); add_jump(compiler, &common->calllimit, JUMP(SLJIT_ZERO)); } @@ -2347,7 +2653,7 @@ static SLJIT_INLINE void allocate_stack(compiler_common *common, int size) DEFINE_COMPILER; SLJIT_ASSERT(size > 0); -OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, size * sizeof(sljit_sw)); +OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, size * sizeof(sljit_sw)); #ifdef DESTROY_REGISTERS OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 12345); OP1(SLJIT_MOV, TMP3, 0, TMP1, 0); @@ -2355,7 +2661,7 @@ OP1(SLJIT_MOV, RETURN_ADDR, 0, TMP1, 0); OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS0, TMP1, 0); OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS1, TMP1, 0); #endif -add_stub(common, CMP(SLJIT_GREATER, STACK_TOP, 0, STACK_LIMIT, 0)); +add_stub(common, CMP(SLJIT_LESS, STACK_TOP, 0, STACK_LIMIT, 0)); } static SLJIT_INLINE void free_stack(compiler_common *common, int size) @@ -2363,7 +2669,7 @@ static SLJIT_INLINE void free_stack(compiler_common *common, int size) DEFINE_COMPILER; SLJIT_ASSERT(size > 0); -OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, size * sizeof(sljit_sw)); +OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, size * sizeof(sljit_sw)); } static sljit_uw * allocate_read_only_data(compiler_common *common, sljit_uw size) @@ -2403,12 +2709,25 @@ if (length < 8) } else { - GET_LOCAL_BASE(SLJIT_R1, 0, OVECTOR_START); - OP1(SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, length - 1); - loop = LABEL(); - OP1(SLJIT_MOVU, SLJIT_MEM1(SLJIT_R1), sizeof(sljit_sw), SLJIT_R0, 0); - OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_R2, 0, SLJIT_R2, 0, SLJIT_IMM, 1); - JUMPTO(SLJIT_NOT_ZERO, loop); + if (sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_SUPP | SLJIT_MEM_STORE | SLJIT_MEM_PRE, SLJIT_R0, SLJIT_MEM1(SLJIT_R1), sizeof(sljit_sw)) == SLJIT_SUCCESS) + { + GET_LOCAL_BASE(SLJIT_R1, 0, OVECTOR_START); + OP1(SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, length - 1); + loop = LABEL(); + sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_STORE | SLJIT_MEM_PRE, SLJIT_R0, SLJIT_MEM1(SLJIT_R1), sizeof(sljit_sw)); + OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_R2, 0, SLJIT_R2, 0, SLJIT_IMM, 1); + JUMPTO(SLJIT_NOT_ZERO, loop); + } + else + { + GET_LOCAL_BASE(SLJIT_R1, 0, OVECTOR_START + sizeof(sljit_sw)); + OP1(SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, length - 1); + loop = LABEL(); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_R1), 0, SLJIT_R0, 0); + OP2(SLJIT_ADD, SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_IMM, sizeof(sljit_sw)); + OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_R2, 0, SLJIT_R2, 0, SLJIT_IMM, 1); + JUMPTO(SLJIT_NOT_ZERO, loop); + } } } @@ -2441,12 +2760,25 @@ if (length < 8) } else { - GET_LOCAL_BASE(TMP2, 0, OVECTOR_START + sizeof(sljit_sw)); - OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_IMM, length - 2); - loop = LABEL(); - OP1(SLJIT_MOVU, SLJIT_MEM1(TMP2), sizeof(sljit_sw), TMP1, 0); - OP2(SLJIT_SUB | SLJIT_SET_E, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, 1); - JUMPTO(SLJIT_NOT_ZERO, loop); + if (sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_SUPP | SLJIT_MEM_STORE | SLJIT_MEM_PRE, TMP1, SLJIT_MEM1(TMP2), sizeof(sljit_sw)) == SLJIT_SUCCESS) + { + GET_LOCAL_BASE(TMP2, 0, OVECTOR_START + sizeof(sljit_sw)); + OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_IMM, length - 2); + loop = LABEL(); + sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_STORE | SLJIT_MEM_PRE, TMP1, SLJIT_MEM1(TMP2), sizeof(sljit_sw)); + OP2(SLJIT_SUB | SLJIT_SET_Z, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, 1); + JUMPTO(SLJIT_NOT_ZERO, loop); + } + else + { + GET_LOCAL_BASE(TMP2, 0, OVECTOR_START + 2 * sizeof(sljit_sw)); + OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_IMM, length - 2); + loop = LABEL(); + OP1(SLJIT_MOV, SLJIT_MEM1(TMP2), 0, TMP1, 0); + OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, SLJIT_IMM, sizeof(sljit_sw)); + OP2(SLJIT_SUB | SLJIT_SET_Z, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, 1); + JUMPTO(SLJIT_NOT_ZERO, loop); + } } OP1(SLJIT_MOV, STACK_TOP, 0, ARGUMENTS, 0); @@ -2456,37 +2788,38 @@ if (common->control_head_ptr != 0) OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, SLJIT_IMM, 0); OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(STACK_TOP), SLJIT_OFFSETOF(jit_arguments, stack)); OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->start_ptr); -OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(STACK_TOP), SLJIT_OFFSETOF(struct sljit_stack, base)); +OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(STACK_TOP), SLJIT_OFFSETOF(struct sljit_stack, end)); } -static sljit_sw SLJIT_CALL do_search_mark(sljit_sw *current, PCRE2_SPTR skip_arg) +static sljit_sw SLJIT_FUNC do_search_mark(sljit_sw *current, PCRE2_SPTR skip_arg) { while (current != NULL) { - switch (current[-2]) + switch (current[1]) { case type_then_trap: break; case type_mark: - if (PRIV(strcmp)(skip_arg, (PCRE2_SPTR)current[-3]) == 0) - return current[-4]; + if (PRIV(strcmp)(skip_arg, (PCRE2_SPTR)current[2]) == 0) + return current[3]; break; default: - SLJIT_ASSERT_STOP(); + SLJIT_UNREACHABLE(); break; } - SLJIT_ASSERT(current > (sljit_sw*)current[-1]); - current = (sljit_sw*)current[-1]; + SLJIT_ASSERT(current[0] == 0 || current < (sljit_sw*)current[0]); + current = (sljit_sw*)current[0]; } -return -1; +return 0; } static SLJIT_INLINE void copy_ovector(compiler_common *common, int topbracket) { DEFINE_COMPILER; struct sljit_label *loop; +BOOL has_pre; /* At this point we can freely use all registers. */ OP1(SLJIT_MOV, SLJIT_S2, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(1)); @@ -2503,36 +2836,62 @@ if (common->mark_ptr != 0) OP2(SLJIT_ADD, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_R0), SLJIT_OFFSETOF(jit_arguments, match_data), SLJIT_IMM, SLJIT_OFFSETOF(pcre2_match_data, ovector) - sizeof(PCRE2_SIZE)); -GET_LOCAL_BASE(SLJIT_S0, 0, OVECTOR_START); +has_pre = sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_SUPP | SLJIT_MEM_PRE, SLJIT_S1, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw)) == SLJIT_SUCCESS; + +GET_LOCAL_BASE(SLJIT_S0, 0, OVECTOR_START - (has_pre ? sizeof(sljit_sw) : 0)); OP1(SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_R0), SLJIT_OFFSETOF(jit_arguments, begin)); loop = LABEL(); -OP2(SLJIT_SUB, SLJIT_S1, 0, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_R0, 0); -OP2(SLJIT_ADD, SLJIT_S0, 0, SLJIT_S0, 0, SLJIT_IMM, sizeof(sljit_sw)); + +if (has_pre) + sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_PRE, SLJIT_S1, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw)); +else + { + OP1(SLJIT_MOV, SLJIT_S1, 0, SLJIT_MEM1(SLJIT_S0), 0); + OP2(SLJIT_ADD, SLJIT_S0, 0, SLJIT_S0, 0, SLJIT_IMM, sizeof(sljit_sw)); + } + +OP2(SLJIT_ADD, SLJIT_R2, 0, SLJIT_R2, 0, SLJIT_IMM, sizeof(PCRE2_SIZE)); +OP2(SLJIT_SUB, SLJIT_S1, 0, SLJIT_S1, 0, SLJIT_R0, 0); /* Copy the integer value to the output buffer */ #if PCRE2_CODE_UNIT_WIDTH == 16 || PCRE2_CODE_UNIT_WIDTH == 32 OP2(SLJIT_ASHR, SLJIT_S1, 0, SLJIT_S1, 0, SLJIT_IMM, UCHAR_SHIFT); #endif + SLJIT_ASSERT(sizeof(PCRE2_SIZE) == 4 || sizeof(PCRE2_SIZE) == 8); -if (sizeof(PCRE2_SIZE) == 4) - OP1(SLJIT_MOVU_U32, SLJIT_MEM1(SLJIT_R2), sizeof(PCRE2_SIZE), SLJIT_S1, 0); -else - OP1(SLJIT_MOVU, SLJIT_MEM1(SLJIT_R2), sizeof(PCRE2_SIZE), SLJIT_S1, 0); -OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_IMM, 1); +OP1(((sizeof(PCRE2_SIZE) == 4) ? SLJIT_MOV_U32 : SLJIT_MOV), SLJIT_MEM1(SLJIT_R2), 0, SLJIT_S1, 0); + +OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_IMM, 1); JUMPTO(SLJIT_NOT_ZERO, loop); /* Calculate the return value, which is the maximum ovector value. */ if (topbracket > 1) { - GET_LOCAL_BASE(SLJIT_R0, 0, OVECTOR_START + topbracket * 2 * sizeof(sljit_sw)); - OP1(SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, topbracket + 1); + if (sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_SUPP | SLJIT_MEM_PRE, SLJIT_R2, SLJIT_MEM1(SLJIT_R0), -(2 * (sljit_sw)sizeof(sljit_sw))) == SLJIT_SUCCESS) + { + GET_LOCAL_BASE(SLJIT_R0, 0, OVECTOR_START + topbracket * 2 * sizeof(sljit_sw)); + OP1(SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, topbracket + 1); - /* OVECTOR(0) is never equal to SLJIT_S2. */ - loop = LABEL(); - OP1(SLJIT_MOVU, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_R0), -(2 * (sljit_sw)sizeof(sljit_sw))); - OP2(SLJIT_SUB, SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_IMM, 1); - CMPTO(SLJIT_EQUAL, SLJIT_R2, 0, SLJIT_S2, 0, loop); - OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_R1, 0); + /* OVECTOR(0) is never equal to SLJIT_S2. */ + loop = LABEL(); + sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_PRE, SLJIT_R2, SLJIT_MEM1(SLJIT_R0), -(2 * (sljit_sw)sizeof(sljit_sw))); + OP2(SLJIT_SUB, SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_IMM, 1); + CMPTO(SLJIT_EQUAL, SLJIT_R2, 0, SLJIT_S2, 0, loop); + OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_R1, 0); + } + else + { + GET_LOCAL_BASE(SLJIT_R0, 0, OVECTOR_START + (topbracket - 1) * 2 * sizeof(sljit_sw)); + OP1(SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, topbracket + 1); + + /* OVECTOR(0) is never equal to SLJIT_S2. */ + loop = LABEL(); + OP1(SLJIT_MOV, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_R0), 0); + OP2(SLJIT_SUB, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 2 * (sljit_sw)sizeof(sljit_sw)); + OP2(SLJIT_SUB, SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_IMM, 1); + CMPTO(SLJIT_EQUAL, SLJIT_R2, 0, SLJIT_S2, 0, loop); + OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_R1, 0); + } } else OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, 1); @@ -2543,7 +2902,7 @@ static SLJIT_INLINE void return_with_partial_match(compiler_common *common, stru DEFINE_COMPILER; sljit_s32 mov_opcode; -SLJIT_COMPILE_ASSERT(STR_END == SLJIT_S1, str_end_must_be_saved_reg2); +SLJIT_COMPILE_ASSERT(STR_END == SLJIT_S0, str_end_must_be_saved_reg0); SLJIT_ASSERT(common->start_used_ptr != 0 && common->start_ptr != 0 && (common->mode == PCRE2_JIT_PARTIAL_SOFT ? common->hit_start != 0 : common->hit_start == 0)); @@ -2553,19 +2912,19 @@ OP1(SLJIT_MOV, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_SP), OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE2_ERROR_PARTIAL); /* Store match begin and end. */ -OP1(SLJIT_MOV, SLJIT_S0, 0, SLJIT_MEM1(SLJIT_R1), SLJIT_OFFSETOF(jit_arguments, begin)); +OP1(SLJIT_MOV, SLJIT_S1, 0, SLJIT_MEM1(SLJIT_R1), SLJIT_OFFSETOF(jit_arguments, begin)); OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_R1), SLJIT_OFFSETOF(jit_arguments, startchar_ptr), SLJIT_R2, 0); OP1(SLJIT_MOV, SLJIT_R1, 0, SLJIT_MEM1(SLJIT_R1), SLJIT_OFFSETOF(jit_arguments, match_data)); mov_opcode = (sizeof(PCRE2_SIZE) == 4) ? SLJIT_MOV_U32 : SLJIT_MOV; -OP2(SLJIT_SUB, SLJIT_R2, 0, SLJIT_R2, 0, SLJIT_S0, 0); +OP2(SLJIT_SUB, SLJIT_R2, 0, SLJIT_R2, 0, SLJIT_S1, 0); #if PCRE2_CODE_UNIT_WIDTH == 16 || PCRE2_CODE_UNIT_WIDTH == 32 OP2(SLJIT_ASHR, SLJIT_R2, 0, SLJIT_R2, 0, SLJIT_IMM, UCHAR_SHIFT); #endif OP1(mov_opcode, SLJIT_MEM1(SLJIT_R1), SLJIT_OFFSETOF(pcre2_match_data, ovector), SLJIT_R2, 0); -OP2(SLJIT_SUB, STR_END, 0, STR_END, 0, SLJIT_S0, 0); +OP2(SLJIT_SUB, STR_END, 0, STR_END, 0, SLJIT_S1, 0); #if PCRE2_CODE_UNIT_WIDTH == 16 || PCRE2_CODE_UNIT_WIDTH == 32 OP2(SLJIT_ASHR, STR_END, 0, STR_END, 0, SLJIT_IMM, UCHAR_SHIFT); #endif @@ -3104,8 +3463,8 @@ if (common->utf) OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); /* Skip low surrogate if necessary. */ OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xfc00); - OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xdc00); - OP_FLAGS(SLJIT_MOV, TMP1, 0, SLJIT_UNUSED, 0, SLJIT_EQUAL); + OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xdc00); + OP_FLAGS(SLJIT_MOV, TMP1, 0, SLJIT_EQUAL); OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 1); OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP1, 0); return; @@ -3124,6 +3483,7 @@ struct sljit_jump *jump; if (nltype == NLTYPE_ANY) { add_jump(compiler, &common->anynewline, JUMP(SLJIT_FAST_CALL)); + sljit_set_current_flags(compiler, SLJIT_SET_Z); add_jump(compiler, backtracks, JUMP(jumpifmatch ? SLJIT_NOT_ZERO : SLJIT_ZERO)); } else if (nltype == NLTYPE_ANYCRLF) @@ -3165,7 +3525,7 @@ OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f); OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0); /* Searching for the first zero. */ -OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x800); +OP2(SLJIT_AND | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x800); jump = JUMP(SLJIT_NOT_ZERO); /* Two byte sequence. */ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); @@ -3179,7 +3539,7 @@ OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 6); OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f); OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0); -OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x10000); +OP2(SLJIT_AND | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x10000); jump = JUMP(SLJIT_NOT_ZERO); /* Three byte sequence. */ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2)); @@ -3213,15 +3573,15 @@ OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f); OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0); /* Searching for the first zero. */ -OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x800); +OP2(SLJIT_AND | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x800); jump = JUMP(SLJIT_NOT_ZERO); /* Two byte sequence. */ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); sljit_emit_fast_return(compiler, RETURN_ADDR, 0); JUMPHERE(jump); -OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x400); -OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_NOT_ZERO); +OP2(SLJIT_AND | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x400); +OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_NOT_ZERO); /* This code runs only in 8 bit mode. No need to shift the value. */ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP2, 0); OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1)); @@ -3244,7 +3604,7 @@ struct sljit_jump *compare; sljit_emit_fast_enter(compiler, RETURN_ADDR, 0); -OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_IMM, 0x20); +OP2(SLJIT_AND | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_IMM, 0x20); jump = JUMP(SLJIT_NOT_ZERO); /* Two byte sequence. */ OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0)); @@ -3281,10 +3641,30 @@ static void do_getucd(compiler_common *common) /* Search the UCD record for the character comes in TMP1. Returns chartype in TMP1 and UCD offset in TMP2. */ DEFINE_COMPILER; +#if PCRE2_CODE_UNIT_WIDTH == 32 +struct sljit_jump *jump; +#endif + +#if defined SLJIT_DEBUG && SLJIT_DEBUG +/* dummy_ucd_record */ +const ucd_record *record = GET_UCD(INVALID_UTF_CHAR); +SLJIT_ASSERT(record->script == ucp_Common && record->chartype == ucp_Cn && record->gbprop == ucp_gbOther); +SLJIT_ASSERT(record->caseset == 0 && record->other_case == 0); +#endif SLJIT_ASSERT(UCD_BLOCK_SIZE == 128 && sizeof(ucd_record) == 8); sljit_emit_fast_enter(compiler, RETURN_ADDR, 0); + +#if PCRE2_CODE_UNIT_WIDTH == 32 +if (!common->utf) + { + jump = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, MAX_UTF_CODE_POINT + 1); + OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, INVALID_UTF_CHAR); + JUMPHERE(jump); + } +#endif + OP2(SLJIT_LSHR, TMP2, 0, TMP1, 0, SLJIT_IMM, UCD_BLOCK_SHIFT); OP1(SLJIT_MOV_U8, TMP2, 0, SLJIT_MEM1(TMP2), (sljit_sw)PRIV(ucd_stage1)); OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, UCD_BLOCK_MASK); @@ -3299,7 +3679,7 @@ sljit_emit_fast_return(compiler, RETURN_ADDR, 0); #endif /* SUPPORT_UNICODE */ -static SLJIT_INLINE struct sljit_label *mainloop_entry(compiler_common *common, BOOL hascrorlf, sljit_u32 overall_options) +static SLJIT_INLINE struct sljit_label *mainloop_entry(compiler_common *common) { DEFINE_COMPILER; struct sljit_label *mainloop; @@ -3311,6 +3691,8 @@ struct sljit_jump *end2 = NULL; struct sljit_jump *singlechar; #endif jump_list *newline = NULL; +sljit_u32 overall_options = common->re->overall_options; +BOOL hascrorlf = (common->re->flags & PCRE2_HASCRORLF) != 0; BOOL newlinecheck = FALSE; BOOL readuchar = FALSE; @@ -3318,7 +3700,7 @@ if (!(hascrorlf || (overall_options & PCRE2_FIRSTLINE) != 0) && (common->nltype == NLTYPE_ANY || common->nltype == NLTYPE_ANYCRLF || common->newline > 255)) newlinecheck = TRUE; -SLJIT_ASSERT(common->forced_quit_label == NULL); +SLJIT_ASSERT(common->abort_label == NULL); if ((overall_options & PCRE2_FIRSTLINE) != 0) { @@ -3375,7 +3757,7 @@ else if ((overall_options & PCRE2_USE_OFFSET_LIMIT) != 0) OP1(SLJIT_MOV, TMP2, 0, STR_END, 0); JUMPHERE(end2); OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE2_ERROR_NOMATCH); - add_jump(compiler, &common->forced_quit, CMP(SLJIT_LESS, TMP2, 0, STR_PTR, 0)); + add_jump(compiler, &common->abort, CMP(SLJIT_LESS, TMP2, 0, STR_PTR, 0)); JUMPHERE(end); OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->match_end_ptr, TMP2, 0); } @@ -3388,8 +3770,8 @@ if (newlinecheck) OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); end = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0); - OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, common->newline & 0xff); - OP_FLAGS(SLJIT_MOV, TMP1, 0, SLJIT_UNUSED, 0, SLJIT_EQUAL); + OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, common->newline & 0xff); + OP_FLAGS(SLJIT_MOV, TMP1, 0, SLJIT_EQUAL); #if PCRE2_CODE_UNIT_WIDTH == 16 || PCRE2_CODE_UNIT_WIDTH == 32 OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, UCHAR_SHIFT); #endif @@ -3426,8 +3808,8 @@ if (common->utf) { singlechar = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0xd800); OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xfc00); - OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xd800); - OP_FLAGS(SLJIT_MOV, TMP1, 0, SLJIT_UNUSED, 0, SLJIT_EQUAL); + OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xd800); + OP_FLAGS(SLJIT_MOV, TMP1, 0, SLJIT_EQUAL); OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 1); OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0); JUMPHERE(singlechar); @@ -3445,40 +3827,42 @@ if (newlinecheck) return mainloop; } -#define MAX_N_CHARS 16 -#define MAX_DIFF_CHARS 6 -static SLJIT_INLINE void add_prefix_char(PCRE2_UCHAR chr, PCRE2_UCHAR *chars) +static SLJIT_INLINE void add_prefix_char(PCRE2_UCHAR chr, fast_forward_char_data *chars, BOOL last) { -PCRE2_UCHAR i, len; +sljit_u32 i, count = chars->count; -len = chars[0]; -if (len == 255) +if (count == 255) return; -if (len == 0) +if (count == 0) { - chars[0] = 1; - chars[1] = chr; + chars->count = 1; + chars->chars[0] = chr; + + if (last) + chars->last_count = 1; return; } -for (i = len; i > 0; i--) - if (chars[i] == chr) +for (i = 0; i < count; i++) + if (chars->chars[i] == chr) return; -if (len >= MAX_DIFF_CHARS - 1) +if (count >= MAX_DIFF_CHARS) { - chars[0] = 255; + chars->count = 255; return; } -len++; -chars[len] = chr; -chars[0] = len; +chars->chars[count] = chr; +chars->count = count + 1; + +if (last) + chars->last_count++; } -static int scan_prefix(compiler_common *common, PCRE2_SPTR cc, PCRE2_UCHAR *chars, int max_chars, sljit_u32 *rec_count) +static int scan_prefix(compiler_common *common, PCRE2_SPTR cc, fast_forward_char_data *chars, int max_chars, sljit_u32 *rec_count) { /* Recursive function, which scans prefix literals. */ BOOL last, any, class, caseless; @@ -3487,7 +3871,7 @@ sljit_u32 chr; /* Any unicode character. */ sljit_u8 *bytes, *bytes_end, byte; PCRE2_SPTR alternative, cc_save, oc; #if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 8 -PCRE2_UCHAR othercase[8]; +PCRE2_UCHAR othercase[4]; #elif defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 16 PCRE2_UCHAR othercase[2]; #else @@ -3510,6 +3894,7 @@ while (TRUE) { case OP_CHARI: caseless = TRUE; + /* Fall through */ case OP_CHAR: last = FALSE; cc++; @@ -3541,6 +3926,7 @@ while (TRUE) case OP_MINPLUSI: case OP_POSPLUSI: caseless = TRUE; + /* Fall through */ case OP_PLUS: case OP_MINPLUS: case OP_POSPLUS: @@ -3549,6 +3935,7 @@ while (TRUE) case OP_EXACTI: caseless = TRUE; + /* Fall through */ case OP_EXACT: repeat = GET2(cc, 1); last = FALSE; @@ -3559,6 +3946,7 @@ while (TRUE) case OP_MINQUERYI: case OP_POSQUERYI: caseless = TRUE; + /* Fall through */ case OP_QUERY: case OP_MINQUERY: case OP_POSQUERY: @@ -3582,7 +3970,6 @@ while (TRUE) continue; case OP_ONCE: - case OP_ONCE_NC: case OP_BRA: case OP_BRAPOS: case OP_CBRA: @@ -3703,12 +4090,12 @@ while (TRUE) { do { - chars[0] = 255; + chars->count = 255; consumed++; if (--max_chars == 0) return consumed; - chars += MAX_DIFF_CHARS; + chars++; } while (--repeat > 0); @@ -3752,8 +4139,8 @@ while (TRUE) do { if (bytes[31] & 0x80) - chars[0] = 255; - else if (chars[0] != 255) + chars->count = 255; + else if (chars->count != 255) { bytes_end = bytes + 32; chr = 0; @@ -3768,7 +4155,7 @@ while (TRUE) do { if ((byte & 0x1) != 0) - add_prefix_char(chr, chars); + add_prefix_char(chr, chars, TRUE); byte >>= 1; chr++; } @@ -3776,14 +4163,14 @@ while (TRUE) chr = (chr + 7) & ~7; } } - while (chars[0] != 255 && bytes < bytes_end); + while (chars->count != 255 && bytes < bytes_end); bytes = bytes_end - 32; } consumed++; if (--max_chars == 0) return consumed; - chars += MAX_DIFF_CHARS; + chars++; } while (--repeat > 0); @@ -3847,17 +4234,18 @@ while (TRUE) oc = othercase; do { + len--; + consumed++; + chr = *cc; - add_prefix_char(*cc, chars); + add_prefix_char(*cc, chars, len == 0); if (caseless) - add_prefix_char(*oc, chars); + add_prefix_char(*oc, chars, len == 0); - len--; - consumed++; if (--max_chars == 0) return consumed; - chars += MAX_DIFF_CHARS; + chars++; cc++; oc++; } @@ -3876,7 +4264,37 @@ while (TRUE) } } -#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86) +#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32 +static void jumpto_if_not_utf_char_start(struct sljit_compiler *compiler, sljit_s32 reg, struct sljit_label *label) +{ +#if PCRE2_CODE_UNIT_WIDTH == 8 +OP2(SLJIT_AND, reg, 0, reg, 0, SLJIT_IMM, 0xc0); +CMPTO(SLJIT_EQUAL, reg, 0, SLJIT_IMM, 0x80, label); +#elif PCRE2_CODE_UNIT_WIDTH == 16 +OP2(SLJIT_AND, reg, 0, reg, 0, SLJIT_IMM, 0xfc00); +CMPTO(SLJIT_EQUAL, reg, 0, SLJIT_IMM, 0xdc00, label); +#else +#error "Unknown code width" +#endif +} +#endif + +#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86) && !(defined SUPPORT_VALGRIND) + +#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32 +static struct sljit_jump *jump_if_utf_char_start(struct sljit_compiler *compiler, sljit_s32 reg) +{ +#if PCRE2_CODE_UNIT_WIDTH == 8 +OP2(SLJIT_AND, reg, 0, reg, 0, SLJIT_IMM, 0xc0); +return CMP(SLJIT_NOT_EQUAL, reg, 0, SLJIT_IMM, 0x80); +#elif PCRE2_CODE_UNIT_WIDTH == 16 +OP2(SLJIT_AND, reg, 0, reg, 0, SLJIT_IMM, 0xfc00); +return CMP(SLJIT_NOT_EQUAL, reg, 0, SLJIT_IMM, 0xdc00); +#else +#error "Unknown code width" +#endif +} +#endif static sljit_s32 character_to_int32(PCRE2_UCHAR chr) { @@ -3895,39 +4313,140 @@ return value; #endif } -static SLJIT_INLINE void fast_forward_first_char2_sse2(compiler_common *common, PCRE2_UCHAR char1, PCRE2_UCHAR char2) +static void load_from_mem_sse2(struct sljit_compiler *compiler, sljit_s32 dst_xmm_reg, sljit_s32 src_general_reg) +{ +#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) +sljit_u8 instruction[5]; +#else +sljit_u8 instruction[4]; +#endif + +SLJIT_ASSERT(dst_xmm_reg < 8); + +/* MOVDQA xmm1, xmm2/m128 */ +#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) +if (src_general_reg < 8) + { + instruction[0] = 0x66; + instruction[1] = 0x0f; + instruction[2] = 0x6f; + instruction[3] = (dst_xmm_reg << 3) | src_general_reg; + sljit_emit_op_custom(compiler, instruction, 4); + } +else + { + instruction[0] = 0x66; + instruction[1] = 0x41; + instruction[2] = 0x0f; + instruction[3] = 0x6f; + instruction[4] = (dst_xmm_reg << 3) | (src_general_reg & 0x7); + sljit_emit_op_custom(compiler, instruction, 4); + } +#else +instruction[0] = 0x66; +instruction[1] = 0x0f; +instruction[2] = 0x6f; +instruction[3] = (dst_xmm_reg << 3) | src_general_reg; +sljit_emit_op_custom(compiler, instruction, 4); +#endif +} + +static void fast_forward_char_pair_sse2_compare(struct sljit_compiler *compiler, PCRE2_UCHAR char1, PCRE2_UCHAR char2, + sljit_u32 bit, sljit_s32 dst_ind, sljit_s32 cmp1_ind, sljit_s32 cmp2_ind, sljit_s32 tmp_ind) +{ +sljit_u8 instruction[4]; +instruction[0] = 0x66; +instruction[1] = 0x0f; + +if (char1 == char2 || bit != 0) + { + if (bit != 0) + { + /* POR xmm1, xmm2/m128 */ + /* instruction[0] = 0x66; */ + /* instruction[1] = 0x0f; */ + instruction[2] = 0xeb; + instruction[3] = 0xc0 | (dst_ind << 3) | cmp2_ind; + sljit_emit_op_custom(compiler, instruction, 4); + } + + /* PCMPEQB/W/D xmm1, xmm2/m128 */ + /* instruction[0] = 0x66; */ + /* instruction[1] = 0x0f; */ + instruction[2] = 0x74 + SSE2_COMPARE_TYPE_INDEX; + instruction[3] = 0xc0 | (dst_ind << 3) | cmp1_ind; + sljit_emit_op_custom(compiler, instruction, 4); + } +else + { + /* MOVDQA xmm1, xmm2/m128 */ + /* instruction[0] = 0x66; */ + /* instruction[1] = 0x0f; */ + instruction[2] = 0x6f; + instruction[3] = 0xc0 | (tmp_ind << 3) | dst_ind; + sljit_emit_op_custom(compiler, instruction, 4); + + /* PCMPEQB/W/D xmm1, xmm2/m128 */ + /* instruction[0] = 0x66; */ + /* instruction[1] = 0x0f; */ + instruction[2] = 0x74 + SSE2_COMPARE_TYPE_INDEX; + instruction[3] = 0xc0 | (dst_ind << 3) | cmp1_ind; + sljit_emit_op_custom(compiler, instruction, 4); + + instruction[3] = 0xc0 | (tmp_ind << 3) | cmp2_ind; + sljit_emit_op_custom(compiler, instruction, 4); + + /* POR xmm1, xmm2/m128 */ + /* instruction[0] = 0x66; */ + /* instruction[1] = 0x0f; */ + instruction[2] = 0xeb; + instruction[3] = 0xc0 | (dst_ind << 3) | tmp_ind; + sljit_emit_op_custom(compiler, instruction, 4); + } +} + +static void fast_forward_first_char2_sse2(compiler_common *common, PCRE2_UCHAR char1, PCRE2_UCHAR char2, sljit_s32 offset) { DEFINE_COMPILER; struct sljit_label *start; -struct sljit_jump *quit[3]; -struct sljit_jump *nomatch; +#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32 +struct sljit_label *restart; +#endif +struct sljit_jump *quit; +struct sljit_jump *partial_quit[2]; sljit_u8 instruction[8]; sljit_s32 tmp1_ind = sljit_get_register_index(TMP1); -sljit_s32 tmp2_ind = sljit_get_register_index(TMP2); sljit_s32 str_ptr_ind = sljit_get_register_index(STR_PTR); -BOOL load_twice = FALSE; -PCRE2_UCHAR bit; +sljit_s32 data_ind = 0; +sljit_s32 tmp_ind = 1; +sljit_s32 cmp1_ind = 2; +sljit_s32 cmp2_ind = 3; +sljit_u32 bit = 0; -bit = char1 ^ char2; -if (!is_powerof2(bit)) - bit = 0; +SLJIT_UNUSED_ARG(offset); -if ((char1 != char2) && bit == 0) - load_twice = TRUE; +if (char1 != char2) + { + bit = char1 ^ char2; + if (!is_powerof2(bit)) + bit = 0; + } -quit[0] = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); +partial_quit[0] = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); +if (common->mode == PCRE2_JIT_COMPLETE) + add_jump(compiler, &common->failed_match, partial_quit[0]); /* First part (unaligned start) */ OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, character_to_int32(char1 | bit)); -SLJIT_ASSERT(tmp1_ind < 8 && tmp2_ind == 1); +SLJIT_ASSERT(tmp1_ind < 8); /* MOVD xmm, r/m32 */ instruction[0] = 0x66; instruction[1] = 0x0f; instruction[2] = 0x6e; -instruction[3] = 0xc0 | (2 << 3) | tmp1_ind; +instruction[3] = 0xc0 | (cmp1_ind << 3) | tmp1_ind; sljit_emit_op_custom(compiler, instruction, 4); if (char1 != char2) @@ -3935,224 +4454,521 @@ if (char1 != char2) OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, character_to_int32(bit != 0 ? bit : char2)); /* MOVD xmm, r/m32 */ - instruction[3] = 0xc0 | (3 << 3) | tmp1_ind; + instruction[3] = 0xc0 | (cmp2_ind << 3) | tmp1_ind; sljit_emit_op_custom(compiler, instruction, 4); } +OP1(SLJIT_MOV, TMP2, 0, STR_PTR, 0); + /* PSHUFD xmm1, xmm2/m128, imm8 */ +/* instruction[0] = 0x66; */ +/* instruction[1] = 0x0f; */ instruction[2] = 0x70; -instruction[3] = 0xc0 | (2 << 3) | 2; +instruction[3] = 0xc0 | (cmp1_ind << 3) | 2; instruction[4] = 0; sljit_emit_op_custom(compiler, instruction, 5); if (char1 != char2) { /* PSHUFD xmm1, xmm2/m128, imm8 */ - instruction[3] = 0xc0 | (3 << 3) | 3; - instruction[4] = 0; + instruction[3] = 0xc0 | (cmp2_ind << 3) | 3; sljit_emit_op_custom(compiler, instruction, 5); } -OP2(SLJIT_AND, TMP2, 0, STR_PTR, 0, SLJIT_IMM, 0xf); +#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32 +restart = LABEL(); +#endif OP2(SLJIT_AND, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, ~0xf); +OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0xf); -/* MOVDQA xmm1, xmm2/m128 */ -#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) +load_from_mem_sse2(compiler, data_ind, str_ptr_ind); +fast_forward_char_pair_sse2_compare(compiler, char1, char2, bit, data_ind, cmp1_ind, cmp2_ind, tmp_ind); -if (str_ptr_ind < 8) - { - instruction[2] = 0x6f; - instruction[3] = (0 << 3) | str_ptr_ind; - sljit_emit_op_custom(compiler, instruction, 4); - - if (load_twice) - { - instruction[3] = (1 << 3) | str_ptr_ind; - sljit_emit_op_custom(compiler, instruction, 4); - } - } -else - { - instruction[1] = 0x41; - instruction[2] = 0x0f; - instruction[3] = 0x6f; - instruction[4] = (0 << 3) | (str_ptr_ind & 0x7); - sljit_emit_op_custom(compiler, instruction, 5); +/* PMOVMSKB reg, xmm */ +/* instruction[0] = 0x66; */ +/* instruction[1] = 0x0f; */ +instruction[2] = 0xd7; +instruction[3] = 0xc0 | (tmp1_ind << 3) | 0; +sljit_emit_op_custom(compiler, instruction, 4); - if (load_twice) - { - instruction[4] = (1 << 3) | str_ptr_ind; - sljit_emit_op_custom(compiler, instruction, 5); - } - instruction[1] = 0x0f; - } +OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP2, 0); +OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, TMP2, 0); -#else +/* BSF r32, r/m32 */ +instruction[0] = 0x0f; +instruction[1] = 0xbc; +instruction[2] = 0xc0 | (tmp1_ind << 3) | tmp1_ind; +sljit_emit_op_custom(compiler, instruction, 3); +sljit_set_current_flags(compiler, SLJIT_SET_Z); -instruction[2] = 0x6f; -instruction[3] = (0 << 3) | str_ptr_ind; -sljit_emit_op_custom(compiler, instruction, 4); +quit = JUMP(SLJIT_NOT_ZERO); -if (load_twice) - { - instruction[3] = (1 << 3) | str_ptr_ind; - sljit_emit_op_custom(compiler, instruction, 4); - } +OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP2, 0); -#endif +start = LABEL(); +OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, 16); -if (bit != 0) - { - /* POR xmm1, xmm2/m128 */ - instruction[2] = 0xeb; - instruction[3] = 0xc0 | (0 << 3) | 3; - sljit_emit_op_custom(compiler, instruction, 4); - } +partial_quit[1] = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); +if (common->mode == PCRE2_JIT_COMPLETE) + add_jump(compiler, &common->failed_match, partial_quit[1]); -/* PCMPEQB/W/D xmm1, xmm2/m128 */ -instruction[2] = 0x74 + SSE2_COMPARE_TYPE_INDEX; -instruction[3] = 0xc0 | (0 << 3) | 2; -sljit_emit_op_custom(compiler, instruction, 4); +/* Second part (aligned) */ -if (load_twice) - { - instruction[3] = 0xc0 | (1 << 3) | 3; - sljit_emit_op_custom(compiler, instruction, 4); - } +load_from_mem_sse2(compiler, 0, str_ptr_ind); +fast_forward_char_pair_sse2_compare(compiler, char1, char2, bit, data_ind, cmp1_ind, cmp2_ind, tmp_ind); /* PMOVMSKB reg, xmm */ +instruction[0] = 0x66; +instruction[1] = 0x0f; instruction[2] = 0xd7; instruction[3] = 0xc0 | (tmp1_ind << 3) | 0; sljit_emit_op_custom(compiler, instruction, 4); -if (load_twice) - { - OP1(SLJIT_MOV, RETURN_ADDR, 0, TMP2, 0); - instruction[3] = 0xc0 | (tmp2_ind << 3) | 1; - sljit_emit_op_custom(compiler, instruction, 4); - - OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0); - OP1(SLJIT_MOV, TMP2, 0, RETURN_ADDR, 0); - } - -OP2(SLJIT_ASHR, TMP1, 0, TMP1, 0, TMP2, 0); - /* BSF r32, r/m32 */ instruction[0] = 0x0f; instruction[1] = 0xbc; instruction[2] = 0xc0 | (tmp1_ind << 3) | tmp1_ind; sljit_emit_op_custom(compiler, instruction, 3); +sljit_set_current_flags(compiler, SLJIT_SET_Z); -nomatch = JUMP(SLJIT_ZERO); +JUMPTO(SLJIT_ZERO, start); -OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP2, 0); +JUMPHERE(quit); OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0); -quit[1] = JUMP(SLJIT_JUMP); -JUMPHERE(nomatch); +if (common->mode != PCRE2_JIT_COMPLETE) + { + JUMPHERE(partial_quit[0]); + JUMPHERE(partial_quit[1]); + OP2(SLJIT_SUB | SLJIT_SET_GREATER, SLJIT_UNUSED, 0, STR_PTR, 0, STR_END, 0); + CMOV(SLJIT_GREATER, STR_PTR, STR_END, 0); + } +else + add_jump(compiler, &common->failed_match, CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0)); -start = LABEL(); -OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, 16); -quit[2] = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); +#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32 +if (common->utf && offset > 0) + { + SLJIT_ASSERT(common->mode == PCRE2_JIT_COMPLETE); -/* Second part (aligned) */ + OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-offset)); -instruction[0] = 0x66; -instruction[1] = 0x0f; + quit = jump_if_utf_char_start(compiler, TMP1); -/* MOVDQA xmm1, xmm2/m128 */ -#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) + OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); + add_jump(compiler, &common->failed_match, CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0)); + OP1(SLJIT_MOV, TMP2, 0, STR_PTR, 0); + JUMPTO(SLJIT_JUMP, restart); -if (str_ptr_ind < 8) + JUMPHERE(quit); + } +#endif +} + +#ifndef _WIN64 + +static SLJIT_INLINE sljit_u32 max_fast_forward_char_pair_sse2_offset(void) +{ +#if PCRE2_CODE_UNIT_WIDTH == 8 +return 15; +#elif PCRE2_CODE_UNIT_WIDTH == 16 +return 7; +#elif PCRE2_CODE_UNIT_WIDTH == 32 +return 3; +#else +#error "Unsupported unit width" +#endif +} + +static void fast_forward_char_pair_sse2(compiler_common *common, sljit_s32 offs1, + PCRE2_UCHAR char1a, PCRE2_UCHAR char1b, sljit_s32 offs2, PCRE2_UCHAR char2a, PCRE2_UCHAR char2b) +{ +DEFINE_COMPILER; +sljit_u32 bit1 = 0; +sljit_u32 bit2 = 0; +sljit_u32 diff = IN_UCHARS(offs1 - offs2); +sljit_s32 tmp1_ind = sljit_get_register_index(TMP1); +sljit_s32 tmp2_ind = sljit_get_register_index(TMP2); +sljit_s32 str_ptr_ind = sljit_get_register_index(STR_PTR); +sljit_s32 data1_ind = 0; +sljit_s32 data2_ind = 1; +sljit_s32 tmp_ind = 2; +sljit_s32 cmp1a_ind = 3; +sljit_s32 cmp1b_ind = 4; +sljit_s32 cmp2a_ind = 5; +sljit_s32 cmp2b_ind = 6; +struct sljit_label *start; +#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32 +struct sljit_label *restart; +#endif +struct sljit_jump *jump[2]; + +sljit_u8 instruction[8]; + +SLJIT_ASSERT(common->mode == PCRE2_JIT_COMPLETE && offs1 > offs2); +SLJIT_ASSERT(diff <= IN_UCHARS(max_fast_forward_char_pair_sse2_offset())); +SLJIT_ASSERT(tmp1_ind < 8 && tmp2_ind == 1); + +/* Initialize. */ +if (common->match_end_ptr != 0) { - instruction[2] = 0x6f; - instruction[3] = (0 << 3) | str_ptr_ind; - sljit_emit_op_custom(compiler, instruction, 4); + OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->match_end_ptr); + OP1(SLJIT_MOV, TMP3, 0, STR_END, 0); + OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, IN_UCHARS(offs1 + 1)); + + OP2(SLJIT_SUB | SLJIT_SET_LESS, SLJIT_UNUSED, 0, TMP1, 0, STR_END, 0); + CMOV(SLJIT_LESS, STR_END, TMP1, 0); + } + +OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(offs1)); +add_jump(compiler, &common->failed_match, CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0)); - if (load_twice) +/* MOVD xmm, r/m32 */ +instruction[0] = 0x66; +instruction[1] = 0x0f; +instruction[2] = 0x6e; + +if (char1a == char1b) + OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, character_to_int32(char1a)); +else + { + bit1 = char1a ^ char1b; + if (is_powerof2(bit1)) { - instruction[3] = (1 << 3) | str_ptr_ind; - sljit_emit_op_custom(compiler, instruction, 4); + OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, character_to_int32(char1a | bit1)); + OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, character_to_int32(bit1)); + } + else + { + bit1 = 0; + OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, character_to_int32(char1a)); + OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, character_to_int32(char1b)); } } -else + +instruction[3] = 0xc0 | (cmp1a_ind << 3) | tmp1_ind; +sljit_emit_op_custom(compiler, instruction, 4); + +if (char1a != char1b) { - instruction[1] = 0x41; - instruction[2] = 0x0f; - instruction[3] = 0x6f; - instruction[4] = (0 << 3) | (str_ptr_ind & 0x7); - sljit_emit_op_custom(compiler, instruction, 5); + instruction[3] = 0xc0 | (cmp1b_ind << 3) | tmp2_ind; + sljit_emit_op_custom(compiler, instruction, 4); + } - if (load_twice) +if (char2a == char2b) + OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, character_to_int32(char2a)); +else + { + bit2 = char2a ^ char2b; + if (is_powerof2(bit2)) { - instruction[4] = (1 << 3) | str_ptr_ind; - sljit_emit_op_custom(compiler, instruction, 5); + OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, character_to_int32(char2a | bit2)); + OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, character_to_int32(bit2)); + } + else + { + bit2 = 0; + OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, character_to_int32(char2a)); + OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, character_to_int32(char2b)); } - instruction[1] = 0x0f; } -#else - -instruction[2] = 0x6f; -instruction[3] = (0 << 3) | str_ptr_ind; +instruction[3] = 0xc0 | (cmp2a_ind << 3) | tmp1_ind; sljit_emit_op_custom(compiler, instruction, 4); -if (load_twice) +if (char2a != char2b) { - instruction[3] = (1 << 3) | str_ptr_ind; + instruction[3] = 0xc0 | (cmp2b_ind << 3) | tmp2_ind; sljit_emit_op_custom(compiler, instruction, 4); } -#endif +/* PSHUFD xmm1, xmm2/m128, imm8 */ +/* instruction[0] = 0x66; */ +/* instruction[1] = 0x0f; */ +instruction[2] = 0x70; +instruction[4] = 0; -if (bit != 0) +instruction[3] = 0xc0 | (cmp1a_ind << 3) | cmp1a_ind; +sljit_emit_op_custom(compiler, instruction, 5); + +if (char1a != char1b) { - /* POR xmm1, xmm2/m128 */ - instruction[2] = 0xeb; - instruction[3] = 0xc0 | (0 << 3) | 3; - sljit_emit_op_custom(compiler, instruction, 4); + instruction[3] = 0xc0 | (cmp1b_ind << 3) | cmp1b_ind; + sljit_emit_op_custom(compiler, instruction, 5); } -/* PCMPEQB/W/D xmm1, xmm2/m128 */ -instruction[2] = 0x74 + SSE2_COMPARE_TYPE_INDEX; -instruction[3] = 0xc0 | (0 << 3) | 2; -sljit_emit_op_custom(compiler, instruction, 4); +instruction[3] = 0xc0 | (cmp2a_ind << 3) | cmp2a_ind; +sljit_emit_op_custom(compiler, instruction, 5); -if (load_twice) +if (char2a != char2b) { - instruction[3] = 0xc0 | (1 << 3) | 3; - sljit_emit_op_custom(compiler, instruction, 4); + instruction[3] = 0xc0 | (cmp2b_ind << 3) | cmp2b_ind; + sljit_emit_op_custom(compiler, instruction, 5); } +#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32 +restart = LABEL(); +#endif + +OP2(SLJIT_SUB, TMP1, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(offs1 - offs2)); +OP1(SLJIT_MOV, TMP2, 0, STR_PTR, 0); +OP2(SLJIT_AND, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, ~0xf); +OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, ~0xf); + +load_from_mem_sse2(compiler, data1_ind, str_ptr_ind); + +jump[0] = CMP(SLJIT_EQUAL, STR_PTR, 0, TMP1, 0); + +load_from_mem_sse2(compiler, data2_ind, tmp1_ind); + +/* MOVDQA xmm1, xmm2/m128 */ +/* instruction[0] = 0x66; */ +/* instruction[1] = 0x0f; */ +instruction[2] = 0x6f; +instruction[3] = 0xc0 | (tmp_ind << 3) | data1_ind; +sljit_emit_op_custom(compiler, instruction, 4); + +/* PSLLDQ xmm1, xmm2/m128, imm8 */ +/* instruction[0] = 0x66; */ +/* instruction[1] = 0x0f; */ +instruction[2] = 0x73; +instruction[3] = 0xc0 | (7 << 3) | tmp_ind; +instruction[4] = diff; +sljit_emit_op_custom(compiler, instruction, 5); + +/* PSRLDQ xmm1, xmm2/m128, imm8 */ +/* instruction[0] = 0x66; */ +/* instruction[1] = 0x0f; */ +/* instruction[2] = 0x73; */ +instruction[3] = 0xc0 | (3 << 3) | data2_ind; +instruction[4] = 16 - diff; +sljit_emit_op_custom(compiler, instruction, 5); + +/* POR xmm1, xmm2/m128 */ +/* instruction[0] = 0x66; */ +/* instruction[1] = 0x0f; */ +instruction[2] = 0xeb; +instruction[3] = 0xc0 | (data2_ind << 3) | tmp_ind; +sljit_emit_op_custom(compiler, instruction, 4); + +jump[1] = JUMP(SLJIT_JUMP); + +JUMPHERE(jump[0]); + +/* MOVDQA xmm1, xmm2/m128 */ +/* instruction[0] = 0x66; */ +/* instruction[1] = 0x0f; */ +instruction[2] = 0x6f; +instruction[3] = 0xc0 | (data2_ind << 3) | data1_ind; +sljit_emit_op_custom(compiler, instruction, 4); + +/* PSLLDQ xmm1, xmm2/m128, imm8 */ +/* instruction[0] = 0x66; */ +/* instruction[1] = 0x0f; */ +instruction[2] = 0x73; +instruction[3] = 0xc0 | (7 << 3) | data2_ind; +instruction[4] = diff; +sljit_emit_op_custom(compiler, instruction, 5); + +JUMPHERE(jump[1]); + +OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0xf); + +fast_forward_char_pair_sse2_compare(compiler, char2a, char2b, bit2, data2_ind, cmp2a_ind, cmp2b_ind, tmp_ind); +fast_forward_char_pair_sse2_compare(compiler, char1a, char1b, bit1, data1_ind, cmp1a_ind, cmp1b_ind, tmp_ind); + +/* PAND xmm1, xmm2/m128 */ +/* instruction[0] = 0x66; */ +/* instruction[1] = 0x0f; */ +instruction[2] = 0xdb; +instruction[3] = 0xc0 | (data1_ind << 3) | data2_ind; +sljit_emit_op_custom(compiler, instruction, 4); + /* PMOVMSKB reg, xmm */ +/* instruction[0] = 0x66; */ +/* instruction[1] = 0x0f; */ instruction[2] = 0xd7; instruction[3] = 0xc0 | (tmp1_ind << 3) | 0; sljit_emit_op_custom(compiler, instruction, 4); -if (load_twice) - { - instruction[3] = 0xc0 | (tmp2_ind << 3) | 1; - sljit_emit_op_custom(compiler, instruction, 4); +/* Ignore matches before the first STR_PTR. */ +OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP2, 0); +OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, TMP2, 0); - OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0); - } +/* BSF r32, r/m32 */ +instruction[0] = 0x0f; +instruction[1] = 0xbc; +instruction[2] = 0xc0 | (tmp1_ind << 3) | tmp1_ind; +sljit_emit_op_custom(compiler, instruction, 3); +sljit_set_current_flags(compiler, SLJIT_SET_Z); + +jump[0] = JUMP(SLJIT_NOT_ZERO); + +OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP2, 0); + +/* Main loop. */ +instruction[0] = 0x66; +instruction[1] = 0x0f; + +start = LABEL(); + +load_from_mem_sse2(compiler, data2_ind, str_ptr_ind); + +OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, 16); +add_jump(compiler, &common->failed_match, CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0)); + +load_from_mem_sse2(compiler, data1_ind, str_ptr_ind); + +/* PSRLDQ xmm1, xmm2/m128, imm8 */ +/* instruction[0] = 0x66; */ +/* instruction[1] = 0x0f; */ +instruction[2] = 0x73; +instruction[3] = 0xc0 | (3 << 3) | data2_ind; +instruction[4] = 16 - diff; +sljit_emit_op_custom(compiler, instruction, 5); + +/* MOVDQA xmm1, xmm2/m128 */ +/* instruction[0] = 0x66; */ +/* instruction[1] = 0x0f; */ +instruction[2] = 0x6f; +instruction[3] = 0xc0 | (tmp_ind << 3) | data1_ind; +sljit_emit_op_custom(compiler, instruction, 4); + +/* PSLLDQ xmm1, xmm2/m128, imm8 */ +/* instruction[0] = 0x66; */ +/* instruction[1] = 0x0f; */ +instruction[2] = 0x73; +instruction[3] = 0xc0 | (7 << 3) | tmp_ind; +instruction[4] = diff; +sljit_emit_op_custom(compiler, instruction, 5); + +/* POR xmm1, xmm2/m128 */ +/* instruction[0] = 0x66; */ +/* instruction[1] = 0x0f; */ +instruction[2] = 0xeb; +instruction[3] = 0xc0 | (data2_ind << 3) | tmp_ind; +sljit_emit_op_custom(compiler, instruction, 4); + +fast_forward_char_pair_sse2_compare(compiler, char1a, char1b, bit1, data1_ind, cmp1a_ind, cmp1b_ind, tmp_ind); +fast_forward_char_pair_sse2_compare(compiler, char2a, char2b, bit2, data2_ind, cmp2a_ind, cmp2b_ind, tmp_ind); + +/* PAND xmm1, xmm2/m128 */ +/* instruction[0] = 0x66; */ +/* instruction[1] = 0x0f; */ +instruction[2] = 0xdb; +instruction[3] = 0xc0 | (data1_ind << 3) | data2_ind; +sljit_emit_op_custom(compiler, instruction, 4); + +/* PMOVMSKB reg, xmm */ +/* instruction[0] = 0x66; */ +/* instruction[1] = 0x0f; */ +instruction[2] = 0xd7; +instruction[3] = 0xc0 | (tmp1_ind << 3) | 0; +sljit_emit_op_custom(compiler, instruction, 4); /* BSF r32, r/m32 */ instruction[0] = 0x0f; instruction[1] = 0xbc; instruction[2] = 0xc0 | (tmp1_ind << 3) | tmp1_ind; sljit_emit_op_custom(compiler, instruction, 3); +sljit_set_current_flags(compiler, SLJIT_SET_Z); JUMPTO(SLJIT_ZERO, start); +JUMPHERE(jump[0]); + OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0); -start = LABEL(); -SET_LABEL(quit[0], start); -SET_LABEL(quit[1], start); -SET_LABEL(quit[2], start); +add_jump(compiler, &common->failed_match, CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0)); + +if (common->match_end_ptr != 0) + OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(SLJIT_SP), common->match_end_ptr); + +#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32 +if (common->utf) + { + OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-offs1)); + + jump[0] = jump_if_utf_char_start(compiler, TMP1); + + OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); + CMPTO(SLJIT_LESS, STR_PTR, 0, STR_END, 0, restart); + + add_jump(compiler, &common->failed_match, JUMP(SLJIT_JUMP)); + + JUMPHERE(jump[0]); + } +#endif + +OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(offs1)); + +if (common->match_end_ptr != 0) + OP1(SLJIT_MOV, STR_END, 0, TMP3, 0); +} + +static BOOL check_fast_forward_char_pair_sse2(compiler_common *common, fast_forward_char_data *chars, int max) +{ +sljit_s32 i, j, priority, count; +sljit_u32 priorities; +PCRE2_UCHAR a1, a2, b1, b2; + +priorities = 0; + +count = 0; +for (i = 0; i < max; i++) + { + if (chars[i].last_count > 2) + { + SLJIT_ASSERT(chars[i].last_count <= 7); + + priorities |= (1 << chars[i].last_count); + count++; + } + } + +if (count < 2) + return FALSE; + +for (priority = 7; priority > 2; priority--) + { + if ((priorities & (1 << priority)) == 0) + continue; + + for (i = max - 1; i >= 1; i--) + if (chars[i].last_count >= priority) + { + SLJIT_ASSERT(chars[i].count <= 2 && chars[i].count >= 1); + + a1 = chars[i].chars[0]; + a2 = chars[i].chars[1]; + + j = i - max_fast_forward_char_pair_sse2_offset(); + if (j < 0) + j = 0; + + while (j < i) + { + if (chars[j].last_count >= priority) + { + b1 = chars[j].chars[0]; + b2 = chars[j].chars[1]; + + if (a1 != b1 && a1 != b2 && a2 != b1 && a2 != b2) + { + fast_forward_char_pair_sse2(common, i, a1, a2, j, b1, b2); + return TRUE; + } + } + j++; + } + } + } + +return FALSE; } +#endif + #undef SSE2_COMPARE_TYPE_INDEX #endif @@ -4161,15 +4977,16 @@ static void fast_forward_first_char2(compiler_common *common, PCRE2_UCHAR char1, { DEFINE_COMPILER; struct sljit_label *start; -struct sljit_jump *quit; -struct sljit_jump *found; +struct sljit_jump *match; +struct sljit_jump *partial_quit; PCRE2_UCHAR mask; -#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32 -struct sljit_label *utf_start = NULL; -struct sljit_jump *utf_quit = NULL; -#endif BOOL has_match_end = (common->match_end_ptr != 0); +SLJIT_ASSERT(common->mode == PCRE2_JIT_COMPLETE || offset == 0); + +if (has_match_end) + OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->match_end_ptr); + if (offset > 0) OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(offset)); @@ -4177,76 +4994,21 @@ if (has_match_end) { OP1(SLJIT_MOV, TMP3, 0, STR_END, 0); - OP2(SLJIT_ADD, STR_END, 0, SLJIT_MEM1(SLJIT_SP), common->match_end_ptr, SLJIT_IMM, IN_UCHARS(offset + 1)); -#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86) - if (sljit_x86_is_cmov_available()) - { - OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, STR_END, 0, TMP3, 0); - sljit_x86_emit_cmov(compiler, SLJIT_GREATER, STR_END, TMP3, 0); - } -#endif - { - quit = CMP(SLJIT_LESS_EQUAL, STR_END, 0, TMP3, 0); - OP1(SLJIT_MOV, STR_END, 0, TMP3, 0); - JUMPHERE(quit); - } + OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, IN_UCHARS(offset + 1)); + OP2(SLJIT_SUB | SLJIT_SET_GREATER, SLJIT_UNUSED, 0, STR_END, 0, TMP1, 0); + CMOV(SLJIT_GREATER, STR_END, TMP1, 0); } -#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32 -if (common->utf && offset > 0) - utf_start = LABEL(); -#endif - -#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86) +#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86) && !(defined SUPPORT_VALGRIND) /* SSE2 accelerated first character search. */ -if (sljit_x86_is_sse2_available()) +if (sljit_has_cpu_feature(SLJIT_HAS_SSE2)) { - fast_forward_first_char2_sse2(common, char1, char2); + fast_forward_first_char2_sse2(common, char1, char2, offset); - SLJIT_ASSERT(common->mode == PCRE2_JIT_COMPLETE || offset == 0); - if (common->mode == PCRE2_JIT_COMPLETE) - { - /* In complete mode, we don't need to run a match when STR_PTR == STR_END. */ - SLJIT_ASSERT(common->forced_quit_label == NULL); - OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE2_ERROR_NOMATCH); - add_jump(compiler, &common->forced_quit, CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0)); - -#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32 - if (common->utf && offset > 0) - { - SLJIT_ASSERT(common->mode == PCRE2_JIT_COMPLETE); - - OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-offset)); - OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); -#if PCRE2_CODE_UNIT_WIDTH == 8 - OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xc0); - CMPTO(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, 0x80, utf_start); -#elif PCRE2_CODE_UNIT_WIDTH == 16 - OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xfc00); - CMPTO(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, 0xdc00, utf_start); -#else -#error "Unknown code width" -#endif - OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); - } -#endif - - if (offset > 0) - OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(offset)); - } - else if (sljit_x86_is_cmov_available()) - { - OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, STR_PTR, 0, STR_END, 0); - sljit_x86_emit_cmov(compiler, SLJIT_GREATER_EQUAL, STR_PTR, has_match_end ? SLJIT_MEM1(SLJIT_SP) : STR_END, has_match_end ? common->match_end_ptr : 0); - } - else - { - quit = CMP(SLJIT_LESS, STR_PTR, 0, STR_END, 0); - OP1(SLJIT_MOV, STR_PTR, 0, has_match_end ? SLJIT_MEM1(SLJIT_SP) : STR_END, has_match_end ? common->match_end_ptr : 0); - JUMPHERE(quit); - } + if (offset > 0) + OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(offset)); if (has_match_end) OP1(SLJIT_MOV, STR_END, 0, TMP3, 0); @@ -4255,85 +5017,56 @@ if (sljit_x86_is_sse2_available()) #endif -quit = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); - start = LABEL(); + +partial_quit = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); +if (common->mode == PCRE2_JIT_COMPLETE) + add_jump(compiler, &common->failed_match, partial_quit); + OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0); +OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); if (char1 == char2) - found = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, char1); + CMPTO(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, char1, start); else { mask = char1 ^ char2; if (is_powerof2(mask)) { OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, mask); - found = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, char1 | mask); + CMPTO(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, char1 | mask, start); } else { - OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, char1); - OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_EQUAL); - OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, char2); - OP_FLAGS(SLJIT_OR | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_EQUAL); - found = JUMP(SLJIT_NOT_ZERO); + match = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, char1); + CMPTO(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, char2, start); + JUMPHERE(match); } } -OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); -CMPTO(SLJIT_LESS, STR_PTR, 0, STR_END, 0, start); - -#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32 -if (common->utf && offset > 0) - utf_quit = JUMP(SLJIT_JUMP); -#endif - -JUMPHERE(found); - #if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32 if (common->utf && offset > 0) { - OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-offset)); - OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); -#if PCRE2_CODE_UNIT_WIDTH == 8 - OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xc0); - CMPTO(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, 0x80, utf_start); -#elif PCRE2_CODE_UNIT_WIDTH == 16 - OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xfc00); - CMPTO(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, 0xdc00, utf_start); -#else -#error "Unknown code width" -#endif - OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); - JUMPHERE(utf_quit); + OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-(offset + 1))); + jumpto_if_not_utf_char_start(compiler, TMP1, start); } #endif -JUMPHERE(quit); +OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(offset + 1)); + +if (common->mode != PCRE2_JIT_COMPLETE) + JUMPHERE(partial_quit); if (has_match_end) - { - quit = CMP(SLJIT_LESS, STR_PTR, 0, STR_END, 0); - OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), common->match_end_ptr); - if (offset > 0) - OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(offset)); - JUMPHERE(quit); OP1(SLJIT_MOV, STR_END, 0, TMP3, 0); - } - -if (offset > 0) - OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(offset)); } static SLJIT_INLINE BOOL fast_forward_first_n_chars(compiler_common *common) { DEFINE_COMPILER; struct sljit_label *start; -struct sljit_jump *quit; struct sljit_jump *match; -/* bytes[0] represent the number of characters between 0 -and MAX_N_BYTES - 1, 255 represents any character. */ -PCRE2_UCHAR chars[MAX_N_CHARS * MAX_DIFF_CHARS]; +fast_forward_char_data chars[MAX_N_CHARS]; sljit_s32 offset; PCRE2_UCHAR mask; PCRE2_UCHAR *char_set, *char_set_end; @@ -4344,7 +5077,10 @@ BOOL in_range; sljit_u32 rec_count; for (i = 0; i < MAX_N_CHARS; i++) - chars[i * MAX_DIFF_CHARS] = 0; + { + chars[i].count = 0; + chars[i].last_count = 0; + } rec_count = 10000; max = scan_prefix(common, common->start, chars, MAX_N_CHARS, &rec_count); @@ -4352,21 +5088,50 @@ max = scan_prefix(common, common->start, chars, MAX_N_CHARS, &rec_count); if (max < 1) return FALSE; +/* Convert last_count to priority. */ +for (i = 0; i < max; i++) + { + SLJIT_ASSERT(chars[i].count > 0 && chars[i].last_count <= chars[i].count); + + if (chars[i].count == 1) + { + chars[i].last_count = (chars[i].last_count == 1) ? 7 : 5; + /* Simplifies algorithms later. */ + chars[i].chars[1] = chars[i].chars[0]; + } + else if (chars[i].count == 2) + { + SLJIT_ASSERT(chars[i].chars[0] != chars[i].chars[1]); + + if (is_powerof2(chars[i].chars[0] ^ chars[i].chars[1])) + chars[i].last_count = (chars[i].last_count == 2) ? 6 : 4; + else + chars[i].last_count = (chars[i].last_count == 2) ? 3 : 2; + } + else + chars[i].last_count = (chars[i].count == 255) ? 0 : 1; + } + +#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86) && !(defined SUPPORT_VALGRIND) && !(defined _WIN64) +if (check_fast_forward_char_pair_sse2(common, chars, max)) + return TRUE; +#endif + in_range = FALSE; /* Prevent compiler "uninitialized" warning */ from = 0; range_len = 4 /* minimum length */ - 1; for (i = 0; i <= max; i++) { - if (in_range && (i - from) > range_len && (chars[(i - 1) * MAX_DIFF_CHARS] < 255)) + if (in_range && (i - from) > range_len && (chars[i - 1].count < 255)) { range_len = i - from; range_right = i - 1; } - if (i < max && chars[i * MAX_DIFF_CHARS] < 255) + if (i < max && chars[i].count < 255) { - SLJIT_ASSERT(chars[i * MAX_DIFF_CHARS] > 0); + SLJIT_ASSERT(chars[i].count > 0); if (!in_range) { in_range = TRUE; @@ -4386,16 +5151,17 @@ if (range_right >= 0) for (i = 0; i < range_len; i++) { - char_set = chars + ((range_right - i) * MAX_DIFF_CHARS); - SLJIT_ASSERT(char_set[0] > 0 && char_set[0] < 255); - char_set_end = char_set + char_set[0]; - char_set++; - while (char_set <= char_set_end) + SLJIT_ASSERT(chars[range_right - i].count > 0 && chars[range_right - i].count < 255); + + char_set = chars[range_right - i].chars; + char_set_end = char_set + chars[range_right - i].count; + do { if (update_table[(*char_set) & 0xff] > IN_UCHARS(i)) update_table[(*char_set) & 0xff] = IN_UCHARS(i); char_set++; } + while (char_set < char_set_end); } } @@ -4403,54 +5169,38 @@ offset = -1; /* Scan forward. */ for (i = 0; i < max; i++) { + if (range_right == i) + continue; + if (offset == -1) { - if (chars[i * MAX_DIFF_CHARS] <= 2) + if (chars[i].last_count >= 2) offset = i; } - else if (chars[offset * MAX_DIFF_CHARS] == 2 && chars[i * MAX_DIFF_CHARS] <= 2) - { - if (chars[i * MAX_DIFF_CHARS] == 1) - offset = i; - else - { - mask = chars[offset * MAX_DIFF_CHARS + 1] ^ chars[offset * MAX_DIFF_CHARS + 2]; - if (!is_powerof2(mask)) - { - mask = chars[i * MAX_DIFF_CHARS + 1] ^ chars[i * MAX_DIFF_CHARS + 2]; - if (is_powerof2(mask)) - offset = i; - } - } - } + else if (chars[offset].last_count < chars[i].last_count) + offset = i; } +SLJIT_ASSERT(offset == -1 || (chars[offset].count >= 1 && chars[offset].count <= 2)); + if (range_right < 0) { if (offset < 0) return FALSE; - SLJIT_ASSERT(chars[offset * MAX_DIFF_CHARS] >= 1 && chars[offset * MAX_DIFF_CHARS] <= 2); /* Works regardless the value is 1 or 2. */ - mask = chars[offset * MAX_DIFF_CHARS + chars[offset * MAX_DIFF_CHARS]]; - fast_forward_first_char2(common, chars[offset * MAX_DIFF_CHARS + 1], mask, offset); + fast_forward_first_char2(common, chars[offset].chars[0], chars[offset].chars[1], offset); return TRUE; } -if (range_right == offset) - offset = -1; +SLJIT_ASSERT(range_right != offset); -SLJIT_ASSERT(offset == -1 || (chars[offset * MAX_DIFF_CHARS] >= 1 && chars[offset * MAX_DIFF_CHARS] <= 2)); - -max -= 1; -SLJIT_ASSERT(max > 0); if (common->match_end_ptr != 0) { OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->match_end_ptr); OP1(SLJIT_MOV, TMP3, 0, STR_END, 0); OP2(SLJIT_SUB, STR_END, 0, STR_END, 0, SLJIT_IMM, IN_UCHARS(max)); - quit = CMP(SLJIT_LESS_EQUAL, STR_END, 0, TMP1, 0); - OP1(SLJIT_MOV, STR_END, 0, TMP1, 0); - JUMPHERE(quit); + OP2(SLJIT_SUB | SLJIT_SET_GREATER, SLJIT_UNUSED, 0, STR_END, 0, TMP1, 0); + CMOV(SLJIT_GREATER, STR_END, TMP1, 0); } else OP2(SLJIT_SUB, STR_END, 0, STR_END, 0, SLJIT_IMM, IN_UCHARS(max)); @@ -4462,7 +5212,7 @@ OP1(SLJIT_MOV, RETURN_ADDR, 0, SLJIT_IMM, (sljit_sw)update_table); #endif start = LABEL(); -quit = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); +add_jump(compiler, &common->failed_match, CMP(SLJIT_GREATER, STR_PTR, 0, STR_END, 0)); #if PCRE2_CODE_UNIT_WIDTH == 8 || (defined SLJIT_LITTLE_ENDIAN && SLJIT_LITTLE_ENDIAN) OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(range_right)); @@ -4483,20 +5233,20 @@ if (offset >= 0) OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(offset)); OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); - if (chars[offset * MAX_DIFF_CHARS] == 1) - CMPTO(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, chars[offset * MAX_DIFF_CHARS + 1], start); + if (chars[offset].count == 1) + CMPTO(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, chars[offset].chars[0], start); else { - mask = chars[offset * MAX_DIFF_CHARS + 1] ^ chars[offset * MAX_DIFF_CHARS + 2]; + mask = chars[offset].chars[0] ^ chars[offset].chars[1]; if (is_powerof2(mask)) { OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, mask); - CMPTO(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, chars[offset * MAX_DIFF_CHARS + 1] | mask, start); + CMPTO(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, chars[offset].chars[0] | mask, start); } else { - match = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, chars[offset * MAX_DIFF_CHARS + 1]); - CMPTO(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, chars[offset * MAX_DIFF_CHARS + 2], start); + match = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, chars[offset].chars[0]); + CMPTO(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, chars[offset].chars[1], start); JUMPHERE(match); } } @@ -4512,15 +5262,9 @@ if (common->utf && offset != 0) } else OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-1)); -#if PCRE2_CODE_UNIT_WIDTH == 8 - OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xc0); - CMPTO(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, 0x80, start); -#elif PCRE2_CODE_UNIT_WIDTH == 16 - OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xfc00); - CMPTO(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, 0xdc00, start); -#else -#error "Unknown code width" -#endif + + jumpto_if_not_utf_char_start(compiler, TMP1, start); + if (offset < 0) OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); } @@ -4529,33 +5273,20 @@ if (common->utf && offset != 0) if (offset >= 0) OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); -JUMPHERE(quit); - if (common->match_end_ptr != 0) - { - if (range_right >= 0) - OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->match_end_ptr); OP1(SLJIT_MOV, STR_END, 0, TMP3, 0); - if (range_right >= 0) - { - quit = CMP(SLJIT_LESS_EQUAL, STR_PTR, 0, TMP1, 0); - OP1(SLJIT_MOV, STR_PTR, 0, TMP1, 0); - JUMPHERE(quit); - } - } else OP2(SLJIT_ADD, STR_END, 0, STR_END, 0, SLJIT_IMM, IN_UCHARS(max)); return TRUE; } -#undef MAX_N_CHARS - -static SLJIT_INLINE void fast_forward_first_char(compiler_common *common, PCRE2_UCHAR first_char, BOOL caseless) +static SLJIT_INLINE void fast_forward_first_char(compiler_common *common) { +PCRE2_UCHAR first_char = (PCRE2_UCHAR)(common->re->first_codeunit); PCRE2_UCHAR oc; oc = first_char; -if (caseless) +if ((common->re->flags & PCRE2_FIRSTCASELESS) != 0) { oc = TABLE_GET(first_char, common->fcc, first_char); #if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 8 @@ -4593,8 +5324,8 @@ if (common->nltype == NLTYPE_FIXED && common->newline > 255) firstchar = CMP(SLJIT_LESS_EQUAL, STR_PTR, 0, TMP2, 0); OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, IN_UCHARS(2)); - OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, STR_PTR, 0, TMP1, 0); - OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_GREATER_EQUAL); + OP2(SLJIT_SUB | SLJIT_SET_GREATER_EQUAL, SLJIT_UNUSED, 0, STR_PTR, 0, TMP1, 0); + OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_GREATER_EQUAL); #if PCRE2_CODE_UNIT_WIDTH == 16 || PCRE2_CODE_UNIT_WIDTH == 32 OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, UCHAR_SHIFT); #endif @@ -4638,8 +5369,8 @@ if (common->nltype == NLTYPE_ANY || common->nltype == NLTYPE_ANYCRLF) JUMPHERE(foundcr); notfoundnl = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0); - OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, CHAR_NL); - OP_FLAGS(SLJIT_MOV, TMP1, 0, SLJIT_UNUSED, 0, SLJIT_EQUAL); + OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, CHAR_NL); + OP_FLAGS(SLJIT_MOV, TMP1, 0, SLJIT_EQUAL); #if PCRE2_CODE_UNIT_WIDTH == 16 || PCRE2_CODE_UNIT_WIDTH == 32 OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, UCHAR_SHIFT); #endif @@ -4654,79 +5385,75 @@ if (common->match_end_ptr != 0) OP1(SLJIT_MOV, STR_END, 0, TMP3, 0); } -static BOOL check_class_ranges(compiler_common *common, const sljit_u8 *bits, BOOL nclass, BOOL invert, jump_list **backtracks); +static BOOL optimize_class(compiler_common *common, const sljit_u8 *bits, BOOL nclass, BOOL invert, jump_list **backtracks); -static SLJIT_INLINE void fast_forward_start_bits(compiler_common *common, const sljit_u8 *start_bits) +static SLJIT_INLINE void fast_forward_start_bits(compiler_common *common) { DEFINE_COMPILER; +const sljit_u8 *start_bits = common->re->start_bitmap; struct sljit_label *start; -struct sljit_jump *quit; -struct sljit_jump *found = NULL; -jump_list *matches = NULL; +struct sljit_jump *partial_quit; #if PCRE2_CODE_UNIT_WIDTH != 8 -struct sljit_jump *jump; +struct sljit_jump *found = NULL; #endif +jump_list *matches = NULL; if (common->match_end_ptr != 0) { + OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->match_end_ptr); OP1(SLJIT_MOV, RETURN_ADDR, 0, STR_END, 0); - OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(SLJIT_SP), common->match_end_ptr); + OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, IN_UCHARS(1)); + OP2(SLJIT_SUB | SLJIT_SET_GREATER, SLJIT_UNUSED, 0, STR_END, 0, TMP1, 0); + CMOV(SLJIT_GREATER, STR_END, TMP1, 0); } start = LABEL(); -quit = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); + +partial_quit = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); +if (common->mode == PCRE2_JIT_COMPLETE) + add_jump(compiler, &common->failed_match, partial_quit); + OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0); -#ifdef SUPPORT_UNICODE -if (common->utf) - OP1(SLJIT_MOV, TMP3, 0, TMP1, 0); -#endif +OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); -if (!check_class_ranges(common, start_bits, (start_bits[31] & 0x80) != 0, TRUE, &matches)) +if (!optimize_class(common, start_bits, (start_bits[31] & 0x80) != 0, FALSE, &matches)) { #if PCRE2_CODE_UNIT_WIDTH != 8 - jump = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 255); - OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 255); - JUMPHERE(jump); + if ((start_bits[31] & 0x80) != 0) + found = CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 255); + else + CMPTO(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 255, start); +#elif defined SUPPORT_UNICODE + if (common->utf && is_char7_bitset(start_bits, FALSE)) + CMPTO(SLJIT_GREATER, TMP1, 0, SLJIT_IMM, 127, start); #endif OP2(SLJIT_AND, TMP2, 0, TMP1, 0, SLJIT_IMM, 0x7); OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, SLJIT_IMM, 3); OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_sw)start_bits); - OP2(SLJIT_SHL, TMP2, 0, SLJIT_IMM, 1, TMP2, 0); - OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, TMP2, 0); - found = JUMP(SLJIT_NOT_ZERO); + if (sljit_get_register_index(TMP3) >= 0) + { + OP2(SLJIT_SHL, TMP3, 0, SLJIT_IMM, 1, TMP2, 0); + OP2(SLJIT_AND | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, TMP3, 0); + } + else + { + OP2(SLJIT_SHL, TMP2, 0, SLJIT_IMM, 1, TMP2, 0); + OP2(SLJIT_AND | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, TMP2, 0); + } + JUMPTO(SLJIT_ZERO, start); } +else + set_jumps(matches, start); -#ifdef SUPPORT_UNICODE -if (common->utf) - OP1(SLJIT_MOV, TMP1, 0, TMP3, 0); -#endif -OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); -#ifdef SUPPORT_UNICODE -#if PCRE2_CODE_UNIT_WIDTH == 8 -if (common->utf) - { - CMPTO(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0xc0, start); - OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_sw)PRIV(utf8_table4) - 0xc0); - OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0); - } -#elif PCRE2_CODE_UNIT_WIDTH == 16 -if (common->utf) - { - CMPTO(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0xd800, start); - OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xfc00); - OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xd800); - OP_FLAGS(SLJIT_MOV, TMP1, 0, SLJIT_UNUSED, 0, SLJIT_EQUAL); - OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 1); - OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0); - } -#endif /* PCRE2_CODE_UNIT_WIDTH == [8|16] */ -#endif /* SUPPORT_UNICODE */ -JUMPTO(SLJIT_JUMP, start); +#if PCRE2_CODE_UNIT_WIDTH != 8 if (found != NULL) JUMPHERE(found); -if (matches != NULL) - set_jumps(matches, LABEL()); -JUMPHERE(quit); +#endif + +OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); + +if (common->mode != PCRE2_JIT_COMPLETE) + JUMPHERE(partial_quit); if (common->match_end_ptr != 0) OP1(SLJIT_MOV, STR_END, 0, RETURN_ADDR, 0); @@ -4802,31 +5529,50 @@ struct sljit_jump *jump; struct sljit_label *mainloop; sljit_emit_fast_enter(compiler, RETURN_ADDR, 0); -OP1(SLJIT_MOV, TMP1, 0, STACK_TOP, 0); -GET_LOCAL_BASE(TMP3, 0, 0); +GET_LOCAL_BASE(TMP1, 0, 0); /* Drop frames until we reach STACK_TOP. */ mainloop = LABEL(); -OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), 0); -OP2(SLJIT_SUB | SLJIT_SET_S, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_IMM, 0); -jump = JUMP(SLJIT_SIG_LESS_EQUAL); - -OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, TMP3, 0); -OP1(SLJIT_MOV, SLJIT_MEM1(TMP2), 0, SLJIT_MEM1(TMP1), sizeof(sljit_sw)); -OP1(SLJIT_MOV, SLJIT_MEM1(TMP2), sizeof(sljit_sw), SLJIT_MEM1(TMP1), 2 * sizeof(sljit_sw)); -OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 3 * sizeof(sljit_sw)); +OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), -sizeof(sljit_sw)); +jump = CMP(SLJIT_SIG_LESS_EQUAL, TMP2, 0, SLJIT_IMM, 0); + +OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, TMP1, 0); +if (sljit_get_register_index (TMP3) < 0) + { + OP1(SLJIT_MOV, SLJIT_MEM1(TMP2), 0, SLJIT_MEM1(STACK_TOP), -(2 * sizeof(sljit_sw))); + OP1(SLJIT_MOV, SLJIT_MEM1(TMP2), sizeof(sljit_sw), SLJIT_MEM1(STACK_TOP), -(3 * sizeof(sljit_sw))); + OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, 3 * sizeof(sljit_sw)); + } +else + { + OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), -(2 * sizeof(sljit_sw))); + OP1(SLJIT_MOV, TMP3, 0, SLJIT_MEM1(STACK_TOP), -(3 * sizeof(sljit_sw))); + OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, 3 * sizeof(sljit_sw)); + OP1(SLJIT_MOV, SLJIT_MEM1(TMP2), 0, TMP1, 0); + GET_LOCAL_BASE(TMP1, 0, 0); + OP1(SLJIT_MOV, SLJIT_MEM1(TMP2), sizeof(sljit_sw), TMP3, 0); + } JUMPTO(SLJIT_JUMP, mainloop); JUMPHERE(jump); -jump = JUMP(SLJIT_SIG_LESS); -/* End of dropping frames. */ +jump = CMP(SLJIT_NOT_ZERO /* SIG_LESS */, TMP2, 0, SLJIT_IMM, 0); +/* End of reverting values. */ sljit_emit_fast_return(compiler, RETURN_ADDR, 0); JUMPHERE(jump); OP1(SLJIT_NEG, TMP2, 0, TMP2, 0); -OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, TMP3, 0); -OP1(SLJIT_MOV, SLJIT_MEM1(TMP2), 0, SLJIT_MEM1(TMP1), sizeof(sljit_sw)); -OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 2 * sizeof(sljit_sw)); +OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, TMP1, 0); +if (sljit_get_register_index (TMP3) < 0) + { + OP1(SLJIT_MOV, SLJIT_MEM1(TMP2), 0, SLJIT_MEM1(STACK_TOP), -(2 * sizeof(sljit_sw))); + OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, 2 * sizeof(sljit_sw)); + } +else + { + OP1(SLJIT_MOV, TMP3, 0, SLJIT_MEM1(STACK_TOP), -(2 * sizeof(sljit_sw))); + OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, 2 * sizeof(sljit_sw)); + OP1(SLJIT_MOV, SLJIT_MEM1(TMP2), 0, TMP3, 0); + } JUMPTO(SLJIT_JUMP, mainloop); } @@ -4859,11 +5605,11 @@ if (common->use_ucp) jump = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_UNDERSCORE); add_jump(compiler, &common->getucd, JUMP(SLJIT_FAST_CALL)); OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ucp_Ll); - OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ucp_Lu - ucp_Ll); - OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_LESS_EQUAL); + OP2(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ucp_Lu - ucp_Ll); + OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_LESS_EQUAL); OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ucp_Nd - ucp_Ll); - OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ucp_No - ucp_Nd); - OP_FLAGS(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_LESS_EQUAL); + OP2(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ucp_No - ucp_Nd); + OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_LESS_EQUAL); JUMPHERE(jump); OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS1, TMP2, 0); } @@ -4903,11 +5649,11 @@ if (common->use_ucp) jump = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_UNDERSCORE); add_jump(compiler, &common->getucd, JUMP(SLJIT_FAST_CALL)); OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ucp_Ll); - OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ucp_Lu - ucp_Ll); - OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_LESS_EQUAL); + OP2(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ucp_Lu - ucp_Ll); + OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_LESS_EQUAL); OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ucp_Nd - ucp_Ll); - OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ucp_No - ucp_Nd); - OP_FLAGS(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_LESS_EQUAL); + OP2(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ucp_No - ucp_Nd); + OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_LESS_EQUAL); JUMPHERE(jump); } else @@ -4935,15 +5681,15 @@ else } set_jumps(skipread_list, LABEL()); -OP2(SLJIT_XOR | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_MEM1(SLJIT_SP), LOCALS1); +OP2(SLJIT_XOR | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_MEM1(SLJIT_SP), LOCALS1); sljit_emit_fast_return(compiler, SLJIT_MEM1(SLJIT_SP), LOCALS0); } -static BOOL check_class_ranges(compiler_common *common, const sljit_u8 *bits, BOOL nclass, BOOL invert, jump_list **backtracks) +static BOOL optimize_class_ranges(compiler_common *common, const sljit_u8 *bits, BOOL nclass, BOOL invert, jump_list **backtracks) { /* May destroy TMP1. */ DEFINE_COMPILER; -int ranges[MAX_RANGE_SIZE]; +int ranges[MAX_CLASS_RANGE_SIZE]; sljit_u8 bit, cbit, all; int i, byte, length = 0; @@ -4961,7 +5707,7 @@ for (i = 0; i < 256; ) cbit = (bits[byte] >> (i & 0x7)) & 0x1; if (cbit != bit) { - if (length >= MAX_RANGE_SIZE) + if (length >= MAX_CLASS_RANGE_SIZE) return FALSE; ranges[length] = i; length++; @@ -4974,7 +5720,7 @@ for (i = 0; i < 256; ) if (((bit == 0) && nclass) || ((bit == 1) && !nclass)) { - if (length >= MAX_RANGE_SIZE) + if (length >= MAX_CLASS_RANGE_SIZE) return FALSE; ranges[length] = 256; length++; @@ -5086,9 +5832,116 @@ switch(length) return TRUE; default: - SLJIT_ASSERT_STOP(); + SLJIT_UNREACHABLE(); + return FALSE; + } +} + +static BOOL optimize_class_chars(compiler_common *common, const sljit_u8 *bits, BOOL nclass, BOOL invert, jump_list **backtracks) +{ +/* May destroy TMP1. */ +DEFINE_COMPILER; +uint16_t char_list[MAX_CLASS_CHARS_SIZE]; +uint8_t byte; +sljit_s32 type; +int i, j, k, len, c; + +if (!sljit_has_cpu_feature(SLJIT_HAS_CMOV)) return FALSE; + +if (invert) + nclass = !nclass; + +len = 0; + +for (i = 0; i < 32; i++) + { + byte = bits[i]; + + if (nclass) + byte = ~byte; + + j = 0; + while (byte != 0) + { + if (byte & 0x1) + { + c = i * 8 + j; + + k = len; + + if ((c & 0x20) != 0) + { + for (k = 0; k < len; k++) + if (char_list[k] == c - 0x20) + { + char_list[k] |= 0x120; + break; + } + } + + if (k == len) + { + if (len >= MAX_CLASS_CHARS_SIZE) + return FALSE; + + char_list[len++] = (uint16_t) c; + } + } + + byte >>= 1; + j++; + } + } + +i = 0; +j = 0; + +if (char_list[0] == 0) + { + i++; + OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0); + OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_ZERO); } +else + OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 0); + +while (i < len) + { + if ((char_list[i] & 0x100) != 0) + j++; + else + { + OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, char_list[i]); + CMOV(SLJIT_ZERO, TMP2, TMP1, 0); + } + i++; + } + +if (j != 0) + { + OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x20); + + for (i = 0; i < len; i++) + if ((char_list[i] & 0x100) != 0) + { + j--; + OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, char_list[i] & 0xff); + CMOV(SLJIT_ZERO, TMP2, TMP1, 0); + } + } + +type = nclass ? SLJIT_NOT_EQUAL : SLJIT_EQUAL; +add_jump(compiler, backtracks, CMP(type, TMP2, 0, SLJIT_IMM, 0)); +return TRUE; +} + +static BOOL optimize_class(compiler_common *common, const sljit_u8 *bits, BOOL nclass, BOOL invert, jump_list **backtracks) +{ +/* May destroy TMP1. */ +if (optimize_class_ranges(common, bits, nclass, invert, backtracks)) + return TRUE; +return optimize_class_chars(common, bits, nclass, invert, backtracks); } static void check_anynewline(compiler_common *common) @@ -5099,22 +5952,22 @@ DEFINE_COMPILER; sljit_emit_fast_enter(compiler, RETURN_ADDR, 0); OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x0a); -OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x0d - 0x0a); -OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_LESS_EQUAL); -OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x85 - 0x0a); +OP2(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x0d - 0x0a); +OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_LESS_EQUAL); +OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x85 - 0x0a); #if defined SUPPORT_UNICODE || PCRE2_CODE_UNIT_WIDTH == 16 || PCRE2_CODE_UNIT_WIDTH == 32 #if PCRE2_CODE_UNIT_WIDTH == 8 if (common->utf) { #endif - OP_FLAGS(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_EQUAL); + OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL); OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x1); - OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x2029 - 0x0a); + OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x2029 - 0x0a); #if PCRE2_CODE_UNIT_WIDTH == 8 } #endif #endif /* SUPPORT_UNICODE || PCRE2_CODE_UNIT_WIDTH == [16|32] */ -OP_FLAGS(SLJIT_OR | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_EQUAL); +OP_FLAGS(SLJIT_OR | SLJIT_SET_Z, TMP2, 0, SLJIT_EQUAL); sljit_emit_fast_return(compiler, RETURN_ADDR, 0); } @@ -5125,34 +5978,34 @@ DEFINE_COMPILER; sljit_emit_fast_enter(compiler, RETURN_ADDR, 0); -OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x09); -OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_EQUAL); -OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x20); -OP_FLAGS(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_EQUAL); -OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xa0); +OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x09); +OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_EQUAL); +OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x20); +OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL); +OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xa0); #if defined SUPPORT_UNICODE || PCRE2_CODE_UNIT_WIDTH == 16 || PCRE2_CODE_UNIT_WIDTH == 32 #if PCRE2_CODE_UNIT_WIDTH == 8 if (common->utf) { #endif - OP_FLAGS(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_EQUAL); - OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x1680); - OP_FLAGS(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_EQUAL); - OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x180e); - OP_FLAGS(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_EQUAL); + OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL); + OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x1680); + OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL); + OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x180e); + OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL); OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x2000); - OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x200A - 0x2000); - OP_FLAGS(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_LESS_EQUAL); - OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x202f - 0x2000); - OP_FLAGS(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_EQUAL); - OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x205f - 0x2000); - OP_FLAGS(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_EQUAL); - OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x3000 - 0x2000); + OP2(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x200A - 0x2000); + OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_LESS_EQUAL); + OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x202f - 0x2000); + OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL); + OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x205f - 0x2000); + OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL); + OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x3000 - 0x2000); #if PCRE2_CODE_UNIT_WIDTH == 8 } #endif #endif /* SUPPORT_UNICODE || PCRE2_CODE_UNIT_WIDTH == [16|32] */ -OP_FLAGS(SLJIT_OR | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_EQUAL); +OP_FLAGS(SLJIT_OR | SLJIT_SET_Z, TMP2, 0, SLJIT_EQUAL); sljit_emit_fast_return(compiler, RETURN_ADDR, 0); } @@ -5165,113 +6018,210 @@ DEFINE_COMPILER; sljit_emit_fast_enter(compiler, RETURN_ADDR, 0); OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x0a); -OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x0d - 0x0a); -OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_LESS_EQUAL); -OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x85 - 0x0a); +OP2(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x0d - 0x0a); +OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_LESS_EQUAL); +OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x85 - 0x0a); #if defined SUPPORT_UNICODE || PCRE2_CODE_UNIT_WIDTH == 16 || PCRE2_CODE_UNIT_WIDTH == 32 #if PCRE2_CODE_UNIT_WIDTH == 8 if (common->utf) { #endif - OP_FLAGS(SLJIT_OR | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_EQUAL); + OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL); OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x1); - OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x2029 - 0x0a); + OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x2029 - 0x0a); #if PCRE2_CODE_UNIT_WIDTH == 8 } #endif #endif /* SUPPORT_UNICODE || PCRE2_CODE_UNIT_WIDTH == [16|32] */ -OP_FLAGS(SLJIT_OR | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_EQUAL); +OP_FLAGS(SLJIT_OR | SLJIT_SET_Z, TMP2, 0, SLJIT_EQUAL); sljit_emit_fast_return(compiler, RETURN_ADDR, 0); } -#define CHAR1 STR_END -#define CHAR2 STACK_TOP - static void do_casefulcmp(compiler_common *common) { DEFINE_COMPILER; struct sljit_jump *jump; struct sljit_label *label; +int char1_reg; +int char2_reg; -sljit_emit_fast_enter(compiler, RETURN_ADDR, 0); +if (sljit_get_register_index(TMP3) < 0) + { + char1_reg = STR_END; + char2_reg = STACK_TOP; + } +else + { + char1_reg = TMP3; + char2_reg = RETURN_ADDR; + } + +sljit_emit_fast_enter(compiler, SLJIT_MEM1(SLJIT_SP), LOCALS0); OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP2, 0); -OP1(SLJIT_MOV, TMP3, 0, CHAR1, 0); -OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS0, CHAR2, 0); -OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, IN_UCHARS(1)); -OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); -label = LABEL(); -OP1(MOVU_UCHAR, CHAR1, 0, SLJIT_MEM1(TMP1), IN_UCHARS(1)); -OP1(MOVU_UCHAR, CHAR2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1)); -jump = CMP(SLJIT_NOT_EQUAL, CHAR1, 0, CHAR2, 0); -OP2(SLJIT_SUB | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_IMM, IN_UCHARS(1)); -JUMPTO(SLJIT_NOT_ZERO, label); +if (char1_reg == STR_END) + { + OP1(SLJIT_MOV, TMP3, 0, char1_reg, 0); + OP1(SLJIT_MOV, RETURN_ADDR, 0, char2_reg, 0); + } -JUMPHERE(jump); -OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); -OP1(SLJIT_MOV, CHAR1, 0, TMP3, 0); -OP1(SLJIT_MOV, CHAR2, 0, SLJIT_MEM1(SLJIT_SP), LOCALS0); -sljit_emit_fast_return(compiler, RETURN_ADDR, 0); -} +if (sljit_emit_mem(compiler, MOV_UCHAR | SLJIT_MEM_SUPP | SLJIT_MEM_POST, char1_reg, SLJIT_MEM1(TMP1), IN_UCHARS(1)) == SLJIT_SUCCESS) + { + label = LABEL(); + sljit_emit_mem(compiler, MOV_UCHAR | SLJIT_MEM_POST, char1_reg, SLJIT_MEM1(TMP1), IN_UCHARS(1)); + sljit_emit_mem(compiler, MOV_UCHAR | SLJIT_MEM_POST, char2_reg, SLJIT_MEM1(STR_PTR), IN_UCHARS(1)); + jump = CMP(SLJIT_NOT_EQUAL, char1_reg, 0, char2_reg, 0); + OP2(SLJIT_SUB | SLJIT_SET_Z, TMP2, 0, TMP2, 0, SLJIT_IMM, IN_UCHARS(1)); + JUMPTO(SLJIT_NOT_ZERO, label); -#define LCC_TABLE STACK_LIMIT + JUMPHERE(jump); + OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), LOCALS0); + } +else if (sljit_emit_mem(compiler, MOV_UCHAR | SLJIT_MEM_SUPP | SLJIT_MEM_PRE, char1_reg, SLJIT_MEM1(TMP1), IN_UCHARS(1)) == SLJIT_SUCCESS) + { + OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, IN_UCHARS(1)); + OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); + + label = LABEL(); + sljit_emit_mem(compiler, MOV_UCHAR | SLJIT_MEM_PRE, char1_reg, SLJIT_MEM1(TMP1), IN_UCHARS(1)); + sljit_emit_mem(compiler, MOV_UCHAR | SLJIT_MEM_PRE, char2_reg, SLJIT_MEM1(STR_PTR), IN_UCHARS(1)); + jump = CMP(SLJIT_NOT_EQUAL, char1_reg, 0, char2_reg, 0); + OP2(SLJIT_SUB | SLJIT_SET_Z, TMP2, 0, TMP2, 0, SLJIT_IMM, IN_UCHARS(1)); + JUMPTO(SLJIT_NOT_ZERO, label); + + JUMPHERE(jump); + OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), LOCALS0); + OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); + } +else + { + label = LABEL(); + OP1(MOV_UCHAR, char1_reg, 0, SLJIT_MEM1(TMP1), 0); + OP1(MOV_UCHAR, char2_reg, 0, SLJIT_MEM1(STR_PTR), 0); + OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, IN_UCHARS(1)); + OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); + jump = CMP(SLJIT_NOT_EQUAL, char1_reg, 0, char2_reg, 0); + OP2(SLJIT_SUB | SLJIT_SET_Z, TMP2, 0, TMP2, 0, SLJIT_IMM, IN_UCHARS(1)); + JUMPTO(SLJIT_NOT_ZERO, label); + + JUMPHERE(jump); + OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), LOCALS0); + } + +if (char1_reg == STR_END) + { + OP1(SLJIT_MOV, char1_reg, 0, TMP3, 0); + OP1(SLJIT_MOV, char2_reg, 0, RETURN_ADDR, 0); + } + +sljit_emit_fast_return(compiler, TMP1, 0); +} static void do_caselesscmp(compiler_common *common) { DEFINE_COMPILER; struct sljit_jump *jump; struct sljit_label *label; +int char1_reg = STR_END; +int char2_reg; +int lcc_table; +int opt_type = 0; -sljit_emit_fast_enter(compiler, RETURN_ADDR, 0); +if (sljit_get_register_index(TMP3) < 0) + { + char2_reg = STACK_TOP; + lcc_table = STACK_LIMIT; + } +else + { + char2_reg = RETURN_ADDR; + lcc_table = TMP3; + } + +if (sljit_emit_mem(compiler, MOV_UCHAR | SLJIT_MEM_SUPP | SLJIT_MEM_POST, char1_reg, SLJIT_MEM1(TMP1), IN_UCHARS(1)) == SLJIT_SUCCESS) + opt_type = 1; +else if (sljit_emit_mem(compiler, MOV_UCHAR | SLJIT_MEM_SUPP | SLJIT_MEM_PRE, char1_reg, SLJIT_MEM1(TMP1), IN_UCHARS(1)) == SLJIT_SUCCESS) + opt_type = 2; + +sljit_emit_fast_enter(compiler, SLJIT_MEM1(SLJIT_SP), LOCALS0); OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP2, 0); -OP1(SLJIT_MOV, TMP3, 0, LCC_TABLE, 0); -OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS0, CHAR1, 0); -OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS1, CHAR2, 0); -OP1(SLJIT_MOV, LCC_TABLE, 0, SLJIT_IMM, common->lcc); -OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, IN_UCHARS(1)); -OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); +OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS1, char1_reg, 0); + +if (char2_reg == STACK_TOP) + { + OP1(SLJIT_MOV, TMP3, 0, char2_reg, 0); + OP1(SLJIT_MOV, RETURN_ADDR, 0, lcc_table, 0); + } + +OP1(SLJIT_MOV, lcc_table, 0, SLJIT_IMM, common->lcc); + +if (opt_type == 1) + { + label = LABEL(); + sljit_emit_mem(compiler, MOV_UCHAR | SLJIT_MEM_POST, char1_reg, SLJIT_MEM1(TMP1), IN_UCHARS(1)); + sljit_emit_mem(compiler, MOV_UCHAR | SLJIT_MEM_POST, char2_reg, SLJIT_MEM1(STR_PTR), IN_UCHARS(1)); + } +else if (opt_type == 2) + { + OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, IN_UCHARS(1)); + OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); + + label = LABEL(); + sljit_emit_mem(compiler, MOV_UCHAR | SLJIT_MEM_PRE, char1_reg, SLJIT_MEM1(TMP1), IN_UCHARS(1)); + sljit_emit_mem(compiler, MOV_UCHAR | SLJIT_MEM_PRE, char2_reg, SLJIT_MEM1(STR_PTR), IN_UCHARS(1)); + } +else + { + label = LABEL(); + OP1(MOV_UCHAR, char1_reg, 0, SLJIT_MEM1(TMP1), 0); + OP1(MOV_UCHAR, char2_reg, 0, SLJIT_MEM1(STR_PTR), 0); + OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, IN_UCHARS(1)); + } -label = LABEL(); -OP1(MOVU_UCHAR, CHAR1, 0, SLJIT_MEM1(TMP1), IN_UCHARS(1)); -OP1(MOVU_UCHAR, CHAR2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1)); #if PCRE2_CODE_UNIT_WIDTH != 8 -jump = CMP(SLJIT_GREATER, CHAR1, 0, SLJIT_IMM, 255); +jump = CMP(SLJIT_GREATER, char1_reg, 0, SLJIT_IMM, 255); #endif -OP1(SLJIT_MOV_U8, CHAR1, 0, SLJIT_MEM2(LCC_TABLE, CHAR1), 0); +OP1(SLJIT_MOV_U8, char1_reg, 0, SLJIT_MEM2(lcc_table, char1_reg), 0); #if PCRE2_CODE_UNIT_WIDTH != 8 JUMPHERE(jump); -jump = CMP(SLJIT_GREATER, CHAR2, 0, SLJIT_IMM, 255); +jump = CMP(SLJIT_GREATER, char2_reg, 0, SLJIT_IMM, 255); #endif -OP1(SLJIT_MOV_U8, CHAR2, 0, SLJIT_MEM2(LCC_TABLE, CHAR2), 0); +OP1(SLJIT_MOV_U8, char2_reg, 0, SLJIT_MEM2(lcc_table, char2_reg), 0); #if PCRE2_CODE_UNIT_WIDTH != 8 JUMPHERE(jump); #endif -jump = CMP(SLJIT_NOT_EQUAL, CHAR1, 0, CHAR2, 0); -OP2(SLJIT_SUB | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_IMM, IN_UCHARS(1)); + +if (opt_type == 0) + OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); + +jump = CMP(SLJIT_NOT_EQUAL, char1_reg, 0, char2_reg, 0); +OP2(SLJIT_SUB | SLJIT_SET_Z, TMP2, 0, TMP2, 0, SLJIT_IMM, IN_UCHARS(1)); JUMPTO(SLJIT_NOT_ZERO, label); JUMPHERE(jump); -OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); -OP1(SLJIT_MOV, LCC_TABLE, 0, TMP3, 0); -OP1(SLJIT_MOV, CHAR1, 0, SLJIT_MEM1(SLJIT_SP), LOCALS0); -OP1(SLJIT_MOV, CHAR2, 0, SLJIT_MEM1(SLJIT_SP), LOCALS1); -sljit_emit_fast_return(compiler, RETURN_ADDR, 0); -} +OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), LOCALS0); -#undef LCC_TABLE -#undef CHAR1 -#undef CHAR2 +if (opt_type == 2) + OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); + +if (char2_reg == STACK_TOP) + { + OP1(SLJIT_MOV, char2_reg, 0, TMP3, 0); + OP1(SLJIT_MOV, lcc_table, 0, RETURN_ADDR, 0); + } + +OP1(SLJIT_MOV, char1_reg, 0, SLJIT_MEM1(SLJIT_SP), LOCALS1); +sljit_emit_fast_return(compiler, TMP1, 0); +} #if defined SUPPORT_UNICODE -static PCRE2_SPTR SLJIT_CALL do_utf_caselesscmp(PCRE2_SPTR src1, jit_arguments *args, PCRE2_SPTR end1) +static PCRE2_SPTR SLJIT_FUNC do_utf_caselesscmp(PCRE2_SPTR src1, PCRE2_SPTR src2, PCRE2_SPTR end1, PCRE2_SPTR end2) { /* This function would be ineffective to do in JIT level. */ sljit_u32 c1, c2; -PCRE2_SPTR src2 = args->startchar_ptr; -PCRE2_SPTR end2 = args->end; const ucd_record *ur; const sljit_u32 *pp; @@ -5416,7 +6366,7 @@ do #endif default: - SLJIT_ASSERT_STOP(); + SLJIT_UNREACHABLE(); break; } context->ucharptr = 0; @@ -5591,7 +6541,7 @@ while (*cc != XCL_END) break; default: - SLJIT_ASSERT_STOP(); + SLJIT_UNREACHABLE(); break; } cc += 2; @@ -5609,13 +6559,13 @@ if ((cc[-1] & XCL_HASPROP) == 0) if ((cc[-1] & XCL_MAP) != 0) { jump = CMP(SLJIT_GREATER, TMP1, 0, SLJIT_IMM, 255); - if (!check_class_ranges(common, (const sljit_u8 *)cc, (((const sljit_u8 *)cc)[31] & 0x80) != 0, TRUE, &found)) + if (!optimize_class(common, (const sljit_u8 *)cc, (((const sljit_u8 *)cc)[31] & 0x80) != 0, TRUE, &found)) { OP2(SLJIT_AND, TMP2, 0, TMP1, 0, SLJIT_IMM, 0x7); OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, SLJIT_IMM, 3); OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_sw)cc); OP2(SLJIT_SHL, TMP2, 0, SLJIT_IMM, 1, TMP2, 0); - OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, TMP2, 0); + OP2(SLJIT_AND | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, TMP2, 0); add_jump(compiler, &found, JUMP(SLJIT_NOT_ZERO)); } @@ -5636,7 +6586,7 @@ else if ((cc[-1] & XCL_MAP) != 0) #ifdef SUPPORT_UNICODE charsaved = TRUE; #endif - if (!check_class_ranges(common, (const sljit_u8 *)cc, FALSE, TRUE, list)) + if (!optimize_class(common, (const sljit_u8 *)cc, FALSE, TRUE, list)) { #if PCRE2_CODE_UNIT_WIDTH == 8 jump = NULL; @@ -5648,7 +6598,7 @@ else if ((cc[-1] & XCL_MAP) != 0) OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, SLJIT_IMM, 3); OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_sw)cc); OP2(SLJIT_SHL, TMP2, 0, SLJIT_IMM, 1, TMP2, 0); - OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, TMP2, 0); + OP2(SLJIT_AND | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, TMP2, 0); add_jump(compiler, list, JUMP(SLJIT_NOT_ZERO)); #if PCRE2_CODE_UNIT_WIDTH == 8 @@ -5667,6 +6617,15 @@ if (needstype || needsscript) if (needschar && !charsaved) OP1(SLJIT_MOV, RETURN_ADDR, 0, TMP1, 0); +#if PCRE2_CODE_UNIT_WIDTH == 32 + if (!common->utf) + { + jump = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, MAX_UTF_CODE_POINT + 1); + OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, INVALID_UTF_CHAR); + JUMPHERE(jump); + } +#endif + OP2(SLJIT_LSHR, TMP2, 0, TMP1, 0, SLJIT_IMM, UCD_BLOCK_SHIFT); OP1(SLJIT_MOV_U8, TMP2, 0, SLJIT_MEM1(TMP2), (sljit_sw)PRIV(ucd_stage1)); OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, UCD_BLOCK_MASK); @@ -5758,14 +6717,14 @@ while (*cc != XCL_END) if (numberofcmps < 3 && (*cc == XCL_SINGLE || *cc == XCL_RANGE)) { - OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(c - charoffset)); - OP_FLAGS(numberofcmps == 0 ? SLJIT_MOV : SLJIT_OR, TMP2, 0, numberofcmps == 0 ? SLJIT_UNUSED : TMP2, 0, SLJIT_EQUAL); + OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(c - charoffset)); + OP_FLAGS(numberofcmps == 0 ? SLJIT_MOV : SLJIT_OR, TMP2, 0, SLJIT_EQUAL); numberofcmps++; } else if (numberofcmps > 0) { - OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(c - charoffset)); - OP_FLAGS(SLJIT_OR | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_EQUAL); + OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(c - charoffset)); + OP_FLAGS(SLJIT_OR | SLJIT_SET_Z, TMP2, 0, SLJIT_EQUAL); jump = JUMP(SLJIT_NOT_ZERO ^ invertcmp); numberofcmps = 0; } @@ -5784,14 +6743,14 @@ while (*cc != XCL_END) if (numberofcmps < 3 && (*cc == XCL_SINGLE || *cc == XCL_RANGE)) { - OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(c - charoffset)); - OP_FLAGS(numberofcmps == 0 ? SLJIT_MOV : SLJIT_OR, TMP2, 0, numberofcmps == 0 ? SLJIT_UNUSED : TMP2, 0, SLJIT_LESS_EQUAL); + OP2(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(c - charoffset)); + OP_FLAGS(numberofcmps == 0 ? SLJIT_MOV : SLJIT_OR, TMP2, 0, SLJIT_LESS_EQUAL); numberofcmps++; } else if (numberofcmps > 0) { - OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(c - charoffset)); - OP_FLAGS(SLJIT_OR | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_LESS_EQUAL); + OP2(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(c - charoffset)); + OP_FLAGS(SLJIT_OR | SLJIT_SET_Z, TMP2, 0, SLJIT_LESS_EQUAL); jump = JUMP(SLJIT_NOT_ZERO ^ invertcmp); numberofcmps = 0; } @@ -5816,12 +6775,12 @@ while (*cc != XCL_END) break; case PT_LAMP: - OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_Lu - typeoffset); - OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_EQUAL); - OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_Ll - typeoffset); - OP_FLAGS(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_EQUAL); - OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_Lt - typeoffset); - OP_FLAGS(SLJIT_OR | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_EQUAL); + OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_Lu - typeoffset); + OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_EQUAL); + OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_Ll - typeoffset); + OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL); + OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_Lt - typeoffset); + OP_FLAGS(SLJIT_OR | SLJIT_SET_Z, TMP2, 0, SLJIT_EQUAL); jump = JUMP(SLJIT_NOT_ZERO ^ invertcmp); break; @@ -5843,33 +6802,33 @@ while (*cc != XCL_END) case PT_SPACE: case PT_PXSPACE: SET_CHAR_OFFSET(9); - OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xd - 0x9); - OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_LESS_EQUAL); + OP2(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xd - 0x9); + OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_LESS_EQUAL); - OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x85 - 0x9); - OP_FLAGS(SLJIT_OR | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_EQUAL); + OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x85 - 0x9); + OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL); - OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x180e - 0x9); - OP_FLAGS(SLJIT_OR | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_EQUAL); + OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x180e - 0x9); + OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL); SET_TYPE_OFFSET(ucp_Zl); - OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_Zs - ucp_Zl); - OP_FLAGS(SLJIT_OR | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_LESS_EQUAL); + OP2(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_Zs - ucp_Zl); + OP_FLAGS(SLJIT_OR | SLJIT_SET_Z, TMP2, 0, SLJIT_LESS_EQUAL); jump = JUMP(SLJIT_NOT_ZERO ^ invertcmp); break; case PT_WORD: - OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(CHAR_UNDERSCORE - charoffset)); - OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_EQUAL); + OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(CHAR_UNDERSCORE - charoffset)); + OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_EQUAL); /* Fall through. */ case PT_ALNUM: SET_TYPE_OFFSET(ucp_Ll); - OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_Lu - ucp_Ll); - OP_FLAGS((*cc == PT_ALNUM) ? SLJIT_MOV : SLJIT_OR, TMP2, 0, (*cc == PT_ALNUM) ? SLJIT_UNUSED : TMP2, 0, SLJIT_LESS_EQUAL); + OP2(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_Lu - ucp_Ll); + OP_FLAGS((*cc == PT_ALNUM) ? SLJIT_MOV : SLJIT_OR, TMP2, 0, SLJIT_LESS_EQUAL); SET_TYPE_OFFSET(ucp_Nd); - OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_No - ucp_Nd); - OP_FLAGS(SLJIT_OR | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_LESS_EQUAL); + OP2(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_No - ucp_Nd); + OP_FLAGS(SLJIT_OR | SLJIT_SET_Z, TMP2, 0, SLJIT_LESS_EQUAL); jump = JUMP(SLJIT_NOT_ZERO ^ invertcmp); break; @@ -5891,8 +6850,8 @@ while (*cc != XCL_END) OP2(SLJIT_ADD, TMP2, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)charoffset); OP2(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_IMM, other_cases[1] ^ other_cases[0]); } - OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_IMM, other_cases[1]); - OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_EQUAL); + OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_IMM, other_cases[1]); + OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_EQUAL); other_cases += 2; } else if (is_powerof2(other_cases[2] ^ other_cases[1])) @@ -5904,63 +6863,63 @@ while (*cc != XCL_END) OP2(SLJIT_ADD, TMP2, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)charoffset); OP2(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_IMM, other_cases[1] ^ other_cases[0]); } - OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_IMM, other_cases[2]); - OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_EQUAL); + OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_IMM, other_cases[2]); + OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_EQUAL); - OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(other_cases[0] - charoffset)); - OP_FLAGS(SLJIT_OR | ((other_cases[3] == NOTACHAR) ? SLJIT_SET_E : 0), TMP2, 0, TMP2, 0, SLJIT_EQUAL); + OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(other_cases[0] - charoffset)); + OP_FLAGS(SLJIT_OR | ((other_cases[3] == NOTACHAR) ? SLJIT_SET_Z : 0), TMP2, 0, SLJIT_EQUAL); other_cases += 3; } else { - OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(*other_cases++ - charoffset)); - OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_EQUAL); + OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(*other_cases++ - charoffset)); + OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_EQUAL); } while (*other_cases != NOTACHAR) { - OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(*other_cases++ - charoffset)); - OP_FLAGS(SLJIT_OR | ((*other_cases == NOTACHAR) ? SLJIT_SET_E : 0), TMP2, 0, TMP2, 0, SLJIT_EQUAL); + OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(*other_cases++ - charoffset)); + OP_FLAGS(SLJIT_OR | ((*other_cases == NOTACHAR) ? SLJIT_SET_Z : 0), TMP2, 0, SLJIT_EQUAL); } jump = JUMP(SLJIT_NOT_ZERO ^ invertcmp); break; case PT_UCNC: - OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(CHAR_DOLLAR_SIGN - charoffset)); - OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_EQUAL); - OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(CHAR_COMMERCIAL_AT - charoffset)); - OP_FLAGS(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_EQUAL); - OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(CHAR_GRAVE_ACCENT - charoffset)); - OP_FLAGS(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_EQUAL); + OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(CHAR_DOLLAR_SIGN - charoffset)); + OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_EQUAL); + OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(CHAR_COMMERCIAL_AT - charoffset)); + OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL); + OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(CHAR_GRAVE_ACCENT - charoffset)); + OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL); SET_CHAR_OFFSET(0xa0); - OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(0xd7ff - charoffset)); - OP_FLAGS(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_LESS_EQUAL); + OP2(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(0xd7ff - charoffset)); + OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_LESS_EQUAL); SET_CHAR_OFFSET(0); - OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xe000 - 0); - OP_FLAGS(SLJIT_OR | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_GREATER_EQUAL); + OP2(SLJIT_SUB | SLJIT_SET_GREATER_EQUAL, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xe000 - 0); + OP_FLAGS(SLJIT_OR | SLJIT_SET_Z, TMP2, 0, SLJIT_GREATER_EQUAL); jump = JUMP(SLJIT_NOT_ZERO ^ invertcmp); break; case PT_PXGRAPH: /* C and Z groups are the farthest two groups. */ SET_TYPE_OFFSET(ucp_Ll); - OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_So - ucp_Ll); - OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_GREATER); + OP2(SLJIT_SUB | SLJIT_SET_GREATER, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_So - ucp_Ll); + OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_GREATER); jump = CMP(SLJIT_NOT_EQUAL, typereg, 0, SLJIT_IMM, ucp_Cf - ucp_Ll); /* In case of ucp_Cf, we overwrite the result. */ SET_CHAR_OFFSET(0x2066); - OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x2069 - 0x2066); - OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_LESS_EQUAL); + OP2(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x2069 - 0x2066); + OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_LESS_EQUAL); - OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x061c - 0x2066); - OP_FLAGS(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_EQUAL); + OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x061c - 0x2066); + OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL); - OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x180e - 0x2066); - OP_FLAGS(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_EQUAL); + OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x180e - 0x2066); + OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL); JUMPHERE(jump); jump = CMP(SLJIT_ZERO ^ invertcmp, TMP2, 0, SLJIT_IMM, 0); @@ -5969,21 +6928,21 @@ while (*cc != XCL_END) case PT_PXPRINT: /* C and Z groups are the farthest two groups. */ SET_TYPE_OFFSET(ucp_Ll); - OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_So - ucp_Ll); - OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_GREATER); + OP2(SLJIT_SUB | SLJIT_SET_GREATER, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_So - ucp_Ll); + OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_GREATER); - OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_Zs - ucp_Ll); - OP_FLAGS(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_NOT_EQUAL); + OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_Zs - ucp_Ll); + OP_FLAGS(SLJIT_AND, TMP2, 0, SLJIT_NOT_EQUAL); jump = CMP(SLJIT_NOT_EQUAL, typereg, 0, SLJIT_IMM, ucp_Cf - ucp_Ll); /* In case of ucp_Cf, we overwrite the result. */ SET_CHAR_OFFSET(0x2066); - OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x2069 - 0x2066); - OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_LESS_EQUAL); + OP2(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x2069 - 0x2066); + OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_LESS_EQUAL); - OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x061c - 0x2066); - OP_FLAGS(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_EQUAL); + OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x061c - 0x2066); + OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL); JUMPHERE(jump); jump = CMP(SLJIT_ZERO ^ invertcmp, TMP2, 0, SLJIT_IMM, 0); @@ -5991,21 +6950,21 @@ while (*cc != XCL_END) case PT_PXPUNCT: SET_TYPE_OFFSET(ucp_Sc); - OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_So - ucp_Sc); - OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_LESS_EQUAL); + OP2(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_So - ucp_Sc); + OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_LESS_EQUAL); SET_CHAR_OFFSET(0); - OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x7f); - OP_FLAGS(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_LESS_EQUAL); + OP2(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x7f); + OP_FLAGS(SLJIT_AND, TMP2, 0, SLJIT_LESS_EQUAL); SET_TYPE_OFFSET(ucp_Pc); - OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_Ps - ucp_Pc); - OP_FLAGS(SLJIT_OR | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_LESS_EQUAL); + OP2(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_Ps - ucp_Pc); + OP_FLAGS(SLJIT_OR | SLJIT_SET_Z, TMP2, 0, SLJIT_LESS_EQUAL); jump = JUMP(SLJIT_NOT_ZERO ^ invertcmp); break; default: - SLJIT_ASSERT_STOP(); + SLJIT_UNREACHABLE(); break; } cc += 2; @@ -6051,6 +7010,7 @@ switch(type) case OP_NOT_WORD_BOUNDARY: case OP_WORD_BOUNDARY: add_jump(compiler, &common->wordboundary, JUMP(SLJIT_FAST_CALL)); + sljit_set_current_flags(compiler, SLJIT_SET_Z); add_jump(compiler, backtracks, JUMP(type == OP_NOT_WORD_BOUNDARY ? SLJIT_NOT_ZERO : SLJIT_ZERO)); return cc; @@ -6066,10 +7026,10 @@ switch(type) else { jump[1] = CMP(SLJIT_EQUAL, TMP2, 0, STR_END, 0); - OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP2, 0, STR_END, 0); - OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_LESS); - OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff); - OP_FLAGS(SLJIT_OR | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_NOT_EQUAL); + OP2(SLJIT_SUB | SLJIT_SET_LESS, SLJIT_UNUSED, 0, TMP2, 0, STR_END, 0); + OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_LESS); + OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff); + OP_FLAGS(SLJIT_OR | SLJIT_SET_Z, TMP2, 0, SLJIT_NOT_EQUAL); add_jump(compiler, backtracks, JUMP(SLJIT_NOT_EQUAL)); check_partial(common, TRUE); add_jump(compiler, backtracks, JUMP(SLJIT_JUMP)); @@ -6091,9 +7051,9 @@ switch(type) OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0)); jump[1] = CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_CR); OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2)); - OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP2, 0, STR_END, 0); + OP2(SLJIT_SUB | SLJIT_SET_Z | SLJIT_SET_GREATER, SLJIT_UNUSED, 0, TMP2, 0, STR_END, 0); jump[2] = JUMP(SLJIT_GREATER); - add_jump(compiler, backtracks, JUMP(SLJIT_LESS)); + add_jump(compiler, backtracks, JUMP(SLJIT_NOT_EQUAL) /* LESS */); /* Equal. */ OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1)); jump[3] = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_NL); @@ -6112,6 +7072,7 @@ switch(type) read_char_range(common, common->nlmin, common->nlmax, TRUE); add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, STR_PTR, 0, STR_END, 0)); add_jump(compiler, &common->anynewline, JUMP(SLJIT_FAST_CALL)); + sljit_set_current_flags(compiler, SLJIT_SET_Z); add_jump(compiler, backtracks, JUMP(SLJIT_ZERO)); OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), LOCALS1); } @@ -6129,8 +7090,8 @@ switch(type) case OP_DOLL: OP1(SLJIT_MOV, TMP2, 0, ARGUMENTS, 0); - OP2(SLJIT_AND32 | SLJIT_SET_E, SLJIT_UNUSED, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, options), SLJIT_IMM, PCRE2_NOTEOL); - add_jump(compiler, backtracks, JUMP(SLJIT_NOT_ZERO)); + OP2(SLJIT_AND32 | SLJIT_SET_Z, SLJIT_UNUSED, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, options), SLJIT_IMM, PCRE2_NOTEOL); + add_jump(compiler, backtracks, JUMP(SLJIT_NOT_ZERO32)); if (!common->endonly) compile_simple_assertion_matchingpath(common, OP_EODN, cc, backtracks); @@ -6144,8 +7105,8 @@ switch(type) case OP_DOLLM: jump[1] = CMP(SLJIT_LESS, STR_PTR, 0, STR_END, 0); OP1(SLJIT_MOV, TMP2, 0, ARGUMENTS, 0); - OP2(SLJIT_AND32 | SLJIT_SET_E, SLJIT_UNUSED, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, options), SLJIT_IMM, PCRE2_NOTEOL); - add_jump(compiler, backtracks, JUMP(SLJIT_NOT_ZERO)); + OP2(SLJIT_AND32 | SLJIT_SET_Z, SLJIT_UNUSED, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, options), SLJIT_IMM, PCRE2_NOTEOL); + add_jump(compiler, backtracks, JUMP(SLJIT_NOT_ZERO32)); check_partial(common, FALSE); jump[0] = JUMP(SLJIT_JUMP); JUMPHERE(jump[1]); @@ -6182,16 +7143,16 @@ switch(type) OP1(SLJIT_MOV, TMP2, 0, ARGUMENTS, 0); OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, begin)); add_jump(compiler, backtracks, CMP(SLJIT_GREATER, STR_PTR, 0, TMP1, 0)); - OP2(SLJIT_AND32 | SLJIT_SET_E, SLJIT_UNUSED, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, options), SLJIT_IMM, PCRE2_NOTBOL); - add_jump(compiler, backtracks, JUMP(SLJIT_NOT_ZERO)); + OP2(SLJIT_AND32 | SLJIT_SET_Z, SLJIT_UNUSED, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, options), SLJIT_IMM, PCRE2_NOTBOL); + add_jump(compiler, backtracks, JUMP(SLJIT_NOT_ZERO32)); return cc; case OP_CIRCM: OP1(SLJIT_MOV, TMP2, 0, ARGUMENTS, 0); OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, begin)); jump[1] = CMP(SLJIT_GREATER, STR_PTR, 0, TMP1, 0); - OP2(SLJIT_AND32 | SLJIT_SET_E, SLJIT_UNUSED, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, options), SLJIT_IMM, PCRE2_NOTBOL); - add_jump(compiler, backtracks, JUMP(SLJIT_NOT_ZERO)); + OP2(SLJIT_AND32 | SLJIT_SET_Z, SLJIT_UNUSED, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, options), SLJIT_IMM, PCRE2_NOTBOL); + add_jump(compiler, backtracks, JUMP(SLJIT_NOT_ZERO32)); jump[0] = JUMP(SLJIT_JUMP); JUMPHERE(jump[1]); @@ -6229,7 +7190,7 @@ switch(type) label = LABEL(); add_jump(compiler, backtracks, CMP(SLJIT_LESS_EQUAL, STR_PTR, 0, TMP3, 0)); skip_char_back(common); - OP2(SLJIT_SUB | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_IMM, 1); + OP2(SLJIT_SUB | SLJIT_SET_Z, TMP2, 0, TMP2, 0, SLJIT_IMM, 1); JUMPTO(SLJIT_NOT_ZERO, label); } else @@ -6242,10 +7203,126 @@ switch(type) check_start_used_ptr(common); return cc + LINK_SIZE; } -SLJIT_ASSERT_STOP(); +SLJIT_UNREACHABLE(); +return cc; +} + +#ifdef SUPPORT_UNICODE + +#if PCRE2_CODE_UNIT_WIDTH != 32 + +static PCRE2_SPTR SLJIT_FUNC do_extuni_utf(jit_arguments *args, PCRE2_SPTR cc) +{ +PCRE2_SPTR start_subject = args->begin; +PCRE2_SPTR end_subject = args->end; +int lgb, rgb, len, ricount; +PCRE2_SPTR prevcc, bptr; +uint32_t c; + +prevcc = cc; +GETCHARINC(c, cc); +lgb = UCD_GRAPHBREAK(c); + +while (cc < end_subject) + { + len = 1; + GETCHARLEN(c, cc, len); + rgb = UCD_GRAPHBREAK(c); + + if ((PRIV(ucp_gbtable)[lgb] & (1 << rgb)) == 0) break; + + /* Not breaking between Regional Indicators is allowed only if there + are an even number of preceding RIs. */ + + if (lgb == ucp_gbRegionalIndicator && rgb == ucp_gbRegionalIndicator) + { + ricount = 0; + bptr = prevcc; + + /* bptr is pointing to the left-hand character */ + while (bptr > start_subject) + { + bptr--; + BACKCHAR(bptr); + GETCHAR(c, bptr); + + if (UCD_GRAPHBREAK(c) != ucp_gbRegionalIndicator) break; + + ricount++; + } + + if ((ricount & 1) != 0) break; /* Grapheme break required */ + } + + /* If Extend follows E_Base[_GAZ] do not update lgb; this allows + any number of Extend before a following E_Modifier. */ + + if (rgb != ucp_gbExtend || (lgb != ucp_gbE_Base && lgb != ucp_gbE_Base_GAZ)) + lgb = rgb; + + prevcc = cc; + cc += len; + } + return cc; } +#endif + +static PCRE2_SPTR SLJIT_FUNC do_extuni_no_utf(jit_arguments *args, PCRE2_SPTR cc) +{ +PCRE2_SPTR start_subject = args->begin; +PCRE2_SPTR end_subject = args->end; +int lgb, rgb, ricount; +PCRE2_SPTR bptr; +uint32_t c; + +GETCHARINC(c, cc); +lgb = UCD_GRAPHBREAK(c); + +while (cc < end_subject) + { + c = *cc; + rgb = UCD_GRAPHBREAK(c); + + if ((PRIV(ucp_gbtable)[lgb] & (1 << rgb)) == 0) break; + + /* Not breaking between Regional Indicators is allowed only if there + are an even number of preceding RIs. */ + + if (lgb == ucp_gbRegionalIndicator && rgb == ucp_gbRegionalIndicator) + { + ricount = 0; + bptr = cc - 1; + + /* bptr is pointing to the left-hand character */ + while (bptr > start_subject) + { + bptr--; + c = *bptr; + + if (UCD_GRAPHBREAK(c) != ucp_gbRegionalIndicator) break; + + ricount++; + } + + if ((ricount & 1) != 0) break; /* Grapheme break required */ + } + + /* If Extend follows E_Base[_GAZ] do not update lgb; this allows + any number of Extend before a following E_Modifier. */ + + if (rgb != ucp_gbExtend || (lgb != ucp_gbE_Base && lgb != ucp_gbE_Base_GAZ)) + lgb = rgb; + + cc++; + } + +return cc; +} + +#endif + static PCRE2_SPTR compile_char1_matchingpath(compiler_common *common, PCRE2_UCHAR type, PCRE2_SPTR cc, jump_list **backtracks, BOOL check_str_ptr) { DEFINE_COMPILER; @@ -6255,7 +7332,6 @@ compare_context context; struct sljit_jump *jump[3]; jump_list *end_list; #ifdef SUPPORT_UNICODE -struct sljit_label *label; PCRE2_UCHAR propdata[5]; #endif /* SUPPORT_UNICODE */ @@ -6273,7 +7349,7 @@ switch(type) #endif read_char8_type(common, type == OP_NOT_DIGIT); /* Flip the starting bit in the negative case. */ - OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ctype_digit); + OP2(SLJIT_AND | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ctype_digit); add_jump(compiler, backtracks, JUMP(type == OP_DIGIT ? SLJIT_ZERO : SLJIT_NOT_ZERO)); return cc; @@ -6287,7 +7363,7 @@ switch(type) else #endif read_char8_type(common, type == OP_NOT_WHITESPACE); - OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ctype_space); + OP2(SLJIT_AND | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ctype_space); add_jump(compiler, backtracks, JUMP(type == OP_WHITESPACE ? SLJIT_ZERO : SLJIT_NOT_ZERO)); return cc; @@ -6301,7 +7377,7 @@ switch(type) else #endif read_char8_type(common, type == OP_NOT_WORDCHAR); - OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ctype_word); + OP2(SLJIT_AND | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ctype_word); add_jump(compiler, backtracks, JUMP(type == OP_WORDCHAR ? SLJIT_ZERO : SLJIT_NOT_ZERO)); return cc; @@ -6343,8 +7419,8 @@ switch(type) #elif PCRE2_CODE_UNIT_WIDTH == 16 jump[0] = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0xd800); OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xfc00); - OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xd800); - OP_FLAGS(SLJIT_MOV, TMP1, 0, SLJIT_UNUSED, 0, SLJIT_EQUAL); + OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xd800); + OP_FLAGS(SLJIT_MOV, TMP1, 0, SLJIT_EQUAL); OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 1); OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0); #endif @@ -6404,6 +7480,7 @@ switch(type) detect_partial_match(common, backtracks); read_char_range(common, 0x9, 0x3000, type == OP_NOT_HSPACE); add_jump(compiler, &common->hspace, JUMP(SLJIT_FAST_CALL)); + sljit_set_current_flags(compiler, SLJIT_SET_Z); add_jump(compiler, backtracks, JUMP(type == OP_NOT_HSPACE ? SLJIT_NOT_ZERO : SLJIT_ZERO)); return cc; @@ -6413,6 +7490,7 @@ switch(type) detect_partial_match(common, backtracks); read_char_range(common, 0xa, 0x2029, type == OP_NOT_VSPACE); add_jump(compiler, &common->vspace, JUMP(SLJIT_FAST_CALL)); + sljit_set_current_flags(compiler, SLJIT_SET_Z); add_jump(compiler, backtracks, JUMP(type == OP_NOT_VSPACE ? SLJIT_NOT_ZERO : SLJIT_ZERO)); return cc; @@ -6420,35 +7498,22 @@ switch(type) case OP_EXTUNI: if (check_str_ptr) detect_partial_match(common, backtracks); - read_char(common); - add_jump(compiler, &common->getucd, JUMP(SLJIT_FAST_CALL)); - OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, (sljit_sw)PRIV(ucd_records) + SLJIT_OFFSETOF(ucd_record, gbprop)); - /* Optimize register allocation: use a real register. */ - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS0, STACK_TOP, 0); - OP1(SLJIT_MOV_U8, STACK_TOP, 0, SLJIT_MEM2(TMP1, TMP2), 3); - label = LABEL(); - jump[0] = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); - OP1(SLJIT_MOV, TMP3, 0, STR_PTR, 0); - read_char(common); - add_jump(compiler, &common->getucd, JUMP(SLJIT_FAST_CALL)); - OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, (sljit_sw)PRIV(ucd_records) + SLJIT_OFFSETOF(ucd_record, gbprop)); - OP1(SLJIT_MOV_U8, TMP2, 0, SLJIT_MEM2(TMP1, TMP2), 3); + SLJIT_ASSERT(TMP1 == SLJIT_R0 && STR_PTR == SLJIT_R1); + OP1(SLJIT_MOV, SLJIT_R0, 0, ARGUMENTS, 0); - OP2(SLJIT_SHL, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, 2); - OP1(SLJIT_MOV_U32, TMP1, 0, SLJIT_MEM1(STACK_TOP), (sljit_sw)PRIV(ucp_gbtable)); - OP1(SLJIT_MOV, STACK_TOP, 0, TMP2, 0); - OP2(SLJIT_SHL, TMP2, 0, SLJIT_IMM, 1, TMP2, 0); - OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, TMP2, 0); - JUMPTO(SLJIT_NOT_ZERO, label); +#if PCRE2_CODE_UNIT_WIDTH != 32 + sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_RET(SW) | SLJIT_ARG1(SW) | SLJIT_ARG2(SW), SLJIT_IMM, + common->utf ? SLJIT_FUNC_OFFSET(do_extuni_utf) : SLJIT_FUNC_OFFSET(do_extuni_no_utf)); +#else + sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_RET(SW) | SLJIT_ARG1(SW) | SLJIT_ARG2(SW), SLJIT_IMM, SLJIT_FUNC_OFFSET(do_extuni_no_utf)); +#endif - OP1(SLJIT_MOV, STR_PTR, 0, TMP3, 0); - JUMPHERE(jump[0]); - OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), LOCALS0); + OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_RETURN_REG, 0); if (common->mode == PCRE2_JIT_PARTIAL_HARD) { - jump[0] = CMP(SLJIT_LESS, STR_PTR, 0, STR_END, 0); + jump[0] = CMP(SLJIT_LESS, SLJIT_RETURN_REG, 0, STR_END, 0); /* Since we successfully read a char above, partial matching must occure. */ check_partial(common, TRUE); JUMPHERE(jump[0]); @@ -6582,7 +7647,7 @@ switch(type) read_char_range(common, 0, 255, type == OP_NCLASS); #endif - if (check_class_ranges(common, (const sljit_u8 *)cc, type == OP_NCLASS, FALSE, backtracks)) + if (optimize_class(common, (const sljit_u8 *)cc, type == OP_NCLASS, FALSE, backtracks)) return cc + 32 / sizeof(PCRE2_UCHAR); #if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 8 @@ -6609,7 +7674,7 @@ switch(type) OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, SLJIT_IMM, 3); OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_sw)cc); OP2(SLJIT_SHL, TMP2, 0, SLJIT_IMM, 1, TMP2, 0); - OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, TMP2, 0); + OP2(SLJIT_AND | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, TMP2, 0); add_jump(compiler, backtracks, JUMP(SLJIT_ZERO)); #if defined SUPPORT_UNICODE || PCRE2_CODE_UNIT_WIDTH != 8 @@ -6626,7 +7691,7 @@ switch(type) return cc + GET(cc, 0) - 1; #endif } -SLJIT_ASSERT_STOP(); +SLJIT_UNREACHABLE(); return cc; } @@ -6781,40 +7846,42 @@ else #if defined SUPPORT_UNICODE if (common->utf && *cc == OP_REFI) { - SLJIT_ASSERT(TMP1 == SLJIT_R0 && STACK_TOP == SLJIT_R1 && TMP2 == SLJIT_R2); + SLJIT_ASSERT(TMP1 == SLJIT_R0 && STR_PTR == SLJIT_R1); if (ref) - OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset + 1)); + OP1(SLJIT_MOV, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset + 1)); else - OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP2), sizeof(sljit_sw)); + OP1(SLJIT_MOV, SLJIT_R2, 0, SLJIT_MEM1(TMP2), sizeof(sljit_sw)); if (withchecks) - jump = CMP(SLJIT_EQUAL, TMP1, 0, TMP2, 0); - - /* Needed to save important temporary registers. */ - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS0, STACK_TOP, 0); - OP1(SLJIT_MOV, SLJIT_R1, 0, ARGUMENTS, 0); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_R1), SLJIT_OFFSETOF(jit_arguments, startchar_ptr), STR_PTR, 0); - sljit_emit_ijump(compiler, SLJIT_CALL3, SLJIT_IMM, SLJIT_FUNC_OFFSET(do_utf_caselesscmp)); - OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), LOCALS0); + jump = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_R2, 0); + /* No free saved registers so save data on stack. */ + + OP1(SLJIT_MOV, SLJIT_R3, 0, STR_END, 0); + sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_RET(SW) | SLJIT_ARG1(SW) | SLJIT_ARG2(SW) | SLJIT_ARG3(SW) | SLJIT_ARG4(SW), SLJIT_IMM, SLJIT_FUNC_OFFSET(do_utf_caselesscmp)); + OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_RETURN_REG, 0); + if (common->mode == PCRE2_JIT_COMPLETE) add_jump(compiler, backtracks, CMP(SLJIT_LESS_EQUAL, SLJIT_RETURN_REG, 0, SLJIT_IMM, 1)); else { - add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, SLJIT_RETURN_REG, 0, SLJIT_IMM, 0)); - nopartial = CMP(SLJIT_NOT_EQUAL, SLJIT_RETURN_REG, 0, SLJIT_IMM, 1); + OP2(SLJIT_SUB | SLJIT_SET_Z | SLJIT_SET_LESS, SLJIT_UNUSED, 0, SLJIT_RETURN_REG, 0, SLJIT_IMM, 1); + + add_jump(compiler, backtracks, JUMP(SLJIT_LESS)); + + nopartial = JUMP(SLJIT_NOT_EQUAL); + OP1(SLJIT_MOV, STR_PTR, 0, STR_END, 0); check_partial(common, FALSE); add_jump(compiler, backtracks, JUMP(SLJIT_JUMP)); JUMPHERE(nopartial); } - OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_RETURN_REG, 0); } else #endif /* SUPPORT_UNICODE */ { if (ref) - OP2(SLJIT_SUB | SLJIT_SET_E, TMP2, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset + 1), TMP1, 0); + OP2(SLJIT_SUB | SLJIT_SET_Z, TMP2, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset + 1), TMP1, 0); else - OP2(SLJIT_SUB | SLJIT_SET_E, TMP2, 0, SLJIT_MEM1(TMP2), sizeof(sljit_sw), TMP1, 0); + OP2(SLJIT_SUB | SLJIT_SET_Z, TMP2, 0, SLJIT_MEM1(TMP2), sizeof(sljit_sw), TMP1, 0); if (withchecks) jump = JUMP(SLJIT_ZERO); @@ -6905,7 +7972,7 @@ switch(type) cc += 1 + IMM2_SIZE + 1 + 2 * IMM2_SIZE; break; default: - SLJIT_ASSERT_STOP(); + SLJIT_UNREACHABLE(); break; } @@ -6919,7 +7986,7 @@ if (!minimize) OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, 0); /* Temporary release of STR_PTR. */ - OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_sw)); + OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_sw)); /* Handles both invalid and empty cases. Since the minimum repeat, is zero the invalid case is basically the same as an empty case. */ if (ref) @@ -6932,7 +7999,7 @@ if (!minimize) zerolength = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_MEM1(TMP2), sizeof(sljit_sw)); } /* Restore if not zero length. */ - OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_sw)); + OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_sw)); } else { @@ -7096,8 +8163,10 @@ if (entry == NULL) if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) return NULL; entry->next = NULL; - entry->entry = NULL; - entry->calls = NULL; + entry->entry_label = NULL; + entry->backtrack_label = NULL; + entry->entry_calls = NULL; + entry->backtrack_calls = NULL; entry->start = start; if (prev != NULL) @@ -7106,71 +8175,74 @@ if (entry == NULL) common->entries = entry; } -if (common->has_set_som && common->mark_ptr != 0) - { - OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(0)); - allocate_stack(common, 2); - OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->mark_ptr); - OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP2, 0); - OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP1, 0); - } -else if (common->has_set_som || common->mark_ptr != 0) - { - OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), common->has_set_som ? (int)(OVECTOR(0)) : common->mark_ptr); - allocate_stack(common, 1); - OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP2, 0); - } +BACKTRACK_AS(recurse_backtrack)->entry = entry; -if (entry->entry == NULL) - add_jump(compiler, &entry->calls, JUMP(SLJIT_FAST_CALL)); +if (entry->entry_label == NULL) + add_jump(compiler, &entry->entry_calls, JUMP(SLJIT_FAST_CALL)); else - JUMPTO(SLJIT_FAST_CALL, entry->entry); + JUMPTO(SLJIT_FAST_CALL, entry->entry_label); /* Leave if the match is failed. */ add_jump(compiler, &backtrack->topbacktracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, 0)); +BACKTRACK_AS(recurse_backtrack)->matchingpath = LABEL(); return cc + 1 + LINK_SIZE; } -static int SLJIT_CALL do_callout(struct jit_arguments *arguments, pcre2_callout_block *callout_block, PCRE2_SPTR *jit_ovector) +static sljit_s32 SLJIT_FUNC do_callout(struct jit_arguments *arguments, pcre2_callout_block *callout_block, PCRE2_SPTR *jit_ovector) { -PCRE2_SPTR begin = arguments->begin; -PCRE2_SIZE *ovector = arguments->match_data->ovector; -sljit_u32 oveccount = arguments->oveccount; -sljit_u32 i; +PCRE2_SPTR begin; +PCRE2_SIZE *ovector; +sljit_u32 oveccount, capture_top; if (arguments->callout == NULL) return 0; -callout_block->version = 1; +SLJIT_COMPILE_ASSERT(sizeof (PCRE2_SIZE) <= sizeof (sljit_sw), pcre2_size_must_be_lower_than_sljit_sw_size); + +begin = arguments->begin; +ovector = (PCRE2_SIZE*)(callout_block + 1); +oveccount = callout_block->capture_top; + +SLJIT_ASSERT(oveccount >= 1); + +callout_block->version = 2; +callout_block->callout_flags = 0; /* Offsets in subject. */ callout_block->subject_length = arguments->end - arguments->begin; -callout_block->start_match = (PCRE2_SPTR)callout_block->subject - arguments->begin; -callout_block->current_position = (PCRE2_SPTR)callout_block->offset_vector - arguments->begin; +callout_block->start_match = jit_ovector[0] - begin; +callout_block->current_position = (PCRE2_SPTR)callout_block->offset_vector - begin; callout_block->subject = begin; /* Convert and copy the JIT offset vector to the ovector array. */ -callout_block->capture_top = 0; +callout_block->capture_top = 1; callout_block->offset_vector = ovector; -for (i = 2; i < oveccount; i += 2) - { - ovector[i] = jit_ovector[i] - begin; - ovector[i + 1] = jit_ovector[i + 1] - begin; - if (jit_ovector[i] >= begin) - callout_block->capture_top = i; - } -callout_block->capture_top = (callout_block->capture_top >> 1) + 1; ovector[0] = PCRE2_UNSET; ovector[1] = PCRE2_UNSET; +ovector += 2; +jit_ovector += 2; +capture_top = 1; + +/* Convert pointers to sizes. */ +while (--oveccount != 0) + { + capture_top++; + + ovector[0] = (PCRE2_SIZE)(jit_ovector[0] - begin); + ovector[1] = (PCRE2_SIZE)(jit_ovector[1] - begin); + + if (ovector[0] != PCRE2_UNSET) + callout_block->capture_top = capture_top; + + ovector += 2; + jit_ovector += 2; + } + return (arguments->callout)(callout_block, arguments->callout_data); } -/* Aligning to 8 byte. */ -#define CALLOUT_ARG_SIZE \ - (((int)sizeof(pcre2_callout_block) + 7) & ~7) - #define CALLOUT_ARG_OFFSET(arg) \ - (-CALLOUT_ARG_SIZE + SLJIT_OFFSETOF(pcre2_callout_block, arg)) + SLJIT_OFFSETOF(pcre2_callout_block, arg) static SLJIT_INLINE PCRE2_SPTR compile_callout_matchingpath(compiler_common *common, PCRE2_SPTR cc, backtrack_common *parent) { @@ -7182,10 +8254,13 @@ unsigned int callout_length = (*cc == OP_CALLOUT) sljit_sw value1; sljit_sw value2; sljit_sw value3; +sljit_uw callout_arg_size = (common->re->top_bracket + 1) * 2 * sizeof(sljit_sw); PUSH_BACKTRACK(sizeof(backtrack_common), cc, NULL); -allocate_stack(common, CALLOUT_ARG_SIZE / sizeof(sljit_sw)); +callout_arg_size = (sizeof(pcre2_callout_block) + callout_arg_size + sizeof(sljit_sw) - 1) / sizeof(sljit_sw); + +allocate_stack(common, callout_arg_size); SLJIT_ASSERT(common->capture_last_ptr != 0); OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), common->capture_last_ptr); @@ -7193,11 +8268,10 @@ OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0); value1 = (*cc == OP_CALLOUT) ? cc[1 + 2 * LINK_SIZE] : 0; OP1(SLJIT_MOV_U32, SLJIT_MEM1(STACK_TOP), CALLOUT_ARG_OFFSET(callout_number), SLJIT_IMM, value1); OP1(SLJIT_MOV_U32, SLJIT_MEM1(STACK_TOP), CALLOUT_ARG_OFFSET(capture_last), TMP2, 0); +OP1(SLJIT_MOV_U32, SLJIT_MEM1(STACK_TOP), CALLOUT_ARG_OFFSET(capture_top), SLJIT_IMM, common->re->top_bracket + 1); /* These pointer sized fields temporarly stores internal variables. */ -OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(0)); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), CALLOUT_ARG_OFFSET(offset_vector), STR_PTR, 0); -OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), CALLOUT_ARG_OFFSET(subject), TMP2, 0); if (common->mark_ptr != 0) OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, mark_ptr)); @@ -7223,22 +8297,24 @@ OP1(mov_opcode, SLJIT_MEM1(STACK_TOP), CALLOUT_ARG_OFFSET(callout_string_length) OP1(mov_opcode, SLJIT_MEM1(STACK_TOP), CALLOUT_ARG_OFFSET(callout_string_offset), SLJIT_IMM, value3); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), CALLOUT_ARG_OFFSET(mark), (common->mark_ptr != 0) ? TMP2 : SLJIT_IMM, 0); +SLJIT_ASSERT(TMP1 == SLJIT_R0 && STR_PTR == SLJIT_R1); + /* Needed to save important temporary registers. */ -OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS0, STACK_TOP, 0); -OP2(SLJIT_SUB, SLJIT_R1, 0, STACK_TOP, 0, SLJIT_IMM, CALLOUT_ARG_SIZE); +OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS0, STR_PTR, 0); +/* SLJIT_R0 = arguments */ +OP1(SLJIT_MOV, SLJIT_R1, 0, STACK_TOP, 0); GET_LOCAL_BASE(SLJIT_R2, 0, OVECTOR_START); -sljit_emit_ijump(compiler, SLJIT_CALL3, SLJIT_IMM, SLJIT_FUNC_OFFSET(do_callout)); -OP1(SLJIT_MOV_S32, SLJIT_RETURN_REG, 0, SLJIT_RETURN_REG, 0); -OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), LOCALS0); -free_stack(common, CALLOUT_ARG_SIZE / sizeof(sljit_sw)); +sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_RET(S32) | SLJIT_ARG1(SW) | SLJIT_ARG2(SW) | SLJIT_ARG3(SW), SLJIT_IMM, SLJIT_FUNC_OFFSET(do_callout)); +OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), LOCALS0); +free_stack(common, callout_arg_size); /* Check return value. */ -OP2(SLJIT_SUB | SLJIT_SET_S, SLJIT_UNUSED, 0, SLJIT_RETURN_REG, 0, SLJIT_IMM, 0); -add_jump(compiler, &backtrack->topbacktracks, JUMP(SLJIT_SIG_GREATER)); -if (common->forced_quit_label == NULL) - add_jump(compiler, &common->forced_quit, JUMP(SLJIT_SIG_LESS)); +OP2(SLJIT_SUB32 | SLJIT_SET_Z | SLJIT_SET_SIG_GREATER, SLJIT_UNUSED, 0, SLJIT_RETURN_REG, 0, SLJIT_IMM, 0); +add_jump(compiler, &backtrack->topbacktracks, JUMP(SLJIT_SIG_GREATER32)); +if (common->abort_label == NULL) + add_jump(compiler, &common->abort, JUMP(SLJIT_NOT_EQUAL32) /* SIG_LESS */); else - JUMPTO(SLJIT_SIG_LESS, common->forced_quit_label); + JUMPTO(SLJIT_NOT_EQUAL32 /* SIG_LESS */, common->abort_label); return cc + callout_length; } @@ -7280,6 +8356,7 @@ static PCRE2_SPTR compile_assert_matchingpath(compiler_common *common, PCRE2_SPT DEFINE_COMPILER; int framesize; int extrasize; +BOOL local_quit_available = FALSE; BOOL needs_control_head; int private_data_ptr; backtrack_common altbacktrack; @@ -7290,13 +8367,13 @@ jump_list *tmp = NULL; jump_list **target = (conditional) ? &backtrack->condfailed : &backtrack->common.topbacktracks; jump_list **found; /* Saving previous accept variables. */ -BOOL save_local_exit = common->local_exit; -BOOL save_positive_assert = common->positive_assert; +BOOL save_local_quit_available = common->local_quit_available; +BOOL save_in_positive_assertion = common->in_positive_assertion; then_trap_backtrack *save_then_trap = common->then_trap; struct sljit_label *save_quit_label = common->quit_label; struct sljit_label *save_accept_label = common->accept_label; jump_list *save_quit = common->quit; -jump_list *save_positive_assert_quit = common->positive_assert_quit; +jump_list *save_positive_assertion_quit = common->positive_assertion_quit; jump_list *save_accept = common->accept; struct sljit_jump *jump; struct sljit_jump *brajump = NULL; @@ -7363,7 +8440,7 @@ else allocate_stack(common, framesize + extrasize); OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr); - OP2(SLJIT_SUB, TMP2, 0, STACK_TOP, 0, SLJIT_IMM, (framesize + extrasize) * sizeof(sljit_sw)); + OP2(SLJIT_ADD, TMP2, 0, STACK_TOP, 0, SLJIT_IMM, (framesize + extrasize) * sizeof(sljit_sw)); OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, TMP2, 0); if (needs_control_head) OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr); @@ -7378,21 +8455,21 @@ else else OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP1, 0); - init_frame(common, ccbegin, NULL, framesize + extrasize - 1, extrasize, FALSE); + init_frame(common, ccbegin, NULL, framesize + extrasize - 1, extrasize); } memset(&altbacktrack, 0, sizeof(backtrack_common)); -if (opcode == OP_ASSERT_NOT || opcode == OP_ASSERTBACK_NOT) +if (conditional || (opcode == OP_ASSERT_NOT || opcode == OP_ASSERTBACK_NOT)) { - /* Negative assert is stronger than positive assert. */ - common->local_exit = TRUE; + /* Control verbs cannot escape from these asserts. */ + local_quit_available = TRUE; + common->local_quit_available = TRUE; common->quit_label = NULL; common->quit = NULL; - common->positive_assert = FALSE; } -else - common->positive_assert = TRUE; -common->positive_assert_quit = NULL; + +common->in_positive_assertion = (opcode == OP_ASSERT || opcode == OP_ASSERTBACK); +common->positive_assertion_quit = NULL; while (1) { @@ -7408,16 +8485,16 @@ while (1) compile_matchingpath(common, ccbegin + 1 + LINK_SIZE, cc, &altbacktrack); if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) { - if (opcode == OP_ASSERT_NOT || opcode == OP_ASSERTBACK_NOT) + if (local_quit_available) { - common->local_exit = save_local_exit; + common->local_quit_available = save_local_quit_available; common->quit_label = save_quit_label; common->quit = save_quit; } - common->positive_assert = save_positive_assert; + common->in_positive_assertion = save_in_positive_assertion; common->then_trap = save_then_trap; common->accept_label = save_accept_label; - common->positive_assert_quit = save_positive_assert_quit; + common->positive_assertion_quit = save_positive_assertion_quit; common->accept = save_accept; return NULL; } @@ -7434,23 +8511,24 @@ while (1) free_stack(common, extrasize); if (needs_control_head) - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, SLJIT_MEM1(STACK_TOP), 0); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, SLJIT_MEM1(STACK_TOP), STACK(-1)); } else { if ((opcode != OP_ASSERT_NOT && opcode != OP_ASSERTBACK_NOT) || conditional) { /* We don't need to keep the STR_PTR, only the previous private_data_ptr. */ - OP2(SLJIT_ADD, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr, SLJIT_IMM, (framesize + 1) * sizeof(sljit_sw)); + OP2(SLJIT_SUB, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr, SLJIT_IMM, (framesize + 1) * sizeof(sljit_sw)); if (needs_control_head) - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, SLJIT_MEM1(STACK_TOP), 0); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, SLJIT_MEM1(STACK_TOP), STACK(-1)); } else { OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr); if (needs_control_head) - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, SLJIT_MEM1(STACK_TOP), (framesize + 1) * sizeof(sljit_sw)); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, SLJIT_MEM1(STACK_TOP), STACK(-framesize - 2)); add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL)); + OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, (framesize - 1) * sizeof(sljit_sw)); } } @@ -7460,25 +8538,25 @@ while (1) if (conditional) { if (extrasize > 0) - OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), needs_control_head ? sizeof(sljit_sw) : 0); + OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), needs_control_head ? STACK(-2) : STACK(-1)); } else if (bra == OP_BRAZERO) { if (framesize < 0) - OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), (extrasize - 1) * sizeof(sljit_sw)); + OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(-extrasize)); else { - OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), framesize * sizeof(sljit_sw)); - OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), (framesize + extrasize - 1) * sizeof(sljit_sw)); + OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(-framesize - 1)); + OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(-framesize - extrasize)); OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, TMP1, 0); } - OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_sw)); + OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_sw)); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0); } else if (framesize >= 0) { /* For OP_BRA and OP_BRAMINZERO. */ - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, SLJIT_MEM1(STACK_TOP), framesize * sizeof(sljit_sw)); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, SLJIT_MEM1(STACK_TOP), STACK(-framesize - 1)); } } add_jump(compiler, found, JUMP(SLJIT_JUMP)); @@ -7486,16 +8564,16 @@ while (1) compile_backtrackingpath(common, altbacktrack.top); if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) { - if (opcode == OP_ASSERT_NOT || opcode == OP_ASSERTBACK_NOT) + if (local_quit_available) { - common->local_exit = save_local_exit; + common->local_quit_available = save_local_quit_available; common->quit_label = save_quit_label; common->quit = save_quit; } - common->positive_assert = save_positive_assert; + common->in_positive_assertion = save_in_positive_assertion; common->then_trap = save_then_trap; common->accept_label = save_accept_label; - common->positive_assert_quit = save_positive_assert_quit; + common->positive_assertion_quit = save_positive_assertion_quit; common->accept = save_accept; return NULL; } @@ -7508,26 +8586,26 @@ while (1) cc += GET(cc, 1); } -if (opcode == OP_ASSERT_NOT || opcode == OP_ASSERTBACK_NOT) +if (local_quit_available) { - SLJIT_ASSERT(common->positive_assert_quit == NULL); + SLJIT_ASSERT(common->positive_assertion_quit == NULL); /* Makes the check less complicated below. */ - common->positive_assert_quit = common->quit; + common->positive_assertion_quit = common->quit; } /* None of them matched. */ -if (common->positive_assert_quit != NULL) +if (common->positive_assertion_quit != NULL) { jump = JUMP(SLJIT_JUMP); - set_jumps(common->positive_assert_quit, LABEL()); + set_jumps(common->positive_assertion_quit, LABEL()); SLJIT_ASSERT(framesize != no_stack); if (framesize < 0) - OP2(SLJIT_ADD, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr, SLJIT_IMM, extrasize * sizeof(sljit_sw)); + OP2(SLJIT_SUB, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr, SLJIT_IMM, extrasize * sizeof(sljit_sw)); else { OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr); add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL)); - OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, (framesize + extrasize) * sizeof(sljit_sw)); + OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, (extrasize + 1) * sizeof(sljit_sw)); } JUMPHERE(jump); } @@ -7576,18 +8654,18 @@ if (opcode == OP_ASSERT || opcode == OP_ASSERTBACK) { /* We know that STR_PTR was stored on the top of the stack. */ if (extrasize > 0) - OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), (extrasize - 1) * sizeof(sljit_sw)); + OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(-extrasize)); /* Keep the STR_PTR on the top of the stack. */ if (bra == OP_BRAZERO) { - OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_sw)); + OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_sw)); if (extrasize == 2) OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); } else if (bra == OP_BRAMINZERO) { - OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_sw)); + OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_sw)); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0); } } @@ -7596,13 +8674,13 @@ if (opcode == OP_ASSERT || opcode == OP_ASSERTBACK) if (bra == OP_BRA) { /* We don't need to keep the STR_PTR, only the previous private_data_ptr. */ - OP2(SLJIT_ADD, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr, SLJIT_IMM, (framesize + 1) * sizeof(sljit_sw)); - OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), (extrasize - 2) * sizeof(sljit_sw)); + OP2(SLJIT_SUB, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr, SLJIT_IMM, (framesize + 1) * sizeof(sljit_sw)); + OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(-extrasize + 1)); } else { /* We don't need to keep the STR_PTR, only the previous private_data_ptr. */ - OP2(SLJIT_ADD, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr, SLJIT_IMM, (framesize + 2) * sizeof(sljit_sw)); + OP2(SLJIT_SUB, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr, SLJIT_IMM, (framesize + 2) * sizeof(sljit_sw)); if (extrasize == 2) { OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); @@ -7630,7 +8708,9 @@ if (opcode == OP_ASSERT || opcode == OP_ASSERTBACK) { OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr); add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL)); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, SLJIT_MEM1(STACK_TOP), framesize * sizeof(sljit_sw)); + OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(-2)); + OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, (framesize - 1) * sizeof(sljit_sw)); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, TMP1, 0); } set_jumps(backtrack->common.topbacktracks, LABEL()); } @@ -7683,16 +8763,16 @@ else } } -if (opcode == OP_ASSERT_NOT || opcode == OP_ASSERTBACK_NOT) +if (local_quit_available) { - common->local_exit = save_local_exit; + common->local_quit_available = save_local_quit_available; common->quit_label = save_quit_label; common->quit = save_quit; } -common->positive_assert = save_positive_assert; +common->in_positive_assertion = save_in_positive_assertion; common->then_trap = save_then_trap; common->accept_label = save_accept_label; -common->positive_assert_quit = save_positive_assert_quit; +common->positive_assertion_quit = save_positive_assertion_quit; common->accept = save_accept; return cc + 1 + LINK_SIZE; } @@ -7717,23 +8797,23 @@ if (framesize < 0) } if (needs_control_head) - OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), (ket != OP_KET || has_alternatives) ? sizeof(sljit_sw) : 0); + OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), (ket != OP_KET || has_alternatives) ? STACK(-2) : STACK(-1)); /* TMP2 which is set here used by OP_KETRMAX below. */ if (ket == OP_KETRMAX) - OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), 0); + OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(-1)); else if (ket == OP_KETRMIN) { /* Move the STR_PTR to the private_data_ptr. */ - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, SLJIT_MEM1(STACK_TOP), 0); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, SLJIT_MEM1(STACK_TOP), STACK(-1)); } } else { stacksize = (ket != OP_KET || has_alternatives) ? 2 : 1; - OP2(SLJIT_ADD, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr, SLJIT_IMM, (framesize + stacksize) * sizeof(sljit_sw)); + OP2(SLJIT_SUB, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr, SLJIT_IMM, (framesize + stacksize) * sizeof(sljit_sw)); if (needs_control_head) - OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), 0); + OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(-1)); if (ket == OP_KETRMAX) { @@ -7820,7 +8900,6 @@ return stacksize; (|) OP_*BRA | OP_ALT ... M A (?()|) OP_*COND | OP_ALT M A (?>|) OP_ONCE | OP_ALT ... [stack trace] M A - (?>|) OP_ONCE_NC | OP_ALT ... [stack trace] M A Or nothing, if trace is unnecessary */ @@ -7888,8 +8967,6 @@ if (SLJIT_UNLIKELY(opcode == OP_COND || opcode == OP_SCOND)) if (SLJIT_UNLIKELY(opcode == OP_COND) && (*cc == OP_KETRMAX || *cc == OP_KETRMIN)) opcode = OP_SCOND; -if (SLJIT_UNLIKELY(opcode == OP_ONCE_NC)) - opcode = OP_ONCE; if (opcode == OP_CBRA || opcode == OP_SCBRA) { @@ -7966,7 +9043,7 @@ if (bra == OP_BRAMINZERO) { /* Except when the whole stack frame must be saved. */ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr); - braminzero = CMP(SLJIT_EQUAL, STR_PTR, 0, SLJIT_MEM1(TMP1), (BACKTRACK_AS(bracket_backtrack)->u.framesize + 1) * sizeof(sljit_sw)); + braminzero = CMP(SLJIT_EQUAL, STR_PTR, 0, SLJIT_MEM1(TMP1), STACK(-BACKTRACK_AS(bracket_backtrack)->u.framesize - 2)); } JUMPHERE(skip); } @@ -8039,7 +9116,7 @@ if (opcode == OP_ONCE) OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), STR_PTR, 0); if (BACKTRACK_AS(bracket_backtrack)->u.framesize == no_frame) - OP2(SLJIT_SUB, SLJIT_MEM1(SLJIT_SP), private_data_ptr, STACK_TOP, 0, SLJIT_IMM, needs_control_head ? (2 * sizeof(sljit_sw)) : sizeof(sljit_sw)); + OP2(SLJIT_ADD, SLJIT_MEM1(SLJIT_SP), private_data_ptr, STACK_TOP, 0, SLJIT_IMM, needs_control_head ? (2 * sizeof(sljit_sw)) : sizeof(sljit_sw)); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize + 1), TMP2, 0); } else if (ket == OP_KETRMAX || has_alternatives) @@ -8057,7 +9134,7 @@ if (opcode == OP_ONCE) OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP2, 0); OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr); - OP2(SLJIT_SUB, TMP2, 0, STACK_TOP, 0, SLJIT_IMM, stacksize * sizeof(sljit_sw)); + OP2(SLJIT_ADD, TMP2, 0, STACK_TOP, 0, SLJIT_IMM, stacksize * sizeof(sljit_sw)); stacksize = needs_control_head ? 1 : 0; if (ket != OP_KET || has_alternatives) @@ -8072,7 +9149,7 @@ if (opcode == OP_ONCE) OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, TMP2, 0); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), TMP1, 0); } - init_frame(common, ccbegin, NULL, BACKTRACK_AS(bracket_backtrack)->u.framesize + stacksize, stacksize + 1, FALSE); + init_frame(common, ccbegin, NULL, BACKTRACK_AS(bracket_backtrack)->u.framesize + stacksize, stacksize + 1); } } else if (opcode == OP_CBRA || opcode == OP_SCBRA) @@ -8129,13 +9206,13 @@ if (opcode == OP_COND || opcode == OP_SCOND) slot = common->name_table + GET2(matchingpath, 1) * common->name_entry_size; OP1(SLJIT_MOV, TMP3, 0, STR_PTR, 0); OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(1)); - OP2(SLJIT_SUB | SLJIT_SET_E, TMP2, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(GET2(slot, 0) << 1), TMP1, 0); + OP2(SLJIT_SUB | SLJIT_SET_Z, TMP2, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(GET2(slot, 0) << 1), TMP1, 0); slot += common->name_entry_size; i--; while (i-- > 0) { OP2(SLJIT_SUB, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(GET2(slot, 0) << 1), TMP1, 0); - OP2(SLJIT_OR | SLJIT_SET_E, TMP2, 0, TMP2, 0, STR_PTR, 0); + OP2(SLJIT_OR | SLJIT_SET_Z, TMP2, 0, TMP2, 0, STR_PTR, 0); slot += common->name_entry_size; } OP1(SLJIT_MOV, STR_PTR, 0, TMP3, 0); @@ -8288,7 +9365,7 @@ if (ket == OP_KETRMAX) { if (has_alternatives) BACKTRACK_AS(bracket_backtrack)->alternative_matchingpath = LABEL(); - OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_MEM1(SLJIT_SP), repeat_ptr, SLJIT_MEM1(SLJIT_SP), repeat_ptr, SLJIT_IMM, 1); + OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_MEM1(SLJIT_SP), repeat_ptr, SLJIT_MEM1(SLJIT_SP), repeat_ptr, SLJIT_IMM, 1); JUMPTO(SLJIT_NOT_ZERO, rmax_label); /* Drop STR_PTR for greedy plus quantifier. */ if (opcode != OP_ONCE) @@ -8318,7 +9395,7 @@ if (ket == OP_KETRMAX) if (repeat_type == OP_EXACT) { count_match(common); - OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_MEM1(SLJIT_SP), repeat_ptr, SLJIT_MEM1(SLJIT_SP), repeat_ptr, SLJIT_IMM, 1); + OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_MEM1(SLJIT_SP), repeat_ptr, SLJIT_MEM1(SLJIT_SP), repeat_ptr, SLJIT_IMM, 1); JUMPTO(SLJIT_NOT_ZERO, rmax_label); } else if (repeat_type == OP_UPTO) @@ -8346,6 +9423,7 @@ if (bra == OP_BRAMINZERO) { OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr); add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL)); + OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, (BACKTRACK_AS(bracket_backtrack)->u.framesize - 1) * sizeof(sljit_sw)); } else if (ket == OP_KETRMIN && opcode != OP_ONCE) free_stack(common, 1); @@ -8418,7 +9496,7 @@ switch(opcode) break; default: - SLJIT_ASSERT_STOP(); + SLJIT_UNREACHABLE(); break; } @@ -8496,7 +9574,7 @@ else OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr); if (needs_control_head) OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr); - OP2(SLJIT_SUB, SLJIT_MEM1(SLJIT_SP), private_data_ptr, STACK_TOP, 0, SLJIT_IMM, -STACK(stacksize - 1)); + OP2(SLJIT_ADD, SLJIT_MEM1(SLJIT_SP), private_data_ptr, STACK_TOP, 0, SLJIT_IMM, stacksize * sizeof(sljit_sw)); stack = 0; if (!zero) @@ -8515,7 +9593,7 @@ else stack++; } OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stack), TMP1, 0); - init_frame(common, cc, NULL, stacksize - 1, stacksize - framesize, FALSE); + init_frame(common, cc, NULL, stacksize - 1, stacksize - framesize); stack -= 1 + (offset == 0); } @@ -8568,7 +9646,7 @@ while (*cc != OP_KETRPOS) { if (offset != 0) { - OP2(SLJIT_ADD, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr, SLJIT_IMM, stacksize * sizeof(sljit_sw)); + OP2(SLJIT_SUB, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr, SLJIT_IMM, stacksize * sizeof(sljit_sw)); OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), cbraprivptr); OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset + 1), STR_PTR, 0); OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), cbraprivptr, STR_PTR, 0); @@ -8579,10 +9657,10 @@ while (*cc != OP_KETRPOS) else { OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr); - OP2(SLJIT_ADD, STACK_TOP, 0, TMP2, 0, SLJIT_IMM, stacksize * sizeof(sljit_sw)); + OP2(SLJIT_SUB, STACK_TOP, 0, TMP2, 0, SLJIT_IMM, stacksize * sizeof(sljit_sw)); if (opcode == OP_SBRAPOS) - OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP2), (framesize + 1) * sizeof(sljit_sw)); - OP1(SLJIT_MOV, SLJIT_MEM1(TMP2), (framesize + 1) * sizeof(sljit_sw), STR_PTR, 0); + OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP2), STACK(-framesize - 2)); + OP1(SLJIT_MOV, SLJIT_MEM1(TMP2), STACK(-framesize - 2), STR_PTR, 0); } /* Even if the match is empty, we need to reset the control head. */ @@ -8628,7 +9706,7 @@ while (*cc != OP_KETRPOS) else { OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr); - OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(TMP2), (framesize + 1) * sizeof(sljit_sw)); + OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(TMP2), STACK(-framesize - 2)); } } @@ -8645,7 +9723,7 @@ if (!zero) if (framesize < 0) add_jump(compiler, &backtrack->topbacktracks, CMP(SLJIT_NOT_EQUAL, SLJIT_MEM1(STACK_TOP), STACK(stacksize - 1), SLJIT_IMM, 0)); else /* TMP2 is set to [private_data_ptr] above. */ - add_jump(compiler, &backtrack->topbacktracks, CMP(SLJIT_NOT_EQUAL, SLJIT_MEM1(TMP2), (stacksize - 1) * sizeof(sljit_sw), SLJIT_IMM, 0)); + add_jump(compiler, &backtrack->topbacktracks, CMP(SLJIT_NOT_EQUAL, SLJIT_MEM1(TMP2), STACK(-stacksize), SLJIT_IMM, 0)); } /* None of them matched. */ @@ -8868,7 +9946,7 @@ if (exact > 1) OP1(SLJIT_MOV, tmp_base, tmp_offset, SLJIT_IMM, exact); label = LABEL(); compile_char1_matchingpath(common, type, cc, &backtrack->topbacktracks, FALSE); - OP2(SLJIT_SUB | SLJIT_SET_E, tmp_base, tmp_offset, tmp_base, tmp_offset, SLJIT_IMM, 1); + OP2(SLJIT_SUB | SLJIT_SET_Z, tmp_base, tmp_offset, tmp_base, tmp_offset, SLJIT_IMM, 1); JUMPTO(SLJIT_NOT_ZERO, label); } else @@ -8876,7 +9954,7 @@ if (exact > 1) OP1(SLJIT_MOV, tmp_base, tmp_offset, SLJIT_IMM, exact); label = LABEL(); compile_char1_matchingpath(common, type, cc, &backtrack->topbacktracks, TRUE); - OP2(SLJIT_SUB | SLJIT_SET_E, tmp_base, tmp_offset, tmp_base, tmp_offset, SLJIT_IMM, 1); + OP2(SLJIT_SUB | SLJIT_SET_Z, tmp_base, tmp_offset, tmp_base, tmp_offset, SLJIT_IMM, 1); JUMPTO(SLJIT_NOT_ZERO, label); } } @@ -8906,7 +9984,7 @@ switch(opcode) if (opcode == OP_UPTO) { OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), POSSESSIVE0); - OP2(SLJIT_SUB | SLJIT_SET_E, TMP1, 0, TMP1, 0, SLJIT_IMM, 1); + OP2(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, TMP1, 0, SLJIT_IMM, 1); jump = JUMP(SLJIT_ZERO); OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), POSSESSIVE0, TMP1, 0); } @@ -8968,7 +10046,7 @@ switch(opcode) label = LABEL(); if (opcode == OP_UPTO) { - OP2(SLJIT_SUB | SLJIT_SET_E, tmp_base, tmp_offset, tmp_base, tmp_offset, SLJIT_IMM, 1); + OP2(SLJIT_SUB | SLJIT_SET_Z, tmp_base, tmp_offset, tmp_base, tmp_offset, SLJIT_IMM, 1); add_jump(compiler, &backtrack->topbacktracks, JUMP(SLJIT_ZERO)); } compile_char1_matchingpath(common, type, cc, &backtrack->topbacktracks, FALSE); @@ -8988,7 +10066,7 @@ switch(opcode) OP1(SLJIT_MOV, base, offset1, STR_PTR, 0); if (opcode == OP_UPTO) { - OP2(SLJIT_SUB | SLJIT_SET_E, tmp_base, tmp_offset, tmp_base, tmp_offset, SLJIT_IMM, 1); + OP2(SLJIT_SUB | SLJIT_SET_Z, tmp_base, tmp_offset, tmp_base, tmp_offset, SLJIT_IMM, 1); add_jump(compiler, &no_match, JUMP(SLJIT_ZERO)); } @@ -9015,7 +10093,7 @@ switch(opcode) if (opcode == OP_UPTO) { - OP2(SLJIT_SUB | SLJIT_SET_E, tmp_base, tmp_offset, tmp_base, tmp_offset, SLJIT_IMM, 1); + OP2(SLJIT_SUB | SLJIT_SET_Z, tmp_base, tmp_offset, tmp_base, tmp_offset, SLJIT_IMM, 1); JUMPTO(SLJIT_NOT_ZERO, label); } else @@ -9044,7 +10122,7 @@ switch(opcode) if (opcode == OP_UPTO) { - OP2(SLJIT_SUB | SLJIT_SET_E, tmp_base, tmp_offset, tmp_base, tmp_offset, SLJIT_IMM, 1); + OP2(SLJIT_SUB | SLJIT_SET_Z, tmp_base, tmp_offset, tmp_base, tmp_offset, SLJIT_IMM, 1); JUMPTO(SLJIT_NOT_ZERO, label); } else @@ -9070,7 +10148,7 @@ switch(opcode) compile_char1_matchingpath(common, type, cc, &no_char1_match, FALSE); if (opcode == OP_UPTO) { - OP2(SLJIT_SUB | SLJIT_SET_E, tmp_base, tmp_offset, tmp_base, tmp_offset, SLJIT_IMM, 1); + OP2(SLJIT_SUB | SLJIT_SET_Z, tmp_base, tmp_offset, tmp_base, tmp_offset, SLJIT_IMM, 1); JUMPTO(SLJIT_NOT_ZERO, label); OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); } @@ -9157,7 +10235,7 @@ switch(opcode) label = LABEL(); compile_char1_matchingpath(common, type, cc, &no_match, TRUE); OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), POSSESSIVE1, STR_PTR, 0); - OP2(SLJIT_SUB | SLJIT_SET_E, tmp_base, tmp_offset, tmp_base, tmp_offset, SLJIT_IMM, 1); + OP2(SLJIT_SUB | SLJIT_SET_Z, tmp_base, tmp_offset, tmp_base, tmp_offset, SLJIT_IMM, 1); JUMPTO(SLJIT_NOT_ZERO, label); set_jumps(no_match, LABEL()); OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), POSSESSIVE1); @@ -9168,7 +10246,7 @@ switch(opcode) label = LABEL(); detect_partial_match(common, &no_match); compile_char1_matchingpath(common, type, cc, &no_char1_match, FALSE); - OP2(SLJIT_SUB | SLJIT_SET_E, tmp_base, tmp_offset, tmp_base, tmp_offset, SLJIT_IMM, 1); + OP2(SLJIT_SUB | SLJIT_SET_Z, tmp_base, tmp_offset, tmp_base, tmp_offset, SLJIT_IMM, 1); JUMPTO(SLJIT_NOT_ZERO, label); OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); set_jumps(no_char1_match, LABEL()); @@ -9186,7 +10264,7 @@ switch(opcode) break; default: - SLJIT_ASSERT_STOP(); + SLJIT_UNREACHABLE(); break; } @@ -9207,6 +10285,9 @@ if (*cc == OP_FAIL) return cc + 1; } +if (*cc == OP_ACCEPT && common->currententry == NULL && (common->re->overall_options & PCRE2_ENDANCHORED) != 0) + add_jump(compiler, &common->reset_match, CMP(SLJIT_NOT_EQUAL, STR_PTR, 0, STR_END, 0)); + if (*cc == OP_ASSERT_ACCEPT || common->currententry != NULL || !common->might_be_empty) { /* No need to check notempty conditions. */ @@ -9223,9 +10304,9 @@ else CMPTO(SLJIT_NOT_EQUAL, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(0), common->accept_label); OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0); OP1(SLJIT_MOV_U32, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, options)); -OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_IMM, PCRE2_NOTEMPTY); +OP2(SLJIT_AND | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_IMM, PCRE2_NOTEMPTY); add_jump(compiler, &backtrack->topbacktracks, JUMP(SLJIT_NOT_ZERO)); -OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_IMM, PCRE2_NOTEMPTY_ATSTART); +OP2(SLJIT_AND | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_IMM, PCRE2_NOTEMPTY_ATSTART); if (common->accept_label == NULL) add_jump(compiler, &common->accept, JUMP(SLJIT_ZERO)); else @@ -9309,7 +10390,7 @@ size = 3 + (size < 0 ? 0 : size); OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr); allocate_stack(common, size); if (size > 3) - OP2(SLJIT_SUB, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, STACK_TOP, 0, SLJIT_IMM, (size - 3) * sizeof(sljit_sw)); + OP2(SLJIT_ADD, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, STACK_TOP, 0, SLJIT_IMM, (size - 3) * sizeof(sljit_sw)); else OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, STACK_TOP, 0); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(size - 1), SLJIT_IMM, BACKTRACK_AS(then_trap_backtrack)->start); @@ -9318,7 +10399,7 @@ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(size - 3), TMP2, 0); size = BACKTRACK_AS(then_trap_backtrack)->framesize; if (size >= 0) - init_frame(common, cc, ccend, size - 1, 0, FALSE); + init_frame(common, cc, ccend, size - 1, 0); } static void compile_matchingpath(compiler_common *common, PCRE2_SPTR cc, PCRE2_SPTR ccend, backtrack_common *parent) @@ -9540,7 +10621,6 @@ while (cc < ccend) break; case OP_ONCE: - case OP_ONCE_NC: case OP_BRA: case OP_CBRA: case OP_COND: @@ -9615,7 +10695,7 @@ while (cc < ccend) break; default: - SLJIT_ASSERT_STOP(); + SLJIT_UNREACHABLE(); return; } if (cc == NULL) @@ -9723,7 +10803,7 @@ switch(opcode) case OP_MINUPTO: OP1(SLJIT_MOV, TMP1, 0, base, offset1); OP1(SLJIT_MOV, STR_PTR, 0, base, offset0); - OP2(SLJIT_SUB | SLJIT_SET_E, TMP1, 0, TMP1, 0, SLJIT_IMM, 1); + OP2(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, TMP1, 0, SLJIT_IMM, 1); add_jump(compiler, &jumplist, JUMP(SLJIT_ZERO)); OP1(SLJIT_MOV, base, offset1, TMP1, 0); @@ -9769,7 +10849,7 @@ switch(opcode) break; default: - SLJIT_ASSERT_STOP(); + SLJIT_UNREACHABLE(); break; } @@ -9804,27 +10884,21 @@ free_stack(common, ref ? 2 : 3); static SLJIT_INLINE void compile_recurse_backtrackingpath(compiler_common *common, struct backtrack_common *current) { DEFINE_COMPILER; +recurse_entry *entry; -if (CURRENT_AS(recurse_backtrack)->inlined_pattern) - compile_backtrackingpath(common, current->top); -set_jumps(current->topbacktracks, LABEL()); -if (CURRENT_AS(recurse_backtrack)->inlined_pattern) - return; - -if (common->has_set_som && common->mark_ptr != 0) +if (!CURRENT_AS(recurse_backtrack)->inlined_pattern) { - OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); - OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(1)); - free_stack(common, 2); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(0), TMP2, 0); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->mark_ptr, TMP1, 0); - } -else if (common->has_set_som || common->mark_ptr != 0) - { - OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); - free_stack(common, 1); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->has_set_som ? (int)(OVECTOR(0)) : common->mark_ptr, TMP2, 0); + entry = CURRENT_AS(recurse_backtrack)->entry; + if (entry->backtrack_label == NULL) + add_jump(compiler, &entry->backtrack_calls, JUMP(SLJIT_FAST_CALL)); + else + JUMPTO(SLJIT_FAST_CALL, entry->backtrack_label); + CMPTO(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, 0, CURRENT_AS(recurse_backtrack)->matchingpath); } +else + compile_backtrackingpath(common, current->top); + +set_jumps(current->topbacktracks, LABEL()); } static void compile_assert_backtrackingpath(compiler_common *common, struct backtrack_common *current) @@ -9877,7 +10951,9 @@ if (*cc == OP_ASSERT || *cc == OP_ASSERTBACK) { OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), CURRENT_AS(assert_backtrack)->private_data_ptr); add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL)); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), CURRENT_AS(assert_backtrack)->private_data_ptr, SLJIT_MEM1(STACK_TOP), CURRENT_AS(assert_backtrack)->framesize * sizeof(sljit_sw)); + OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(-2)); + OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, (CURRENT_AS(assert_backtrack)->framesize - 1) * sizeof(sljit_sw)); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), CURRENT_AS(assert_backtrack)->private_data_ptr, TMP1, 0); set_jumps(current->topbacktracks, LABEL()); } @@ -9887,7 +10963,7 @@ else if (bra == OP_BRAZERO) { /* We know there is enough place on the stack. */ - OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_sw)); + OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_sw)); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0); JUMPTO(SLJIT_JUMP, CURRENT_AS(assert_backtrack)->matchingpath); JUMPHERE(brajump); @@ -9947,8 +11023,6 @@ if (opcode == OP_CBRA || opcode == OP_SCBRA) offset = (GET2(ccbegin, 1 + LINK_SIZE)) << 1; if (SLJIT_UNLIKELY(opcode == OP_COND) && (*cc == OP_KETRMAX || *cc == OP_KETRMIN)) opcode = OP_SCOND; -if (SLJIT_UNLIKELY(opcode == OP_ONCE_NC)) - opcode = OP_ONCE; alt_max = has_alternatives ? no_alternatives(ccbegin) : 0; @@ -10000,7 +11074,7 @@ else if (ket == OP_KETRMIN) else { OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr); - CMPTO(SLJIT_NOT_EQUAL, STR_PTR, 0, SLJIT_MEM1(TMP1), (CURRENT_AS(bracket_backtrack)->u.framesize + 1) * sizeof(sljit_sw), CURRENT_AS(bracket_backtrack)->recursive_matchingpath); + CMPTO(SLJIT_NOT_EQUAL, STR_PTR, 0, SLJIT_MEM1(TMP1), STACK(-CURRENT_AS(bracket_backtrack)->u.framesize - 2), CURRENT_AS(bracket_backtrack)->recursive_matchingpath); } /* Drop STR_PTR for non-greedy plus quantifier. */ if (opcode != OP_ONCE) @@ -10054,6 +11128,7 @@ if (SLJIT_UNLIKELY(opcode == OP_ONCE)) { OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr); add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL)); + OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, (CURRENT_AS(bracket_backtrack)->u.framesize - 1) * sizeof(sljit_sw)); } once = JUMP(SLJIT_JUMP); } @@ -10106,7 +11181,9 @@ if (SLJIT_UNLIKELY(opcode == OP_COND) || SLJIT_UNLIKELY(opcode == OP_SCOND)) { OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), assert->private_data_ptr); add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL)); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), assert->private_data_ptr, SLJIT_MEM1(STACK_TOP), assert->framesize * sizeof(sljit_sw)); + OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(-2)); + OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, (assert->framesize - 1) * sizeof(sljit_sw)); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), assert->private_data_ptr, TMP1, 0); } cond = JUMP(SLJIT_JUMP); set_jumps(CURRENT_AS(bracket_backtrack)->u.assert->condfailed, LABEL()); @@ -10247,7 +11324,9 @@ if (has_alternatives) { OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), assert->private_data_ptr); add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL)); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), assert->private_data_ptr, SLJIT_MEM1(STACK_TOP), assert->framesize * sizeof(sljit_sw)); + OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(-2)); + OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, (assert->framesize - 1) * sizeof(sljit_sw)); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), assert->private_data_ptr, TMP1, 0); } JUMPHERE(cond); } @@ -10302,7 +11381,7 @@ else if (opcode == OP_ONCE) JUMPHERE(once); /* Restore previous private_data_ptr */ if (CURRENT_AS(bracket_backtrack)->u.framesize >= 0) - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, SLJIT_MEM1(STACK_TOP), CURRENT_AS(bracket_backtrack)->u.framesize * sizeof(sljit_sw)); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, SLJIT_MEM1(STACK_TOP), STACK(-CURRENT_AS(bracket_backtrack)->u.framesize - 1)); else if (ket == OP_KETRMIN) { OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(1)); @@ -10383,6 +11462,7 @@ if (CURRENT_AS(bracketpos_backtrack)->framesize < 0) OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), CURRENT_AS(bracketpos_backtrack)->private_data_ptr); add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL)); +OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, (CURRENT_AS(bracketpos_backtrack)->framesize - 1) * sizeof(sljit_sw)); if (current->topbacktracks) { @@ -10392,7 +11472,7 @@ if (current->topbacktracks) free_stack(common, CURRENT_AS(bracketpos_backtrack)->stacksize); JUMPHERE(jump); } -OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), CURRENT_AS(bracketpos_backtrack)->private_data_ptr, SLJIT_MEM1(STACK_TOP), CURRENT_AS(bracketpos_backtrack)->framesize * sizeof(sljit_sw)); +OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), CURRENT_AS(bracketpos_backtrack)->private_data_ptr, SLJIT_MEM1(STACK_TOP), STACK(-CURRENT_AS(bracketpos_backtrack)->framesize - 1)); } static SLJIT_INLINE void compile_braminzero_backtrackingpath(compiler_common *common, struct backtrack_common *current) @@ -10438,22 +11518,23 @@ if (opcode == OP_THEN || opcode == OP_THEN_ARG) jump = JUMP(SLJIT_JUMP); loop = LABEL(); - OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(STACK_TOP), -(int)sizeof(sljit_sw)); + OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); JUMPHERE(jump); - CMPTO(SLJIT_NOT_EQUAL, SLJIT_MEM1(STACK_TOP), -(int)(2 * sizeof(sljit_sw)), TMP1, 0, loop); - CMPTO(SLJIT_NOT_EQUAL, SLJIT_MEM1(STACK_TOP), -(int)(3 * sizeof(sljit_sw)), TMP2, 0, loop); + CMPTO(SLJIT_NOT_EQUAL, SLJIT_MEM1(STACK_TOP), STACK(1), TMP1, 0, loop); + CMPTO(SLJIT_NOT_EQUAL, SLJIT_MEM1(STACK_TOP), STACK(2), TMP2, 0, loop); add_jump(compiler, &common->then_trap->quit, JUMP(SLJIT_JUMP)); return; } - else if (common->positive_assert) + else if (!common->local_quit_available && common->in_positive_assertion) { - add_jump(compiler, &common->positive_assert_quit, JUMP(SLJIT_JUMP)); + add_jump(compiler, &common->positive_assertion_quit, JUMP(SLJIT_JUMP)); return; } } -if (common->local_exit) +if (common->local_quit_available) { + /* Abort match with a fail. */ if (common->quit_label == NULL) add_jump(compiler, &common->quit, JUMP(SLJIT_JUMP)); else @@ -10463,15 +11544,13 @@ if (common->local_exit) if (opcode == OP_SKIP_ARG) { - SLJIT_ASSERT(common->control_head_ptr != 0); + SLJIT_ASSERT(common->control_head_ptr != 0 && TMP1 == SLJIT_R0 && STR_PTR == SLJIT_R1); OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS0, STACK_TOP, 0); - OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_IMM, (sljit_sw)(current->cc + 2)); - sljit_emit_ijump(compiler, SLJIT_CALL2, SLJIT_IMM, SLJIT_FUNC_OFFSET(do_search_mark)); - OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), LOCALS0); + OP1(SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, (sljit_sw)(current->cc + 2)); + sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_RET(SW) | SLJIT_ARG1(SW) | SLJIT_ARG2(SW), SLJIT_IMM, SLJIT_FUNC_OFFSET(do_search_mark)); - OP1(SLJIT_MOV, STR_PTR, 0, TMP1, 0); - add_jump(compiler, &common->reset_match, CMP(SLJIT_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, -1)); + OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_R0, 0); + add_jump(compiler, &common->reset_match, CMP(SLJIT_NOT_EQUAL, SLJIT_R0, 0, SLJIT_IMM, 0)); return; } @@ -10504,7 +11583,10 @@ jump = JUMP(SLJIT_JUMP); set_jumps(CURRENT_AS(then_trap_backtrack)->quit, LABEL()); /* STACK_TOP is set by THEN. */ if (CURRENT_AS(then_trap_backtrack)->framesize >= 0) + { add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL)); + OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, (CURRENT_AS(then_trap_backtrack)->framesize - 1) * sizeof(sljit_sw)); + } OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); free_stack(common, 3); @@ -10621,7 +11703,6 @@ while (current) break; case OP_ONCE: - case OP_ONCE_NC: case OP_BRA: case OP_CBRA: case OP_COND: @@ -10670,7 +11751,7 @@ while (current) break; case OP_COMMIT: - if (!common->local_exit) + if (!common->local_quit_available) OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE2_ERROR_NOMATCH); if (common->quit_label == NULL) add_jump(compiler, &common->quit, JUMP(SLJIT_JUMP)); @@ -10692,7 +11773,7 @@ while (current) break; default: - SLJIT_ASSERT_STOP(); + SLJIT_UNREACHABLE(); break; } current = current->prev; @@ -10707,38 +11788,52 @@ PCRE2_SPTR cc = common->start + common->currententry->start; PCRE2_SPTR ccbegin = cc + 1 + LINK_SIZE + (*cc == OP_BRA ? 0 : IMM2_SIZE); PCRE2_SPTR ccend = bracketend(cc) - (1 + LINK_SIZE); BOOL needs_control_head; -int framesize = get_framesize(common, cc, NULL, TRUE, &needs_control_head); -int private_data_size = get_private_data_copy_length(common, ccbegin, ccend, needs_control_head); -int alternativesize; -BOOL needs_frame; +BOOL has_quit; +BOOL has_accept; +int private_data_size = get_recurse_data_length(common, ccbegin, ccend, &needs_control_head, &has_quit, &has_accept); +int alt_count, alt_max, local_size; backtrack_common altbacktrack; -struct sljit_jump *jump; +jump_list *match = NULL; +sljit_uw *next_update_addr = NULL; +struct sljit_jump *alt1 = NULL; +struct sljit_jump *alt2 = NULL; +struct sljit_jump *accept_exit = NULL; +struct sljit_label *quit; /* Recurse captures then. */ common->then_trap = NULL; SLJIT_ASSERT(*cc == OP_BRA || *cc == OP_CBRA || *cc == OP_CBRAPOS || *cc == OP_SCBRA || *cc == OP_SCBRAPOS); -needs_frame = framesize >= 0; -if (!needs_frame) - framesize = 0; -alternativesize = *(cc + GET(cc, 1)) == OP_ALT ? 1 : 0; -SLJIT_ASSERT(common->currententry->entry == NULL && common->recursive_head_ptr != 0); -common->currententry->entry = LABEL(); -set_jumps(common->currententry->calls, common->currententry->entry); +alt_max = no_alternatives(cc); +alt_count = 0; + +/* Matching path. */ +SLJIT_ASSERT(common->currententry->entry_label == NULL && common->recursive_head_ptr != 0); +common->currententry->entry_label = LABEL(); +set_jumps(common->currententry->entry_calls, common->currententry->entry_label); sljit_emit_fast_enter(compiler, TMP2, 0); count_match(common); -allocate_stack(common, private_data_size + framesize + alternativesize); -OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(private_data_size + framesize + alternativesize - 1), TMP2, 0); -copy_private_data(common, ccbegin, ccend, TRUE, private_data_size + framesize + alternativesize, framesize + alternativesize, needs_control_head); + +local_size = (alt_max > 1) ? 2 : 1; + +/* (Reversed) stack layout: + [private data][return address][optional: str ptr] ... [optional: alternative index][recursive_head_ptr] */ + +allocate_stack(common, private_data_size + local_size); +/* Save return address. */ +OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(local_size - 1), TMP2, 0); + +copy_recurse_data(common, ccbegin, ccend, recurse_copy_from_global, local_size, private_data_size + local_size, has_quit); + +/* This variable is saved and restored all time when we enter or exit from a recursive context. */ +OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->recursive_head_ptr, STACK_TOP, 0); + if (needs_control_head) OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, SLJIT_IMM, 0); -OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->recursive_head_ptr, STACK_TOP, 0); -if (needs_frame) - init_frame(common, cc, NULL, framesize + alternativesize - 1, alternativesize, TRUE); -if (alternativesize > 0) +if (alt_max > 1) OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); memset(&altbacktrack, 0, sizeof(backtrack_common)); @@ -10760,7 +11855,75 @@ while (1) if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) return; - add_jump(compiler, &common->accept, JUMP(SLJIT_JUMP)); + allocate_stack(common, (alt_max > 1 || has_accept) ? 2 : 1); + OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), common->recursive_head_ptr); + + if (alt_max > 1 || has_accept) + OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, alt_count); + + add_jump(compiler, &match, JUMP(SLJIT_JUMP)); + + if (alt_count == 0) + { + /* Backtracking path entry. */ + SLJIT_ASSERT(common->currententry->backtrack_label == NULL); + common->currententry->backtrack_label = LABEL(); + set_jumps(common->currententry->backtrack_calls, common->currententry->backtrack_label); + + sljit_emit_fast_enter(compiler, TMP1, 0); + + if (has_accept) + accept_exit = CMP(SLJIT_EQUAL, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, alt_max * sizeof (sljit_sw)); + + OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); + /* Save return address. */ + OP1(SLJIT_MOV, SLJIT_MEM1(TMP2), STACK(local_size - 1), TMP1, 0); + + copy_recurse_data(common, ccbegin, ccend, recurse_swap_global, local_size, private_data_size + local_size, has_quit); + + if (alt_max > 1) + { + OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(1)); + free_stack(common, 2); + + if (alt_max > 4) + { + /* Table jump if alt_max is greater than 4. */ + next_update_addr = allocate_read_only_data(common, alt_max * sizeof(sljit_uw)); + if (SLJIT_UNLIKELY(next_update_addr == NULL)) + return; + sljit_emit_ijump(compiler, SLJIT_JUMP, SLJIT_MEM1(TMP1), (sljit_sw)next_update_addr); + add_label_addr(common, next_update_addr++); + } + else + { + if (alt_max == 4) + alt2 = CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 2 * sizeof(sljit_uw)); + alt1 = CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, sizeof(sljit_uw)); + } + } + else + free_stack(common, has_accept ? 2 : 1); + } + else if (alt_max > 4) + add_label_addr(common, next_update_addr++); + else + { + if (alt_count != 2 * sizeof(sljit_uw)) + { + JUMPHERE(alt1); + if (alt_max == 3 && alt_count == sizeof(sljit_uw)) + alt2 = CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 2 * sizeof(sljit_uw)); + } + else + { + JUMPHERE(alt2); + if (alt_max == 4) + alt1 = CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 3 * sizeof(sljit_uw)); + } + } + + alt_count += sizeof(sljit_uw); compile_backtrackingpath(common, altbacktrack.top); if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) @@ -10774,55 +11937,65 @@ while (1) cc += GET(cc, 1); } -/* None of them matched. */ -OP1(SLJIT_MOV, TMP3, 0, SLJIT_IMM, 0); -jump = JUMP(SLJIT_JUMP); +/* No alternative is matched. */ + +quit = LABEL(); + +copy_recurse_data(common, ccbegin, ccend, recurse_copy_private_to_global, local_size, private_data_size + local_size, has_quit); + +OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(local_size - 1)); +free_stack(common, private_data_size + local_size); +OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 0); +sljit_emit_fast_return(compiler, TMP2, 0); if (common->quit != NULL) { + SLJIT_ASSERT(has_quit); + set_jumps(common->quit, LABEL()); OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), common->recursive_head_ptr); - if (needs_frame) - { - OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, (framesize + alternativesize) * sizeof(sljit_sw)); - add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL)); - OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, (framesize + alternativesize) * sizeof(sljit_sw)); - } - OP1(SLJIT_MOV, TMP3, 0, SLJIT_IMM, 0); - common->quit = NULL; - add_jump(compiler, &common->quit, JUMP(SLJIT_JUMP)); + copy_recurse_data(common, ccbegin, ccend, recurse_copy_shared_to_global, local_size, private_data_size + local_size, has_quit); + JUMPTO(SLJIT_JUMP, quit); } -set_jumps(common->accept, LABEL()); -OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), common->recursive_head_ptr); -if (needs_frame) +if (has_accept) { - OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, (framesize + alternativesize) * sizeof(sljit_sw)); - add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL)); - OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, (framesize + alternativesize) * sizeof(sljit_sw)); - } -OP1(SLJIT_MOV, TMP3, 0, SLJIT_IMM, 1); + JUMPHERE(accept_exit); + free_stack(common, 2); -JUMPHERE(jump); -if (common->quit != NULL) - set_jumps(common->quit, LABEL()); -copy_private_data(common, ccbegin, ccend, FALSE, private_data_size + framesize + alternativesize, framesize + alternativesize, needs_control_head); -free_stack(common, private_data_size + framesize + alternativesize); -if (needs_control_head) - { - OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), 2 * sizeof(sljit_sw)); - OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), sizeof(sljit_sw)); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->recursive_head_ptr, TMP1, 0); - OP1(SLJIT_MOV, TMP1, 0, TMP3, 0); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, TMP2, 0); + /* Save return address. */ + OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(local_size - 1), TMP1, 0); + + copy_recurse_data(common, ccbegin, ccend, recurse_copy_kept_shared_to_global, local_size, private_data_size + local_size, has_quit); + + OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(local_size - 1)); + free_stack(common, private_data_size + local_size); + OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 0); + sljit_emit_fast_return(compiler, TMP2, 0); } -else + +if (common->accept != NULL) { - OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), sizeof(sljit_sw)); - OP1(SLJIT_MOV, TMP1, 0, TMP3, 0); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->recursive_head_ptr, TMP2, 0); + SLJIT_ASSERT(has_accept); + + set_jumps(common->accept, LABEL()); + + OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), common->recursive_head_ptr); + OP1(SLJIT_MOV, TMP2, 0, STACK_TOP, 0); + + allocate_stack(common, 2); + OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, alt_count); } -sljit_emit_fast_return(compiler, SLJIT_MEM1(STACK_TOP), 0); + +set_jumps(match, LABEL()); + +OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP2, 0); + +copy_recurse_data(common, ccbegin, ccend, recurse_swap_global, local_size, private_data_size + local_size, has_quit); + +OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP2), STACK(local_size - 1)); +OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 1); +sljit_emit_fast_return(compiler, TMP2, 0); } #undef COMPILE_BACKTRACKINGPATH @@ -10854,11 +12027,13 @@ struct sljit_jump *jump; struct sljit_jump *minlength_check_failed = NULL; struct sljit_jump *reqbyte_notfound = NULL; struct sljit_jump *empty_match = NULL; +struct sljit_jump *end_anchor_failed = NULL; SLJIT_ASSERT(tables); memset(&rootbacktrack, 0, sizeof(backtrack_common)); memset(common, 0, sizeof(compiler_common)); +common->re = re; common->name_table = (PCRE2_SPTR)((uint8_t *)re + sizeof(pcre2_real_code)); rootbacktrack.cc = common->name_table + re->name_count * re->name_entry_size; @@ -11045,7 +12220,7 @@ if (!compiler) common->compiler = compiler; /* Main pcre_jit_exec entry. */ -sljit_emit_enter(compiler, 0, 1, 5, 5, 0, 0, private_data_size); +sljit_emit_enter(compiler, 0, SLJIT_ARG1(SW), 5, 5, 0, 0, private_data_size); /* Register init. */ reset_ovector(common, (re->top_bracket + 1) * 2); @@ -11058,8 +12233,8 @@ OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, str)) OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, end)); OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, stack)); OP1(SLJIT_MOV_U32, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, limit_match)); -OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(struct sljit_stack, base)); -OP1(SLJIT_MOV, STACK_LIMIT, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(struct sljit_stack, limit)); +OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(struct sljit_stack, end)); +OP1(SLJIT_MOV, STACK_LIMIT, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(struct sljit_stack, start)); OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 1); OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LIMIT_MATCH, TMP1, 0); @@ -11076,7 +12251,7 @@ if (common->control_head_ptr != 0) /* Main part of the matching */ if ((re->overall_options & PCRE2_ANCHORED) == 0) { - mainloop_label = mainloop_entry(common, (re->flags & PCRE2_HASCRORLF) != 0, re->overall_options); + mainloop_label = mainloop_entry(common); continue_match_label = LABEL(); /* Forward search if possible. */ if ((re->overall_options & PCRE2_NO_START_OPTIMIZE) == 0) @@ -11084,11 +12259,11 @@ if ((re->overall_options & PCRE2_ANCHORED) == 0) if (mode == PCRE2_JIT_COMPLETE && fast_forward_first_n_chars(common)) ; else if ((re->flags & PCRE2_FIRSTSET) != 0) - fast_forward_first_char(common, (PCRE2_UCHAR)(re->first_codeunit), (re->flags & PCRE2_FIRSTCASELESS) != 0); + fast_forward_first_char(common); else if ((re->flags & PCRE2_STARTLINE) != 0) fast_forward_newline(common); else if ((re->flags & PCRE2_FIRSTMAPSET) != 0) - fast_forward_start_bits(common, re->start_bitmap); + fast_forward_start_bits(common); } } else @@ -11135,6 +12310,9 @@ if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) return PCRE2_ERROR_NOMEMORY; } +if ((re->overall_options & PCRE2_ENDANCHORED) != 0) + end_anchor_failed = CMP(SLJIT_NOT_EQUAL, STR_PTR, 0, STR_END, 0); + if (common->might_be_empty) { empty_match = CMP(SLJIT_EQUAL, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(0)); @@ -11147,15 +12325,26 @@ if (common->accept != NULL) /* This means we have a match. Update the ovector. */ copy_ovector(common, re->top_bracket + 1); -common->quit_label = common->forced_quit_label = LABEL(); +common->quit_label = common->abort_label = LABEL(); if (common->quit != NULL) set_jumps(common->quit, common->quit_label); -if (common->forced_quit != NULL) - set_jumps(common->forced_quit, common->forced_quit_label); +if (common->abort != NULL) + set_jumps(common->abort, common->abort_label); if (minlength_check_failed != NULL) - SET_LABEL(minlength_check_failed, common->forced_quit_label); + SET_LABEL(minlength_check_failed, common->abort_label); sljit_emit_return(compiler, SLJIT_MOV, SLJIT_RETURN_REG, 0); +if (common->failed_match != NULL) + { + SLJIT_ASSERT(common->mode == PCRE2_JIT_COMPLETE); + set_jumps(common->failed_match, LABEL()); + OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE2_ERROR_NOMATCH); + JUMPTO(SLJIT_JUMP, common->abort_label); + } + +if ((re->overall_options & PCRE2_ENDANCHORED) != 0) + JUMPHERE(end_anchor_failed); + if (mode != PCRE2_JIT_COMPLETE) { common->partialmatchlabel = LABEL(); @@ -11236,9 +12425,9 @@ if (common->might_be_empty) JUMPHERE(empty_match); OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0); OP1(SLJIT_MOV_U32, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, options)); - OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_IMM, PCRE2_NOTEMPTY); + OP2(SLJIT_AND | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_IMM, PCRE2_NOTEMPTY); JUMPTO(SLJIT_NOT_ZERO, empty_match_backtrack_label); - OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_IMM, PCRE2_NOTEMPTY_ATSTART); + OP2(SLJIT_AND | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_IMM, PCRE2_NOTEMPTY_ATSTART); JUMPTO(SLJIT_ZERO, empty_match_found_label); OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, str)); CMPTO(SLJIT_NOT_EQUAL, TMP2, 0, STR_PTR, 0, empty_match_found_label); @@ -11249,7 +12438,7 @@ common->fast_forward_bc_ptr = NULL; common->fast_fail_start_ptr = 0; common->fast_fail_end_ptr = 0; common->currententry = common->entries; -common->local_exit = TRUE; +common->local_quit_available = TRUE; quit_label = common->quit_label; while (common->currententry != NULL) { @@ -11266,7 +12455,7 @@ while (common->currententry != NULL) flush_stubs(common); common->currententry = common->currententry->next; } -common->local_exit = FALSE; +common->local_quit_available = FALSE; common->quit_label = quit_label; /* Allocating stack, returns with PCRE_ERROR_JIT_STACKLIMIT if fails. */ @@ -11274,20 +12463,23 @@ common->quit_label = quit_label; set_jumps(common->stackalloc, LABEL()); /* RETURN_ADDR is not a saved register. */ sljit_emit_fast_enter(compiler, SLJIT_MEM1(SLJIT_SP), LOCALS0); -OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS1, TMP2, 0); -OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0); -OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, stack)); -OP1(SLJIT_MOV, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(struct sljit_stack, top), STACK_TOP, 0); -OP2(SLJIT_ADD, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(struct sljit_stack, limit), SLJIT_IMM, STACK_GROWTH_RATE); -sljit_emit_ijump(compiler, SLJIT_CALL2, SLJIT_IMM, SLJIT_FUNC_OFFSET(sljit_stack_resize)); -jump = CMP(SLJIT_NOT_EQUAL, SLJIT_RETURN_REG, 0, SLJIT_IMM, 0); -OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0); -OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, stack)); -OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(struct sljit_stack, top)); -OP1(SLJIT_MOV, STACK_LIMIT, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(struct sljit_stack, limit)); -OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), LOCALS1); -sljit_emit_fast_return(compiler, SLJIT_MEM1(SLJIT_SP), LOCALS0); +SLJIT_ASSERT(TMP1 == SLJIT_R0 && STR_PTR == SLJIT_R1); + +OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS1, STR_PTR, 0); +OP1(SLJIT_MOV, SLJIT_R0, 0, ARGUMENTS, 0); +OP2(SLJIT_SUB, SLJIT_R1, 0, STACK_LIMIT, 0, SLJIT_IMM, STACK_GROWTH_RATE); +OP1(SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_R0), SLJIT_OFFSETOF(jit_arguments, stack)); +OP1(SLJIT_MOV, STACK_LIMIT, 0, TMP2, 0); + +sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_RET(SW) | SLJIT_ARG1(SW) | SLJIT_ARG2(SW), SLJIT_IMM, SLJIT_FUNC_OFFSET(sljit_stack_resize)); + +jump = CMP(SLJIT_EQUAL, SLJIT_RETURN_REG, 0, SLJIT_IMM, 0); +OP1(SLJIT_MOV, TMP2, 0, STACK_LIMIT, 0); +OP1(SLJIT_MOV, STACK_LIMIT, 0, SLJIT_RETURN_REG, 0); +OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), LOCALS0); +OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), LOCALS1); +sljit_emit_fast_return(compiler, TMP1, 0); /* Allocation failed. */ JUMPHERE(jump); diff --git a/thirdparty/pcre2/src/pcre2_jit_match.c b/thirdparty/pcre2/src/pcre2_jit_match.c index a323971ff3..5a66545bae 100644 --- a/thirdparty/pcre2/src/pcre2_jit_match.c +++ b/thirdparty/pcre2/src/pcre2_jit_match.c @@ -49,10 +49,10 @@ static SLJIT_NOINLINE int jit_machine_stack_exec(jit_arguments *arguments, jit_f sljit_u8 local_space[MACHINE_STACK_SIZE]; struct sljit_stack local_stack; -local_stack.top = (sljit_sw)&local_space; -local_stack.base = local_stack.top; -local_stack.limit = local_stack.base + MACHINE_STACK_SIZE; -local_stack.max_limit = local_stack.limit; +local_stack.min_start = local_space; +local_stack.start = local_space; +local_stack.end = local_space + MACHINE_STACK_SIZE; +local_stack.top = local_space + MACHINE_STACK_SIZE; arguments->stack = &local_stack; return executable_func(arguments); } @@ -118,7 +118,7 @@ if ((options & PCRE2_PARTIAL_HARD) != 0) else if ((options & PCRE2_PARTIAL_SOFT) != 0) index = 1; -if (functions->executable_funcs[index] == NULL) +if (functions == NULL || functions->executable_funcs[index] == NULL) return PCRE2_ERROR_JIT_BADOPTION; /* Sanity checks should be handled by pcre_exec. */ diff --git a/thirdparty/pcre2/src/pcre2_jit_test.c b/thirdparty/pcre2/src/pcre2_jit_test.c deleted file mode 100644 index 705ba181eb..0000000000 --- a/thirdparty/pcre2/src/pcre2_jit_test.c +++ /dev/null @@ -1,1735 +0,0 @@ -/************************************************* -* Perl-Compatible Regular Expressions * -*************************************************/ - -/* PCRE is a library of functions to support regular expressions whose syntax -and semantics are as close as possible to those of the Perl 5 language. - - Written by Philip Hazel - Original API code Copyright (c) 1997-2012 University of Cambridge - New API code Copyright (c) 2016 University of Cambridge - ------------------------------------------------------------------------------ -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - * Neither the name of the University of Cambridge nor the names of its - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. ------------------------------------------------------------------------------ -*/ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include <stdio.h> -#include <string.h> - -#define PCRE2_CODE_UNIT_WIDTH 0 -#include "pcre2.h" - -/* - Letter characters: - \xe6\x92\xad = 0x64ad = 25773 (kanji) - Non-letter characters: - \xc2\xa1 = 0xa1 = (Inverted Exclamation Mark) - \xf3\xa9\xb7\x80 = 0xe9dc0 = 957888 - \xed\xa0\x80 = 55296 = 0xd800 (Invalid UTF character) - \xed\xb0\x80 = 56320 = 0xdc00 (Invalid UTF character) - Newlines: - \xc2\x85 = 0x85 = 133 (NExt Line = NEL) - \xe2\x80\xa8 = 0x2028 = 8232 (Line Separator) - Othercase pairs: - \xc3\xa9 = 0xe9 = 233 (e') - \xc3\x89 = 0xc9 = 201 (E') - \xc3\xa1 = 0xe1 = 225 (a') - \xc3\x81 = 0xc1 = 193 (A') - \x53 = 0x53 = S - \x73 = 0x73 = s - \xc5\xbf = 0x17f = 383 (long S) - \xc8\xba = 0x23a = 570 - \xe2\xb1\xa5 = 0x2c65 = 11365 - \xe1\xbd\xb8 = 0x1f78 = 8056 - \xe1\xbf\xb8 = 0x1ff8 = 8184 - \xf0\x90\x90\x80 = 0x10400 = 66560 - \xf0\x90\x90\xa8 = 0x10428 = 66600 - \xc7\x84 = 0x1c4 = 452 - \xc7\x85 = 0x1c5 = 453 - \xc7\x86 = 0x1c6 = 454 - Caseless sets: - ucp_Armenian - \x{531}-\x{556} -> \x{561}-\x{586} - ucp_Coptic - \x{2c80}-\x{2ce3} -> caseless: XOR 0x1 - ucp_Latin - \x{ff21}-\x{ff3a} -> \x{ff41]-\x{ff5a} - - Mark property: - \xcc\x8d = 0x30d = 781 - Special: - \xc2\x80 = 0x80 = 128 (lowest 2 byte character) - \xdf\xbf = 0x7ff = 2047 (highest 2 byte character) - \xe0\xa0\x80 = 0x800 = 2048 (lowest 2 byte character) - \xef\xbf\xbf = 0xffff = 65535 (highest 3 byte character) - \xf0\x90\x80\x80 = 0x10000 = 65536 (lowest 4 byte character) - \xf4\x8f\xbf\xbf = 0x10ffff = 1114111 (highest allowed utf character) -*/ - -static int regression_tests(void); - -int main(void) -{ - int jit = 0; -#if defined SUPPORT_PCRE2_8 - pcre2_config_8(PCRE2_CONFIG_JIT, &jit); -#elif defined SUPPORT_PCRE2_16 - pcre2_config_16(PCRE2_CONFIG_JIT, &jit); -#elif defined SUPPORT_PCRE2_32 - pcre2_config_32(PCRE2_CONFIG_JIT, &jit); -#endif - if (!jit) { - printf("JIT must be enabled to run pcre_jit_test\n"); - return 1; - } - return regression_tests(); -} - -/* --------------------------------------------------------------------------------------- */ - -#if !(defined SUPPORT_PCRE2_8) && !(defined SUPPORT_PCRE2_16) && !(defined SUPPORT_PCRE2_32) -#error SUPPORT_PCRE2_8 or SUPPORT_PCRE2_16 or SUPPORT_PCRE2_32 must be defined -#endif - -#define MU (PCRE2_MULTILINE | PCRE2_UTF) -#define MUP (PCRE2_MULTILINE | PCRE2_UTF | PCRE2_UCP) -#define CMU (PCRE2_CASELESS | PCRE2_MULTILINE | PCRE2_UTF) -#define CMUP (PCRE2_CASELESS | PCRE2_MULTILINE | PCRE2_UTF | PCRE2_UCP) -#define M (PCRE2_MULTILINE) -#define MP (PCRE2_MULTILINE | PCRE2_UCP) -#define U (PCRE2_UTF) -#define CM (PCRE2_CASELESS | PCRE2_MULTILINE) - -#define BSR(x) ((x) << 16) -#define A PCRE2_NEWLINE_ANYCRLF - -#define GET_NEWLINE(x) ((x) & 0xffff) -#define GET_BSR(x) ((x) >> 16) - -#define OFFSET_MASK 0x00ffff -#define F_NO8 0x010000 -#define F_NO16 0x020000 -#define F_NO32 0x020000 -#define F_NOMATCH 0x040000 -#define F_DIFF 0x080000 -#define F_FORCECONV 0x100000 -#define F_PROPERTY 0x200000 - -struct regression_test_case { - int compile_options; - int newline; - int match_options; - int start_offset; - const char *pattern; - const char *input; -}; - -static struct regression_test_case regression_test_cases[] = { - /* Constant strings. */ - { MU, A, 0, 0, "AbC", "AbAbC" }, - { MU, A, 0, 0, "ACCEPT", "AACACCACCEACCEPACCEPTACCEPTT" }, - { CMU, A, 0, 0, "aA#\xc3\xa9\xc3\x81", "aA#Aa#\xc3\x89\xc3\xa1" }, - { M, A, 0, 0, "[^a]", "aAbB" }, - { CM, A, 0, 0, "[^m]", "mMnN" }, - { M, A, 0, 0, "a[^b][^#]", "abacd" }, - { CM, A, 0, 0, "A[^B][^E]", "abacd" }, - { CMU, A, 0, 0, "[^x][^#]", "XxBll" }, - { MU, A, 0, 0, "[^a]", "aaa\xc3\xa1#Ab" }, - { CMU, A, 0, 0, "[^A]", "aA\xe6\x92\xad" }, - { MU, A, 0, 0, "\\W(\\W)?\\w", "\r\n+bc" }, - { MU, A, 0, 0, "\\W(\\W)?\\w", "\n\r+bc" }, - { MU, A, 0, 0, "\\W(\\W)?\\w", "\r\r+bc" }, - { MU, A, 0, 0, "\\W(\\W)?\\w", "\n\n+bc" }, - { MU, A, 0, 0, "[axd]", "sAXd" }, - { CMU, A, 0, 0, "[axd]", "sAXd" }, - { CMU, A, 0, 0 | F_NOMATCH, "[^axd]", "DxA" }, - { MU, A, 0, 0, "[a-dA-C]", "\xe6\x92\xad\xc3\xa9.B" }, - { MU, A, 0, 0, "[^a-dA-C]", "\xe6\x92\xad\xc3\xa9" }, - { CMU, A, 0, 0, "[^\xc3\xa9]", "\xc3\xa9\xc3\x89." }, - { MU, A, 0, 0, "[^\xc3\xa9]", "\xc3\xa9\xc3\x89." }, - { MU, A, 0, 0, "[^a]", "\xc2\x80[]" }, - { CMU, A, 0, 0, "\xf0\x90\x90\xa7", "\xf0\x90\x91\x8f" }, - { CM, A, 0, 0, "1a2b3c4", "1a2B3c51A2B3C4" }, - { PCRE2_CASELESS, 0, 0, 0, "\xff#a", "\xff#\xff\xfe##\xff#A" }, - { PCRE2_CASELESS, 0, 0, 0, "\xfe", "\xff\xfc#\xfe\xfe" }, - { PCRE2_CASELESS, 0, 0, 0, "a1", "Aa1" }, - { M, A, 0, 0, "\\Ca", "cda" }, - { CM, A, 0, 0, "\\Ca", "CDA" }, - { M, A, 0, 0 | F_NOMATCH, "\\Cx", "cda" }, - { CM, A, 0, 0 | F_NOMATCH, "\\Cx", "CDA" }, - { CMUP, A, 0, 0, "\xf0\x90\x90\x80\xf0\x90\x90\xa8", "\xf0\x90\x90\xa8\xf0\x90\x90\x80" }, - { CMUP, A, 0, 0, "\xf0\x90\x90\x80{2}", "\xf0\x90\x90\x80#\xf0\x90\x90\xa8\xf0\x90\x90\x80" }, - { CMUP, A, 0, 0, "\xf0\x90\x90\xa8{2}", "\xf0\x90\x90\x80#\xf0\x90\x90\xa8\xf0\x90\x90\x80" }, - { CMUP, A, 0, 0, "\xe1\xbd\xb8\xe1\xbf\xb8", "\xe1\xbf\xb8\xe1\xbd\xb8" }, - { M, A, 0, 0, "[3-57-9]", "5" }, - - /* Assertions. */ - { MU, A, 0, 0, "\\b[^A]", "A_B#" }, - { M, A, 0, 0 | F_NOMATCH, "\\b\\W", "\n*" }, - { MU, A, 0, 0, "\\B[^,]\\b[^s]\\b", "#X" }, - { MP, A, 0, 0, "\\B", "_\xa1" }, - { MP, A, 0, 0 | F_PROPERTY, "\\b_\\b[,A]\\B", "_," }, - { MUP, A, 0, 0, "\\b", "\xe6\x92\xad!" }, - { MUP, A, 0, 0, "\\B", "_\xc2\xa1\xc3\xa1\xc2\x85" }, - { MUP, A, 0, 0, "\\b[^A]\\B[^c]\\b[^_]\\B", "_\xc3\xa1\xe2\x80\xa8" }, - { MUP, A, 0, 0, "\\b\\w+\\B", "\xc3\x89\xc2\xa1\xe6\x92\xad\xc3\x81\xc3\xa1" }, - { MU, A, 0, 0 | F_NOMATCH, "\\b.", "\xcd\xbe" }, - { CMUP, A, 0, 0, "\\By", "\xf0\x90\x90\xa8y" }, - { M, A, 0, 0 | F_NOMATCH, "\\R^", "\n" }, - { M, A, 0, 1 | F_NOMATCH, "^", "\n" }, - { 0, 0, 0, 0, "^ab", "ab" }, - { 0, 0, 0, 0 | F_NOMATCH, "^ab", "aab" }, - { M, PCRE2_NEWLINE_CRLF, 0, 0, "^a", "\r\raa\n\naa\r\naa" }, - { MU, A, 0, 0, "^-", "\xe2\x80\xa8--\xc2\x85-\r\n-" }, - { M, PCRE2_NEWLINE_ANY, 0, 0, "^-", "a--b--\x85--" }, - { MU, PCRE2_NEWLINE_ANY, 0, 0, "^-", "a--\xe2\x80\xa8--" }, - { MU, PCRE2_NEWLINE_ANY, 0, 0, "^-", "a--\xc2\x85--" }, - { 0, 0, 0, 0, "ab$", "ab" }, - { 0, 0, 0, 0 | F_NOMATCH, "ab$", "abab\n\n" }, - { PCRE2_DOLLAR_ENDONLY, 0, 0, 0 | F_NOMATCH, "ab$", "abab\r\n" }, - { M, PCRE2_NEWLINE_CRLF, 0, 0, "a$", "\r\raa\n\naa\r\naa" }, - { M, PCRE2_NEWLINE_ANY, 0, 0, "a$", "aaa" }, - { MU, PCRE2_NEWLINE_ANYCRLF, 0, 0, "#$", "#\xc2\x85###\r#" }, - { MU, PCRE2_NEWLINE_ANY, 0, 0, "#$", "#\xe2\x80\xa9" }, - { 0, PCRE2_NEWLINE_ANY, PCRE2_NOTBOL, 0 | F_NOMATCH, "^a", "aa\naa" }, - { M, PCRE2_NEWLINE_ANY, PCRE2_NOTBOL, 0, "^a", "aa\naa" }, - { 0, PCRE2_NEWLINE_ANY, PCRE2_NOTEOL, 0 | F_NOMATCH, "a$", "aa\naa" }, - { 0, PCRE2_NEWLINE_ANY, PCRE2_NOTEOL, 0 | F_NOMATCH, "a$", "aa\r\n" }, - { U | PCRE2_DOLLAR_ENDONLY, PCRE2_NEWLINE_ANY, 0, 0 | F_PROPERTY, "\\p{Any}{2,}$", "aa\r\n" }, - { M, PCRE2_NEWLINE_ANY, PCRE2_NOTEOL, 0, "a$", "aa\naa" }, - { 0, PCRE2_NEWLINE_CR, 0, 0, ".\\Z", "aaa" }, - { U, PCRE2_NEWLINE_CR, 0, 0, "a\\Z", "aaa\r" }, - { 0, PCRE2_NEWLINE_CR, 0, 0, ".\\Z", "aaa\n" }, - { 0, PCRE2_NEWLINE_CRLF, 0, 0, ".\\Z", "aaa\r" }, - { U, PCRE2_NEWLINE_CRLF, 0, 0, ".\\Z", "aaa\n" }, - { 0, PCRE2_NEWLINE_CRLF, 0, 0, ".\\Z", "aaa\r\n" }, - { U, PCRE2_NEWLINE_ANYCRLF, 0, 0, ".\\Z", "aaa" }, - { U, PCRE2_NEWLINE_ANYCRLF, 0, 0, ".\\Z", "aaa\r" }, - { U, PCRE2_NEWLINE_ANYCRLF, 0, 0, ".\\Z", "aaa\n" }, - { U, PCRE2_NEWLINE_ANYCRLF, 0, 0, ".\\Z", "aaa\r\n" }, - { U, PCRE2_NEWLINE_ANYCRLF, 0, 0, ".\\Z", "aaa\xe2\x80\xa8" }, - { U, PCRE2_NEWLINE_ANYCRLF, 0, 0, ".\\Z", "aaa" }, - { U, PCRE2_NEWLINE_ANYCRLF, 0, 0, ".\\Z", "aaa\r" }, - { U, PCRE2_NEWLINE_ANYCRLF, 0, 0, ".\\Z", "aaa\n" }, - { U, PCRE2_NEWLINE_ANYCRLF, 0, 0, ".\\Z", "aaa\r\n" }, - { U, PCRE2_NEWLINE_ANY, 0, 0, ".\\Z", "aaa\xc2\x85" }, - { U, PCRE2_NEWLINE_ANY, 0, 0, ".\\Z", "aaa\xe2\x80\xa8" }, - { M, A, 0, 0, "\\Aa", "aaa" }, - { M, A, 0, 1 | F_NOMATCH, "\\Aa", "aaa" }, - { M, A, 0, 1, "\\Ga", "aaa" }, - { M, A, 0, 1 | F_NOMATCH, "\\Ga", "aba" }, - { M, A, 0, 0, "a\\z", "aaa" }, - { M, A, 0, 0 | F_NOMATCH, "a\\z", "aab" }, - - /* Brackets and alternatives. */ - { MU, A, 0, 0, "(ab|bb|cd)", "bacde" }, - { MU, A, 0, 0, "(?:ab|a)(bc|c)", "ababc" }, - { MU, A, 0, 0, "((ab|(cc))|(bb)|(?:cd|efg))", "abac" }, - { CMU, A, 0, 0, "((aB|(Cc))|(bB)|(?:cd|EFg))", "AcCe" }, - { MU, A, 0, 0, "((ab|(cc))|(bb)|(?:cd|ebg))", "acebebg" }, - { MU, A, 0, 0, "(?:(a)|(?:b))(cc|(?:d|e))(a|b)k", "accabdbbccbk" }, - { MU, A, 0, 0, "\xc7\x82|\xc6\x82", "\xf1\x83\x82\x82\xc7\x82\xc7\x83" }, - { MU, A, 0, 0, "=\xc7\x82|#\xc6\x82", "\xf1\x83\x82\x82=\xc7\x82\xc7\x83" }, - { MU, A, 0, 0, "\xc7\x82\xc7\x83|\xc6\x82\xc6\x82", "\xf1\x83\x82\x82\xc7\x82\xc7\x83" }, - { MU, A, 0, 0, "\xc6\x82\xc6\x82|\xc7\x83\xc7\x83|\xc8\x84\xc8\x84", "\xf1\x83\x82\x82\xc8\x84\xc8\x84" }, - - /* Greedy and non-greedy ? operators. */ - { MU, A, 0, 0, "(?:a)?a", "laab" }, - { CMU, A, 0, 0, "(A)?A", "llaab" }, - { MU, A, 0, 0, "(a)?\?a", "aab" }, /* ?? is the prefix of trygraphs in GCC. */ - { MU, A, 0, 0, "(a)?a", "manm" }, - { CMU, A, 0, 0, "(a|b)?\?d((?:e)?)", "ABABdx" }, - { MU, A, 0, 0, "(a|b)?\?d((?:e)?)", "abcde" }, - { MU, A, 0, 0, "((?:ab)?\?g|b(?:g(nn|d)?\?)?)?\?(?:n)?m", "abgnbgnnbgdnmm" }, - - /* Greedy and non-greedy + operators */ - { MU, A, 0, 0, "(aa)+aa", "aaaaaaa" }, - { MU, A, 0, 0, "(aa)+?aa", "aaaaaaa" }, - { MU, A, 0, 0, "(?:aba|ab|a)+l", "ababamababal" }, - { MU, A, 0, 0, "(?:aba|ab|a)+?l", "ababamababal" }, - { MU, A, 0, 0, "(a(?:bc|cb|b|c)+?|ss)+e", "accssabccbcacbccbbXaccssabccbcacbccbbe" }, - { MU, A, 0, 0, "(a(?:bc|cb|b|c)+|ss)+?e", "accssabccbcacbccbbXaccssabccbcacbccbbe" }, - { MU, A, 0, 0, "(?:(b(c)+?)+)?\?(?:(bc)+|(cb)+)+(?:m)+", "bccbcccbcbccbcbPbccbcccbcbccbcbmmn" }, - - /* Greedy and non-greedy * operators */ - { CMU, A, 0, 0, "(?:AA)*AB", "aaaaaaamaaaaaaab" }, - { MU, A, 0, 0, "(?:aa)*?ab", "aaaaaaamaaaaaaab" }, - { MU, A, 0, 0, "(aa|ab)*ab", "aaabaaab" }, - { CMU, A, 0, 0, "(aa|Ab)*?aB", "aaabaaab" }, - { MU, A, 0, 0, "(a|b)*(?:a)*(?:b)*m", "abbbaaababanabbbaaababamm" }, - { MU, A, 0, 0, "(a|b)*?(?:a)*?(?:b)*?m", "abbbaaababanabbbaaababamm" }, - { M, A, 0, 0, "a(a(\\1*)a|(b)b+){0}a", "aa" }, - { M, A, 0, 0, "((?:a|)*){0}a", "a" }, - - /* Combining ? + * operators */ - { MU, A, 0, 0, "((bm)+)?\?(?:a)*(bm)+n|((am)+?)?(?:a)+(am)*n", "bmbmabmamaaamambmaman" }, - { MU, A, 0, 0, "(((ab)?cd)*ef)+g", "abcdcdefcdefefmabcdcdefcdefefgg" }, - { MU, A, 0, 0, "(((ab)?\?cd)*?ef)+?g", "abcdcdefcdefefmabcdcdefcdefefgg" }, - { MU, A, 0, 0, "(?:(ab)?c|(?:ab)+?d)*g", "ababcdccababddg" }, - { MU, A, 0, 0, "(?:(?:ab)?\?c|(ab)+d)*?g", "ababcdccababddg" }, - - /* Single character iterators. */ - { MU, A, 0, 0, "(a+aab)+aaaab", "aaaabcaaaabaabcaabcaaabaaaab" }, - { MU, A, 0, 0, "(a*a*aab)+x", "aaaaabaabaaabmaabx" }, - { MU, A, 0, 0, "(a*?(b|ab)a*?)+x", "aaaabcxbbaabaacbaaabaabax" }, - { MU, A, 0, 0, "(a+(ab|ad)a+)+x", "aaabaaaadaabaaabaaaadaaax" }, - { MU, A, 0, 0, "(a?(a)a?)+(aaa)", "abaaabaaaaaaaa" }, - { MU, A, 0, 0, "(a?\?(a)a?\?)+(b)", "aaaacaaacaacacbaaab" }, - { MU, A, 0, 0, "(a{0,4}(b))+d", "aaaaaabaabcaaaaabaaaaabd" }, - { MU, A, 0, 0, "(a{0,4}?[^b])+d+(a{0,4}[^b])d+", "aaaaadaaaacaadddaaddd" }, - { MU, A, 0, 0, "(ba{2})+c", "baabaaabacbaabaac" }, - { MU, A, 0, 0, "(a*+bc++)+", "aaabbcaaabcccab" }, - { MU, A, 0, 0, "(a?+[^b])+", "babaacacb" }, - { MU, A, 0, 0, "(a{0,3}+b)(a{0,3}+b)(a{0,3}+)[^c]", "abaabaaacbaabaaaac" }, - { CMU, A, 0, 0, "([a-c]+[d-f]+?)+?g", "aBdacdehAbDaFgA" }, - { CMU, A, 0, 0, "[c-f]+k", "DemmFke" }, - { MU, A, 0, 0, "([DGH]{0,4}M)+", "GGDGHDGMMHMDHHGHM" }, - { MU, A, 0, 0, "([a-c]{4,}s)+", "abasabbasbbaabsbba" }, - { CMU, A, 0, 0, "[ace]{3,7}", "AcbDAcEEcEd" }, - { CMU, A, 0, 0, "[ace]{3,7}?", "AcbDAcEEcEd" }, - { CMU, A, 0, 0, "[ace]{3,}", "AcbDAcEEcEd" }, - { CMU, A, 0, 0, "[ace]{3,}?", "AcbDAcEEcEd" }, - { MU, A, 0, 0, "[ckl]{2,}?g", "cdkkmlglglkcg" }, - { CMU, A, 0, 0, "[ace]{5}?", "AcCebDAcEEcEd" }, - { MU, A, 0, 0, "([AbC]{3,5}?d)+", "BACaAbbAEAACCbdCCbdCCAAbb" }, - { MU, A, 0, 0, "([^ab]{0,}s){2}", "abaabcdsABamsDDs" }, - { MU, A, 0, 0, "\\b\\w+\\B", "x,a_cd" }, - { MUP, A, 0, 0, "\\b[^\xc2\xa1]+\\B", "\xc3\x89\xc2\xa1\xe6\x92\xad\xc3\x81\xc3\xa1" }, - { CMU, A, 0, 0, "[^b]+(a*)([^c]?d{3})", "aaaaddd" }, - { CMUP, A, 0, 0, "\xe1\xbd\xb8{2}", "\xe1\xbf\xb8#\xe1\xbf\xb8\xe1\xbd\xb8" }, - { CMU, A, 0, 0, "[^\xf0\x90\x90\x80]{2,4}@", "\xf0\x90\x90\xa8\xf0\x90\x90\x80###\xf0\x90\x90\x80@@@" }, - { CMU, A, 0, 0, "[^\xe1\xbd\xb8][^\xc3\xa9]", "\xe1\xbd\xb8\xe1\xbf\xb8\xc3\xa9\xc3\x89#" }, - { MU, A, 0, 0, "[^\xe1\xbd\xb8][^\xc3\xa9]", "\xe1\xbd\xb8\xe1\xbf\xb8\xc3\xa9\xc3\x89#" }, - { MU, A, 0, 0, "[^\xe1\xbd\xb8]{3,}?", "##\xe1\xbd\xb8#\xe1\xbd\xb8#\xc3\x89#\xe1\xbd\xb8" }, - { MU, A, 0, 0, "\\d+123", "987654321,01234" }, - { MU, A, 0, 0, "abcd*|\\w+xy", "aaaaa,abxyz" }, - { MU, A, 0, 0, "(?:abc|((?:amc|\\b\\w*xy)))", "aaaaa,abxyz" }, - { MU, A, 0, 0, "a(?R)|([a-z]++)#", ".abcd.abcd#."}, - { MU, A, 0, 0, "a(?R)|([a-z]++)#", ".abcd.mbcd#."}, - { MU, A, 0, 0, ".[ab]*.", "xx" }, - { MU, A, 0, 0, ".[ab]*a", "xxa" }, - { MU, A, 0, 0, ".[ab]?.", "xx" }, - - /* Bracket repeats with limit. */ - { MU, A, 0, 0, "(?:(ab){2}){5}M", "abababababababababababM" }, - { MU, A, 0, 0, "(?:ab|abab){1,5}M", "abababababababababababM" }, - { MU, A, 0, 0, "(?>ab|abab){1,5}M", "abababababababababababM" }, - { MU, A, 0, 0, "(?:ab|abab){1,5}?M", "abababababababababababM" }, - { MU, A, 0, 0, "(?>ab|abab){1,5}?M", "abababababababababababM" }, - { MU, A, 0, 0, "(?:(ab){1,4}?){1,3}?M", "abababababababababababababM" }, - { MU, A, 0, 0, "(?:(ab){1,4}){1,3}abababababababababababM", "ababababababababababababM" }, - { MU, A, 0, 0 | F_NOMATCH, "(?:(ab){1,4}){1,3}abababababababababababM", "abababababababababababM" }, - { MU, A, 0, 0, "(ab){4,6}?M", "abababababababM" }, - - /* Basic character sets. */ - { MU, A, 0, 0, "(?:\\s)+(?:\\S)+", "ab \t\xc3\xa9\xe6\x92\xad " }, - { MU, A, 0, 0, "(\\w)*(k)(\\W)?\?", "abcdef abck11" }, - { MU, A, 0, 0, "\\((\\d)+\\)\\D", "a() (83 (8)2 (9)ab" }, - { MU, A, 0, 0, "\\w(\\s|(?:\\d)*,)+\\w\\wb", "a 5, 4,, bb 5, 4,, aab" }, - { MU, A, 0, 0, "(\\v+)(\\V+)", "\x0e\xc2\x85\xe2\x80\xa8\x0b\x09\xe2\x80\xa9" }, - { MU, A, 0, 0, "(\\h+)(\\H+)", "\xe2\x80\xa8\xe2\x80\x80\x20\xe2\x80\x8a\xe2\x81\x9f\xe3\x80\x80\x09\x20\xc2\xa0\x0a" }, - { MU, A, 0, 0, "x[bcef]+", "xaxdxecbfg" }, - { MU, A, 0, 0, "x[bcdghij]+", "xaxexfxdgbjk" }, - { MU, A, 0, 0, "x[^befg]+", "xbxexacdhg" }, - { MU, A, 0, 0, "x[^bcdl]+", "xlxbxaekmd" }, - { MU, A, 0, 0, "x[^bcdghi]+", "xbxdxgxaefji" }, - { MU, A, 0, 0, "x[B-Fb-f]+", "xaxAxgxbfBFG" }, - { CMU, A, 0, 0, "\\x{e9}+", "#\xf0\x90\x90\xa8\xc3\xa8\xc3\xa9\xc3\x89\xc3\x88" }, - { CMU, A, 0, 0, "[^\\x{e9}]+", "\xc3\xa9#\xf0\x90\x90\xa8\xc3\xa8\xc3\x88\xc3\x89" }, - { MU, A, 0, 0, "[\\x02\\x7e]+", "\xc3\x81\xe1\xbf\xb8\xf0\x90\x90\xa8\x01\x02\x7e\x7f" }, - { MU, A, 0, 0, "[^\\x02\\x7e]+", "\x02\xc3\x81\xe1\xbf\xb8\xf0\x90\x90\xa8\x01\x7f\x7e" }, - { MU, A, 0, 0, "[\\x{81}-\\x{7fe}]+", "#\xe1\xbf\xb8\xf0\x90\x90\xa8\xc2\x80\xc2\x81\xdf\xbe\xdf\xbf" }, - { MU, A, 0, 0, "[^\\x{81}-\\x{7fe}]+", "\xc2\x81#\xe1\xbf\xb8\xf0\x90\x90\xa8\xc2\x80\xdf\xbf\xdf\xbe" }, - { MU, A, 0, 0, "[\\x{801}-\\x{fffe}]+", "#\xc3\xa9\xf0\x90\x90\x80\xe0\xa0\x80\xe0\xa0\x81\xef\xbf\xbe\xef\xbf\xbf" }, - { MU, A, 0, 0, "[^\\x{801}-\\x{fffe}]+", "\xe0\xa0\x81#\xc3\xa9\xf0\x90\x90\x80\xe0\xa0\x80\xef\xbf\xbf\xef\xbf\xbe" }, - { MU, A, 0, 0, "[\\x{10001}-\\x{10fffe}]+", "#\xc3\xa9\xe2\xb1\xa5\xf0\x90\x80\x80\xf0\x90\x80\x81\xf4\x8f\xbf\xbe\xf4\x8f\xbf\xbf" }, - { MU, A, 0, 0, "[^\\x{10001}-\\x{10fffe}]+", "\xf0\x90\x80\x81#\xc3\xa9\xe2\xb1\xa5\xf0\x90\x80\x80\xf4\x8f\xbf\xbf\xf4\x8f\xbf\xbe" }, - - /* Unicode properties. */ - { MUP, A, 0, 0, "[1-5\xc3\xa9\\w]", "\xc3\xa1_" }, - { MUP, A, 0, 0 | F_PROPERTY, "[\xc3\x81\\p{Ll}]", "A_\xc3\x89\xc3\xa1" }, - { MUP, A, 0, 0, "[\\Wd-h_x-z]+", "a\xc2\xa1#_yhzdxi" }, - { MUP, A, 0, 0 | F_NOMATCH | F_PROPERTY, "[\\P{Any}]", "abc" }, - { MUP, A, 0, 0 | F_NOMATCH | F_PROPERTY, "[^\\p{Any}]", "abc" }, - { MUP, A, 0, 0 | F_NOMATCH | F_PROPERTY, "[\\P{Any}\xc3\xa1-\xc3\xa8]", "abc" }, - { MUP, A, 0, 0 | F_NOMATCH | F_PROPERTY, "[^\\p{Any}\xc3\xa1-\xc3\xa8]", "abc" }, - { MUP, A, 0, 0 | F_NOMATCH | F_PROPERTY, "[\xc3\xa1-\xc3\xa8\\P{Any}]", "abc" }, - { MUP, A, 0, 0 | F_NOMATCH | F_PROPERTY, "[^\xc3\xa1-\xc3\xa8\\p{Any}]", "abc" }, - { MUP, A, 0, 0 | F_PROPERTY, "[\xc3\xa1-\xc3\xa8\\p{Any}]", "abc" }, - { MUP, A, 0, 0 | F_PROPERTY, "[^\xc3\xa1-\xc3\xa8\\P{Any}]", "abc" }, - { MUP, A, 0, 0, "[b-\xc3\xa9\\s]", "a\xc\xe6\x92\xad" }, - { CMUP, A, 0, 0, "[\xc2\x85-\xc2\x89\xc3\x89]", "\xc2\x84\xc3\xa9" }, - { MUP, A, 0, 0, "[^b-d^&\\s]{3,}", "db^ !a\xe2\x80\xa8_ae" }, - { MUP, A, 0, 0 | F_PROPERTY, "[^\\S\\P{Any}][\\sN]{1,3}[\\P{N}]{4}", "\xe2\x80\xaa\xa N\x9\xc3\xa9_0" }, - { MU, A, 0, 0 | F_PROPERTY, "[^\\P{L}\x9!D-F\xa]{2,3}", "\x9,.DF\xa.CG\xc3\x81" }, - { CMUP, A, 0, 0, "[\xc3\xa1-\xc3\xa9_\xe2\x80\xa0-\xe2\x80\xaf]{1,5}[^\xe2\x80\xa0-\xe2\x80\xaf]", "\xc2\xa1\xc3\x89\xc3\x89\xe2\x80\xaf_\xe2\x80\xa0" }, - { MUP, A, 0, 0 | F_PROPERTY, "[\xc3\xa2-\xc3\xa6\xc3\x81-\xc3\x84\xe2\x80\xa8-\xe2\x80\xa9\xe6\x92\xad\\p{Zs}]{2,}", "\xe2\x80\xa7\xe2\x80\xa9\xe6\x92\xad \xe6\x92\xae" }, - { MUP, A, 0, 0 | F_PROPERTY, "[\\P{L&}]{2}[^\xc2\x85-\xc2\x89\\p{Ll}\\p{Lu}]{2}", "\xc3\xa9\xe6\x92\xad.a\xe6\x92\xad|\xc2\x8a#" }, - { PCRE2_UCP, 0, 0, 0 | F_PROPERTY, "[a-b\\s]{2,5}[^a]", "AB baaa" }, - - /* Possible empty brackets. */ - { MU, A, 0, 0, "(?:|ab||bc|a)+d", "abcxabcabd" }, - { MU, A, 0, 0, "(|ab||bc|a)+d", "abcxabcabd" }, - { MU, A, 0, 0, "(?:|ab||bc|a)*d", "abcxabcabd" }, - { MU, A, 0, 0, "(|ab||bc|a)*d", "abcxabcabd" }, - { MU, A, 0, 0, "(?:|ab||bc|a)+?d", "abcxabcabd" }, - { MU, A, 0, 0, "(|ab||bc|a)+?d", "abcxabcabd" }, - { MU, A, 0, 0, "(?:|ab||bc|a)*?d", "abcxabcabd" }, - { MU, A, 0, 0, "(|ab||bc|a)*?d", "abcxabcabd" }, - { MU, A, 0, 0, "(((a)*?|(?:ba)+)+?|(?:|c|ca)*)*m", "abaacaccabacabalabaacaccabacabamm" }, - { MU, A, 0, 0, "(?:((?:a)*|(ba)+?)+|(|c|ca)*?)*?m", "abaacaccabacabalabaacaccabacabamm" }, - - /* Start offset. */ - { MU, A, 0, 3, "(\\d|(?:\\w)*\\w)+", "0ac01Hb" }, - { MU, A, 0, 4 | F_NOMATCH, "(\\w\\W\\w)+", "ab#d" }, - { MU, A, 0, 2 | F_NOMATCH, "(\\w\\W\\w)+", "ab#d" }, - { MU, A, 0, 1, "(\\w\\W\\w)+", "ab#d" }, - - /* Newline. */ - { M, PCRE2_NEWLINE_CRLF, 0, 0, "\\W{0,2}[^#]{3}", "\r\n#....." }, - { M, PCRE2_NEWLINE_CR, 0, 0, "\\W{0,2}[^#]{3}", "\r\n#....." }, - { M, PCRE2_NEWLINE_CRLF, 0, 0, "\\W{1,3}[^#]", "\r\n##...." }, - { MU, A, PCRE2_NO_UTF_CHECK, 1, "^.a", "\n\x80\nxa" }, - { MU, A, 0, 1, "^", "\r\n" }, - { M, PCRE2_NEWLINE_CRLF, 0, 1 | F_NOMATCH, "^", "\r\n" }, - { M, PCRE2_NEWLINE_CRLF, 0, 1, "^", "\r\na" }, - - /* Any character except newline or any newline. */ - { 0, PCRE2_NEWLINE_CRLF, 0, 0, ".", "\r" }, - { U, PCRE2_NEWLINE_CRLF, 0, 0, ".(.).", "a\xc3\xa1\r\n\n\r\r" }, - { 0, PCRE2_NEWLINE_ANYCRLF, 0, 0, ".(.)", "a\rb\nc\r\n\xc2\x85\xe2\x80\xa8" }, - { U, PCRE2_NEWLINE_ANYCRLF, 0, 0, ".(.)", "a\rb\nc\r\n\xc2\x85\xe2\x80\xa8" }, - { U, PCRE2_NEWLINE_ANY, 0, 0, "(.).", "a\rb\nc\r\n\xc2\x85\xe2\x80\xa9$de" }, - { U, PCRE2_NEWLINE_ANYCRLF, 0, 0 | F_NOMATCH, ".(.).", "\xe2\x80\xa8\nb\r" }, - { 0, PCRE2_NEWLINE_ANY, 0, 0, "(.)(.)", "#\x85#\r#\n#\r\n#\x84" }, - { U, PCRE2_NEWLINE_ANY, 0, 0, "(.+)#", "#\rMn\xc2\x85#\n###" }, - { 0, BSR(PCRE2_BSR_ANYCRLF), 0, 0, "\\R", "\r" }, - { 0, BSR(PCRE2_BSR_ANYCRLF), 0, 0, "\\R", "\x85#\r\n#" }, - { U, BSR(PCRE2_BSR_UNICODE), 0, 0, "\\R", "ab\xe2\x80\xa8#c" }, - { U, BSR(PCRE2_BSR_UNICODE), 0, 0, "\\R", "ab\r\nc" }, - { U, PCRE2_NEWLINE_CRLF | BSR(PCRE2_BSR_UNICODE), 0, 0, "(\\R.)+", "\xc2\x85\r\n#\xe2\x80\xa8\n\r\n\r" }, - { MU, A, 0, 0 | F_NOMATCH, "\\R+", "ab" }, - { MU, A, 0, 0, "\\R+", "ab\r\n\r" }, - { MU, A, 0, 0, "\\R*", "ab\r\n\r" }, - { MU, A, 0, 0, "\\R*", "\r\n\r" }, - { MU, A, 0, 0, "\\R{2,4}", "\r\nab\r\r" }, - { MU, A, 0, 0, "\\R{2,4}", "\r\nab\n\n\n\r\r\r" }, - { MU, A, 0, 0, "\\R{2,}", "\r\nab\n\n\n\r\r\r" }, - { MU, A, 0, 0, "\\R{0,3}", "\r\n\r\n\r\n\r\n\r\n" }, - { MU, A, 0, 0 | F_NOMATCH, "\\R+\\R\\R", "\r\n\r\n" }, - { MU, A, 0, 0, "\\R+\\R\\R", "\r\r\r" }, - { MU, A, 0, 0, "\\R*\\R\\R", "\n\r" }, - { MU, A, 0, 0 | F_NOMATCH, "\\R{2,4}\\R\\R", "\r\r\r" }, - { MU, A, 0, 0, "\\R{2,4}\\R\\R", "\r\r\r\r" }, - - /* Atomic groups (no fallback from "next" direction). */ - { MU, A, 0, 0 | F_NOMATCH, "(?>ab)ab", "bab" }, - { MU, A, 0, 0 | F_NOMATCH, "(?>(ab))ab", "bab" }, - { MU, A, 0, 0, "(?>ab)+abc(?>de)*def(?>gh)?ghe(?>ij)+?k(?>lm)*?n(?>op)?\?op", - "bababcdedefgheijijklmlmnop" }, - { MU, A, 0, 0, "(?>a(b)+a|(ab)?\?(b))an", "abban" }, - { MU, A, 0, 0, "(?>ab+a|(?:ab)?\?b)an", "abban" }, - { MU, A, 0, 0, "((?>ab|ad|)*?)(?>|c)*abad", "abababcababad" }, - { MU, A, 0, 0, "(?>(aa|b|)*+(?>(##)|###)*d|(aa)(?>(baa)?)m)", "aabaa#####da" }, - { MU, A, 0, 0, "((?>a|)+?)b", "aaacaaab" }, - { MU, A, 0, 0, "(?>x|)*$", "aaa" }, - { MU, A, 0, 0, "(?>(x)|)*$", "aaa" }, - { MU, A, 0, 0, "(?>x|())*$", "aaa" }, - { MU, A, 0, 0, "((?>[cxy]a|[a-d])*?)b", "aaa+ aaab" }, - { MU, A, 0, 0, "((?>[cxy](a)|[a-d])*?)b", "aaa+ aaab" }, - { MU, A, 0, 0, "(?>((?>(a+))))bab|(?>((?>(a+))))bb", "aaaabaaabaabab" }, - { MU, A, 0, 0, "(?>(?>a+))bab|(?>(?>a+))bb", "aaaabaaabaabab" }, - { MU, A, 0, 0, "(?>(a)c|(?>(c)|(a))a)b*?bab", "aaaabaaabaabab" }, - { MU, A, 0, 0, "(?>ac|(?>c|a)a)b*?bab", "aaaabaaabaabab" }, - { MU, A, 0, 0, "(?>(b)b|(a))*b(?>(c)|d)?x", "ababcaaabdbx" }, - { MU, A, 0, 0, "(?>bb|a)*b(?>c|d)?x", "ababcaaabdbx" }, - { MU, A, 0, 0, "(?>(bb)|a)*b(?>c|(d))?x", "ababcaaabdbx" }, - { MU, A, 0, 0, "(?>(a))*?(?>(a))+?(?>(a))??x", "aaaaaacccaaaaabax" }, - { MU, A, 0, 0, "(?>a)*?(?>a)+?(?>a)??x", "aaaaaacccaaaaabax" }, - { MU, A, 0, 0, "(?>(a)|)*?(?>(a)|)+?(?>(a)|)??x", "aaaaaacccaaaaabax" }, - { MU, A, 0, 0, "(?>a|)*?(?>a|)+?(?>a|)??x", "aaaaaacccaaaaabax" }, - { MU, A, 0, 0, "(?>a(?>(a{0,2}))*?b|aac)+b", "aaaaaaacaaaabaaaaacaaaabaacaaabb" }, - { CM, A, 0, 0, "(?>((?>a{32}|b+|(a*))?(?>c+|d*)?\?)+e)+?f", "aaccebbdde bbdaaaccebbdee bbdaaaccebbdeef" }, - { MU, A, 0, 0, "(?>(?:(?>aa|a||x)+?b|(?>aa|a||(x))+?c)?(?>[ad]{0,2})*?d)+d", "aaacdbaabdcabdbaaacd aacaabdbdcdcaaaadaabcbaadd" }, - { MU, A, 0, 0, "(?>(?:(?>aa|a||(x))+?b|(?>aa|a||x)+?c)?(?>[ad]{0,2})*?d)+d", "aaacdbaabdcabdbaaacd aacaabdbdcdcaaaadaabcbaadd" }, - { MU, A, 0, 0 | F_PROPERTY, "\\X", "\xcc\x8d\xcc\x8d" }, - { MU, A, 0, 0 | F_PROPERTY, "\\X", "\xcc\x8d\xcc\x8d#\xcc\x8d\xcc\x8d" }, - { MU, A, 0, 0 | F_PROPERTY, "\\X+..", "\xcc\x8d#\xcc\x8d#\xcc\x8d\xcc\x8d" }, - { MU, A, 0, 0 | F_PROPERTY, "\\X{2,4}", "abcdef" }, - { MU, A, 0, 0 | F_PROPERTY, "\\X{2,4}?", "abcdef" }, - { MU, A, 0, 0 | F_NOMATCH | F_PROPERTY, "\\X{2,4}..", "#\xcc\x8d##" }, - { MU, A, 0, 0 | F_PROPERTY, "\\X{2,4}..", "#\xcc\x8d#\xcc\x8d##" }, - { MU, A, 0, 0, "(c(ab)?+ab)+", "cabcababcab" }, - { MU, A, 0, 0, "(?>(a+)b)+aabab", "aaaabaaabaabab" }, - - /* Possessive quantifiers. */ - { MU, A, 0, 0, "(?:a|b)++m", "mababbaaxababbaam" }, - { MU, A, 0, 0, "(?:a|b)*+m", "mababbaaxababbaam" }, - { MU, A, 0, 0, "(?:a|b)*+m", "ababbaaxababbaam" }, - { MU, A, 0, 0, "(a|b)++m", "mababbaaxababbaam" }, - { MU, A, 0, 0, "(a|b)*+m", "mababbaaxababbaam" }, - { MU, A, 0, 0, "(a|b)*+m", "ababbaaxababbaam" }, - { MU, A, 0, 0, "(a|b(*ACCEPT))++m", "maaxab" }, - { MU, A, 0, 0, "(?:b*)++m", "bxbbxbbbxm" }, - { MU, A, 0, 0, "(?:b*)++m", "bxbbxbbbxbbm" }, - { MU, A, 0, 0, "(?:b*)*+m", "bxbbxbbbxm" }, - { MU, A, 0, 0, "(?:b*)*+m", "bxbbxbbbxbbm" }, - { MU, A, 0, 0, "(b*)++m", "bxbbxbbbxm" }, - { MU, A, 0, 0, "(b*)++m", "bxbbxbbbxbbm" }, - { MU, A, 0, 0, "(b*)*+m", "bxbbxbbbxm" }, - { MU, A, 0, 0, "(b*)*+m", "bxbbxbbbxbbm" }, - { MU, A, 0, 0, "(?:a|(b))++m", "mababbaaxababbaam" }, - { MU, A, 0, 0, "(?:(a)|b)*+m", "mababbaaxababbaam" }, - { MU, A, 0, 0, "(?:(a)|(b))*+m", "ababbaaxababbaam" }, - { MU, A, 0, 0, "(a|(b))++m", "mababbaaxababbaam" }, - { MU, A, 0, 0, "((a)|b)*+m", "mababbaaxababbaam" }, - { MU, A, 0, 0, "((a)|(b))*+m", "ababbaaxababbaam" }, - { MU, A, 0, 0, "(a|(b)(*ACCEPT))++m", "maaxab" }, - { MU, A, 0, 0, "(?:(b*))++m", "bxbbxbbbxm" }, - { MU, A, 0, 0, "(?:(b*))++m", "bxbbxbbbxbbm" }, - { MU, A, 0, 0, "(?:(b*))*+m", "bxbbxbbbxm" }, - { MU, A, 0, 0, "(?:(b*))*+m", "bxbbxbbbxbbm" }, - { MU, A, 0, 0, "((b*))++m", "bxbbxbbbxm" }, - { MU, A, 0, 0, "((b*))++m", "bxbbxbbbxbbm" }, - { MU, A, 0, 0, "((b*))*+m", "bxbbxbbbxm" }, - { MU, A, 0, 0, "((b*))*+m", "bxbbxbbbxbbm" }, - { MU, A, 0, 0 | F_NOMATCH, "(?>(b{2,4}))(?:(?:(aa|c))++m|(?:(aa|c))+n)", "bbaacaaccaaaacxbbbmbn" }, - { MU, A, 0, 0, "((?:b)++a)+(cd)*+m", "bbababbacdcdnbbababbacdcdm" }, - { MU, A, 0, 0, "((?:(b))++a)+((c)d)*+m", "bbababbacdcdnbbababbacdcdm" }, - { MU, A, 0, 0, "(?:(?:(?:ab)*+k)++(?:n(?:cd)++)*+)*+m", "ababkkXababkkabkncXababkkabkncdcdncdXababkkabkncdcdncdkkabkncdXababkkabkncdcdncdkkabkncdm" }, - { MU, A, 0, 0, "(?:((ab)*+(k))++(n(?:c(d))++)*+)*+m", "ababkkXababkkabkncXababkkabkncdcdncdXababkkabkncdcdncdkkabkncdXababkkabkncdcdncdkkabkncdm" }, - - /* Back references. */ - { MU, A, 0, 0, "(aa|bb)(\\1*)(ll|)(\\3*)bbbbbbc", "aaaaaabbbbbbbbc" }, - { CMU, A, 0, 0, "(aa|bb)(\\1+)(ll|)(\\3+)bbbbbbc", "bBbbBbCbBbbbBbbcbbBbbbBBbbC" }, - { CM, A, 0, 0, "(a{2,4})\\1", "AaAaaAaA" }, - { MU, A, 0, 0, "(aa|bb)(\\1?)aa(\\1?)(ll|)(\\4+)bbc", "aaaaaaaabbaabbbbaabbbbc" }, - { MU, A, 0, 0, "(aa|bb)(\\1{0,5})(ll|)(\\3{0,5})cc", "bbxxbbbbxxaaaaaaaaaaaaaaaacc" }, - { MU, A, 0, 0, "(aa|bb)(\\1{3,5})(ll|)(\\3{3,5})cc", "bbbbbbbbbbbbaaaaaaccbbbbbbbbbbbbbbcc" }, - { MU, A, 0, 0, "(aa|bb)(\\1{3,})(ll|)(\\3{3,})cc", "bbbbbbbbbbbbaaaaaaccbbbbbbbbbbbbbbcc" }, - { MU, A, 0, 0, "(\\w+)b(\\1+)c", "GabGaGaDbGaDGaDc" }, - { MU, A, 0, 0, "(?:(aa)|b)\\1?b", "bb" }, - { CMU, A, 0, 0, "(aa|bb)(\\1*?)aa(\\1+?)", "bBBbaaAAaaAAaa" }, - { MU, A, 0, 0, "(aa|bb)(\\1*?)(dd|)cc(\\3+?)", "aaaaaccdd" }, - { CMU, A, 0, 0, "(?:(aa|bb)(\\1?\?)cc){2}(\\1?\?)", "aAaABBbbAAaAcCaAcCaA" }, - { MU, A, 0, 0, "(?:(aa|bb)(\\1{3,5}?)){2}(dd|)(\\3{3,5}?)", "aaaaaabbbbbbbbbbaaaaaaaaaaaaaa" }, - { CM, A, 0, 0, "(?:(aa|bb)(\\1{3,}?)){2}(dd|)(\\3{3,}?)", "aaaaaabbbbbbbbbbaaaaaaaaaaaaaa" }, - { MU, A, 0, 0, "(?:(aa|bb)(\\1{0,3}?)){2}(dd|)(\\3{0,3}?)b(\\1{0,3}?)(\\1{0,3})", "aaaaaaaaaaaaaaabaaaaa" }, - { MU, A, 0, 0, "(a(?:\\1|)a){3}b", "aaaaaaaaaaab" }, - { M, A, 0, 0, "(a?)b(\\1\\1*\\1+\\1?\\1*?\\1+?\\1??\\1*+\\1++\\1?+\\1{4}\\1{3,5}\\1{4,}\\1{0,5}\\1{3,5}?\\1{4,}?\\1{0,5}?\\1{3,5}+\\1{4,}+\\1{0,5}+#){2}d", "bb#b##d" }, - { MUP, A, 0, 0 | F_PROPERTY, "(\\P{N})\\1{2,}", ".www." }, - { MUP, A, 0, 0 | F_PROPERTY, "(\\P{N})\\1{0,2}", "wwwww." }, - { MUP, A, 0, 0 | F_PROPERTY, "(\\P{N})\\1{1,2}ww", "wwww" }, - { MUP, A, 0, 0 | F_PROPERTY, "(\\P{N})\\1{1,2}ww", "wwwww" }, - { PCRE2_UCP, 0, 0, 0 | F_PROPERTY, "(\\P{N})\\1{2,}", ".www." }, - { CMUP, A, 0, 0, "(\xf0\x90\x90\x80)\\1", "\xf0\x90\x90\xa8\xf0\x90\x90\xa8" }, - { MU | PCRE2_DUPNAMES, A, 0, 0 | F_NOMATCH, "\\k<A>{1,3}(?<A>aa)(?<A>bb)", "aabb" }, - { MU | PCRE2_DUPNAMES | PCRE2_MATCH_UNSET_BACKREF, A, 0, 0, "\\k<A>{1,3}(?<A>aa)(?<A>bb)", "aabb" }, - { MU | PCRE2_DUPNAMES | PCRE2_MATCH_UNSET_BACKREF, A, 0, 0, "\\k<A>*(?<A>aa)(?<A>bb)", "aabb" }, - { MU | PCRE2_DUPNAMES, A, 0, 0, "(?<A>aa)(?<A>bb)\\k<A>{0,3}aaaaaa", "aabbaaaaaa" }, - { MU | PCRE2_DUPNAMES, A, 0, 0, "(?<A>aa)(?<A>bb)\\k<A>{2,5}bb", "aabbaaaabb" }, - { MU | PCRE2_DUPNAMES, A, 0, 0, "(?:(?<A>aa)|(?<A>bb))\\k<A>{0,3}m", "aaaaaaaabbbbaabbbbm" }, - { MU | PCRE2_DUPNAMES, A, 0, 0 | F_NOMATCH, "\\k<A>{1,3}?(?<A>aa)(?<A>bb)", "aabb" }, - { MU | PCRE2_DUPNAMES | PCRE2_MATCH_UNSET_BACKREF, A, 0, 0, "\\k<A>{1,3}?(?<A>aa)(?<A>bb)", "aabb" }, - { MU | PCRE2_DUPNAMES, A, 0, 0, "\\k<A>*?(?<A>aa)(?<A>bb)", "aabb" }, - { MU | PCRE2_DUPNAMES, A, 0, 0, "(?:(?<A>aa)|(?<A>bb))\\k<A>{0,3}?m", "aaaaaabbbbbbaabbbbbbbbbbm" }, - { MU | PCRE2_DUPNAMES, A, 0, 0, "(?:(?<A>aa)|(?<A>bb))\\k<A>*?m", "aaaaaabbbbbbaabbbbbbbbbbm" }, - { MU | PCRE2_DUPNAMES, A, 0, 0, "(?:(?<A>aa)|(?<A>bb))\\k<A>{2,3}?", "aaaabbbbaaaabbbbbbbbbb" }, - { CMU | PCRE2_DUPNAMES, A, 0, 0, "(?:(?<A>AA)|(?<A>BB))\\k<A>{0,3}M", "aaaaaaaabbbbaabbbbm" }, - { CMU | PCRE2_DUPNAMES, A, 0, 0, "(?:(?<A>AA)|(?<A>BB))\\k<A>{1,3}M", "aaaaaaaabbbbaabbbbm" }, - { CMU | PCRE2_DUPNAMES, A, 0, 0, "(?:(?<A>AA)|(?<A>BB))\\k<A>{0,3}?M", "aaaaaabbbbbbaabbbbbbbbbbm" }, - { CMU | PCRE2_DUPNAMES, A, 0, 0, "(?:(?<A>AA)|(?<A>BB))\\k<A>{2,3}?", "aaaabbbbaaaabbbbbbbbbb" }, - - /* Assertions. */ - { MU, A, 0, 0, "(?=xx|yy|zz)\\w{4}", "abczzdefg" }, - { MU, A, 0, 0, "(?=((\\w+)b){3}|ab)", "dbbbb ab" }, - { MU, A, 0, 0, "(?!ab|bc|cd)[a-z]{2}", "Xabcdef" }, - { MU, A, 0, 0, "(?<=aaa|aa|a)a", "aaa" }, - { MU, A, 0, 2, "(?<=aaa|aa|a)a", "aaa" }, - { M, A, 0, 0, "(?<=aaa|aa|a)a", "aaa" }, - { M, A, 0, 2, "(?<=aaa|aa|a)a", "aaa" }, - { MU, A, 0, 0, "(\\d{2})(?!\\w+c|(((\\w?)m){2}n)+|\\1)", "x5656" }, - { MU, A, 0, 0, "((?=((\\d{2,6}\\w){2,}))\\w{5,20}K){2,}", "567v09708K12l00M00 567v09708K12l00M00K45K" }, - { MU, A, 0, 0, "(?=(?:(?=\\S+a)\\w*(b)){3})\\w+\\d", "bba bbab nbbkba nbbkba0kl" }, - { MU, A, 0, 0, "(?>a(?>(b+))a(?=(..)))*?k", "acabbcabbaabacabaabbakk" }, - { MU, A, 0, 0, "((?(?=(a))a)+k)", "bbak" }, - { MU, A, 0, 0, "((?(?=a)a)+k)", "bbak" }, - { MU, A, 0, 0 | F_NOMATCH, "(?=(?>(a))m)amk", "a k" }, - { MU, A, 0, 0 | F_NOMATCH, "(?!(?>(a))m)amk", "a k" }, - { MU, A, 0, 0 | F_NOMATCH, "(?>(?=(a))am)amk", "a k" }, - { MU, A, 0, 0, "(?=(?>a|(?=(?>(b+))a|c)[a-c]+)*?m)[a-cm]+k", "aaam bbam baaambaam abbabba baaambaamk" }, - { MU, A, 0, 0, "(?> ?\?\\b(?(?=\\w{1,4}(a))m)\\w{0,8}bc){2,}?", "bca ssbc mabd ssbc mabc" }, - { MU, A, 0, 0, "(?:(?=ab)?[^n][^n])+m", "ababcdabcdcdabnababcdabcdcdabm" }, - { MU, A, 0, 0, "(?:(?=a(b))?[^n][^n])+m", "ababcdabcdcdabnababcdabcdcdabm" }, - { MU, A, 0, 0, "(?:(?=.(.))??\\1.)+m", "aabbbcbacccanaabbbcbacccam" }, - { MU, A, 0, 0, "(?:(?=.)??[a-c])+m", "abacdcbacacdcaccam" }, - { MU, A, 0, 0, "((?!a)?(?!([^a]))?)+$", "acbab" }, - { MU, A, 0, 0, "((?!a)?\?(?!([^a]))?\?)+$", "acbab" }, - { MU, A, 0, 0, "a(?=(?C)\\B(?C`x`))b", "ab" }, - { MU, A, 0, 0, "a(?!(?C)\\B(?C`x`))bb|ab", "abb" }, - { MU, A, 0, 0, "a(?=\\b|(?C)\\B(?C`x`))b", "ab" }, - { MU, A, 0, 0, "a(?!\\b|(?C)\\B(?C`x`))bb|ab", "abb" }, - { MU, A, 0, 0, "c(?(?=(?C)\\B(?C`x`))ab|a)", "cab" }, - { MU, A, 0, 0, "c(?(?!(?C)\\B(?C`x`))ab|a)", "cab" }, - { MU, A, 0, 0, "c(?(?=\\b|(?C)\\B(?C`x`))ab|a)", "cab" }, - { MU, A, 0, 0, "c(?(?!\\b|(?C)\\B(?C`x`))ab|a)", "cab" }, - { MU, A, 0, 0, "a(?=)b", "ab" }, - { MU, A, 0, 0 | F_NOMATCH, "a(?!)b", "ab" }, - - /* Not empty, ACCEPT, FAIL */ - { MU, A, PCRE2_NOTEMPTY, 0 | F_NOMATCH, "a*", "bcx" }, - { MU, A, PCRE2_NOTEMPTY, 0, "a*", "bcaad" }, - { MU, A, PCRE2_NOTEMPTY, 0, "a*?", "bcaad" }, - { MU, A, PCRE2_NOTEMPTY_ATSTART, 0, "a*", "bcaad" }, - { MU, A, 0, 0, "a(*ACCEPT)b", "ab" }, - { MU, A, PCRE2_NOTEMPTY, 0 | F_NOMATCH, "a*(*ACCEPT)b", "bcx" }, - { MU, A, PCRE2_NOTEMPTY, 0, "a*(*ACCEPT)b", "bcaad" }, - { MU, A, PCRE2_NOTEMPTY, 0, "a*?(*ACCEPT)b", "bcaad" }, - { MU, A, PCRE2_NOTEMPTY, 0 | F_NOMATCH, "(?:z|a*(*ACCEPT)b)", "bcx" }, - { MU, A, PCRE2_NOTEMPTY, 0, "(?:z|a*(*ACCEPT)b)", "bcaad" }, - { MU, A, PCRE2_NOTEMPTY, 0, "(?:z|a*?(*ACCEPT)b)", "bcaad" }, - { MU, A, PCRE2_NOTEMPTY_ATSTART, 0, "a*(*ACCEPT)b", "bcx" }, - { MU, A, PCRE2_NOTEMPTY_ATSTART, 0 | F_NOMATCH, "a*(*ACCEPT)b", "" }, - { MU, A, 0, 0, "((a(*ACCEPT)b))", "ab" }, - { MU, A, 0, 0, "(a(*FAIL)a|a)", "aaa" }, - { MU, A, 0, 0, "(?=ab(*ACCEPT)b)a", "ab" }, - { MU, A, 0, 0, "(?=(?:x|ab(*ACCEPT)b))", "ab" }, - { MU, A, 0, 0, "(?=(a(b(*ACCEPT)b)))a", "ab" }, - { MU, A, PCRE2_NOTEMPTY, 0, "(?=a*(*ACCEPT))c", "c" }, - - /* Conditional blocks. */ - { MU, A, 0, 0, "(?(?=(a))a|b)+k", "ababbalbbadabak" }, - { MU, A, 0, 0, "(?(?!(b))a|b)+k", "ababbalbbadabak" }, - { MU, A, 0, 0, "(?(?=a)a|b)+k", "ababbalbbadabak" }, - { MU, A, 0, 0, "(?(?!b)a|b)+k", "ababbalbbadabak" }, - { MU, A, 0, 0, "(?(?=(a))a*|b*)+k", "ababbalbbadabak" }, - { MU, A, 0, 0, "(?(?!(b))a*|b*)+k", "ababbalbbadabak" }, - { MU, A, 0, 0, "(?(?!(b))(?:aaaaaa|a)|(?:bbbbbb|b))+aaaak", "aaaaaaaaaaaaaa bbbbbbbbbbbbbbb aaaaaaak" }, - { MU, A, 0, 0, "(?(?!b)(?:aaaaaa|a)|(?:bbbbbb|b))+aaaak", "aaaaaaaaaaaaaa bbbbbbbbbbbbbbb aaaaaaak" }, - { MU, A, 0, 0 | F_DIFF, "(?(?!(b))(?:aaaaaa|a)|(?:bbbbbb|b))+bbbbk", "aaaaaaaaaaaaaa bbbbbbbbbbbbbbb bbbbbbbk" }, - { MU, A, 0, 0, "(?(?!b)(?:aaaaaa|a)|(?:bbbbbb|b))+bbbbk", "aaaaaaaaaaaaaa bbbbbbbbbbbbbbb bbbbbbbk" }, - { MU, A, 0, 0, "(?(?=a)a*|b*)+k", "ababbalbbadabak" }, - { MU, A, 0, 0, "(?(?!b)a*|b*)+k", "ababbalbbadabak" }, - { MU, A, 0, 0, "(?(?=a)ab)", "a" }, - { MU, A, 0, 0, "(?(?<!b)c)", "b" }, - { MU, A, 0, 0, "(?(DEFINE)a(b))", "a" }, - { MU, A, 0, 0, "a(?(DEFINE)(?:b|(?:c?)+)*)", "a" }, - { MU, A, 0, 0, "(?(?=.[a-c])[k-l]|[A-D])", "kdB" }, - { MU, A, 0, 0, "(?(?!.{0,4}[cd])(aa|bb)|(cc|dd))+", "aabbccddaa" }, - { MU, A, 0, 0, "(?(?=[^#@]*@)(aaab|aa|aba)|(aba|aab)){3,}", "aaabaaaba#aaabaaaba#aaabaaaba@" }, - { MU, A, 0, 0, "((?=\\w{5})\\w(?(?=\\w*k)\\d|[a-f_])*\\w\\s)+", "mol m10kk m088k _f_a_ mbkkl" }, - { MU, A, 0, 0, "(c)?\?(?(1)a|b)", "cdcaa" }, - { MU, A, 0, 0, "(c)?\?(?(1)a|b)", "cbb" }, - { MU, A, 0, 0 | F_DIFF, "(?(?=(a))(aaaa|a?))+aak", "aaaaab aaaaak" }, - { MU, A, 0, 0, "(?(?=a)(aaaa|a?))+aak", "aaaaab aaaaak" }, - { MU, A, 0, 0, "(?(?!(b))(aaaa|a?))+aak", "aaaaab aaaaak" }, - { MU, A, 0, 0, "(?(?!b)(aaaa|a?))+aak", "aaaaab aaaaak" }, - { MU, A, 0, 0 | F_DIFF, "(?(?=(a))a*)+aak", "aaaaab aaaaak" }, - { MU, A, 0, 0, "(?(?=a)a*)+aak", "aaaaab aaaaak" }, - { MU, A, 0, 0, "(?(?!(b))a*)+aak", "aaaaab aaaaak" }, - { MU, A, 0, 0, "(?(?!b)a*)+aak", "aaaaab aaaaak" }, - { MU, A, 0, 0, "(?(?=(?=(?!(x))a)aa)aaa|(?(?=(?!y)bb)bbb))*k", "abaabbaaabbbaaabbb abaabbaaabbbaaabbbk" }, - { MU, A, 0, 0, "(?P<Name>a)?(?P<Name2>b)?(?(Name)c|d)*l", "bc ddd abccabccl" }, - { MU, A, 0, 0, "(?P<Name>a)?(?P<Name2>b)?(?(Name)c|d)+?dd", "bcabcacdb bdddd" }, - { MU, A, 0, 0, "(?P<Name>a)?(?P<Name2>b)?(?(Name)c|d)+l", "ababccddabdbccd abcccl" }, - { MU, A, 0, 0, "((?:a|aa)(?(1)aaa))x", "aax" }, - { MU, A, 0, 0, "(?(?!)a|b)", "ab" }, - { MU, A, 0, 0, "(?(?!)a)", "ab" }, - { MU, A, 0, 0 | F_NOMATCH, "(?(?!)a|b)", "ac" }, - - /* Set start of match. */ - { MU, A, 0, 0, "(?:\\Ka)*aaaab", "aaaaaaaa aaaaaaabb" }, - { MU, A, 0, 0, "(?>\\Ka\\Ka)*aaaab", "aaaaaaaa aaaaaaaaaabb" }, - { MU, A, 0, 0, "a+\\K(?<=\\Gaa)a", "aaaaaa" }, - { MU, A, PCRE2_NOTEMPTY, 0 | F_NOMATCH, "a\\K(*ACCEPT)b", "aa" }, - { MU, A, PCRE2_NOTEMPTY_ATSTART, 0, "a\\K(*ACCEPT)b", "aa" }, - - /* First line. */ - { MU | PCRE2_FIRSTLINE, A, 0, 0 | F_PROPERTY, "\\p{Any}a", "bb\naaa" }, - { MU | PCRE2_FIRSTLINE, A, 0, 0 | F_NOMATCH | F_PROPERTY, "\\p{Any}a", "bb\r\naaa" }, - { MU | PCRE2_FIRSTLINE, A, 0, 0, "(?<=a)", "a" }, - { MU | PCRE2_FIRSTLINE, A, 0, 0 | F_NOMATCH, "[^a][^b]", "ab" }, - { MU | PCRE2_FIRSTLINE, A, 0, 0 | F_NOMATCH, "a", "\na" }, - { MU | PCRE2_FIRSTLINE, A, 0, 0 | F_NOMATCH, "[abc]", "\na" }, - { MU | PCRE2_FIRSTLINE, A, 0, 0 | F_NOMATCH, "^a", "\na" }, - { MU | PCRE2_FIRSTLINE, A, 0, 0 | F_NOMATCH, "^(?<=\n)", "\na" }, - { MU | PCRE2_FIRSTLINE, A, 0, 0, "\xf0\x90\x90\x80", "\xf0\x90\x90\x80" }, - { MU | PCRE2_FIRSTLINE, PCRE2_NEWLINE_ANY, 0, 0 | F_NOMATCH, "#", "\xc2\x85#" }, - { M | PCRE2_FIRSTLINE, PCRE2_NEWLINE_ANY, 0, 0 | F_NOMATCH, "#", "\x85#" }, - { MU | PCRE2_FIRSTLINE, PCRE2_NEWLINE_ANY, 0, 0 | F_NOMATCH, "^#", "\xe2\x80\xa8#" }, - { MU | PCRE2_FIRSTLINE, PCRE2_NEWLINE_CRLF, 0, 0 | F_PROPERTY, "\\p{Any}", "\r\na" }, - { MU | PCRE2_FIRSTLINE, PCRE2_NEWLINE_CRLF, 0, 0, ".", "\r" }, - { MU | PCRE2_FIRSTLINE, PCRE2_NEWLINE_CRLF, 0, 0, "a", "\ra" }, - { MU | PCRE2_FIRSTLINE, PCRE2_NEWLINE_CRLF, 0, 0 | F_NOMATCH, "ba", "bbb\r\nba" }, - { MU | PCRE2_FIRSTLINE, PCRE2_NEWLINE_CRLF, 0, 0 | F_NOMATCH | F_PROPERTY, "\\p{Any}{4}|a", "\r\na" }, - { MU | PCRE2_FIRSTLINE, PCRE2_NEWLINE_CRLF, 0, 1, ".", "\r\n" }, - { PCRE2_FIRSTLINE | PCRE2_DOTALL, PCRE2_NEWLINE_LF, 0, 0 | F_NOMATCH, "ab.", "ab" }, - { MU | PCRE2_FIRSTLINE, A, 0, 1 | F_NOMATCH, "^[a-d0-9]", "\nxx\nd" }, - { PCRE2_FIRSTLINE | PCRE2_DOTALL, PCRE2_NEWLINE_ANY, 0, 0, "....a", "012\n0a" }, - { MU | PCRE2_FIRSTLINE, A, 0, 0, "[aC]", "a" }, - - /* Recurse. */ - { MU, A, 0, 0, "(a)(?1)", "aa" }, - { MU, A, 0, 0, "((a))(?1)", "aa" }, - { MU, A, 0, 0, "(b|a)(?1)", "aa" }, - { MU, A, 0, 0, "(b|(a))(?1)", "aa" }, - { MU, A, 0, 0 | F_NOMATCH, "((a)(b)(?:a*))(?1)", "aba" }, - { MU, A, 0, 0, "((a)(b)(?:a*))(?1)", "abab" }, - { MU, A, 0, 0, "((a+)c(?2))b(?1)", "aacaabaca" }, - { MU, A, 0, 0, "((?2)b|(a)){2}(?1)", "aabab" }, - { MU, A, 0, 0, "(?1)(a)*+(?2)(b(?1))", "aababa" }, - { MU, A, 0, 0, "(?1)(((a(*ACCEPT)))b)", "axaa" }, - { MU, A, 0, 0, "(?1)(?(DEFINE) (((ac(*ACCEPT)))b) )", "akaac" }, - { MU, A, 0, 0, "(a+)b(?1)b\\1", "abaaabaaaaa" }, - { MU, A, 0, 0 | F_NOMATCH, "(?(DEFINE)(aa|a))(?1)ab", "aab" }, - { MU, A, 0, 0, "(?(DEFINE)(a\\Kb))(?1)+ababc", "abababxabababc" }, - { MU, A, 0, 0, "(a\\Kb)(?1)+ababc", "abababxababababc" }, - { MU, A, 0, 0 | F_NOMATCH, "(a\\Kb)(?1)+ababc", "abababxababababxc" }, - { MU, A, 0, 0, "b|<(?R)*>", "<<b>" }, - { MU, A, 0, 0, "(a\\K){0}(?:(?1)b|ac)", "ac" }, - { MU, A, 0, 0, "(?(DEFINE)(a(?2)|b)(b(?1)|(a)))(?:(?1)|(?2))m", "ababababnababababaam" }, - { MU, A, 0, 0, "(a)((?(R)a|b))(?2)", "aabbabaa" }, - { MU, A, 0, 0, "(a)((?(R2)a|b))(?2)", "aabbabaa" }, - { MU, A, 0, 0, "(a)((?(R1)a|b))(?2)", "ababba" }, - { MU, A, 0, 0, "(?(R0)aa|bb(?R))", "abba aabb bbaa" }, - { MU, A, 0, 0, "((?(R)(?:aaaa|a)|(?:(aaaa)|(a)))+)(?1)$", "aaaaaaaaaa aaaa" }, - { MU, A, 0, 0, "(?P<Name>a(?(R&Name)a|b))(?1)", "aab abb abaa" }, - { MU, A, 0, 0, "((?(R)a|(?1)){3})", "XaaaaaaaaaX" }, - { MU, A, 0, 0, "((?:(?(R)a|(?1))){3})", "XaaaaaaaaaX" }, - { MU, A, 0, 0, "((?(R)a|(?1)){1,3})aaaaaa", "aaaaaaaaXaaaaaaaaa" }, - { MU, A, 0, 0, "((?(R)a|(?1)){1,3}?)M", "aaaM" }, - - /* 16 bit specific tests. */ - { CM, A, 0, 0 | F_FORCECONV, "\xc3\xa1", "\xc3\x81\xc3\xa1" }, - { CM, A, 0, 0 | F_FORCECONV, "\xe1\xbd\xb8", "\xe1\xbf\xb8\xe1\xbd\xb8" }, - { CM, A, 0, 0 | F_FORCECONV, "[\xc3\xa1]", "\xc3\x81\xc3\xa1" }, - { CM, A, 0, 0 | F_FORCECONV, "[\xe1\xbd\xb8]", "\xe1\xbf\xb8\xe1\xbd\xb8" }, - { CM, A, 0, 0 | F_FORCECONV, "[a-\xed\xb0\x80]", "A" }, - { CM, A, 0, 0 | F_NO8 | F_FORCECONV, "[a-\\x{dc00}]", "B" }, - { CM, A, 0, 0 | F_NO8 | F_NOMATCH | F_FORCECONV, "[b-\\x{dc00}]", "a" }, - { CM, A, 0, 0 | F_NO8 | F_FORCECONV, "\xed\xa0\x80\\x{d800}\xed\xb0\x80\\x{dc00}", "\xed\xa0\x80\xed\xa0\x80\xed\xb0\x80\xed\xb0\x80" }, - { CM, A, 0, 0 | F_NO8 | F_FORCECONV, "[\xed\xa0\x80\\x{d800}]{1,2}?[\xed\xb0\x80\\x{dc00}]{1,2}?#", "\xed\xa0\x80\xed\xa0\x80\xed\xb0\x80\xed\xb0\x80#" }, - { CM, A, 0, 0 | F_FORCECONV, "[\xed\xa0\x80\xed\xb0\x80#]{0,3}(?<=\xed\xb0\x80.)", "\xed\xa0\x80#\xed\xa0\x80##\xed\xb0\x80\xed\xa0\x80" }, - { CM, A, 0, 0 | F_FORCECONV, "[\xed\xa0\x80-\xed\xb3\xbf]", "\xed\x9f\xbf\xed\xa0\x83" }, - { CM, A, 0, 0 | F_FORCECONV, "[\xed\xa0\x80-\xed\xb3\xbf]", "\xed\xb4\x80\xed\xb3\xb0" }, - { CM, A, 0, 0 | F_NO8 | F_FORCECONV, "[\\x{d800}-\\x{dcff}]", "\xed\x9f\xbf\xed\xa0\x83" }, - { CM, A, 0, 0 | F_NO8 | F_FORCECONV, "[\\x{d800}-\\x{dcff}]", "\xed\xb4\x80\xed\xb3\xb0" }, - { CM, A, 0, 0 | F_FORCECONV, "[\xed\xa0\x80-\xef\xbf\xbf]+[\x1-\xed\xb0\x80]+#", "\xed\xa0\x85\xc3\x81\xed\xa0\x85\xef\xbf\xb0\xc2\x85\xed\xa9\x89#" }, - { CM, A, 0, 0 | F_FORCECONV, "[\xed\xa0\x80][\xed\xb0\x80]{2,}", "\xed\xa0\x80\xed\xb0\x80\xed\xa0\x80\xed\xb0\x80\xed\xb0\x80\xed\xb0\x80" }, - { M, A, 0, 0 | F_FORCECONV, "[^\xed\xb0\x80]{3,}?", "##\xed\xb0\x80#\xed\xb0\x80#\xc3\x89#\xed\xb0\x80" }, - { M, A, 0, 0 | F_NO8 | F_FORCECONV, "[^\\x{dc00}]{3,}?", "##\xed\xb0\x80#\xed\xb0\x80#\xc3\x89#\xed\xb0\x80" }, - { CM, A, 0, 0 | F_FORCECONV, ".\\B.", "\xed\xa0\x80\xed\xb0\x80" }, - { CM, A, 0, 0 | F_FORCECONV, "\\D+(?:\\d+|.)\\S+(?:\\s+|.)\\W+(?:\\w+|.)\xed\xa0\x80\xed\xa0\x80", "\xed\xa0\x80\xed\xa0\x80\xed\xa0\x80\xed\xa0\x80\xed\xa0\x80\xed\xa0\x80\xed\xa0\x80\xed\xa0\x80" }, - { CM, A, 0, 0 | F_FORCECONV, "\\d*\\s*\\w*\xed\xa0\x80\xed\xa0\x80", "\xed\xa0\x80\xed\xa0\x80" }, - { CM, A, 0, 0 | F_FORCECONV | F_NOMATCH, "\\d*?\\D*?\\s*?\\S*?\\w*?\\W*?##", "\xed\xa0\x80\xed\xa0\x80\xed\xa0\x80\xed\xa0\x80#" }, - { CM | PCRE2_EXTENDED, A, 0, 0 | F_FORCECONV, "\xed\xa0\x80 \xed\xb0\x80 !", "\xed\xa0\x80\xed\xb0\x80!" }, - { CM, A, 0, 0 | F_FORCECONV, "\xed\xa0\x80+#[^#]+\xed\xa0\x80", "\xed\xa0\x80#a\xed\xa0\x80" }, - { CM, A, 0, 0 | F_FORCECONV, "(\xed\xa0\x80+)#\\1", "\xed\xa0\x80\xed\xa0\x80#\xed\xa0\x80\xed\xa0\x80" }, - { M, PCRE2_NEWLINE_ANY, 0, 0 | F_NO8 | F_FORCECONV, "^-", "a--\xe2\x80\xa8--" }, - { 0, BSR(PCRE2_BSR_UNICODE), 0, 0 | F_NO8 | F_FORCECONV, "\\R", "ab\xe2\x80\xa8" }, - { 0, 0, 0, 0 | F_NO8 | F_FORCECONV, "\\v", "ab\xe2\x80\xa9" }, - { 0, 0, 0, 0 | F_NO8 | F_FORCECONV, "\\h", "ab\xe1\xa0\x8e" }, - { 0, 0, 0, 0 | F_NO8 | F_FORCECONV, "\\v+?\\V+?#", "\xe2\x80\xa9\xe2\x80\xa9\xef\xbf\xbf\xef\xbf\xbf#" }, - { 0, 0, 0, 0 | F_NO8 | F_FORCECONV, "\\h+?\\H+?#", "\xe1\xa0\x8e\xe1\xa0\x8e\xef\xbf\xbf\xef\xbf\xbf#" }, - - /* Partial matching. */ - { MU, A, PCRE2_PARTIAL_SOFT, 0, "ab", "a" }, - { MU, A, PCRE2_PARTIAL_SOFT, 0, "ab|a", "a" }, - { MU, A, PCRE2_PARTIAL_HARD, 0, "ab|a", "a" }, - { MU, A, PCRE2_PARTIAL_SOFT, 0, "\\b#", "a" }, - { MU, A, PCRE2_PARTIAL_SOFT, 0, "(?<=a)b", "a" }, - { MU, A, PCRE2_PARTIAL_SOFT, 0, "abc|(?<=xxa)bc", "xxab" }, - { MU, A, PCRE2_PARTIAL_SOFT, 0, "a\\B", "a" }, - { MU, A, PCRE2_PARTIAL_HARD, 0, "a\\b", "a" }, - - /* (*MARK) verb. */ - { MU, A, 0, 0, "a(*MARK:aa)a", "ababaa" }, - { MU, A, 0, 0 | F_NOMATCH, "a(*:aa)a", "abab" }, - { MU, A, 0, 0, "a(*:aa)(b(*:bb)b|bc)", "abc" }, - { MU, A, 0, 0 | F_NOMATCH, "a(*:1)x|b(*:2)y", "abc" }, - { MU, A, 0, 0, "(?>a(*:aa))b|ac", "ac" }, - { MU, A, 0, 0, "(?(DEFINE)(a(*:aa)))(?1)", "a" }, - { MU, A, 0, 0 | F_NOMATCH, "(?(DEFINE)((a)(*:aa)))(?1)b", "aa" }, - { MU, A, 0, 0, "(?(DEFINE)(a(*:aa)))a(?1)b|aac", "aac" }, - { MU, A, 0, 0, "(a(*:aa)){0}(?:b(?1)b|c)+c", "babbab cc" }, - { MU, A, 0, 0, "(a(*:aa)){0}(?:b(?1)b)+", "babba" }, - { MU, A, 0, 0 | F_NOMATCH, "(a(*:aa)){0}(?:b(?1)b)+", "ba" }, - { MU, A, 0, 0, "(a\\K(*:aa)){0}(?:b(?1)b|c)+c", "babbab cc" }, - { MU, A, 0, 0, "(a\\K(*:aa)){0}(?:b(?1)b)+", "babba" }, - { MU, A, 0, 0 | F_NOMATCH, "(a\\K(*:aa)){0}(?:b(?1)b)+", "ba" }, - { MU, A, 0, 0 | F_NOMATCH, "(*:mark)m", "a" }, - - /* (*COMMIT) verb. */ - { MU, A, 0, 0 | F_NOMATCH, "a(*COMMIT)b", "ac" }, - { MU, A, 0, 0, "aa(*COMMIT)b", "xaxaab" }, - { MU, A, 0, 0 | F_NOMATCH, "a(*COMMIT)(*:msg)b|ac", "ac" }, - { MU, A, 0, 0 | F_NOMATCH, "(a(*COMMIT)b)++", "abac" }, - { MU, A, 0, 0 | F_NOMATCH, "((a)(*COMMIT)b)++", "abac" }, - { MU, A, 0, 0 | F_NOMATCH, "(?=a(*COMMIT)b)ab|ad", "ad" }, - - /* (*PRUNE) verb. */ - { MU, A, 0, 0, "aa\\K(*PRUNE)b", "aaab" }, - { MU, A, 0, 0, "aa(*PRUNE:bb)b|a", "aa" }, - { MU, A, 0, 0, "(a)(a)(*PRUNE)b|(a)", "aa" }, - { MU, A, 0, 0, "(a)(a)(a)(a)(a)(a)(a)(a)(*PRUNE)b|(a)", "aaaaaaaa" }, - { MU, A, PCRE2_PARTIAL_SOFT, 0, "a(*PRUNE)a|", "a" }, - { MU, A, PCRE2_PARTIAL_SOFT, 0, "a(*PRUNE)a|m", "a" }, - { MU, A, 0, 0 | F_NOMATCH, "(?=a(*PRUNE)b)ab|ad", "ad" }, - { MU, A, 0, 0, "a(*COMMIT)(*PRUNE)d|bc", "abc" }, - { MU, A, 0, 0, "(?=a(*COMMIT)b)a(*PRUNE)c|bc", "abc" }, - { MU, A, 0, 0 | F_NOMATCH, "(*COMMIT)(?=a(*COMMIT)b)a(*PRUNE)c|bc", "abc" }, - { MU, A, 0, 0, "(?=(a)(*COMMIT)b)a(*PRUNE)c|bc", "abc" }, - { MU, A, 0, 0 | F_NOMATCH, "(*COMMIT)(?=(a)(*COMMIT)b)a(*PRUNE)c|bc", "abc" }, - { MU, A, 0, 0, "(a(*COMMIT)b){0}a(?1)(*PRUNE)c|bc", "abc" }, - { MU, A, 0, 0 | F_NOMATCH, "(a(*COMMIT)b){0}a(*COMMIT)(?1)(*PRUNE)c|bc", "abc" }, - { MU, A, 0, 0, "(a(*COMMIT)b)++(*PRUNE)d|c", "ababc" }, - { MU, A, 0, 0 | F_NOMATCH, "(*COMMIT)(a(*COMMIT)b)++(*PRUNE)d|c", "ababc" }, - { MU, A, 0, 0, "((a)(*COMMIT)b)++(*PRUNE)d|c", "ababc" }, - { MU, A, 0, 0 | F_NOMATCH, "(*COMMIT)((a)(*COMMIT)b)++(*PRUNE)d|c", "ababc" }, - { MU, A, 0, 0, "(?>a(*COMMIT)b)*abab(*PRUNE)d|ba", "ababab" }, - { MU, A, 0, 0 | F_NOMATCH, "(*COMMIT)(?>a(*COMMIT)b)*abab(*PRUNE)d|ba", "ababab" }, - { MU, A, 0, 0, "(?>a(*COMMIT)b)+abab(*PRUNE)d|ba", "ababab" }, - { MU, A, 0, 0 | F_NOMATCH, "(*COMMIT)(?>a(*COMMIT)b)+abab(*PRUNE)d|ba", "ababab" }, - { MU, A, 0, 0, "(?>a(*COMMIT)b)?ab(*PRUNE)d|ba", "aba" }, - { MU, A, 0, 0 | F_NOMATCH, "(*COMMIT)(?>a(*COMMIT)b)?ab(*PRUNE)d|ba", "aba" }, - { MU, A, 0, 0, "(?>a(*COMMIT)b)*?n(*PRUNE)d|ba", "abababn" }, - { MU, A, 0, 0 | F_NOMATCH, "(*COMMIT)(?>a(*COMMIT)b)*?n(*PRUNE)d|ba", "abababn" }, - { MU, A, 0, 0, "(?>a(*COMMIT)b)+?n(*PRUNE)d|ba", "abababn" }, - { MU, A, 0, 0 | F_NOMATCH, "(*COMMIT)(?>a(*COMMIT)b)+?n(*PRUNE)d|ba", "abababn" }, - { MU, A, 0, 0, "(?>a(*COMMIT)b)??n(*PRUNE)d|bn", "abn" }, - { MU, A, 0, 0 | F_NOMATCH, "(*COMMIT)(?>a(*COMMIT)b)??n(*PRUNE)d|bn", "abn" }, - - /* (*SKIP) verb. */ - { MU, A, 0, 0 | F_NOMATCH, "(?=a(*SKIP)b)ab|ad", "ad" }, - { MU, A, 0, 0, "(\\w+(*SKIP)#)", "abcd,xyz#," }, - { MU, A, 0, 0, "\\w+(*SKIP)#|mm", "abcd,xyz#," }, - { MU, A, 0, 0 | F_NOMATCH, "b+(?<=(*SKIP)#c)|b+", "#bbb" }, - - /* (*THEN) verb. */ - { MU, A, 0, 0, "((?:a(*THEN)|aab)(*THEN)c|a+)+m", "aabcaabcaabcaabcnacm" }, - { MU, A, 0, 0 | F_NOMATCH, "((?:a(*THEN)|aab)(*THEN)c|a+)+m", "aabcm" }, - { MU, A, 0, 0, "((?:a(*THEN)|aab)c|a+)+m", "aabcaabcnmaabcaabcm" }, - { MU, A, 0, 0, "((?:a|aab)(*THEN)c|a+)+m", "aam" }, - { MU, A, 0, 0, "((?:a(*COMMIT)|aab)(*THEN)c|a+)+m", "aam" }, - { MU, A, 0, 0, "(?(?=a(*THEN)b)ab|ad)", "ad" }, - { MU, A, 0, 0, "(?(?!a(*THEN)b)ad|add)", "add" }, - { MU, A, 0, 0 | F_NOMATCH, "(?(?=a)a(*THEN)b|ad)", "ad" }, - { MU, A, 0, 0, "(?!(?(?=a)ab|b(*THEN)d))bn|bnn", "bnn" }, - - /* Deep recursion. */ - { MU, A, 0, 0, "((((?:(?:(?:\\w)+)?)*|(?>\\w)+?)+|(?>\\w)?\?)*)?\\s", "aaaaa+ " }, - { MU, A, 0, 0, "(?:((?:(?:(?:\\w*?)+)??|(?>\\w)?|\\w*+)*)+)+?\\s", "aa+ " }, - { MU, A, 0, 0, "((a?)+)+b", "aaaaaaaaaaaa b" }, - - /* Deep recursion: Stack limit reached. */ - { M, A, 0, 0 | F_NOMATCH, "a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?aaaaaaaaaaaaaaaaaaaaaaa", "aaaaaaaaaaaaaaaaaaaaaaa" }, - { M, A, 0, 0 | F_NOMATCH, "(?:a+)+b", "aaaaaaaaaaaaaaaaaaaaaaaa b" }, - { M, A, 0, 0 | F_NOMATCH, "(?:a+?)+?b", "aaaaaaaaaaaaaaaaaaaaaaaa b" }, - { M, A, 0, 0 | F_NOMATCH, "(?:a*)*b", "aaaaaaaaaaaaaaaaaaaaaaaa b" }, - { M, A, 0, 0 | F_NOMATCH, "(?:a*?)*?b", "aaaaaaaaaaaaaaaaaaaaaaaa b" }, - - { 0, 0, 0, 0, NULL, NULL } -}; - -#ifdef SUPPORT_PCRE2_8 -static pcre2_jit_stack_8* callback8(void *arg) -{ - return (pcre2_jit_stack_8 *)arg; -} -#endif - -#ifdef SUPPORT_PCRE2_16 -static pcre2_jit_stack_16* callback16(void *arg) -{ - return (pcre2_jit_stack_16 *)arg; -} -#endif - -#ifdef SUPPORT_PCRE2_32 -static pcre2_jit_stack_32* callback32(void *arg) -{ - return (pcre2_jit_stack_32 *)arg; -} -#endif - -#ifdef SUPPORT_PCRE2_8 -static pcre2_jit_stack_8 *stack8; - -static pcre2_jit_stack_8 *getstack8(void) -{ - if (!stack8) - stack8 = pcre2_jit_stack_create_8(1, 1024 * 1024, NULL); - return stack8; -} - -static void setstack8(pcre2_match_context_8 *mcontext) -{ - if (!mcontext) { - if (stack8) - pcre2_jit_stack_free_8(stack8); - stack8 = NULL; - return; - } - - pcre2_jit_stack_assign_8(mcontext, callback8, getstack8()); -} -#endif /* SUPPORT_PCRE2_8 */ - -#ifdef SUPPORT_PCRE2_16 -static pcre2_jit_stack_16 *stack16; - -static pcre2_jit_stack_16 *getstack16(void) -{ - if (!stack16) - stack16 = pcre2_jit_stack_create_16(1, 1024 * 1024, NULL); - return stack16; -} - -static void setstack16(pcre2_match_context_16 *mcontext) -{ - if (!mcontext) { - if (stack16) - pcre2_jit_stack_free_16(stack16); - stack16 = NULL; - return; - } - - pcre2_jit_stack_assign_16(mcontext, callback16, getstack16()); -} -#endif /* SUPPORT_PCRE2_16 */ - -#ifdef SUPPORT_PCRE2_32 -static pcre2_jit_stack_32 *stack32; - -static pcre2_jit_stack_32 *getstack32(void) -{ - if (!stack32) - stack32 = pcre2_jit_stack_create_32(1, 1024 * 1024, NULL); - return stack32; -} - -static void setstack32(pcre2_match_context_32 *mcontext) -{ - if (!mcontext) { - if (stack32) - pcre2_jit_stack_free_32(stack32); - stack32 = NULL; - return; - } - - pcre2_jit_stack_assign_32(mcontext, callback32, getstack32()); -} -#endif /* SUPPORT_PCRE2_32 */ - -#ifdef SUPPORT_PCRE2_16 - -static int convert_utf8_to_utf16(PCRE2_SPTR8 input, PCRE2_UCHAR16 *output, int *offsetmap, int max_length) -{ - PCRE2_SPTR8 iptr = input; - PCRE2_UCHAR16 *optr = output; - unsigned int c; - - if (max_length == 0) - return 0; - - while (*iptr && max_length > 1) { - c = 0; - if (offsetmap) - *offsetmap++ = (int)(iptr - (unsigned char*)input); - - if (*iptr < 0xc0) - c = *iptr++; - else if (!(*iptr & 0x20)) { - c = ((iptr[0] & 0x1f) << 6) | (iptr[1] & 0x3f); - iptr += 2; - } else if (!(*iptr & 0x10)) { - c = ((iptr[0] & 0x0f) << 12) | ((iptr[1] & 0x3f) << 6) | (iptr[2] & 0x3f); - iptr += 3; - } else if (!(*iptr & 0x08)) { - c = ((iptr[0] & 0x07) << 18) | ((iptr[1] & 0x3f) << 12) | ((iptr[2] & 0x3f) << 6) | (iptr[3] & 0x3f); - iptr += 4; - } - - if (c < 65536) { - *optr++ = c; - max_length--; - } else if (max_length <= 2) { - *optr = '\0'; - return (int)(optr - output); - } else { - c -= 0x10000; - *optr++ = 0xd800 | ((c >> 10) & 0x3ff); - *optr++ = 0xdc00 | (c & 0x3ff); - max_length -= 2; - if (offsetmap) - offsetmap++; - } - } - if (offsetmap) - *offsetmap = (int)(iptr - (unsigned char*)input); - *optr = '\0'; - return (int)(optr - output); -} - -static int copy_char8_to_char16(PCRE2_SPTR8 input, PCRE2_UCHAR16 *output, int max_length) -{ - PCRE2_SPTR8 iptr = input; - PCRE2_UCHAR16 *optr = output; - - if (max_length == 0) - return 0; - - while (*iptr && max_length > 1) { - *optr++ = *iptr++; - max_length--; - } - *optr = '\0'; - return (int)(optr - output); -} - -#define REGTEST_MAX_LENGTH16 4096 -static PCRE2_UCHAR16 regtest_buf16[REGTEST_MAX_LENGTH16]; -static int regtest_offsetmap16[REGTEST_MAX_LENGTH16]; - -#endif /* SUPPORT_PCRE2_16 */ - -#ifdef SUPPORT_PCRE2_32 - -static int convert_utf8_to_utf32(PCRE2_SPTR8 input, PCRE2_UCHAR32 *output, int *offsetmap, int max_length) -{ - PCRE2_SPTR8 iptr = input; - PCRE2_UCHAR32 *optr = output; - unsigned int c; - - if (max_length == 0) - return 0; - - while (*iptr && max_length > 1) { - c = 0; - if (offsetmap) - *offsetmap++ = (int)(iptr - (unsigned char*)input); - - if (*iptr < 0xc0) - c = *iptr++; - else if (!(*iptr & 0x20)) { - c = ((iptr[0] & 0x1f) << 6) | (iptr[1] & 0x3f); - iptr += 2; - } else if (!(*iptr & 0x10)) { - c = ((iptr[0] & 0x0f) << 12) | ((iptr[1] & 0x3f) << 6) | (iptr[2] & 0x3f); - iptr += 3; - } else if (!(*iptr & 0x08)) { - c = ((iptr[0] & 0x07) << 18) | ((iptr[1] & 0x3f) << 12) | ((iptr[2] & 0x3f) << 6) | (iptr[3] & 0x3f); - iptr += 4; - } - - *optr++ = c; - max_length--; - } - if (offsetmap) - *offsetmap = (int)(iptr - (unsigned char*)input); - *optr = 0; - return (int)(optr - output); -} - -static int copy_char8_to_char32(PCRE2_SPTR8 input, PCRE2_UCHAR32 *output, int max_length) -{ - PCRE2_SPTR8 iptr = input; - PCRE2_UCHAR32 *optr = output; - - if (max_length == 0) - return 0; - - while (*iptr && max_length > 1) { - *optr++ = *iptr++; - max_length--; - } - *optr = '\0'; - return (int)(optr - output); -} - -#define REGTEST_MAX_LENGTH32 4096 -static PCRE2_UCHAR32 regtest_buf32[REGTEST_MAX_LENGTH32]; -static int regtest_offsetmap32[REGTEST_MAX_LENGTH32]; - -#endif /* SUPPORT_PCRE2_32 */ - -static int check_ascii(const char *input) -{ - const unsigned char *ptr = (unsigned char *)input; - while (*ptr) { - if (*ptr > 127) - return 0; - ptr++; - } - return 1; -} - -#define OVECTOR_SIZE 15 - -static int regression_tests(void) -{ - struct regression_test_case *current = regression_test_cases; - int error; - PCRE2_SIZE err_offs; - int is_successful; - int is_ascii; - int total = 0; - int successful = 0; - int successful_row = 0; - int counter = 0; - int jit_compile_mode; - int utf = 0; - int disabled_options = 0; - int i; -#ifdef SUPPORT_PCRE2_8 - pcre2_code_8 *re8; - pcre2_compile_context_8 *ccontext8; - pcre2_match_data_8 *mdata8_1; - pcre2_match_data_8 *mdata8_2; - pcre2_match_context_8 *mcontext8; - PCRE2_SIZE *ovector8_1 = NULL; - PCRE2_SIZE *ovector8_2 = NULL; - int return_value8[2]; -#endif -#ifdef SUPPORT_PCRE2_16 - pcre2_code_16 *re16; - pcre2_compile_context_16 *ccontext16; - pcre2_match_data_16 *mdata16_1; - pcre2_match_data_16 *mdata16_2; - pcre2_match_context_16 *mcontext16; - PCRE2_SIZE *ovector16_1 = NULL; - PCRE2_SIZE *ovector16_2 = NULL; - int return_value16[2]; - int length16; -#endif -#ifdef SUPPORT_PCRE2_32 - pcre2_code_32 *re32; - pcre2_compile_context_32 *ccontext32; - pcre2_match_data_32 *mdata32_1; - pcre2_match_data_32 *mdata32_2; - pcre2_match_context_32 *mcontext32; - PCRE2_SIZE *ovector32_1 = NULL; - PCRE2_SIZE *ovector32_2 = NULL; - int return_value32[2]; - int length32; -#endif - -#if defined SUPPORT_PCRE2_8 - PCRE2_UCHAR8 cpu_info[128]; -#elif defined SUPPORT_PCRE2_16 - PCRE2_UCHAR16 cpu_info[128]; -#elif defined SUPPORT_PCRE2_32 - PCRE2_UCHAR32 cpu_info[128]; -#endif -#if defined SUPPORT_UTF && ((defined(SUPPORT_PCRE2_8) + defined(SUPPORT_PCRE2_16) + defined(SUPPORT_PCRE2_32)) >= 2) - int return_value; -#endif - - /* This test compares the behaviour of interpreter and JIT. Although disabling - utf or ucp may make tests fail, if the pcre_exec result is the SAME, it is - still considered successful from pcre_jit_test point of view. */ - -#if defined SUPPORT_PCRE2_8 - pcre2_config_8(PCRE2_CONFIG_JITTARGET, &cpu_info); -#elif defined SUPPORT_PCRE2_16 - pcre2_config_16(PCRE2_CONFIG_JITTARGET, &cpu_info); -#elif defined SUPPORT_PCRE2_32 - pcre2_config_32(PCRE2_CONFIG_JITTARGET, &cpu_info); -#endif - - printf("Running JIT regression tests\n"); - printf(" target CPU of SLJIT compiler: "); - for (i = 0; cpu_info[i]; i++) - printf("%c", (char)(cpu_info[i])); - printf("\n"); - -#if defined SUPPORT_PCRE2_8 - pcre2_config_8(PCRE2_CONFIG_UNICODE, &utf); -#elif defined SUPPORT_PCRE2_16 - pcre2_config_16(PCRE2_CONFIG_UNICODE, &utf); -#elif defined SUPPORT_PCRE2_32 - pcre2_config_32(PCRE2_CONFIG_UNICODE, &utf); -#endif - - if (!utf) - disabled_options |= PCRE2_UTF; -#ifdef SUPPORT_PCRE2_8 - printf(" in 8 bit mode with UTF-8 %s:\n", utf ? "enabled" : "disabled"); -#endif -#ifdef SUPPORT_PCRE2_16 - printf(" in 16 bit mode with UTF-16 %s:\n", utf ? "enabled" : "disabled"); -#endif -#ifdef SUPPORT_PCRE2_32 - printf(" in 32 bit mode with UTF-32 %s:\n", utf ? "enabled" : "disabled"); -#endif - - while (current->pattern) { - /* printf("\nPattern: %s :\n", current->pattern); */ - total++; - is_ascii = 0; - if (!(current->start_offset & F_PROPERTY)) - is_ascii = check_ascii(current->pattern) && check_ascii(current->input); - - if (current->match_options & PCRE2_PARTIAL_SOFT) - jit_compile_mode = PCRE2_JIT_PARTIAL_SOFT; - else if (current->match_options & PCRE2_PARTIAL_HARD) - jit_compile_mode = PCRE2_JIT_PARTIAL_HARD; - else - jit_compile_mode = PCRE2_JIT_COMPLETE; - error = 0; -#ifdef SUPPORT_PCRE2_8 - re8 = NULL; - ccontext8 = pcre2_compile_context_create_8(NULL); - if (ccontext8) { - if (GET_NEWLINE(current->newline)) - pcre2_set_newline_8(ccontext8, GET_NEWLINE(current->newline)); - if (GET_BSR(current->newline)) - pcre2_set_bsr_8(ccontext8, GET_BSR(current->newline)); - - if (!(current->start_offset & F_NO8)) { - re8 = pcre2_compile_8((PCRE2_SPTR8)current->pattern, PCRE2_ZERO_TERMINATED, - current->compile_options & ~disabled_options, - &error, &err_offs, ccontext8); - - if (!re8 && (utf || is_ascii)) - printf("\n8 bit: Cannot compile pattern \"%s\": %d\n", current->pattern, error); - } - pcre2_compile_context_free_8(ccontext8); - } - else - printf("\n8 bit: Cannot allocate compile context\n"); -#endif -#ifdef SUPPORT_PCRE2_16 - if ((current->compile_options & PCRE2_UTF) || (current->start_offset & F_FORCECONV)) - convert_utf8_to_utf16((PCRE2_SPTR8)current->pattern, regtest_buf16, NULL, REGTEST_MAX_LENGTH16); - else - copy_char8_to_char16((PCRE2_SPTR8)current->pattern, regtest_buf16, REGTEST_MAX_LENGTH16); - - re16 = NULL; - ccontext16 = pcre2_compile_context_create_16(NULL); - if (ccontext16) { - if (GET_NEWLINE(current->newline)) - pcre2_set_newline_16(ccontext16, GET_NEWLINE(current->newline)); - if (GET_BSR(current->newline)) - pcre2_set_bsr_16(ccontext16, GET_BSR(current->newline)); - - if (!(current->start_offset & F_NO16)) { - re16 = pcre2_compile_16(regtest_buf16, PCRE2_ZERO_TERMINATED, - current->compile_options & ~disabled_options, - &error, &err_offs, ccontext16); - - if (!re16 && (utf || is_ascii)) - printf("\n16 bit: Cannot compile pattern \"%s\": %d\n", current->pattern, error); - } - pcre2_compile_context_free_16(ccontext16); - } - else - printf("\n16 bit: Cannot allocate compile context\n"); -#endif -#ifdef SUPPORT_PCRE2_32 - if ((current->compile_options & PCRE2_UTF) || (current->start_offset & F_FORCECONV)) - convert_utf8_to_utf32((PCRE2_SPTR8)current->pattern, regtest_buf32, NULL, REGTEST_MAX_LENGTH32); - else - copy_char8_to_char32((PCRE2_SPTR8)current->pattern, regtest_buf32, REGTEST_MAX_LENGTH32); - - re32 = NULL; - ccontext32 = pcre2_compile_context_create_32(NULL); - if (ccontext32) { - if (GET_NEWLINE(current->newline)) - pcre2_set_newline_32(ccontext32, GET_NEWLINE(current->newline)); - if (GET_BSR(current->newline)) - pcre2_set_bsr_32(ccontext32, GET_BSR(current->newline)); - - if (!(current->start_offset & F_NO32)) { - re32 = pcre2_compile_32(regtest_buf32, PCRE2_ZERO_TERMINATED, - current->compile_options & ~disabled_options, - &error, &err_offs, ccontext32); - - if (!re32 && (utf || is_ascii)) - printf("\n32 bit: Cannot compile pattern \"%s\": %d\n", current->pattern, error); - } - pcre2_compile_context_free_32(ccontext32); - } - else - printf("\n32 bit: Cannot allocate compile context\n"); -#endif - - counter++; - if ((counter & 0x3) != 0) { -#ifdef SUPPORT_PCRE2_8 - setstack8(NULL); -#endif -#ifdef SUPPORT_PCRE2_16 - setstack16(NULL); -#endif -#ifdef SUPPORT_PCRE2_32 - setstack32(NULL); -#endif - } - -#ifdef SUPPORT_PCRE2_8 - return_value8[0] = -1000; - return_value8[1] = -1000; - mdata8_1 = pcre2_match_data_create_8(OVECTOR_SIZE, NULL); - mdata8_2 = pcre2_match_data_create_8(OVECTOR_SIZE, NULL); - mcontext8 = pcre2_match_context_create_8(NULL); - if (!mdata8_1 || !mdata8_2 || !mcontext8) { - printf("\n8 bit: Cannot allocate match data\n"); - pcre2_match_data_free_8(mdata8_1); - pcre2_match_data_free_8(mdata8_2); - pcre2_match_context_free_8(mcontext8); - pcre2_code_free_8(re8); - re8 = NULL; - } else { - ovector8_1 = pcre2_get_ovector_pointer_8(mdata8_1); - ovector8_2 = pcre2_get_ovector_pointer_8(mdata8_2); - for (i = 0; i < OVECTOR_SIZE * 3; ++i) - ovector8_1[i] = -2; - for (i = 0; i < OVECTOR_SIZE * 3; ++i) - ovector8_2[i] = -2; - } - if (re8) { - return_value8[1] = pcre2_match_8(re8, (PCRE2_SPTR8)current->input, strlen(current->input), - current->start_offset & OFFSET_MASK, current->match_options, mdata8_2, NULL); - - if (pcre2_jit_compile_8(re8, jit_compile_mode)) { - printf("\n8 bit: JIT compiler does not support \"%s\"\n", current->pattern); - } else if ((counter & 0x1) != 0) { - setstack8(mcontext8); - return_value8[0] = pcre2_match_8(re8, (PCRE2_SPTR8)current->input, strlen(current->input), - current->start_offset & OFFSET_MASK, current->match_options, mdata8_1, mcontext8); - } else { - pcre2_jit_stack_assign_8(mcontext8, NULL, getstack8()); - return_value8[0] = pcre2_jit_match_8(re8, (PCRE2_SPTR8)current->input, strlen(current->input), - current->start_offset & OFFSET_MASK, current->match_options, mdata8_1, mcontext8); - } - } -#endif - -#ifdef SUPPORT_PCRE2_16 - return_value16[0] = -1000; - return_value16[1] = -1000; - mdata16_1 = pcre2_match_data_create_16(OVECTOR_SIZE, NULL); - mdata16_2 = pcre2_match_data_create_16(OVECTOR_SIZE, NULL); - mcontext16 = pcre2_match_context_create_16(NULL); - if (!mdata16_1 || !mdata16_2 || !mcontext16) { - printf("\n16 bit: Cannot allocate match data\n"); - pcre2_match_data_free_16(mdata16_1); - pcre2_match_data_free_16(mdata16_2); - pcre2_match_context_free_16(mcontext16); - pcre2_code_free_16(re16); - re16 = NULL; - } else { - ovector16_1 = pcre2_get_ovector_pointer_16(mdata16_1); - ovector16_2 = pcre2_get_ovector_pointer_16(mdata16_2); - for (i = 0; i < OVECTOR_SIZE * 3; ++i) - ovector16_1[i] = -2; - for (i = 0; i < OVECTOR_SIZE * 3; ++i) - ovector16_2[i] = -2; - } - if (re16) { - if ((current->compile_options & PCRE2_UTF) || (current->start_offset & F_FORCECONV)) - length16 = convert_utf8_to_utf16((PCRE2_SPTR8)current->input, regtest_buf16, regtest_offsetmap16, REGTEST_MAX_LENGTH16); - else - length16 = copy_char8_to_char16((PCRE2_SPTR8)current->input, regtest_buf16, REGTEST_MAX_LENGTH16); - - return_value16[1] = pcre2_match_16(re16, regtest_buf16, length16, - current->start_offset & OFFSET_MASK, current->match_options, mdata16_2, NULL); - - if (pcre2_jit_compile_16(re16, jit_compile_mode)) { - printf("\n16 bit: JIT compiler does not support \"%s\"\n", current->pattern); - } else if ((counter & 0x1) != 0) { - setstack16(mcontext16); - return_value16[0] = pcre2_match_16(re16, regtest_buf16, length16, - current->start_offset & OFFSET_MASK, current->match_options, mdata16_1, mcontext16); - } else { - pcre2_jit_stack_assign_16(mcontext16, NULL, getstack16()); - return_value16[0] = pcre2_jit_match_16(re16, regtest_buf16, length16, - current->start_offset & OFFSET_MASK, current->match_options, mdata16_1, mcontext16); - } - } -#endif - -#ifdef SUPPORT_PCRE2_32 - return_value32[0] = -1000; - return_value32[1] = -1000; - mdata32_1 = pcre2_match_data_create_32(OVECTOR_SIZE, NULL); - mdata32_2 = pcre2_match_data_create_32(OVECTOR_SIZE, NULL); - mcontext32 = pcre2_match_context_create_32(NULL); - if (!mdata32_1 || !mdata32_2 || !mcontext32) { - printf("\n32 bit: Cannot allocate match data\n"); - pcre2_match_data_free_32(mdata32_1); - pcre2_match_data_free_32(mdata32_2); - pcre2_match_context_free_32(mcontext32); - pcre2_code_free_32(re32); - re32 = NULL; - } else { - ovector32_1 = pcre2_get_ovector_pointer_32(mdata32_1); - ovector32_2 = pcre2_get_ovector_pointer_32(mdata32_2); - for (i = 0; i < OVECTOR_SIZE * 3; ++i) - ovector32_1[i] = -2; - for (i = 0; i < OVECTOR_SIZE * 3; ++i) - ovector32_2[i] = -2; - } - if (re32) { - if ((current->compile_options & PCRE2_UTF) || (current->start_offset & F_FORCECONV)) - length32 = convert_utf8_to_utf32((PCRE2_SPTR8)current->input, regtest_buf32, regtest_offsetmap32, REGTEST_MAX_LENGTH32); - else - length32 = copy_char8_to_char32((PCRE2_SPTR8)current->input, regtest_buf32, REGTEST_MAX_LENGTH32); - - return_value32[1] = pcre2_match_32(re32, regtest_buf32, length32, - current->start_offset & OFFSET_MASK, current->match_options, mdata32_2, NULL); - - if (pcre2_jit_compile_32(re32, jit_compile_mode)) { - printf("\n32 bit: JIT compiler does not support \"%s\"\n", current->pattern); - } else if ((counter & 0x1) != 0) { - setstack32(mcontext32); - return_value32[0] = pcre2_match_32(re32, regtest_buf32, length32, - current->start_offset & OFFSET_MASK, current->match_options, mdata32_1, mcontext32); - } else { - pcre2_jit_stack_assign_32(mcontext32, NULL, getstack32()); - return_value32[0] = pcre2_jit_match_32(re32, regtest_buf32, length32, - current->start_offset & OFFSET_MASK, current->match_options, mdata32_1, mcontext32); - } - } -#endif - - /* printf("[%d-%d-%d|%d-%d|%d-%d|%d-%d]%s", - return_value8[0], return_value16[0], return_value32[0], - (int)ovector8_1[0], (int)ovector8_1[1], - (int)ovector16_1[0], (int)ovector16_1[1], - (int)ovector32_1[0], (int)ovector32_1[1], - (current->compile_options & PCRE2_CASELESS) ? "C" : ""); */ - - /* If F_DIFF is set, just run the test, but do not compare the results. - Segfaults can still be captured. */ - - is_successful = 1; - if (!(current->start_offset & F_DIFF)) { -#if defined SUPPORT_UTF && ((defined(SUPPORT_PCRE2_8) + defined(SUPPORT_PCRE2_16) + defined(SUPPORT_PCRE2_32)) >= 2) - if (!(current->start_offset & F_FORCECONV)) { - - /* All results must be the same. */ -#ifdef SUPPORT_PCRE2_8 - if ((return_value = return_value8[0]) != return_value8[1]) { - printf("\n8 bit: Return value differs(J8:%d,I8:%d): [%d] '%s' @ '%s'\n", - return_value8[0], return_value8[1], total, current->pattern, current->input); - is_successful = 0; - } else -#endif -#ifdef SUPPORT_PCRE2_16 - if ((return_value = return_value16[0]) != return_value16[1]) { - printf("\n16 bit: Return value differs(J16:%d,I16:%d): [%d] '%s' @ '%s'\n", - return_value16[0], return_value16[1], total, current->pattern, current->input); - is_successful = 0; - } else -#endif -#ifdef SUPPORT_PCRE2_32 - if ((return_value = return_value32[0]) != return_value32[1]) { - printf("\n32 bit: Return value differs(J32:%d,I32:%d): [%d] '%s' @ '%s'\n", - return_value32[0], return_value32[1], total, current->pattern, current->input); - is_successful = 0; - } else -#endif -#if defined SUPPORT_PCRE2_8 && defined SUPPORT_PCRE2_16 - if (return_value8[0] != return_value16[0]) { - printf("\n8 and 16 bit: Return value differs(J8:%d,J16:%d): [%d] '%s' @ '%s'\n", - return_value8[0], return_value16[0], - total, current->pattern, current->input); - is_successful = 0; - } else -#endif -#if defined SUPPORT_PCRE2_8 && defined SUPPORT_PCRE2_32 - if (return_value8[0] != return_value32[0]) { - printf("\n8 and 32 bit: Return value differs(J8:%d,J32:%d): [%d] '%s' @ '%s'\n", - return_value8[0], return_value32[0], - total, current->pattern, current->input); - is_successful = 0; - } else -#endif -#if defined SUPPORT_PCRE2_16 && defined SUPPORT_PCRE2_32 - if (return_value16[0] != return_value32[0]) { - printf("\n16 and 32 bit: Return value differs(J16:%d,J32:%d): [%d] '%s' @ '%s'\n", - return_value16[0], return_value32[0], - total, current->pattern, current->input); - is_successful = 0; - } else -#endif - if (return_value >= 0 || return_value == PCRE_ERROR_PARTIAL) { - if (return_value == PCRE_ERROR_PARTIAL) { - return_value = 2; - } else { - return_value *= 2; - } -#ifdef SUPPORT_PCRE2_8 - return_value8[0] = return_value; -#endif -#ifdef SUPPORT_PCRE2_16 - return_value16[0] = return_value; -#endif -#ifdef SUPPORT_PCRE2_32 - return_value32[0] = return_value; -#endif - /* Transform back the results. */ - if (current->flags & PCRE_UTF8) { -#ifdef SUPPORT_PCRE2_16 - for (i = 0; i < return_value; ++i) { - if (ovector16_1[i] >= 0) - ovector16_1[i] = regtest_offsetmap16[ovector16_1[i]]; - if (ovector16_2[i] >= 0) - ovector16_2[i] = regtest_offsetmap16[ovector16_2[i]]; - } -#endif -#ifdef SUPPORT_PCRE2_32 - for (i = 0; i < return_value; ++i) { - if (ovector32_1[i] >= 0) - ovector32_1[i] = regtest_offsetmap32[ovector32_1[i]]; - if (ovector32_2[i] >= 0) - ovector32_2[i] = regtest_offsetmap32[ovector32_2[i]]; - } -#endif - } - - for (i = 0; i < return_value; ++i) { -#if defined SUPPORT_PCRE2_8 && defined SUPPORT_PCRE2_16 - if (ovector8_1[i] != ovector8_2[i] || ovector8_1[i] != ovector16_1[i] || ovector8_1[i] != ovector16_2[i]) { - printf("\n8 and 16 bit: Ovector[%d] value differs(J8:%d,I8:%d,J16:%d,I16:%d): [%d] '%s' @ '%s' \n", - i, ovector8_1[i], ovector8_2[i], ovector16_1[i], ovector16_2[i], - total, current->pattern, current->input); - is_successful = 0; - } -#endif -#if defined SUPPORT_PCRE2_8 && defined SUPPORT_PCRE2_32 - if (ovector8_1[i] != ovector8_2[i] || ovector8_1[i] != ovector32_1[i] || ovector8_1[i] != ovector32_2[i]) { - printf("\n8 and 32 bit: Ovector[%d] value differs(J8:%d,I8:%d,J32:%d,I32:%d): [%d] '%s' @ '%s' \n", - i, ovector8_1[i], ovector8_2[i], ovector32_1[i], ovector32_2[i], - total, current->pattern, current->input); - is_successful = 0; - } -#endif -#if defined SUPPORT_PCRE2_16 && defined SUPPORT_PCRE2_32 - if (ovector16_1[i] != ovector16_2[i] || ovector16_1[i] != ovector32_1[i] || ovector16_1[i] != ovector32_2[i]) { - printf("\n16 and 32 bit: Ovector[%d] value differs(J16:%d,I16:%d,J32:%d,I32:%d): [%d] '%s' @ '%s' \n", - i, ovector16_1[i], ovector16_2[i], ovector32_1[i], ovector32_2[i], - total, current->pattern, current->input); - is_successful = 0; - } -#endif - } - } - } else -#endif /* more than one of SUPPORT_PCRE2_8, SUPPORT_PCRE2_16 and SUPPORT_PCRE2_32 */ - { -#ifdef SUPPORT_PCRE2_8 - if (return_value8[0] != return_value8[1]) { - printf("\n8 bit: Return value differs(%d:%d): [%d] '%s' @ '%s'\n", - return_value8[0], return_value8[1], total, current->pattern, current->input); - is_successful = 0; - } else if (return_value8[0] >= 0 || return_value8[0] == PCRE2_ERROR_PARTIAL) { - if (return_value8[0] == PCRE2_ERROR_PARTIAL) - return_value8[0] = 2; - else - return_value8[0] *= 2; - - for (i = 0; i < return_value8[0]; ++i) - if (ovector8_1[i] != ovector8_2[i]) { - printf("\n8 bit: Ovector[%d] value differs(%d:%d): [%d] '%s' @ '%s'\n", - i, (int)ovector8_1[i], (int)ovector8_2[i], total, current->pattern, current->input); - is_successful = 0; - } - } -#endif - -#ifdef SUPPORT_PCRE2_16 - if (return_value16[0] != return_value16[1]) { - printf("\n16 bit: Return value differs(%d:%d): [%d] '%s' @ '%s'\n", - return_value16[0], return_value16[1], total, current->pattern, current->input); - is_successful = 0; - } else if (return_value16[0] >= 0 || return_value16[0] == PCRE2_ERROR_PARTIAL) { - if (return_value16[0] == PCRE2_ERROR_PARTIAL) - return_value16[0] = 2; - else - return_value16[0] *= 2; - - for (i = 0; i < return_value16[0]; ++i) - if (ovector16_1[i] != ovector16_2[i]) { - printf("\n16 bit: Ovector[%d] value differs(%d:%d): [%d] '%s' @ '%s'\n", - i, (int)ovector16_1[i], (int)ovector16_2[i], total, current->pattern, current->input); - is_successful = 0; - } - } -#endif - -#ifdef SUPPORT_PCRE2_32 - if (return_value32[0] != return_value32[1]) { - printf("\n32 bit: Return value differs(%d:%d): [%d] '%s' @ '%s'\n", - return_value32[0], return_value32[1], total, current->pattern, current->input); - is_successful = 0; - } else if (return_value32[0] >= 0 || return_value32[0] == PCRE2_ERROR_PARTIAL) { - if (return_value32[0] == PCRE2_ERROR_PARTIAL) - return_value32[0] = 2; - else - return_value32[0] *= 2; - - for (i = 0; i < return_value32[0]; ++i) - if (ovector32_1[i] != ovector32_2[i]) { - printf("\n32 bit: Ovector[%d] value differs(%d:%d): [%d] '%s' @ '%s'\n", - i, (int)ovector32_1[i], (int)ovector32_2[i], total, current->pattern, current->input); - is_successful = 0; - } - } -#endif - } - } - - if (is_successful) { -#ifdef SUPPORT_PCRE2_8 - if (!(current->start_offset & F_NO8) && (utf || is_ascii)) { - if (return_value8[0] < 0 && !(current->start_offset & F_NOMATCH)) { - printf("8 bit: Test should match: [%d] '%s' @ '%s'\n", - total, current->pattern, current->input); - is_successful = 0; - } - - if (return_value8[0] >= 0 && (current->start_offset & F_NOMATCH)) { - printf("8 bit: Test should not match: [%d] '%s' @ '%s'\n", - total, current->pattern, current->input); - is_successful = 0; - } - } -#endif -#ifdef SUPPORT_PCRE2_16 - if (!(current->start_offset & F_NO16) && (utf || is_ascii)) { - if (return_value16[0] < 0 && !(current->start_offset & F_NOMATCH)) { - printf("16 bit: Test should match: [%d] '%s' @ '%s'\n", - total, current->pattern, current->input); - is_successful = 0; - } - - if (return_value16[0] >= 0 && (current->start_offset & F_NOMATCH)) { - printf("16 bit: Test should not match: [%d] '%s' @ '%s'\n", - total, current->pattern, current->input); - is_successful = 0; - } - } -#endif -#ifdef SUPPORT_PCRE2_32 - if (!(current->start_offset & F_NO32) && (utf || is_ascii)) { - if (return_value32[0] < 0 && !(current->start_offset & F_NOMATCH)) { - printf("32 bit: Test should match: [%d] '%s' @ '%s'\n", - total, current->pattern, current->input); - is_successful = 0; - } - - if (return_value32[0] >= 0 && (current->start_offset & F_NOMATCH)) { - printf("32 bit: Test should not match: [%d] '%s' @ '%s'\n", - total, current->pattern, current->input); - is_successful = 0; - } - } -#endif - } - - if (is_successful) { -#ifdef SUPPORT_PCRE2_8 - if (re8 && !(current->start_offset & F_NO8) && pcre2_get_mark_8(mdata8_1) != pcre2_get_mark_8(mdata8_2)) { - printf("8 bit: Mark value mismatch: [%d] '%s' @ '%s'\n", - total, current->pattern, current->input); - is_successful = 0; - } -#endif -#ifdef SUPPORT_PCRE2_16 - if (re16 && !(current->start_offset & F_NO16) && pcre2_get_mark_16(mdata16_1) != pcre2_get_mark_16(mdata16_2)) { - printf("16 bit: Mark value mismatch: [%d] '%s' @ '%s'\n", - total, current->pattern, current->input); - is_successful = 0; - } -#endif -#ifdef SUPPORT_PCRE2_32 - if (re32 && !(current->start_offset & F_NO32) && pcre2_get_mark_32(mdata32_1) != pcre2_get_mark_32(mdata32_2)) { - printf("32 bit: Mark value mismatch: [%d] '%s' @ '%s'\n", - total, current->pattern, current->input); - is_successful = 0; - } -#endif - } - -#ifdef SUPPORT_PCRE2_8 - pcre2_code_free_8(re8); - pcre2_match_data_free_8(mdata8_1); - pcre2_match_data_free_8(mdata8_2); - pcre2_match_context_free_8(mcontext8); -#endif -#ifdef SUPPORT_PCRE2_16 - pcre2_code_free_16(re16); - pcre2_match_data_free_16(mdata16_1); - pcre2_match_data_free_16(mdata16_2); - pcre2_match_context_free_16(mcontext16); -#endif -#ifdef SUPPORT_PCRE2_32 - pcre2_code_free_32(re32); - pcre2_match_data_free_32(mdata32_1); - pcre2_match_data_free_32(mdata32_2); - pcre2_match_context_free_32(mcontext32); -#endif - - if (is_successful) { - successful++; - successful_row++; - printf("."); - if (successful_row >= 60) { - successful_row = 0; - printf("\n"); - } - } else - successful_row = 0; - - fflush(stdout); - current++; - } -#ifdef SUPPORT_PCRE2_8 - setstack8(NULL); -#endif -#ifdef SUPPORT_PCRE2_16 - setstack16(NULL); -#endif -#ifdef SUPPORT_PCRE2_32 - setstack32(NULL); -#endif - - if (total == successful) { - printf("\nAll JIT regression tests are successfully passed.\n"); - return 0; - } else { - printf("\nSuccessful test ratio: %d%% (%d failed)\n", successful * 100 / total, total - successful); - return 1; - } -} - -/* End of pcre2_jit_test.c */ diff --git a/thirdparty/pcre2/src/pcre2_match.c b/thirdparty/pcre2/src/pcre2_match.c index 78a9bacbc8..79cc93f918 100644 --- a/thirdparty/pcre2/src/pcre2_match.c +++ b/thirdparty/pcre2/src/pcre2_match.c @@ -7,7 +7,7 @@ and semantics are as close as possible to those of the Perl 5 language. Written by Philip Hazel Original API code Copyright (c) 1997-2012 University of Cambridge - New API code Copyright (c) 2016 University of Cambridge + New API code Copyright (c) 2015-2018 University of Cambridge ----------------------------------------------------------------------------- Redistribution and use in source and binary forms, with or without @@ -43,17 +43,31 @@ POSSIBILITY OF SUCH DAMAGE. #include "config.h" #endif -#define NLBLOCK mb /* Block containing newline information */ -#define PSSTART start_subject /* Field containing processed string start */ -#define PSEND end_subject /* Field containing processed string end */ +/* These defines enables debugging code */ + +//#define DEBUG_FRAMES_DISPLAY +//#define DEBUG_SHOW_OPS +//#define DEBUG_SHOW_RMATCH + +#ifdef DEBUG_FRAME_DISPLAY +#include <stdarg.h> +#endif + +/* These defines identify the name of the block containing "static" +information, and fields within it. */ + +#define NLBLOCK mb /* Block containing newline information */ +#define PSSTART start_subject /* Field containing processed string start */ +#define PSEND end_subject /* Field containing processed string end */ #include "pcre2_internal.h" -/* Masks for identifying the public options that are permitted at match time. -*/ +#define RECURSE_UNSET 0xffffffffu /* Bigger than max group number */ + +/* Masks for identifying the public options that are permitted at match time. */ #define PUBLIC_MATCH_OPTIONS \ - (PCRE2_ANCHORED|PCRE2_NOTBOL|PCRE2_NOTEOL|PCRE2_NOTEMPTY| \ + (PCRE2_ANCHORED|PCRE2_ENDANCHORED|PCRE2_NOTBOL|PCRE2_NOTEOL|PCRE2_NOTEMPTY| \ PCRE2_NOTEMPTY_ATSTART|PCRE2_NO_UTF_CHECK|PCRE2_PARTIAL_HARD| \ PCRE2_PARTIAL_SOFT|PCRE2_NO_JIT) @@ -61,60 +75,255 @@ POSSIBILITY OF SUCH DAMAGE. (PCRE2_NO_UTF_CHECK|PCRE2_NOTBOL|PCRE2_NOTEOL|PCRE2_NOTEMPTY|\ PCRE2_NOTEMPTY_ATSTART|PCRE2_PARTIAL_SOFT|PCRE2_PARTIAL_HARD) -/* The mb->capture_last field uses the lower 16 bits for the last captured -substring (which can never be greater than 65535) and a bit in the top half -to mean "capture vector overflowed". This odd way of doing things was -implemented when it was realized that preserving and restoring the overflow bit -whenever the last capture number was saved/restored made for a neater -interface, and doing it this way saved on (a) another variable, which would -have increased the stack frame size (a big NO-NO in PCRE) and (b) another -separate set of save/restore instructions. The following defines are used in -implementing this. */ - -#define CAPLMASK 0x0000ffff /* The bits used for last_capture */ -#define OVFLMASK 0xffff0000 /* The bits used for the overflow flag */ -#define OVFLBIT 0x00010000 /* The bit that is set for overflow */ - -/* Bits for setting in mb->match_function_type to indicate two special types -of call to match(). We do it this way to save on using another stack variable, -as stack usage is to be discouraged. */ - -#define MATCH_CONDASSERT 1 /* Called to check a condition assertion */ -#define MATCH_CBEGROUP 2 /* Could-be-empty unlimited repeat group */ - -/* Non-error returns from the match() function. Error returns are externally -defined PCRE2_ERROR_xxx codes, which are all negative. */ +/* Non-error returns from and within the match() function. Error returns are +externally defined PCRE2_ERROR_xxx codes, which are all negative. */ #define MATCH_MATCH 1 #define MATCH_NOMATCH 0 -/* Special internal returns from the match() function. Make them sufficiently -negative to avoid the external error codes. */ +/* Special internal returns used in the match() function. Make them +sufficiently negative to avoid the external error codes. */ #define MATCH_ACCEPT (-999) #define MATCH_KETRPOS (-998) -#define MATCH_ONCE (-997) /* The next 5 must be kept together and in sequence so that a test that checks for any one of them can use a range. */ -#define MATCH_COMMIT (-996) -#define MATCH_PRUNE (-995) -#define MATCH_SKIP (-994) -#define MATCH_SKIP_ARG (-993) -#define MATCH_THEN (-992) +#define MATCH_COMMIT (-997) +#define MATCH_PRUNE (-996) +#define MATCH_SKIP (-995) +#define MATCH_SKIP_ARG (-994) +#define MATCH_THEN (-993) #define MATCH_BACKTRACK_MAX MATCH_THEN #define MATCH_BACKTRACK_MIN MATCH_COMMIT -/* Min and max values for the common repeats; for the maxima, 0 => infinity */ +/* Group frame type values. Zero means the frame is not a group frame. The +lower 16 bits are used for data (e.g. the capture number). Group frames are +used for most groups so that information about the start is easily available at +the end without having to scan back through intermediate frames (backtrack +points). */ + +#define GF_CAPTURE 0x00010000u +#define GF_NOCAPTURE 0x00020000u +#define GF_CONDASSERT 0x00030000u +#define GF_RECURSE 0x00040000u -static const char rep_min[] = { 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, }; -static const char rep_max[] = { 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, }; +/* Masks for the identity and data parts of the group frame type. */ -/* Maximum number of ovector elements that can be saved on the system stack -when processing OP_RECURSE in non-HEAP_MATCH_RECURSE mode. If the ovector is -bigger, malloc() is used. This value should be a multiple of 3, because the -ovector length is always a multiple of 3. */ +#define GF_IDMASK(a) ((a) & 0xffff0000u) +#define GF_DATAMASK(a) ((a) & 0x0000ffffu) -#define OP_RECURSE_STACK_SAVE_MAX 45 +/* Repetition types */ + +enum { REPTYPE_MIN, REPTYPE_MAX, REPTYPE_POS }; + +/* Min and max values for the common repeats; a maximum of UINT32_MAX => +infinity. */ + +static const uint32_t rep_min[] = { + 0, 0, /* * and *? */ + 1, 1, /* + and +? */ + 0, 0, /* ? and ?? */ + 0, 0, /* dummy placefillers for OP_CR[MIN]RANGE */ + 0, 1, 0 }; /* OP_CRPOS{STAR, PLUS, QUERY} */ + +static const uint32_t rep_max[] = { + UINT32_MAX, UINT32_MAX, /* * and *? */ + UINT32_MAX, UINT32_MAX, /* + and +? */ + 1, 1, /* ? and ?? */ + 0, 0, /* dummy placefillers for OP_CR[MIN]RANGE */ + UINT32_MAX, UINT32_MAX, 1 }; /* OP_CRPOS{STAR, PLUS, QUERY} */ + +/* Repetition types - must include OP_CRPOSRANGE (not needed above) */ + +static const uint32_t rep_typ[] = { + REPTYPE_MAX, REPTYPE_MIN, /* * and *? */ + REPTYPE_MAX, REPTYPE_MIN, /* + and +? */ + REPTYPE_MAX, REPTYPE_MIN, /* ? and ?? */ + REPTYPE_MAX, REPTYPE_MIN, /* OP_CRRANGE and OP_CRMINRANGE */ + REPTYPE_POS, REPTYPE_POS, /* OP_CRPOSSTAR, OP_CRPOSPLUS */ + REPTYPE_POS, REPTYPE_POS }; /* OP_CRPOSQUERY, OP_CRPOSRANGE */ + +/* Numbers for RMATCH calls at backtracking points. When these lists are +changed, the code at RETURN_SWITCH below must be updated in sync. */ + +enum { RM1=1, RM2, RM3, RM4, RM5, RM6, RM7, RM8, RM9, RM10, + RM11, RM12, RM13, RM14, RM15, RM16, RM17, RM18, RM19, RM20, + RM21, RM22, RM23, RM24, RM25, RM26, RM27, RM28, RM29, RM30, + RM31, RM32, RM33, RM34, RM35 }; + +#ifdef SUPPORT_WIDE_CHARS +enum { RM100=100, RM101 }; +#endif + +#ifdef SUPPORT_UNICODE +enum { RM200=200, RM201, RM202, RM203, RM204, RM205, RM206, RM207, + RM208, RM209, RM210, RM211, RM212, RM213, RM214, RM215, + RM216, RM217, RM218, RM219, RM220, RM221, RM222 }; +#endif + +/* Define short names for general fields in the current backtrack frame, which +is always pointed to by the F variable. Occasional references to fields in +other frames are written out explicitly. There are also some fields in the +current frame whose names start with "temp" that are used for short-term, +localised backtracking memory. These are #defined with Lxxx names at the point +of use and undefined afterwards. */ + +#define Fback_frame F->back_frame +#define Fcapture_last F->capture_last +#define Fcurrent_recurse F->current_recurse +#define Fecode F->ecode +#define Feptr F->eptr +#define Fgroup_frame_type F->group_frame_type +#define Flast_group_offset F->last_group_offset +#define Flength F->length +#define Fmark F->mark +#define Frdepth F->rdepth +#define Fstart_match F->start_match +#define Foffset_top F->offset_top +#define Foccu F->occu +#define Fop F->op +#define Fovector F->ovector +#define Freturn_id F->return_id + + +#ifdef DEBUG_FRAMES_DISPLAY +/************************************************* +* Display current frames and contents * +*************************************************/ + +/* This debugging function displays the current set of frames and their +contents. It is not called automatically from anywhere, the intention being +that calls can be inserted where necessary when debugging frame-related +problems. + +Arguments: + f the file to write to + F the current top frame + P a previous frame of interest + frame_size the frame size + mb points to the match block + s identification text + +Returns: nothing +*/ + +static void +display_frames(FILE *f, heapframe *F, heapframe *P, PCRE2_SIZE frame_size, + match_block *mb, const char *s, ...) +{ +uint32_t i; +heapframe *Q; +va_list ap; +va_start(ap, s); + +fprintf(f, "FRAMES "); +vfprintf(f, s, ap); +va_end(ap); + +if (P != NULL) fprintf(f, " P=%lu", + ((char *)P - (char *)(mb->match_frames))/frame_size); +fprintf(f, "\n"); + +for (i = 0, Q = mb->match_frames; + Q <= F; + i++, Q = (heapframe *)((char *)Q + frame_size)) + { + fprintf(f, "Frame %d type=%x subj=%lu code=%d back=%lu id=%d", + i, Q->group_frame_type, Q->eptr - mb->start_subject, *(Q->ecode), + Q->back_frame, Q->return_id); + + if (Q->last_group_offset == PCRE2_UNSET) + fprintf(f, " lgoffset=unset\n"); + else + fprintf(f, " lgoffset=%lu\n", Q->last_group_offset/frame_size); + } +} + +#endif + + + +/************************************************* +* Process a callout * +*************************************************/ + +/* This function is called for all callouts, whether "standalone" or at the +start of a conditional group. Feptr will be pointing to either OP_CALLOUT or +OP_CALLOUT_STR. A callout block is allocated in pcre2_match() and initialized +with fixed values. + +Arguments: + F points to the current backtracking frame + mb points to the match block + lengthptr where to return the length of the callout item + +Returns: the return from the callout + or 0 if no callout function exists +*/ + +static int +do_callout(heapframe *F, match_block *mb, PCRE2_SIZE *lengthptr) +{ +int rc; +PCRE2_SIZE save0, save1; +PCRE2_SIZE *callout_ovector; +pcre2_callout_block *cb; + +*lengthptr = (*Fecode == OP_CALLOUT)? + PRIV(OP_lengths)[OP_CALLOUT] : GET(Fecode, 1 + 2*LINK_SIZE); + +if (mb->callout == NULL) return 0; /* No callout function provided */ + +/* The original matching code (pre 10.30) worked directly with the ovector +passed by the user, and this was passed to callouts. Now that the working +ovector is in the backtracking frame, it no longer needs to reserve space for +the overall match offsets (which would waste space in the frame). For backward +compatibility, however, we pass capture_top and offset_vector to the callout as +if for the extended ovector, and we ensure that the first two slots are unset +by preserving and restoring their current contents. Picky compilers complain if +references such as Fovector[-2] are use directly, so we set up a separate +pointer. */ + +callout_ovector = (PCRE2_SIZE *)(Fovector) - 2; + +/* The cb->version, cb->subject, cb->subject_length, and cb->start_match fields +are set externally. The first 3 never change; the last is updated for each +bumpalong. */ + +cb = mb->cb; +cb->capture_top = (uint32_t)Foffset_top/2 + 1; +cb->capture_last = Fcapture_last; +cb->offset_vector = callout_ovector; +cb->mark = mb->nomatch_mark; +cb->current_position = (PCRE2_SIZE)(Feptr - mb->start_subject); +cb->pattern_position = GET(Fecode, 1); +cb->next_item_length = GET(Fecode, 1 + LINK_SIZE); + +if (*Fecode == OP_CALLOUT) /* Numerical callout */ + { + cb->callout_number = Fecode[1 + 2*LINK_SIZE]; + cb->callout_string_offset = 0; + cb->callout_string = NULL; + cb->callout_string_length = 0; + } +else /* String callout */ + { + cb->callout_number = 0; + cb->callout_string_offset = GET(Fecode, 1 + 3*LINK_SIZE); + cb->callout_string = Fecode + (1 + 4*LINK_SIZE) + 1; + cb->callout_string_length = + *lengthptr - (1 + 4*LINK_SIZE) - 2; + } + +save0 = callout_ovector[0]; +save1 = callout_ovector[1]; +callout_ovector[0] = callout_ovector[1] = PCRE2_UNSET; +rc = mb->callout(cb, mb->callout_data); +callout_ovector[0] = save0; +callout_ovector[1] = save1; +cb->callout_flags = 0; +return rc; +} @@ -130,10 +339,9 @@ seems unlikely.) Arguments: offset index into the offset vector - offset_top top of the used offset vector - eptr pointer into the subject - mb points to match block caseless TRUE if caseless + F the current backtracking frame pointer + mb points to match block lengthptr pointer for returning the length matched Returns: = 0 sucessful match; number of code units matched is set @@ -142,21 +350,18 @@ Returns: = 0 sucessful match; number of code units matched is set */ static int -match_ref(PCRE2_SIZE offset, PCRE2_SIZE offset_top, PCRE2_SPTR eptr, - match_block *mb, BOOL caseless, PCRE2_SIZE *lengthptr) +match_ref(PCRE2_SIZE offset, BOOL caseless, heapframe *F, match_block *mb, + PCRE2_SIZE *lengthptr) { -#if defined SUPPORT_UNICODE -BOOL utf = (mb->poptions & PCRE2_UTF) != 0; -#endif - PCRE2_SPTR p; PCRE2_SIZE length; -PCRE2_SPTR eptr_start = eptr; +PCRE2_SPTR eptr; +PCRE2_SPTR eptr_start; /* Deal with an unset group. The default is no match, but there is an option to match an empty string. */ -if (offset >= offset_top || mb->ovector[offset] == PCRE2_UNSET) +if (offset >= Foffset_top || Fovector[offset] == PCRE2_UNSET) { if ((mb->poptions & PCRE2_MATCH_UNSET_BACKREF) != 0) { @@ -168,19 +373,20 @@ if (offset >= offset_top || mb->ovector[offset] == PCRE2_UNSET) /* Separate the caseless and UTF cases for speed. */ -p = mb->start_subject + mb->ovector[offset]; -length = mb->ovector[offset+1] - mb->ovector[offset]; +eptr = eptr_start = Feptr; +p = mb->start_subject + Fovector[offset]; +length = Fovector[offset+1] - Fovector[offset]; if (caseless) { #if defined SUPPORT_UNICODE - if (utf) + if ((mb->poptions & PCRE2_UTF) != 0) { /* Match characters up to the end of the reference. NOTE: the number of code units matched may differ, because in UTF-8 there are some characters - whose upper and lower case versions code have different numbers of bytes. - For example, U+023A (2 bytes in UTF-8) is the upper case version of U+2C65 - (3 bytes in UTF-8); a sequence of 3 of the former uses 6 bytes, as does a + whose upper and lower case codes have different numbers of bytes. For + example, U+023A (2 bytes in UTF-8) is the upper case version of U+2C65 (3 + bytes in UTF-8); a sequence of 3 of the former uses 6 bytes, as does a sequence of two of the latter. It is important, therefore, to check the length along the reference, not along the subject (earlier code did this wrong). */ @@ -226,14 +432,26 @@ if (caseless) } /* In the caseful case, we can just compare the code units, whether or not we -are in UTF mode. */ +are in UTF mode. When partial matching, we have to do this unit-by-unit. */ else { - for (; length > 0; length--) + if (mb->partial != 0) + { + for (; length > 0; length--) + { + if (eptr >= mb->end_subject) return 1; /* Partial match */ + if (UCHAR21INCTEST(p) != UCHAR21INCTEST(eptr)) return -1; /* No match */ + } + } + + /* Not partial matching */ + + else { - if (eptr >= mb->end_subject) return 1; /* Partial match */ - if (UCHAR21INCTEST(p) != UCHAR21INCTEST(eptr)) return -1; /*No match */ + if ((PCRE2_SIZE)(mb->end_subject - eptr) < length) return 1; /* Partial */ + if (memcmp(p, eptr, CU2BYTES(length)) != 0) return -1; /* No match */ + eptr += length; } } @@ -243,278 +461,73 @@ return 0; /* Match */ -/*************************************************************************** -**************************************************************************** - RECURSION IN THE match() FUNCTION - -The match() function is highly recursive, though not every recursive call -increases the recursion depth. Nevertheless, some regular expressions can cause -it to recurse to a great depth. I was writing for Unix, so I just let it call -itself recursively. This uses the stack for saving everything that has to be -saved for a recursive call. On Unix, the stack can be large, and this works -fine. - -It turns out that on some non-Unix-like systems there are problems with -programs that use a lot of stack. (This despite the fact that every last chip -has oodles of memory these days, and techniques for extending the stack have -been known for decades.) So.... - -There is a fudge, triggered by defining HEAP_MATCH_RECURSE, which avoids -recursive calls by keeping local variables that need to be preserved in blocks -of memory on the heap instead instead of on the stack. Macros are used to -achieve this so that the actual code doesn't look very different to what it -always used to. - -The original heap-recursive code used longjmp(). However, it seems that this -can be very slow on some operating systems. Following a suggestion from Stan -Switzer, the use of longjmp() has been abolished, at the cost of having to -provide a unique number for each call to RMATCH. There is no way of generating -a sequence of numbers at compile time in C. I have given them names, to make -them stand out more clearly. - -Crude tests on x86 Linux show a small speedup of around 5-8%. However, on -FreeBSD, avoiding longjmp() more than halves the time taken to run the standard -tests. Furthermore, not using longjmp() means that local dynamic variables -don't have indeterminate values; this has meant that the frame size can be -reduced because the result can be "passed back" by straight setting of the -variable instead of being passed in the frame. -**************************************************************************** -***************************************************************************/ - -/* Numbers for RMATCH calls. When this list is changed, the code at HEAP_RETURN -below must be updated in sync. */ - -enum { RM1=1, RM2, RM3, RM4, RM5, RM6, RM7, RM8, RM9, RM10, - RM11, RM12, RM13, RM14, RM15, RM16, RM17, RM18, RM19, RM20, - RM21, RM22, RM23, RM24, RM25, RM26, RM27, RM28, RM29, RM30, - RM31, RM32, RM33, RM34, RM35, RM36, RM37, RM38, RM39, RM40, - RM41, RM42, RM43, RM44, RM45, RM46, RM47, RM48, RM49, RM50, - RM51, RM52, RM53, RM54, RM55, RM56, RM57, RM58, RM59, RM60, - RM61, RM62, RM63, RM64, RM65, RM66, RM67, RM68 }; - -/* These versions of the macros use the stack, as normal. Note that the "rw" -argument of RMATCH isn't actually used in this definition. */ - -#ifndef HEAP_MATCH_RECURSE -#define RMATCH(ra,rb,rc,rd,re,rw) \ - rrc = match(ra,rb,mstart,rc,rd,re,rdepth+1) -#define RRETURN(ra) return ra -#else - -/* These versions of the macros manage a private stack on the heap. Note that -the "rd" argument of RMATCH isn't actually used in this definition. It's the mb -argument of match(), which never changes. */ - -#define RMATCH(ra,rb,rc,rd,re,rw)\ - {\ - heapframe *newframe = frame->Xnextframe;\ - if (newframe == NULL)\ - {\ - newframe = (heapframe *)(mb->stack_memctl.malloc)\ - (sizeof(heapframe), mb->stack_memctl.memory_data);\ - if (newframe == NULL) RRETURN(PCRE2_ERROR_NOMEMORY);\ - newframe->Xnextframe = NULL;\ - frame->Xnextframe = newframe;\ - }\ - frame->Xwhere = rw;\ - newframe->Xeptr = ra;\ - newframe->Xecode = rb;\ - newframe->Xmstart = mstart;\ - newframe->Xoffset_top = rc;\ - newframe->Xeptrb = re;\ - newframe->Xrdepth = frame->Xrdepth + 1;\ - newframe->Xprevframe = frame;\ - frame = newframe;\ - goto HEAP_RECURSE;\ - L_##rw:;\ - } - -#define RRETURN(ra)\ - {\ - heapframe *oldframe = frame;\ - frame = oldframe->Xprevframe;\ - if (frame != NULL)\ - {\ - rrc = ra;\ - goto HEAP_RETURN;\ - }\ - return ra;\ - } - - -/* Structure for remembering the local variables in a private frame. Arrange it -so as to minimize the number of holes. */ - -typedef struct heapframe { - struct heapframe *Xprevframe; - struct heapframe *Xnextframe; - -#ifdef SUPPORT_UNICODE - PCRE2_SPTR Xcharptr; -#endif - PCRE2_SPTR Xeptr; - PCRE2_SPTR Xecode; - PCRE2_SPTR Xmstart; - PCRE2_SPTR Xcallpat; - PCRE2_SPTR Xdata; - PCRE2_SPTR Xnext_ecode; - PCRE2_SPTR Xpp; - PCRE2_SPTR Xprev; - PCRE2_SPTR Xsaved_eptr; - - eptrblock *Xeptrb; - - PCRE2_SIZE Xlength; - PCRE2_SIZE Xoffset; - PCRE2_SIZE Xoffset_top; - PCRE2_SIZE Xsave_offset1, Xsave_offset2, Xsave_offset3; - - uint32_t Xfc; - uint32_t Xnumber; - uint32_t Xrdepth; - uint32_t Xop; - uint32_t Xsave_capture_last; - -#ifdef SUPPORT_UNICODE - uint32_t Xprop_value; - int Xprop_type; - int Xprop_fail_result; - int Xoclength; -#endif - - int Xcodelink; - int Xctype; - int Xfi; - int Xmax; - int Xmin; - int Xwhere; /* Where to jump back to */ - - BOOL Xcondition; - BOOL Xcur_is_word; - BOOL Xprev_is_word; +/****************************************************************************** +******************************************************************************* + "Recursion" in the match() function - eptrblock Xnewptrb; - recursion_info Xnew_recursive; +The original match() function was highly recursive, but this proved to be the +source of a number of problems over the years, mostly because of the relatively +small system stacks that are commonly found. As new features were added to +patterns, various kludges were invented to reduce the amount of stack used, +making the code hard to understand in places. -#ifdef SUPPORT_UNICODE - PCRE2_UCHAR Xocchars[6]; -#endif -} heapframe; - -#endif - - -/*************************************************************************** -***************************************************************************/ +A version did exist that used individual frames on the heap instead of calling +match() recursively, but this ran substantially slower. The current version is +a refactoring that uses a vector of frames to remember backtracking points. +This runs no slower, and possibly even a bit faster than the original recursive +implementation. An initial vector of size START_FRAMES_SIZE (enough for maybe +50 frames) is allocated on the system stack. If this is not big enough, the +heap is used for a larger vector. +******************************************************************************* +******************************************************************************/ -/* When HEAP_MATCH_RECURSE is not defined, the match() function implements -backtrack points by calling itself recursively in all but one case. The one -special case is when processing OP_RECURSE, which specifies recursion in the -pattern. The entire ovector must be saved and restored while processing -OP_RECURSE. If the ovector is small enough, instead of calling match() -directly, op_recurse_ovecsave() is called. This function uses the system stack -to save the ovector while calling match() to process the pattern recursion. */ -#ifndef HEAP_MATCH_RECURSE - -/* We need a prototype for match() because it is mutually recursive with -op_recurse_ovecsave(). */ - -static int -match(PCRE2_SPTR eptr, PCRE2_SPTR ecode, PCRE2_SPTR mstart, - PCRE2_SIZE offset_top, match_block *mb, eptrblock *eptrb, uint32_t rdepth); /************************************************* -* Process OP_RECURSE, stacking ovector * +* Macros for the match() function * *************************************************/ -/* When this function is called, mb->recursive has already been updated to -point to a new recursion data block, and all its fields other than ovec_save -have been set. +/* These macros pack up tests that are used for partial matching several times +in the code. We set the "hit end" flag if the pointer is at the end of the +subject and also past the earliest inspected character (i.e. something has been +matched, even if not part of the actual matched string). For hard partial +matching, we then return immediately. The second one is used when we already +know we are past the end of the subject. */ -This function exists so that the local vector variable ovecsave is no longer -defined in the match() function, as it was in PCRE1. It is used only when there -is recursion in the pattern, so it wastes a lot of stack to have it defined for -every call of match(). We now use this function as an indirect way of calling -match() only in the case when ovecsave is needed. (David Wheeler used to say -"All problems in computer science can be solved by another level of -indirection.") - -HOWEVER: when this file is compiled by gcc in an optimizing mode, because this -function is called only once, and only from within match(), gcc will "inline" -it - that is, move it inside match() - and this completely negates its reason -for existence. Therefore, we mark it as non-inline when gcc is in use. - -Arguments: - eptr pointer to current character in subject - callpat the recursion point in the pattern - mstart pointer to the current match start position (can be modified - by encountering \K) - offset_top current top pointer (highest ovector offset used + 1) - mb pointer to "static" info block for the match - eptrb pointer to chain of blocks containing eptr at start of - brackets - for testing for empty matches - rdepth the recursion depth - -Returns: a match() return code -*/ - -static int -#if defined(__GNUC__) && !defined(__INTEL_COMPILER) -__attribute__ ((noinline)) -#endif -op_recurse_ovecsave(PCRE2_SPTR eptr, PCRE2_SPTR callpat, - PCRE2_SPTR mstart, PCRE2_SIZE offset_top, match_block *mb, eptrblock *eptrb, - uint32_t rdepth) -{ -int rrc; -BOOL cbegroup = *callpat >= OP_SBRA; -recursion_info *new_recursive = mb->recursive; -PCRE2_SIZE ovecsave[OP_RECURSE_STACK_SAVE_MAX]; - -/* Save the ovector */ +#define CHECK_PARTIAL()\ + if (mb->partial != 0 && Feptr >= mb->end_subject && \ + Feptr > mb->start_used_ptr) \ + { \ + mb->hitend = TRUE; \ + if (mb->partial > 1) return PCRE2_ERROR_PARTIAL; \ + } -new_recursive->ovec_save = ovecsave; -memcpy(ovecsave, mb->ovector, mb->offset_end * sizeof(PCRE2_SIZE)); +#define SCHECK_PARTIAL()\ + if (mb->partial != 0 && Feptr > mb->start_used_ptr) \ + { \ + mb->hitend = TRUE; \ + if (mb->partial > 1) return PCRE2_ERROR_PARTIAL; \ + } -/* Do the recursion. After processing each alternative, restore the ovector -data and the last captured value. */ +/* These macros are used to implement backtracking. They simulate a recursive +call to the match() function by means of a local vector of frames which +remember the backtracking points. */ -do - { - if (cbegroup) mb->match_function_type |= MATCH_CBEGROUP; - rrc = match(eptr, callpat + PRIV(OP_lengths)[*callpat], mstart, offset_top, - mb, eptrb, rdepth + 1); - memcpy(mb->ovector, new_recursive->ovec_save, - mb->offset_end * sizeof(PCRE2_SIZE)); - mb->capture_last = new_recursive->saved_capture_last; - if (rrc == MATCH_MATCH || rrc == MATCH_ACCEPT) return rrc; - - /* PCRE does not allow THEN, SKIP, PRUNE or COMMIT to escape beyond a - recursion; they cause a NOMATCH for the entire recursion. These codes - are defined in a range that can be tested for. */ - - if (rrc >= MATCH_BACKTRACK_MIN && rrc <= MATCH_BACKTRACK_MAX) - return MATCH_NOMATCH; - - /* Any return code other than NOMATCH is an error. Otherwise, advance to the - next alternative or to the end of the recursing subpattern. If there were - nested recursions, mb->recursive might be changed, so reset it before - looping. */ - - if (rrc != MATCH_NOMATCH) return rrc; - mb->recursive = new_recursive; - callpat += GET(callpat, 1); +#define RMATCH(ra,rb)\ + {\ + start_ecode = ra;\ + Freturn_id = rb;\ + goto MATCH_RECURSE;\ + L_##rb:;\ } -while (*callpat == OP_ALT); /* Loop for the alternatives */ - -/* None of the alternatives matched. */ -return MATCH_NOMATCH; -} -#endif /* HEAP_MATCH_RECURSE */ +#define RRETURN(ra)\ + {\ + rrc = ra;\ + goto RETURN_SWITCH;\ + } @@ -522,2468 +535,1270 @@ return MATCH_NOMATCH; * Match from current position * *************************************************/ -/* This function is called recursively in many circumstances. Whenever it -returns a negative (error) response, the outer incarnation must also return the -same response. */ +/* This function is called to run one match attempt at a single starting point +in the subject. -/* These macros pack up tests that are used for partial matching, and which -appear several times in the code. We set the "hit end" flag if the pointer is -at the end of the subject and also past the earliest inspected character (i.e. -something has been matched, even if not part of the actual matched string). For -hard partial matching, we then return immediately. The second one is used when -we already know we are past the end of the subject. */ - -#define CHECK_PARTIAL()\ - if (mb->partial != 0 && eptr >= mb->end_subject && \ - eptr > mb->start_used_ptr) \ - { \ - mb->hitend = TRUE; \ - if (mb->partial > 1) RRETURN(PCRE2_ERROR_PARTIAL); \ - } - -#define SCHECK_PARTIAL()\ - if (mb->partial != 0 && eptr > mb->start_used_ptr) \ - { \ - mb->hitend = TRUE; \ - if (mb->partial > 1) RRETURN(PCRE2_ERROR_PARTIAL); \ - } - - -/* Performance note: It might be tempting to extract commonly used fields from -the mb structure (e.g. utf, end_subject) into individual variables to improve +Performance note: It might be tempting to extract commonly used fields from the +mb structure (e.g. end_subject) into individual variables to improve performance. Tests using gcc on a SPARC disproved this; in the first case, it made performance worse. Arguments: - eptr pointer to current character in subject - ecode pointer to current position in compiled code - mstart pointer to the current match start position (can be modified - by encountering \K) - offset_top current top pointer (highest ovector offset used + 1) - mb pointer to "static" info block for the match - eptrb pointer to chain of blocks containing eptr at start of - brackets - for testing for empty matches - rdepth the recursion depth - -Returns: MATCH_MATCH if matched ) these values are >= 0 - MATCH_NOMATCH if failed to match ) - a negative MATCH_xxx value for PRUNE, SKIP, etc - a negative PCRE2_ERROR_xxx value if aborted by an error condition - (e.g. stopped by repeated call or recursion limit) + start_eptr starting character in subject + start_ecode starting position in compiled code + ovector pointer to the final output vector + oveccount number of pairs in ovector + top_bracket number of capturing parentheses in the pattern + frame_size size of each backtracking frame + mb pointer to "static" variables block + +Returns: MATCH_MATCH if matched ) these values are >= 0 + MATCH_NOMATCH if failed to match ) + negative MATCH_xxx value for PRUNE, SKIP, etc + negative PCRE2_ERROR_xxx value if aborted by an error condition + (e.g. stopped by repeated call or depth limit) */ static int -match(PCRE2_SPTR eptr, PCRE2_SPTR ecode, PCRE2_SPTR mstart, - PCRE2_SIZE offset_top, match_block *mb, eptrblock *eptrb, uint32_t rdepth) +match(PCRE2_SPTR start_eptr, PCRE2_SPTR start_ecode, PCRE2_SIZE *ovector, + uint16_t oveccount, uint16_t top_bracket, PCRE2_SIZE frame_size, + match_block *mb) { -/* These variables do not need to be preserved over recursion in this function, -so they can be ordinary variables in all cases. Mark some of them with -"register" because they are used a lot in loops. */ - -int rrc; /* Returns from recursive calls */ -int i; /* Used for loops not involving calls to RMATCH() */ -uint32_t c; /* Character values not kept over RMATCH() calls */ -BOOL utf; /* Local copy of UTF flag for speed */ - -BOOL minimize, possessive; /* Quantifier options */ -int condcode; +/* Frame-handling variables */ -/* When recursion is not being used, all "local" variables that have to be -preserved over calls to RMATCH() are part of a "frame". We set up the top-level -frame on the stack here; subsequent instantiations are obtained from the heap -whenever RMATCH() does a "recursion". See the macro definitions above. Putting -the top-level on the stack rather than malloc-ing them all gives a performance -boost in many cases where there is not much "recursion". */ +heapframe *F; /* Current frame pointer */ +heapframe *N = NULL; /* Temporary frame pointers */ +heapframe *P = NULL; +heapframe *assert_accept_frame; /* For passing back the frame with captures */ +PCRE2_SIZE frame_copy_size; /* Amount to copy when creating a new frame */ -#ifdef HEAP_MATCH_RECURSE -heapframe *frame = (heapframe *)mb->match_frames_base; +/* Local variables that do not need to be preserved over calls to RRMATCH(). */ -/* Copy in the original argument variables */ +PCRE2_SPTR bracode; /* Temp pointer to start of group */ +PCRE2_SIZE offset; /* Used for group offsets */ +PCRE2_SIZE length; /* Used for various length calculations */ -frame->Xeptr = eptr; -frame->Xecode = ecode; -frame->Xmstart = mstart; -frame->Xoffset_top = offset_top; -frame->Xeptrb = eptrb; -frame->Xrdepth = rdepth; - -/* This is where control jumps back to to effect "recursion" */ - -HEAP_RECURSE: +int rrc; /* Return from functions & backtracking "recursions" */ +#ifdef SUPPORT_UNICODE +int proptype; /* Type of character property */ +#endif -/* Macros make the argument variables come from the current frame */ +uint32_t i; /* Used for local loops */ +uint32_t fc; /* Character values */ +uint32_t number; /* Used for group and other numbers */ +uint32_t reptype = 0; /* Type of repetition (0 to avoid compiler warning) */ +uint32_t group_frame_type; /* Specifies type for new group frames */ -#define eptr frame->Xeptr -#define ecode frame->Xecode -#define mstart frame->Xmstart -#define offset_top frame->Xoffset_top -#define eptrb frame->Xeptrb -#define rdepth frame->Xrdepth +BOOL condition; /* Used in conditional groups */ +BOOL cur_is_word; /* Used in "word" tests */ +BOOL prev_is_word; /* Used in "word" tests */ -/* Ditto for the local variables */ +/* UTF flag */ #ifdef SUPPORT_UNICODE -#define charptr frame->Xcharptr -#define prop_value frame->Xprop_value -#define prop_type frame->Xprop_type -#define prop_fail_result frame->Xprop_fail_result -#define oclength frame->Xoclength -#define occhars frame->Xocchars +BOOL utf = (mb->poptions & PCRE2_UTF) != 0; +#else +BOOL utf = FALSE; #endif +/* This is the length of the last part of a backtracking frame that must be +copied when a new frame is created. */ -#define callpat frame->Xcallpat -#define codelink frame->Xcodelink -#define data frame->Xdata -#define next_ecode frame->Xnext_ecode -#define pp frame->Xpp -#define prev frame->Xprev -#define saved_eptr frame->Xsaved_eptr - -#define new_recursive frame->Xnew_recursive - -#define ctype frame->Xctype -#define fc frame->Xfc -#define fi frame->Xfi -#define length frame->Xlength -#define max frame->Xmax -#define min frame->Xmin -#define number frame->Xnumber -#define offset frame->Xoffset -#define op frame->Xop -#define save_capture_last frame->Xsave_capture_last -#define save_offset1 frame->Xsave_offset1 -#define save_offset2 frame->Xsave_offset2 -#define save_offset3 frame->Xsave_offset3 - -#define condition frame->Xcondition -#define cur_is_word frame->Xcur_is_word -#define prev_is_word frame->Xprev_is_word - -#define newptrb frame->Xnewptrb - -/* When normal stack-based recursion is being used for match(), local variables -are allocated on the stack and get preserved during recursion in the usual way. -In this environment, fi and i, and fc and c, can be the same variables. */ - -#else /* HEAP_MATCH_RECURSE not defined */ -#define fi i -#define fc c - -/* Many of the following variables are used only in small blocks of the code. -My normal style of coding would have declared them within each of those blocks. -However, in order to accommodate the version of this code that uses an external -"stack" implemented on the heap, it is easier to declare them all here, so the -declarations can be cut out in a block. The only declarations within blocks -below are for variables that do not have to be preserved over a recursive call -to RMATCH(). */ +frame_copy_size = frame_size - offsetof(heapframe, eptr); -#ifdef SUPPORT_UNICODE -PCRE2_SPTR charptr; -#endif -PCRE2_SPTR callpat; -PCRE2_SPTR data; -PCRE2_SPTR next_ecode; -PCRE2_SPTR pp; -PCRE2_SPTR prev; -PCRE2_SPTR saved_eptr; +/* Set up the first current frame at the start of the vector, and initialize +fields that are not reset for new frames. */ -PCRE2_SIZE length; -PCRE2_SIZE offset; -PCRE2_SIZE save_offset1, save_offset2, save_offset3; +F = mb->match_frames; +Frdepth = 0; /* "Recursion" depth */ +Fcapture_last = 0; /* Number of most recent capture */ +Fcurrent_recurse = RECURSE_UNSET; /* Not pattern recursing. */ +Fstart_match = Feptr = start_eptr; /* Current data pointer and start match */ +Fmark = NULL; /* Most recent mark */ +Foffset_top = 0; /* End of captures within the frame */ +Flast_group_offset = PCRE2_UNSET; /* Saved frame of most recent group */ +group_frame_type = 0; /* Not a start of group frame */ +goto NEW_FRAME; /* Start processing with this frame */ -uint32_t number; -uint32_t op; -uint32_t save_capture_last; - -#ifdef SUPPORT_UNICODE -uint32_t prop_value; -int prop_type; -int prop_fail_result; -int oclength; -PCRE2_UCHAR occhars[6]; -#endif +/* Come back here when we want to create a new frame for remembering a +backtracking point. */ -int codelink; -int ctype; -int max; -int min; +MATCH_RECURSE: -BOOL condition; -BOOL cur_is_word; -BOOL prev_is_word; +/* Set up a new backtracking frame. If the vector is full, get a new one +on the heap, doubling the size, but constrained by the heap limit. */ -eptrblock newptrb; -recursion_info new_recursive; -#endif /* HEAP_MATCH_RECURSE not defined */ +N = (heapframe *)((char *)F + frame_size); +if (N >= mb->match_frames_top) + { + PCRE2_SIZE newsize = mb->frame_vector_size * 2; + heapframe *new; -/* To save space on the stack and in the heap frame, I have doubled up on some -of the local variables that are used only in localised parts of the code, but -still need to be preserved over recursive calls of match(). These macros define -the alternative names that are used. */ + if ((newsize / 1024) > mb->heap_limit) + { + PCRE2_SIZE maxsize = ((mb->heap_limit * 1024)/frame_size) * frame_size; + if (mb->frame_vector_size >= maxsize) return PCRE2_ERROR_HEAPLIMIT; + newsize = maxsize; + } -#define allow_zero cur_is_word -#define caseless cur_is_word -#define cbegroup condition -#define code_offset codelink -#define condassert condition -#define foc number -#define matched_once prev_is_word -#define save_mark data + new = mb->memctl.malloc(newsize, mb->memctl.memory_data); + if (new == NULL) return PCRE2_ERROR_NOMEMORY; + memcpy(new, mb->match_frames, mb->frame_vector_size); -/* These statements are here to stop the compiler complaining about unitialized -variables. */ + F = (heapframe *)((char *)new + ((char *)F - (char *)mb->match_frames)); + N = (heapframe *)((char *)F + frame_size); -#ifdef SUPPORT_UNICODE -prop_value = 0; -prop_fail_result = 0; -#endif + if (mb->match_frames != mb->stack_frames) + mb->memctl.free(mb->match_frames, mb->memctl.memory_data); + mb->match_frames = new; + mb->match_frames_top = (heapframe *)((char *)mb->match_frames + newsize); + mb->frame_vector_size = newsize; + } +#ifdef DEBUG_SHOW_RMATCH +fprintf(stderr, "++ RMATCH %2d frame=%d", Freturn_id, Frdepth + 1); +if (group_frame_type != 0) + { + fprintf(stderr, " type=%x ", group_frame_type); + switch (GF_IDMASK(group_frame_type)) + { + case GF_CAPTURE: + fprintf(stderr, "capture=%d", GF_DATAMASK(group_frame_type)); + break; -/* This label is used for tail recursion, which is used in a few cases even -when HEAP_MATCH_RECURSE is not defined, in order to reduce the amount of stack -that is used. Thanks to Ian Taylor for noticing this possibility and sending -the original patch. */ + case GF_NOCAPTURE: + fprintf(stderr, "nocapture op=%d", GF_DATAMASK(group_frame_type)); + break; -TAIL_RECURSE: + case GF_CONDASSERT: + fprintf(stderr, "condassert op=%d", GF_DATAMASK(group_frame_type)); + break; -/* OK, now we can get on with the real code of the function. Recursive calls -are specified by the macro RMATCH and RRETURN is used to return. When -HEAP_MATCH_RECURSE is *not* defined, these just turn into a recursive call to -match() and a "return", respectively. However, RMATCH isn't like a function -call because it's quite a complicated macro. It has to be used in one -particular way. This shouldn't, however, impact performance when true recursion -is being used. */ + case GF_RECURSE: + fprintf(stderr, "recurse=%d", GF_DATAMASK(group_frame_type)); + break; -#ifdef SUPPORT_UNICODE -utf = (mb->poptions & PCRE2_UTF) != 0; -#else -utf = FALSE; + default: + fprintf(stderr, "*** unknown ***"); + break; + } + } +fprintf(stderr, "\n"); #endif -/* First check that we haven't called match() too many times, or that we -haven't exceeded the recursive call limit. */ +/* Copy those fields that must be copied into the new frame, increase the +"recursion" depth (i.e. the new frame's index) and then make the new frame +current. */ + +memcpy((char *)N + offsetof(heapframe, eptr), + (char *)F + offsetof(heapframe, eptr), + frame_copy_size); + +N->rdepth = Frdepth + 1; +F = N; -if (mb->match_call_count++ >= mb->match_limit) RRETURN(PCRE2_ERROR_MATCHLIMIT); -if (rdepth >= mb->match_limit_recursion) RRETURN(PCRE2_ERROR_RECURSIONLIMIT); +/* Carry on processing with a new frame. */ -/* At the start of a group with an unlimited repeat that may match an empty -string, the variable mb->match_function_type contains the MATCH_CBEGROUP bit. -It is done this way to save having to use another function argument, which -would take up space on the stack. See also MATCH_CONDASSERT below. +NEW_FRAME: +Fgroup_frame_type = group_frame_type; +Fecode = start_ecode; /* Starting code pointer */ +Fback_frame = frame_size; /* Default is go back one frame */ -When MATCH_CBEGROUP is set, add the current subject pointer to the chain of -such remembered pointers, to be checked when we hit the closing ket, in order -to break infinite loops that match no characters. When match() is called in -other circumstances, don't add to the chain. The MATCH_CBEGROUP feature must -NOT be used with tail recursion, because the memory block that is used is on -the stack, so a new one may be required for each match(). */ +/* If this is a special type of group frame, remember its offset for quick +access at the end of the group. If this is a recursion, set a new current +recursion value. */ -if ((mb->match_function_type & MATCH_CBEGROUP) != 0) +if (group_frame_type != 0) { - newptrb.epb_saved_eptr = eptr; - newptrb.epb_prev = eptrb; - eptrb = &newptrb; - mb->match_function_type &= ~MATCH_CBEGROUP; + Flast_group_offset = (char *)F - (char *)mb->match_frames; + if (GF_IDMASK(group_frame_type) == GF_RECURSE) + Fcurrent_recurse = GF_DATAMASK(group_frame_type); + group_frame_type = 0; } -/* Now, at last, we can start processing the opcodes. */ + +/* ========================================================================= */ +/* This is the main processing loop. First check that we haven't recorded too +many backtracks (search tree is too large), or that we haven't exceeded the +recursive depth limit (used too many backtracking frames). If not, process the +opcodes. */ + +if (mb->match_call_count++ >= mb->match_limit) return PCRE2_ERROR_MATCHLIMIT; +if (Frdepth >= mb->match_limit_depth) return PCRE2_ERROR_DEPTHLIMIT; for (;;) { - minimize = possessive = FALSE; - op = *ecode; +#ifdef DEBUG_SHOW_OPS +fprintf(stderr, "++ op=%d\n", *Fecode); +#endif - switch(op) + Fop = (uint8_t)(*Fecode); /* Cast needed for 16-bit and 32-bit modes */ + switch(Fop) { - case OP_MARK: - mb->nomatch_mark = ecode + 2; - mb->mark = NULL; /* In case previously set by assertion */ - RMATCH(eptr, ecode + PRIV(OP_lengths)[*ecode] + ecode[1], offset_top, mb, - eptrb, RM55); - if ((rrc == MATCH_MATCH || rrc == MATCH_ACCEPT) && - mb->mark == NULL) mb->mark = ecode + 2; - - /* A return of MATCH_SKIP_ARG means that matching failed at SKIP with an - argument, and we must check whether that argument matches this MARK's - argument. It is passed back in mb->start_match_ptr (an overloading of that - variable). If it does match, we reset that variable to the current subject - position and return MATCH_SKIP. Otherwise, pass back the return code - unaltered. */ + /* ===================================================================== */ + /* Before OP_ACCEPT there may be any number of OP_CLOSE opcodes, to close + any currently open capturing brackets. Unlike reaching the end of a group, + where we know the starting frame is at the top of the chained frames, in + this case we have to search back for the relevant frame in case other types + of group that use chained frames have intervened. Multiple OP_CLOSEs always + come innermost first, which matches the chain order. We can ignore this in + a recursion, because captures are not passed out of recursions. */ - else if (rrc == MATCH_SKIP_ARG && - PRIV(strcmp)(ecode + 2, mb->start_match_ptr) == 0) + case OP_CLOSE: + if (Fcurrent_recurse == RECURSE_UNSET) { - mb->start_match_ptr = eptr; - RRETURN(MATCH_SKIP); + number = GET2(Fecode, 1); + offset = Flast_group_offset; + for(;;) + { + if (offset == PCRE2_UNSET) return PCRE2_ERROR_INTERNAL; + N = (heapframe *)((char *)mb->match_frames + offset); + P = (heapframe *)((char *)N - frame_size); + if (N->group_frame_type == (GF_CAPTURE | number)) break; + offset = P->last_group_offset; + } + offset = (number << 1) - 2; + Fcapture_last = number; + Fovector[offset] = P->eptr - mb->start_subject; + Fovector[offset+1] = Feptr - mb->start_subject; + if (offset >= Foffset_top) Foffset_top = offset + 2; } - RRETURN(rrc); - - case OP_FAIL: - RRETURN(MATCH_NOMATCH); - - case OP_COMMIT: - RMATCH(eptr, ecode + PRIV(OP_lengths)[*ecode], offset_top, mb, - eptrb, RM52); - if (rrc != MATCH_NOMATCH) RRETURN(rrc); - RRETURN(MATCH_COMMIT); - - case OP_PRUNE: - RMATCH(eptr, ecode + PRIV(OP_lengths)[*ecode], offset_top, mb, - eptrb, RM51); - if (rrc != MATCH_NOMATCH) RRETURN(rrc); - RRETURN(MATCH_PRUNE); - - case OP_PRUNE_ARG: - mb->nomatch_mark = ecode + 2; - mb->mark = NULL; /* In case previously set by assertion */ - RMATCH(eptr, ecode + PRIV(OP_lengths)[*ecode] + ecode[1], offset_top, mb, - eptrb, RM56); - if ((rrc == MATCH_MATCH || rrc == MATCH_ACCEPT) && - mb->mark == NULL) mb->mark = ecode + 2; - if (rrc != MATCH_NOMATCH) RRETURN(rrc); - RRETURN(MATCH_PRUNE); + Fecode += PRIV(OP_lengths)[*Fecode]; + break; - case OP_SKIP: - RMATCH(eptr, ecode + PRIV(OP_lengths)[*ecode], offset_top, mb, - eptrb, RM53); - if (rrc != MATCH_NOMATCH) RRETURN(rrc); - mb->start_match_ptr = eptr; /* Pass back current position */ - RRETURN(MATCH_SKIP); - /* Note that, for Perl compatibility, SKIP with an argument does NOT set - nomatch_mark. When a pattern match ends with a SKIP_ARG for which there was - not a matching mark, we have to re-run the match, ignoring the SKIP_ARG - that failed and any that precede it (either they also failed, or were not - triggered). To do this, we maintain a count of executed SKIP_ARGs. If a - SKIP_ARG gets to top level, the match is re-run with mb->ignore_skip_arg - set to the count of the one that failed. */ + /* ===================================================================== */ + /* Real or forced end of the pattern, assertion, or recursion. In an + assertion ACCEPT, update the last used pointer and remember the current + frame so that the captures can be fished out of it. */ - case OP_SKIP_ARG: - mb->skip_arg_count++; - if (mb->skip_arg_count <= mb->ignore_skip_arg) - { - ecode += PRIV(OP_lengths)[*ecode] + ecode[1]; - break; - } - RMATCH(eptr, ecode + PRIV(OP_lengths)[*ecode] + ecode[1], offset_top, mb, - eptrb, RM57); - if (rrc != MATCH_NOMATCH) RRETURN(rrc); + case OP_ASSERT_ACCEPT: + if (Feptr > mb->last_used_ptr) mb->last_used_ptr = Feptr; + assert_accept_frame = F; + RRETURN(MATCH_ACCEPT); - /* Pass back the current skip name by overloading mb->start_match_ptr and - returning the special MATCH_SKIP_ARG return code. This will either be - caught by a matching MARK, or get to the top, where it causes a rematch - with mb->ignore_skip_arg set to the value of mb->skip_arg_count. */ + /* If recursing, we have to find the most recent recursion. */ - mb->start_match_ptr = ecode + 2; - RRETURN(MATCH_SKIP_ARG); - - /* For THEN (and THEN_ARG) we pass back the address of the opcode, so that - the branch in which it occurs can be determined. Overload the start of - match pointer to do this. */ - - case OP_THEN: - RMATCH(eptr, ecode + PRIV(OP_lengths)[*ecode], offset_top, mb, - eptrb, RM54); - if (rrc != MATCH_NOMATCH) RRETURN(rrc); - mb->start_match_ptr = ecode; - RRETURN(MATCH_THEN); + case OP_ACCEPT: + case OP_END: - case OP_THEN_ARG: - mb->nomatch_mark = ecode + 2; - mb->mark = NULL; /* In case previously set by assertion */ - RMATCH(eptr, ecode + PRIV(OP_lengths)[*ecode] + ecode[1], offset_top, - mb, eptrb, RM58); - if ((rrc == MATCH_MATCH || rrc == MATCH_ACCEPT) && - mb->mark == NULL) mb->mark = ecode + 2; - if (rrc != MATCH_NOMATCH) RRETURN(rrc); - mb->start_match_ptr = ecode; - RRETURN(MATCH_THEN); + /* Handle end of a recursion. */ - /* Handle an atomic group that does not contain any capturing parentheses. - This can be handled like an assertion. Prior to 8.13, all atomic groups - were handled this way. In 8.13, the code was changed as below for ONCE, so - that backups pass through the group and thereby reset captured values. - However, this uses a lot more stack, so in 8.20, atomic groups that do not - contain any captures generate OP_ONCE_NC, which can be handled in the old, - less stack intensive way. - - Check the alternative branches in turn - the matching won't pass the KET - for this kind of subpattern. If any one branch matches, we carry on as at - the end of a normal bracket, leaving the subject pointer, but resetting - the start-of-match value in case it was changed by \K. */ - - case OP_ONCE_NC: - prev = ecode; - saved_eptr = eptr; - save_mark = mb->mark; - do + if (Fcurrent_recurse != RECURSE_UNSET) { - RMATCH(eptr, ecode + 1 + LINK_SIZE, offset_top, mb, eptrb, RM64); - if (rrc == MATCH_MATCH) /* Note: _not_ MATCH_ACCEPT */ + offset = Flast_group_offset; + for(;;) { - mstart = mb->start_match_ptr; - break; + if (offset == PCRE2_UNSET) return PCRE2_ERROR_INTERNAL; + N = (heapframe *)((char *)mb->match_frames + offset); + P = (heapframe *)((char *)N - frame_size); + if (GF_IDMASK(N->group_frame_type) == GF_RECURSE) break; + offset = P->last_group_offset; } - if (rrc == MATCH_THEN) - { - next_ecode = ecode + GET(ecode,1); - if (mb->start_match_ptr < next_ecode && - (*ecode == OP_ALT || *next_ecode == OP_ALT)) - rrc = MATCH_NOMATCH; - } - - if (rrc != MATCH_NOMATCH) RRETURN(rrc); - ecode += GET(ecode,1); - mb->mark = save_mark; - } - while (*ecode == OP_ALT); - - /* If hit the end of the group (which could be repeated), fail */ - if (*ecode != OP_ONCE_NC && *ecode != OP_ALT) RRETURN(MATCH_NOMATCH); + /* N is now the frame of the recursion; the previous frame is at the + OP_RECURSE position. Go back there, copying the current subject position + and mark, and move on past the OP_RECURSE. */ - /* Continue as from after the group, updating the offsets high water - mark, since extracts may have been taken. */ - - do ecode += GET(ecode, 1); while (*ecode == OP_ALT); - - offset_top = mb->end_offset_top; - eptr = mb->end_match_ptr; + P->eptr = Feptr; + P->mark = Fmark; + F = P; + Fecode += 1 + LINK_SIZE; + continue; + } - /* For a non-repeating ket, just continue at this level. This also - happens for a repeating ket if no characters were matched in the group. - This is the forcible breaking of infinite loops as implemented in Perl - 5.005. */ + /* Not a recursion. Fail for an empty string match if either PCRE2_NOTEMPTY + is set, or if PCRE2_NOTEMPTY_ATSTART is set and we have matched at the + start of the subject. In both cases, backtracking will then try other + alternatives, if any. */ - if (*ecode == OP_KET || eptr == saved_eptr) - { - ecode += 1+LINK_SIZE; - break; - } + if (Feptr == Fstart_match && + ((mb->moptions & PCRE2_NOTEMPTY) != 0 || + ((mb->moptions & PCRE2_NOTEMPTY_ATSTART) != 0 && + Fstart_match == mb->start_subject + mb->start_offset))) + RRETURN(MATCH_NOMATCH); - /* The repeating kets try the rest of the pattern or restart from the - preceding bracket, in the appropriate order. The second "call" of match() - uses tail recursion, to avoid using another stack frame. */ + /* Also fail if PCRE2_ENDANCHORED is set and the end of the match is not + the end of the subject. After (*ACCEPT) we fail the entire match (at this + position) but backtrack on reaching the end of the pattern. */ - if (*ecode == OP_KETRMIN) - { - RMATCH(eptr, ecode + 1 + LINK_SIZE, offset_top, mb, eptrb, RM65); - if (rrc != MATCH_NOMATCH) RRETURN(rrc); - ecode = prev; - goto TAIL_RECURSE; - } - else /* OP_KETRMAX */ + if (Feptr < mb->end_subject && + ((mb->moptions | mb->poptions) & PCRE2_ENDANCHORED) != 0) { - RMATCH(eptr, prev, offset_top, mb, eptrb, RM66); - if (rrc != MATCH_NOMATCH) RRETURN(rrc); - ecode += 1 + LINK_SIZE; - goto TAIL_RECURSE; + if (Fop == OP_END) RRETURN(MATCH_NOMATCH); + return MATCH_NOMATCH; } - /* Control never gets here */ - /* Handle a capturing bracket, other than those that are possessive with an - unlimited repeat. If there is space in the offset vector, save the current - subject position in the working slot at the top of the vector. We mustn't - change the current values of the data slot, because they may be set from a - previous iteration of this group, and be referred to by a reference inside - the group. A failure to match might occur after the group has succeeded, - if something later on doesn't match. For this reason, we need to restore - the working value and also the values of the final offsets, in case they - were set by a previous iteration of the same bracket. - - If there isn't enough space in the offset vector, treat this as if it were - a non-capturing bracket. Don't worry about setting the flag for the error - case here; that is handled in the code for KET. */ + /* We have a successful match of the whole pattern. Record the result and + then do a direct return from the function. If there is space in the offset + vector, set any pairs that follow the highest-numbered captured string but + are less than the number of capturing groups in the pattern to PCRE2_UNSET. + It is documented that this happens. "Gaps" are set to PCRE2_UNSET + dynamically. It is only those at the end that need setting here. */ - case OP_CBRA: - case OP_SCBRA: - number = GET2(ecode, 1+LINK_SIZE); - offset = number << 1; + mb->end_match_ptr = Feptr; /* Record where we ended */ + mb->end_offset_top = Foffset_top; /* and how many extracts were taken */ + mb->mark = Fmark; /* and the last success mark */ + if (Feptr > mb->last_used_ptr) mb->last_used_ptr = Feptr; - if (offset < mb->offset_max) - { - save_offset1 = mb->ovector[offset]; - save_offset2 = mb->ovector[offset+1]; - save_offset3 = mb->ovector[mb->offset_end - number]; - save_capture_last = mb->capture_last; - save_mark = mb->mark; + ovector[0] = Fstart_match - mb->start_subject; + ovector[1] = Feptr - mb->start_subject; - mb->ovector[mb->offset_end - number] = eptr - mb->start_subject; + /* Set i to the smaller of the sizes of the external and frame ovectors. */ - for (;;) - { - if (op >= OP_SBRA) mb->match_function_type |= MATCH_CBEGROUP; - RMATCH(eptr, ecode + PRIV(OP_lengths)[*ecode], offset_top, mb, - eptrb, RM1); - if (rrc == MATCH_ONCE) break; /* Backing up through an atomic group */ - - /* If we backed up to a THEN, check whether it is within the current - branch by comparing the address of the THEN that is passed back with - the end of the branch. If it is within the current branch, and the - branch is one of two or more alternatives (it either starts or ends - with OP_ALT), we have reached the limit of THEN's action, so convert - the return code to NOMATCH, which will cause normal backtracking to - happen from now on. Otherwise, THEN is passed back to an outer - alternative. This implements Perl's treatment of parenthesized groups, - where a group not containing | does not affect the current alternative, - that is, (X) is NOT the same as (X|(*F)). */ - - if (rrc == MATCH_THEN) - { - next_ecode = ecode + GET(ecode,1); - if (mb->start_match_ptr < next_ecode && - (*ecode == OP_ALT || *next_ecode == OP_ALT)) - rrc = MATCH_NOMATCH; - } + i = 2 * ((top_bracket + 1 > oveccount)? oveccount : top_bracket + 1); + memcpy(ovector + 2, Fovector, (i - 2) * sizeof(PCRE2_SIZE)); + while (--i >= Foffset_top + 2) ovector[i] = PCRE2_UNSET; + return MATCH_MATCH; /* Note: NOT RRETURN */ - /* Anything other than NOMATCH is passed back. */ - if (rrc != MATCH_NOMATCH) RRETURN(rrc); - mb->capture_last = save_capture_last; - ecode += GET(ecode, 1); - mb->mark = save_mark; - if (*ecode != OP_ALT) break; - } - - mb->ovector[offset] = save_offset1; - mb->ovector[offset+1] = save_offset2; - mb->ovector[mb->offset_end - number] = save_offset3; - - /* At this point, rrc will be one of MATCH_ONCE or MATCH_NOMATCH. */ + /*===================================================================== */ + /* Match any single character type except newline; have to take care with + CRLF newlines and partial matching. */ - RRETURN(rrc); + case OP_ANY: + if (IS_NEWLINE(Feptr)) RRETURN(MATCH_NOMATCH); + if (mb->partial != 0 && + Feptr == mb->end_subject - 1 && + NLBLOCK->nltype == NLTYPE_FIXED && + NLBLOCK->nllen == 2 && + UCHAR21TEST(Feptr) == NLBLOCK->nl[0]) + { + mb->hitend = TRUE; + if (mb->partial > 1) return PCRE2_ERROR_PARTIAL; } + /* Fall through */ - /* FALL THROUGH ... Insufficient room for saving captured contents. Treat - as a non-capturing bracket. */ + /* Match any single character whatsoever. */ - /* VVVVVVVVVVVVVVVVVVVVVVVVV */ - /* VVVVVVVVVVVVVVVVVVVVVVVVV */ + case OP_ALLANY: + if (Feptr >= mb->end_subject) /* DO NOT merge the Feptr++ here; it must */ + { /* not be updated before SCHECK_PARTIAL. */ + SCHECK_PARTIAL(); + RRETURN(MATCH_NOMATCH); + } + Feptr++; +#ifdef SUPPORT_UNICODE + if (utf) ACROSSCHAR(Feptr < mb->end_subject, Feptr, Feptr++); +#endif + Fecode++; + break; - /* Non-capturing or atomic group, except for possessive with unlimited - repeat and ONCE group with no captures. Loop for all the alternatives. - When we get to the final alternative within the brackets, we used to return - the result of a recursive call to match() whatever happened so it was - possible to reduce stack usage by turning this into a tail recursion, - except in the case of a possibly empty group. However, now that there is - the possiblity of (*THEN) occurring in the final alternative, this - optimization is no longer always possible. + /* ===================================================================== */ + /* Match a single code unit, even in UTF mode. This opcode really does + match any code unit, even newline. (It really should be called ANYCODEUNIT, + of course - the byte name is from pre-16 bit days.) */ - We can optimize if we know there are no (*THEN)s in the pattern; at present - this is the best that can be done. + case OP_ANYBYTE: + if (Feptr >= mb->end_subject) /* DO NOT merge the Feptr++ here; it must */ + { /* not be updated before SCHECK_PARTIAL. */ + SCHECK_PARTIAL(); + RRETURN(MATCH_NOMATCH); + } + Feptr++; + Fecode++; + break; - MATCH_ONCE is returned when the end of an atomic group is successfully - reached, but subsequent matching fails. It passes back up the tree (causing - captured values to be reset) until the original atomic group level is - reached. This is tested by comparing mb->once_target with the start of the - group. At this point, the return is converted into MATCH_NOMATCH so that - previous backup points can be taken. */ - case OP_ONCE: - case OP_BRA: - case OP_SBRA: + /* ===================================================================== */ + /* Match a single character, casefully */ - for (;;) + case OP_CHAR: +#ifdef SUPPORT_UNICODE + if (utf) { - if (op >= OP_SBRA || op == OP_ONCE) - mb->match_function_type |= MATCH_CBEGROUP; - - /* If this is not a possibly empty group, and there are no (*THEN)s in - the pattern, and this is the final alternative, optimize as described - above. */ - - else if (!mb->hasthen && ecode[GET(ecode, 1)] != OP_ALT) + Flength = 1; + Fecode++; + GETCHARLEN(fc, Fecode, Flength); + if (Flength > (PCRE2_SIZE)(mb->end_subject - Feptr)) { - ecode += PRIV(OP_lengths)[*ecode]; - goto TAIL_RECURSE; - } - - /* In all other cases, we have to make another call to match(). */ - - save_mark = mb->mark; - save_capture_last = mb->capture_last; - RMATCH(eptr, ecode + PRIV(OP_lengths)[*ecode], offset_top, mb, eptrb, - RM2); - - /* See comment in the code for capturing groups above about handling - THEN. */ - - if (rrc == MATCH_THEN) - { - next_ecode = ecode + GET(ecode,1); - if (mb->start_match_ptr < next_ecode && - (*ecode == OP_ALT || *next_ecode == OP_ALT)) - rrc = MATCH_NOMATCH; + CHECK_PARTIAL(); /* Not SCHECK_PARTIAL() */ + RRETURN(MATCH_NOMATCH); } - - if (rrc != MATCH_NOMATCH) + for (; Flength > 0; Flength--) { - if (rrc == MATCH_ONCE) - { - PCRE2_SPTR scode = ecode; - if (*scode != OP_ONCE) /* If not at start, find it */ - { - while (*scode == OP_ALT) scode += GET(scode, 1); - scode -= GET(scode, 1); - } - if (mb->once_target == scode) rrc = MATCH_NOMATCH; - } - RRETURN(rrc); + if (*Fecode++ != UCHAR21INC(Feptr)) RRETURN(MATCH_NOMATCH); } - ecode += GET(ecode, 1); - mb->mark = save_mark; - if (*ecode != OP_ALT) break; - mb->capture_last = save_capture_last; } - - RRETURN(MATCH_NOMATCH); - - /* Handle possessive capturing brackets with an unlimited repeat. We come - here from BRAZERO with allow_zero set TRUE. The ovector values are - handled similarly to the normal case above. However, the matching is - different. The end of these brackets will always be OP_KETRPOS, which - returns MATCH_KETRPOS without going further in the pattern. By this means - we can handle the group by iteration rather than recursion, thereby - reducing the amount of stack needed. If the ovector is too small for - capturing, treat as non-capturing. */ - - case OP_CBRAPOS: - case OP_SCBRAPOS: - allow_zero = FALSE; - - POSSESSIVE_CAPTURE: - number = GET2(ecode, 1+LINK_SIZE); - offset = number << 1; - if (offset >= mb->offset_max) goto POSSESSIVE_NON_CAPTURE; - - matched_once = FALSE; - code_offset = (int)(ecode - mb->start_code); - - save_offset1 = mb->ovector[offset]; - save_offset2 = mb->ovector[offset+1]; - save_offset3 = mb->ovector[mb->offset_end - number]; - save_capture_last = mb->capture_last; - - /* Each time round the loop, save the current subject position for use - when the group matches. For MATCH_MATCH, the group has matched, so we - restart it with a new subject starting position, remembering that we had - at least one match. For MATCH_NOMATCH, carry on with the alternatives, as - usual. If we haven't matched any alternatives in any iteration, check to - see if a previous iteration matched. If so, the group has matched; - continue from afterwards. Otherwise it has failed; restore the previous - capture values before returning NOMATCH. */ - - for (;;) + else +#endif + /* Not UTF mode */ { - mb->ovector[mb->offset_end - number] = eptr - mb->start_subject; - if (op >= OP_SBRA) mb->match_function_type |= MATCH_CBEGROUP; - RMATCH(eptr, ecode + PRIV(OP_lengths)[*ecode], offset_top, mb, - eptrb, RM63); - if (rrc == MATCH_KETRPOS) + if (mb->end_subject - Feptr < 1) { - offset_top = mb->end_offset_top; - ecode = mb->start_code + code_offset; - save_capture_last = mb->capture_last; - matched_once = TRUE; - mstart = mb->start_match_ptr; /* In case \K changed it */ - if (eptr == mb->end_match_ptr) /* Matched an empty string */ - { - do ecode += GET(ecode, 1); while (*ecode == OP_ALT); - break; - } - eptr = mb->end_match_ptr; - continue; + SCHECK_PARTIAL(); /* This one can use SCHECK_PARTIAL() */ + RRETURN(MATCH_NOMATCH); } + if (Fecode[1] != *Feptr++) RRETURN(MATCH_NOMATCH); + Fecode += 2; + } + break; - /* See comment in the code for capturing groups above about handling - THEN. */ - - if (rrc == MATCH_THEN) - { - next_ecode = ecode + GET(ecode,1); - if (mb->start_match_ptr < next_ecode && - (*ecode == OP_ALT || *next_ecode == OP_ALT)) - rrc = MATCH_NOMATCH; - } - if (rrc != MATCH_NOMATCH) RRETURN(rrc); - mb->capture_last = save_capture_last; - ecode += GET(ecode, 1); - if (*ecode != OP_ALT) break; - } + /* ===================================================================== */ + /* Match a single character, caselessly. If we are at the end of the + subject, give up immediately. We get here only when the pattern character + has at most one other case. Characters with more than two cases are coded + as OP_PROP with the pseudo-property PT_CLIST. */ - if (!matched_once) + case OP_CHARI: + if (Feptr >= mb->end_subject) { - mb->ovector[offset] = save_offset1; - mb->ovector[offset+1] = save_offset2; - mb->ovector[mb->offset_end - number] = save_offset3; + SCHECK_PARTIAL(); + RRETURN(MATCH_NOMATCH); } - if (allow_zero || matched_once) +#ifdef SUPPORT_UNICODE + if (utf) { - ecode += 1 + LINK_SIZE; - break; - } - RRETURN(MATCH_NOMATCH); - - /* Non-capturing possessive bracket with unlimited repeat. We come here - from BRAZERO with allow_zero = TRUE. The code is similar to the above, - without the capturing complication. It is written out separately for speed - and cleanliness. */ - - case OP_BRAPOS: - case OP_SBRAPOS: - allow_zero = FALSE; + Flength = 1; + Fecode++; + GETCHARLEN(fc, Fecode, Flength); - POSSESSIVE_NON_CAPTURE: - matched_once = FALSE; - code_offset = (int)(ecode - mb->start_code); - save_capture_last = mb->capture_last; + /* If the pattern character's value is < 128, we know that its other case + (if any) is also < 128 (and therefore only one code unit long in all + code-unit widths), so we can use the fast lookup table. We checked above + that there is at least one character left in the subject. */ - for (;;) - { - if (op >= OP_SBRA) mb->match_function_type |= MATCH_CBEGROUP; - RMATCH(eptr, ecode + PRIV(OP_lengths)[*ecode], offset_top, mb, - eptrb, RM48); - if (rrc == MATCH_KETRPOS) + if (fc < 128) { - offset_top = mb->end_offset_top; - ecode = mb->start_code + code_offset; - matched_once = TRUE; - mstart = mb->start_match_ptr; /* In case \K reset it */ - if (eptr == mb->end_match_ptr) /* Matched an empty string */ - { - do ecode += GET(ecode, 1); while (*ecode == OP_ALT); - break; - } - eptr = mb->end_match_ptr; - continue; + uint32_t cc = UCHAR21(Feptr); + if (mb->lcc[fc] != TABLE_GET(cc, mb->lcc, cc)) RRETURN(MATCH_NOMATCH); + Fecode++; + Feptr++; } - /* See comment in the code for capturing groups above about handling - THEN. */ + /* Otherwise we must pick up the subject character and use Unicode + property support to test its other case. Note that we cannot use the + value of "Flength" to check for sufficient bytes left, because the other + case of the character may have more or fewer code units. */ - if (rrc == MATCH_THEN) + else { - next_ecode = ecode + GET(ecode,1); - if (mb->start_match_ptr < next_ecode && - (*ecode == OP_ALT || *next_ecode == OP_ALT)) - rrc = MATCH_NOMATCH; + uint32_t dc; + GETCHARINC(dc, Feptr); + Fecode += Flength; + if (dc != fc && dc != UCD_OTHERCASE(fc)) RRETURN(MATCH_NOMATCH); } - - if (rrc != MATCH_NOMATCH) RRETURN(rrc); - ecode += GET(ecode, 1); - if (*ecode != OP_ALT) break; - mb->capture_last = save_capture_last; } + else +#endif /* SUPPORT_UNICODE */ - if (matched_once || allow_zero) + /* Not UTF mode; use the table for characters < 256. */ { - ecode += 1 + LINK_SIZE; - break; + if (TABLE_GET(Fecode[1], mb->lcc, Fecode[1]) + != TABLE_GET(*Feptr, mb->lcc, *Feptr)) RRETURN(MATCH_NOMATCH); + Feptr++; + Fecode += 2; } - RRETURN(MATCH_NOMATCH); - - /* Control never reaches here. */ - - /* Conditional group: compilation checked that there are no more than two - branches. If the condition is false, skipping the first branch takes us - past the end of the item if there is only one branch, but that's exactly - what we want. */ - - case OP_COND: - case OP_SCOND: - - /* The variable codelink will be added to ecode when the condition is - false, to get to the second branch. Setting it to the offset to the ALT - or KET, then incrementing ecode achieves this effect. We now have ecode - pointing to the condition or callout. */ + break; - codelink = GET(ecode, 1); /* Offset to the second branch */ - ecode += 1 + LINK_SIZE; /* From this opcode */ - /* Because of the way auto-callout works during compile, a callout item is - inserted between OP_COND and an assertion condition. */ + /* ===================================================================== */ + /* Match not a single character. */ - if (*ecode == OP_CALLOUT || *ecode == OP_CALLOUT_STR) + case OP_NOT: + case OP_NOTI: + if (Feptr >= mb->end_subject) { - unsigned int callout_length = (*ecode == OP_CALLOUT) - ? PRIV(OP_lengths)[OP_CALLOUT] : GET(ecode, 1 + 2*LINK_SIZE); - - if (mb->callout != NULL) - { - pcre2_callout_block cb; - cb.version = 1; - cb.capture_top = (uint32_t)offset_top/2; - cb.capture_last = mb->capture_last & CAPLMASK; - cb.offset_vector = mb->ovector; - cb.mark = mb->nomatch_mark; - cb.subject = mb->start_subject; - cb.subject_length = (PCRE2_SIZE)(mb->end_subject - mb->start_subject); - cb.start_match = (PCRE2_SIZE)(mstart - mb->start_subject); - cb.current_position = (PCRE2_SIZE)(eptr - mb->start_subject); - cb.pattern_position = GET(ecode, 1); - cb.next_item_length = GET(ecode, 1 + LINK_SIZE); - - if (*ecode == OP_CALLOUT) - { - cb.callout_number = ecode[1 + 2*LINK_SIZE]; - cb.callout_string_offset = 0; - cb.callout_string = NULL; - cb.callout_string_length = 0; - } - else - { - cb.callout_number = 0; - cb.callout_string_offset = GET(ecode, 1 + 3*LINK_SIZE); - cb.callout_string = ecode + (1 + 4*LINK_SIZE) + 1; - cb.callout_string_length = - callout_length - (1 + 4*LINK_SIZE) - 2; - } - - if ((rrc = mb->callout(&cb, mb->callout_data)) > 0) - RRETURN(MATCH_NOMATCH); - if (rrc < 0) RRETURN(rrc); - } - - /* Advance ecode past the callout, so it now points to the condition. We - must adjust codelink so that the value of ecode+codelink is unchanged. */ - - ecode += callout_length; - codelink -= callout_length; + SCHECK_PARTIAL(); + RRETURN(MATCH_NOMATCH); } - - /* Test the various possible conditions */ - - condition = FALSE; - switch(condcode = *ecode) +#ifdef SUPPORT_UNICODE + if (utf) { - case OP_RREF: /* Numbered group recursion test */ - if (mb->recursive != NULL) /* Not recursing => FALSE */ - { - uint32_t recno = GET2(ecode, 1); /* Recursion group number*/ - condition = (recno == RREF_ANY || recno == mb->recursive->group_num); - } - break; - - case OP_DNRREF: /* Duplicate named group recursion test */ - if (mb->recursive != NULL) - { - int count = GET2(ecode, 1 + IMM2_SIZE); - PCRE2_SPTR slot = mb->name_table + GET2(ecode, 1) * mb->name_entry_size; - while (count-- > 0) - { - uint32_t recno = GET2(slot, 0); - condition = recno == mb->recursive->group_num; - if (condition) break; - slot += mb->name_entry_size; - } - } - break; - - case OP_CREF: /* Numbered group used test */ - offset = GET2(ecode, 1) << 1; /* Doubled ref number */ - condition = offset < offset_top && - mb->ovector[offset] != PCRE2_UNSET; - break; - - case OP_DNCREF: /* Duplicate named group used test */ - { - int count = GET2(ecode, 1 + IMM2_SIZE); - PCRE2_SPTR slot = mb->name_table + GET2(ecode, 1) * mb->name_entry_size; - while (count-- > 0) - { - offset = GET2(slot, 0) << 1; - condition = offset < offset_top && - mb->ovector[offset] != PCRE2_UNSET; - if (condition) break; - slot += mb->name_entry_size; - } - } - break; - - case OP_FALSE: - case OP_FAIL: /* The assertion (?!) becomes OP_FAIL */ - break; - - case OP_TRUE: - condition = TRUE; - break; - - /* The condition is an assertion. Call match() to evaluate it - setting - the MATCH_CONDASSERT bit in mb->match_function_type causes it to stop at - the end of an assertion. */ - - default: - mb->match_function_type |= MATCH_CONDASSERT; - RMATCH(eptr, ecode, offset_top, mb, NULL, RM3); - if (rrc == MATCH_MATCH) - { - if (mb->end_offset_top > offset_top) - offset_top = mb->end_offset_top; /* Captures may have happened */ - condition = TRUE; - - /* Advance ecode past the assertion to the start of the first branch, - but adjust it so that the general choosing code below works. If the - assertion has a quantifier that allows zero repeats we must skip over - the BRAZERO. This is a lunatic thing to do, but somebody did! */ - - if (*ecode == OP_BRAZERO) ecode++; - ecode += GET(ecode, 1); - while (*ecode == OP_ALT) ecode += GET(ecode, 1); - ecode += 1 + LINK_SIZE - PRIV(OP_lengths)[condcode]; - } - - /* PCRE doesn't allow the effect of (*THEN) to escape beyond an - assertion; it is therefore treated as NOMATCH. Any other return is an - error. */ - - else if (rrc != MATCH_NOMATCH && rrc != MATCH_THEN) + uint32_t ch; + Fecode++; + GETCHARINC(ch, Fecode); + GETCHARINC(fc, Feptr); + if (ch == fc) { - RRETURN(rrc); /* Need braces because of following else */ + RRETURN(MATCH_NOMATCH); /* Caseful match */ } - break; - } - - /* Choose branch according to the condition */ - - ecode += condition? PRIV(OP_lengths)[condcode] : codelink; - - /* We are now at the branch that is to be obeyed. As there is only one, we - can use tail recursion to avoid using another stack frame, except when - there is unlimited repeat of a possibly empty group. In the latter case, a - recursive call to match() is always required, unless the second alternative - doesn't exist, in which case we can just plough on. Note that, for - compatibility with Perl, the | in a conditional group is NOT treated as - creating two alternatives. If a THEN is encountered in the branch, it - propagates out to the enclosing alternative (unless nested in a deeper set - of alternatives, of course). */ - - if (condition || ecode[-(1+LINK_SIZE)] == OP_ALT) - { - if (op != OP_SCOND) + else if (Fop == OP_NOTI) /* If caseless */ { - goto TAIL_RECURSE; + if (ch > 127) + ch = UCD_OTHERCASE(ch); + else + ch = TABLE_GET(ch, mb->fcc, ch); + if (ch == fc) RRETURN(MATCH_NOMATCH); } - - mb->match_function_type |= MATCH_CBEGROUP; - RMATCH(eptr, ecode, offset_top, mb, eptrb, RM49); - RRETURN(rrc); } - - /* Condition false & no alternative; continue after the group. */ - else +#endif /* SUPPORT_UNICODE */ { + uint32_t ch = Fecode[1]; + fc = *Feptr++; + if (ch == fc || (Fop == OP_NOTI && TABLE_GET(ch, mb->fcc, ch) == fc)) + RRETURN(MATCH_NOMATCH); + Fecode += 2; } break; - /* Before OP_ACCEPT there may be any number of OP_CLOSE opcodes, - to close any currently open capturing brackets. */ - - case OP_CLOSE: - number = GET2(ecode, 1); /* Must be less than 65536 */ - offset = number << 1; - mb->capture_last = (mb->capture_last & OVFLMASK) | number; - if (offset >= mb->offset_max) mb->capture_last |= OVFLBIT; else - { - mb->ovector[offset] = - mb->ovector[mb->offset_end - number]; - mb->ovector[offset+1] = eptr - mb->start_subject; - - /* If this group is at or above the current highwater mark, ensure that - any groups between the current high water mark and this group are marked - unset and then update the high water mark. */ - - if (offset >= offset_top) - { - PCRE2_SIZE *iptr = mb->ovector + offset_top; - PCRE2_SIZE *iend = mb->ovector + offset; - while (iptr < iend) *iptr++ = PCRE2_UNSET; - offset_top = offset + 2; - } - } - ecode += 1 + IMM2_SIZE; - break; - + /* ===================================================================== */ + /* Match a single character repeatedly. */ - /* End of the pattern, either real or forced. In an assertion ACCEPT, - update the last used pointer. */ +#define Loclength F->temp_size +#define Lstart_eptr F->temp_sptr[0] +#define Lcharptr F->temp_sptr[1] +#define Lmin F->temp_32[0] +#define Lmax F->temp_32[1] +#define Lc F->temp_32[2] +#define Loc F->temp_32[3] - case OP_ASSERT_ACCEPT: - if (eptr > mb->last_used_ptr) mb->last_used_ptr = eptr; + case OP_EXACT: + case OP_EXACTI: + Lmin = Lmax = GET2(Fecode, 1); + Fecode += 1 + IMM2_SIZE; + goto REPEATCHAR; - case OP_ACCEPT: - case OP_END: + case OP_POSUPTO: + case OP_POSUPTOI: + reptype = REPTYPE_POS; + Lmin = 0; + Lmax = GET2(Fecode, 1); + Fecode += 1 + IMM2_SIZE; + goto REPEATCHAR; - /* If we have matched an empty string, fail if not in an assertion and not - in a recursion if either PCRE2_NOTEMPTY is set, or if PCRE2_NOTEMPTY_ATSTART - is set and we have matched at the start of the subject. In both cases, - backtracking will then try other alternatives, if any. */ + case OP_UPTO: + case OP_UPTOI: + reptype = REPTYPE_MAX; + Lmin = 0; + Lmax = GET2(Fecode, 1); + Fecode += 1 + IMM2_SIZE; + goto REPEATCHAR; - if (eptr == mstart && op != OP_ASSERT_ACCEPT && - mb->recursive == NULL && - ((mb->moptions & PCRE2_NOTEMPTY) != 0 || - ((mb->moptions & PCRE2_NOTEMPTY_ATSTART) != 0 && - mstart == mb->start_subject + mb->start_offset))) - RRETURN(MATCH_NOMATCH); + case OP_MINUPTO: + case OP_MINUPTOI: + reptype = REPTYPE_MIN; + Lmin = 0; + Lmax = GET2(Fecode, 1); + Fecode += 1 + IMM2_SIZE; + goto REPEATCHAR; - /* Otherwise, we have a match. */ + case OP_POSSTAR: + case OP_POSSTARI: + reptype = REPTYPE_POS; + Lmin = 0; + Lmax = UINT32_MAX; + Fecode++; + goto REPEATCHAR; - mb->end_match_ptr = eptr; /* Record where we ended */ - mb->end_offset_top = offset_top; /* and how many extracts were taken */ - mb->start_match_ptr = mstart; /* and the start (\K can modify) */ + case OP_POSPLUS: + case OP_POSPLUSI: + reptype = REPTYPE_POS; + Lmin = 1; + Lmax = UINT32_MAX; + Fecode++; + goto REPEATCHAR; - /* For some reason, the macros don't work properly if an expression is - given as the argument to RRETURN when the heap is in use. */ + case OP_POSQUERY: + case OP_POSQUERYI: + reptype = REPTYPE_POS; + Lmin = 0; + Lmax = 1; + Fecode++; + goto REPEATCHAR; - rrc = (op == OP_END)? MATCH_MATCH : MATCH_ACCEPT; - RRETURN(rrc); + case OP_STAR: + case OP_STARI: + case OP_MINSTAR: + case OP_MINSTARI: + case OP_PLUS: + case OP_PLUSI: + case OP_MINPLUS: + case OP_MINPLUSI: + case OP_QUERY: + case OP_QUERYI: + case OP_MINQUERY: + case OP_MINQUERYI: + fc = *Fecode++ - ((Fop < OP_STARI)? OP_STAR : OP_STARI); + Lmin = rep_min[fc]; + Lmax = rep_max[fc]; + reptype = rep_typ[fc]; - /* Assertion brackets. Check the alternative branches in turn - the - matching won't pass the KET for an assertion. If any one branch matches, - the assertion is true. Lookbehind assertions have an OP_REVERSE item at the - start of each branch to move the current point backwards, so the code at - this level is identical to the lookahead case. When the assertion is part - of a condition, we want to return immediately afterwards. The caller of - this incarnation of the match() function will have set MATCH_CONDASSERT in - mb->match_function type, and one of these opcodes will be the first opcode - that is processed. We use a local variable that is preserved over calls to - match() to remember this case. */ + /* Common code for all repeated single-character matches. We first check + for the minimum number of characters. If the minimum equals the maximum, we + are done. Otherwise, if minimizing, check the rest of the pattern for a + match; if there isn't one, advance up to the maximum, one character at a + time. - case OP_ASSERT: - case OP_ASSERTBACK: - save_mark = mb->mark; - if ((mb->match_function_type & MATCH_CONDASSERT) != 0) - { - condassert = TRUE; - mb->match_function_type &= ~MATCH_CONDASSERT; - } - else condassert = FALSE; + If maximizing, advance up to the maximum number of matching characters, + until Feptr is past the end of the maximum run. If possessive, we are + then done (no backing up). Otherwise, match at this position; anything + other than no match is immediately returned. For nomatch, back up one + character, unless we are matching \R and the last thing matched was + \r\n, in which case, back up two code units until we reach the first + optional character position. - /* Loop for each branch */ + The various UTF/non-UTF and caseful/caseless cases are handled separately, + for speed. */ - do + REPEATCHAR: +#ifdef SUPPORT_UNICODE + if (utf) { - RMATCH(eptr, ecode + 1 + LINK_SIZE, offset_top, mb, NULL, RM4); + Flength = 1; + Lcharptr = Fecode; + GETCHARLEN(fc, Fecode, Flength); + Fecode += Flength; - /* A match means that the assertion is true; break out of the loop - that matches its alternatives. */ + /* Handle multi-code-unit character matching, caseful and caseless. */ - if (rrc == MATCH_MATCH || rrc == MATCH_ACCEPT) + if (Flength > 1) { - mstart = mb->start_match_ptr; /* In case \K reset it */ - break; - } - - /* If not matched, restore the previous mark setting. */ - - mb->mark = save_mark; - - /* See comment in the code for capturing groups above about handling - THEN. */ + uint32_t othercase; - if (rrc == MATCH_THEN) - { - next_ecode = ecode + GET(ecode,1); - if (mb->start_match_ptr < next_ecode && - (*ecode == OP_ALT || *next_ecode == OP_ALT)) - rrc = MATCH_NOMATCH; - } + if (Fop >= OP_STARI && /* Caseless */ + (othercase = UCD_OTHERCASE(fc)) != fc) + Loclength = PRIV(ord2utf)(othercase, Foccu); + else Loclength = 0; - /* Anything other than NOMATCH causes the entire assertion to fail, - passing back the return code. This includes COMMIT, SKIP, PRUNE and an - uncaptured THEN, which means they take their normal effect. This - consistent approach does not always have exactly the same effect as in - Perl. */ + for (i = 1; i <= Lmin; i++) + { + if (Feptr <= mb->end_subject - Flength && + memcmp(Feptr, Lcharptr, CU2BYTES(Flength)) == 0) Feptr += Flength; + else if (Loclength > 0 && + Feptr <= mb->end_subject - Loclength && + memcmp(Feptr, Foccu, CU2BYTES(Loclength)) == 0) + Feptr += Loclength; + else + { + CHECK_PARTIAL(); + RRETURN(MATCH_NOMATCH); + } + } - if (rrc != MATCH_NOMATCH) RRETURN(rrc); - ecode += GET(ecode, 1); - } - while (*ecode == OP_ALT); /* Continue for next alternative */ + if (Lmin == Lmax) continue; - /* If we have tried all the alternative branches, the assertion has - failed. If not, we broke out after a match. */ + if (reptype == REPTYPE_MIN) + { + for (;;) + { + RMATCH(Fecode, RM202); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + if (Lmin++ >= Lmax) RRETURN(MATCH_NOMATCH); + if (Feptr <= mb->end_subject - Flength && + memcmp(Feptr, Lcharptr, CU2BYTES(Flength)) == 0) Feptr += Flength; + else if (Loclength > 0 && + Feptr <= mb->end_subject - Loclength && + memcmp(Feptr, Foccu, CU2BYTES(Loclength)) == 0) + Feptr += Loclength; + else + { + CHECK_PARTIAL(); + RRETURN(MATCH_NOMATCH); + } + } + /* Control never gets here */ + } - if (*ecode == OP_KET) RRETURN(MATCH_NOMATCH); + else /* Maximize */ + { + Lstart_eptr = Feptr; + for (i = Lmin; i < Lmax; i++) + { + if (Feptr <= mb->end_subject - Flength && + memcmp(Feptr, Lcharptr, CU2BYTES(Flength)) == 0) + Feptr += Flength; + else if (Loclength > 0 && + Feptr <= mb->end_subject - Loclength && + memcmp(Feptr, Foccu, CU2BYTES(Loclength)) == 0) + Feptr += Loclength; + else + { + CHECK_PARTIAL(); + break; + } + } - /* If checking an assertion for a condition, return MATCH_MATCH. */ + /* After \C in UTF mode, Lstart_eptr might be in the middle of a + Unicode character. Use <= Lstart_eptr to ensure backtracking doesn't + go too far. */ - if (condassert) RRETURN(MATCH_MATCH); + if (reptype != REPTYPE_POS) for(;;) + { + if (Feptr <= Lstart_eptr) break; + RMATCH(Fecode, RM203); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + Feptr--; + BACKCHAR(Feptr); + } + } + break; /* End of repeated wide character handling */ + } - /* Continue from after a successful assertion, updating the offsets high - water mark, since extracts may have been taken during the assertion. */ + /* Length of UTF character is 1. Put it into the preserved variable and + fall through to the non-UTF code. */ - do ecode += GET(ecode,1); while (*ecode == OP_ALT); - ecode += 1 + LINK_SIZE; - offset_top = mb->end_offset_top; - continue; + Lc = fc; + } + else +#endif /* SUPPORT_UNICODE */ - /* Negative assertion: all branches must fail to match for the assertion to - succeed. */ + /* When not in UTF mode, load a single-code-unit character. Then proceed as + above. */ - case OP_ASSERT_NOT: - case OP_ASSERTBACK_NOT: - save_mark = mb->mark; - if ((mb->match_function_type & MATCH_CONDASSERT) != 0) - { - condassert = TRUE; - mb->match_function_type &= ~MATCH_CONDASSERT; - } - else condassert = FALSE; + Lc = *Fecode++; - /* Loop for each alternative branch. */ + /* Caseless comparison */ - do + if (Fop >= OP_STARI) { - RMATCH(eptr, ecode + 1 + LINK_SIZE, offset_top, mb, NULL, RM5); - mb->mark = save_mark; /* Always restore the mark setting */ +#if PCRE2_CODE_UNIT_WIDTH == 8 + /* Lc must be < 128 in UTF-8 mode. */ + Loc = mb->fcc[Lc]; +#else /* 16-bit & 32-bit */ +#ifdef SUPPORT_UNICODE + if (utf && Lc > 127) Loc = UCD_OTHERCASE(Lc); + else +#endif /* SUPPORT_UNICODE */ + Loc = TABLE_GET(Lc, mb->fcc, Lc); +#endif /* PCRE2_CODE_UNIT_WIDTH == 8 */ - switch(rrc) + for (i = 1; i <= Lmin; i++) { - case MATCH_MATCH: /* A successful match means */ - case MATCH_ACCEPT: /* the assertion has failed. */ - RRETURN(MATCH_NOMATCH); - - case MATCH_NOMATCH: /* Carry on with next branch */ - break; - - /* See comment in the code for capturing groups above about handling - THEN. */ - - case MATCH_THEN: - next_ecode = ecode + GET(ecode,1); - if (mb->start_match_ptr < next_ecode && - (*ecode == OP_ALT || *next_ecode == OP_ALT)) + uint32_t cc; /* Faster than PCRE2_UCHAR */ + if (Feptr >= mb->end_subject) { - rrc = MATCH_NOMATCH; - break; + SCHECK_PARTIAL(); + RRETURN(MATCH_NOMATCH); } - /* Otherwise fall through. */ - - /* COMMIT, SKIP, PRUNE, and an uncaptured THEN cause the whole - assertion to fail to match, without considering any more alternatives. - Failing to match means the assertion is true. This is a consistent - approach, but does not always have the same effect as in Perl. */ - - case MATCH_COMMIT: - case MATCH_SKIP: - case MATCH_SKIP_ARG: - case MATCH_PRUNE: - do ecode += GET(ecode,1); while (*ecode == OP_ALT); - goto NEG_ASSERT_TRUE; /* Break out of alternation loop */ - - /* Anything else is an error */ - - default: - RRETURN(rrc); + cc = UCHAR21TEST(Feptr); + if (Lc != cc && Loc != cc) RRETURN(MATCH_NOMATCH); + Feptr++; } + if (Lmin == Lmax) continue; - /* Continue with next branch */ - - ecode += GET(ecode,1); - } - while (*ecode == OP_ALT); - - /* All branches in the assertion failed to match. */ - - NEG_ASSERT_TRUE: - if (condassert) RRETURN(MATCH_MATCH); /* Condition assertion */ - ecode += 1 + LINK_SIZE; /* Continue with current branch */ - continue; - - /* Move the subject pointer back. This occurs only at the start of - each branch of a lookbehind assertion. If we are too close to the start to - move back, this match function fails. When working with UTF-8 we move - back a number of characters, not bytes. */ - - case OP_REVERSE: - i = GET(ecode, 1); -#ifdef SUPPORT_UNICODE - if (utf) - { - while (i-- > 0) + if (reptype == REPTYPE_MIN) { - if (eptr <= mb->start_subject) RRETURN(MATCH_NOMATCH); - eptr--; - BACKCHAR(eptr); + for (;;) + { + uint32_t cc; /* Faster than PCRE2_UCHAR */ + RMATCH(Fecode, RM25); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + if (Lmin++ >= Lmax) RRETURN(MATCH_NOMATCH); + if (Feptr >= mb->end_subject) + { + SCHECK_PARTIAL(); + RRETURN(MATCH_NOMATCH); + } + cc = UCHAR21TEST(Feptr); + if (Lc != cc && Loc != cc) RRETURN(MATCH_NOMATCH); + Feptr++; + } + /* Control never gets here */ } - } - else -#endif - /* No UTF-8 support, or not in UTF-8 mode: count is byte count */ - - { - if (i > eptr - mb->start_subject) RRETURN(MATCH_NOMATCH); - eptr -= i; - } - - /* Save the earliest consulted character, then skip to next op code */ - - if (eptr < mb->start_used_ptr) mb->start_used_ptr = eptr; - ecode += 1 + LINK_SIZE; - break; - - /* The callout item calls an external function, if one is provided, passing - details of the match so far. This is mainly for debugging, though the - function is able to force a failure. */ - - case OP_CALLOUT: - case OP_CALLOUT_STR: - { - unsigned int callout_length = (*ecode == OP_CALLOUT) - ? PRIV(OP_lengths)[OP_CALLOUT] : GET(ecode, 1 + 2*LINK_SIZE); - - if (mb->callout != NULL) + else /* Maximize */ { - pcre2_callout_block cb; - cb.version = 1; - cb.callout_number = ecode[LINK_SIZE + 1]; - cb.capture_top = (uint32_t)offset_top/2; - cb.capture_last = mb->capture_last & CAPLMASK; - cb.offset_vector = mb->ovector; - cb.mark = mb->nomatch_mark; - cb.subject = mb->start_subject; - cb.subject_length = (PCRE2_SIZE)(mb->end_subject - mb->start_subject); - cb.start_match = (PCRE2_SIZE)(mstart - mb->start_subject); - cb.current_position = (PCRE2_SIZE)(eptr - mb->start_subject); - cb.pattern_position = GET(ecode, 1); - cb.next_item_length = GET(ecode, 1 + LINK_SIZE); - - if (*ecode == OP_CALLOUT) + Lstart_eptr = Feptr; + for (i = Lmin; i < Lmax; i++) { - cb.callout_number = ecode[1 + 2*LINK_SIZE]; - cb.callout_string_offset = 0; - cb.callout_string = NULL; - cb.callout_string_length = 0; + uint32_t cc; /* Faster than PCRE2_UCHAR */ + if (Feptr >= mb->end_subject) + { + SCHECK_PARTIAL(); + break; + } + cc = UCHAR21TEST(Feptr); + if (Lc != cc && Loc != cc) break; + Feptr++; } - else + if (reptype != REPTYPE_POS) for (;;) { - cb.callout_number = 0; - cb.callout_string_offset = GET(ecode, 1 + 3*LINK_SIZE); - cb.callout_string = ecode + (1 + 4*LINK_SIZE) + 1; - cb.callout_string_length = - callout_length - (1 + 4*LINK_SIZE) - 2; + if (Feptr == Lstart_eptr) break; + RMATCH(Fecode, RM26); + Feptr--; + if (rrc != MATCH_NOMATCH) RRETURN(rrc); } - - if ((rrc = mb->callout(&cb, mb->callout_data)) > 0) - RRETURN(MATCH_NOMATCH); - if (rrc < 0) RRETURN(rrc); } - ecode += callout_length; } - break; - - /* Recursion either matches the current regex, or some subexpression. The - offset data is the offset to the starting bracket from the start of the - whole pattern. (This is so that it works from duplicated subpatterns.) - - The state of the capturing groups is preserved over recursion, and - re-instated afterwards. We don't know how many are started and not yet - finished (offset_top records the completed total) so we just have to save - all the potential data. There may be up to 65535 such values, which is too - large to put on the stack, but using malloc for small numbers seems - expensive. As a compromise, the stack is used when there are no more than - OP_RECURSE_STACK_SAVE_MAX values to store; otherwise malloc is used. - There are also other values that have to be saved. We use a chained - sequence of blocks that actually live on the stack. Thanks to Robin Houston - for the original version of this logic. It has, however, been hacked around - a lot, so he is not to blame for the current way it works. */ + /* Caseful comparisons (includes all multi-byte characters) */ - case OP_RECURSE: + else { - ovecsave_frame *fr; - recursion_info *ri; - uint32_t recno; - - callpat = mb->start_code + GET(ecode, 1); - recno = (callpat == mb->start_code)? 0 : GET2(callpat, 1 + LINK_SIZE); - - /* Check for repeating a pattern recursion without advancing the subject - pointer. This should catch convoluted mutual recursions. (Some simple - cases are caught at compile time.) */ - - for (ri = mb->recursive; ri != NULL; ri = ri->prevrec) - if (recno == ri->group_num && eptr == ri->subject_position) - RRETURN(PCRE2_ERROR_RECURSELOOP); - - /* Add to "recursing stack" */ - - new_recursive.group_num = recno; - new_recursive.saved_capture_last = mb->capture_last; - new_recursive.subject_position = eptr; - new_recursive.prevrec = mb->recursive; - mb->recursive = &new_recursive; - - /* Where to continue from afterwards */ - - ecode += 1 + LINK_SIZE; - - /* When we are using the system stack for match() recursion we can call a - function that uses the system stack for preserving the ovector while - processing the pattern recursion, but only if the ovector is small - enough. */ - -#ifndef HEAP_MATCH_RECURSE - if (mb->offset_end <= OP_RECURSE_STACK_SAVE_MAX) - { - rrc = op_recurse_ovecsave(eptr, callpat, mstart, offset_top, mb, - eptrb, rdepth); - mb->recursive = new_recursive.prevrec; - if (rrc != MATCH_MATCH && rrc != MATCH_ACCEPT) RRETURN(rrc); - - /* Set where we got to in the subject, and reset the start, in case - it was changed by \K. This *is* propagated back out of a recursion, - for Perl compatibility. */ - - eptr = mb->end_match_ptr; - mstart = mb->start_match_ptr; - break; /* End of processing OP_RECURSE */ - } -#endif - /* If the ovector is too big, or if we are using the heap for match() - recursion, we have to use the heap for saving the ovector. Used ovecsave - frames are kept on a chain and re-used. This makes a small improvement in - execution time on Linux. */ - - if (mb->ovecsave_chain != NULL) - { - new_recursive.ovec_save = mb->ovecsave_chain->saved_ovec; - mb->ovecsave_chain = mb->ovecsave_chain->next; - } - else + for (i = 1; i <= Lmin; i++) { - fr = (ovecsave_frame *)(mb->memctl.malloc(sizeof(ovecsave_frame *) + - mb->offset_end * sizeof(PCRE2_SIZE), mb->memctl.memory_data)); - if (fr == NULL) RRETURN(PCRE2_ERROR_NOMEMORY); - new_recursive.ovec_save = fr->saved_ovec; + if (Feptr >= mb->end_subject) + { + SCHECK_PARTIAL(); + RRETURN(MATCH_NOMATCH); + } + if (Lc != UCHAR21INCTEST(Feptr)) RRETURN(MATCH_NOMATCH); } - memcpy(new_recursive.ovec_save, mb->ovector, - mb->offset_end * sizeof(PCRE2_SIZE)); + if (Lmin == Lmax) continue; - /* Do the recursion. After processing each alternative, restore the - ovector data and the last captured value. This code has the same overall - logic as the code in the op_recurse_ovecsave() function, but is adapted - to use RMATCH/RRETURN and to release the heap block containing the saved - ovector. */ - - cbegroup = (*callpat >= OP_SBRA); - do + if (reptype == REPTYPE_MIN) { - if (cbegroup) mb->match_function_type |= MATCH_CBEGROUP; - RMATCH(eptr, callpat + PRIV(OP_lengths)[*callpat], offset_top, - mb, eptrb, RM6); - memcpy(mb->ovector, new_recursive.ovec_save, - mb->offset_end * sizeof(PCRE2_SIZE)); - mb->capture_last = new_recursive.saved_capture_last; - mb->recursive = new_recursive.prevrec; - - if (rrc == MATCH_MATCH || rrc == MATCH_ACCEPT) + for (;;) { - fr = (ovecsave_frame *) - ((uint8_t *)new_recursive.ovec_save - sizeof(ovecsave_frame *)); - fr->next = mb->ovecsave_chain; - mb->ovecsave_chain = fr; - - /* Set where we got to in the subject, and reset the start, in case - it was changed by \K. This *is* propagated back out of a recursion, - for Perl compatibility. */ - - eptr = mb->end_match_ptr; - mstart = mb->start_match_ptr; - goto RECURSION_MATCHED; /* Exit loop; end processing */ + RMATCH(Fecode, RM27); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + if (Lmin++ >= Lmax) RRETURN(MATCH_NOMATCH); + if (Feptr >= mb->end_subject) + { + SCHECK_PARTIAL(); + RRETURN(MATCH_NOMATCH); + } + if (Lc != UCHAR21INCTEST(Feptr)) RRETURN(MATCH_NOMATCH); } + /* Control never gets here */ + } + else /* Maximize */ + { + Lstart_eptr = Feptr; + for (i = Lmin; i < Lmax; i++) + { + if (Feptr >= mb->end_subject) + { + SCHECK_PARTIAL(); + break; + } - /* PCRE does not allow THEN, SKIP, PRUNE or COMMIT to escape beyond a - recursion; they cause a NOMATCH for the entire recursion. These codes - are defined in a range that can be tested for. */ + if (Lc != UCHAR21TEST(Feptr)) break; + Feptr++; + } - if (rrc >= MATCH_BACKTRACK_MIN && rrc <= MATCH_BACKTRACK_MAX) + if (reptype != REPTYPE_POS) for (;;) { - rrc = MATCH_NOMATCH; - goto RECURSION_RETURN; + if (Feptr <= Lstart_eptr) break; + RMATCH(Fecode, RM28); + Feptr--; + if (rrc != MATCH_NOMATCH) RRETURN(rrc); } - - /* Any return code other than NOMATCH is an error. */ - - if (rrc != MATCH_NOMATCH) goto RECURSION_RETURN; - mb->recursive = &new_recursive; - callpat += GET(callpat, 1); } - while (*callpat == OP_ALT); - - RECURSION_RETURN: - mb->recursive = new_recursive.prevrec; - fr = (ovecsave_frame *) - ((uint8_t *)new_recursive.ovec_save - sizeof(ovecsave_frame *)); - fr->next = mb->ovecsave_chain; - mb->ovecsave_chain = fr; - RRETURN(rrc); } - - RECURSION_MATCHED: break; - /* An alternation is the end of a branch; scan along to find the end of the - bracketed group and go to there. */ +#undef Loclength +#undef Lstart_eptr +#undef Lcharptr +#undef Lmin +#undef Lmax +#undef Lc +#undef Loc - case OP_ALT: - do ecode += GET(ecode,1); while (*ecode == OP_ALT); - break; - /* BRAZERO, BRAMINZERO and SKIPZERO occur just before a bracket group, - indicating that it may occur zero times. It may repeat infinitely, or not - at all - i.e. it could be ()* or ()? or even (){0} in the pattern. Brackets - with fixed upper repeat limits are compiled as a number of copies, with the - optional ones preceded by BRAZERO or BRAMINZERO. */ + /* ===================================================================== */ + /* Match a negated single one-byte character repeatedly. This is almost a + repeat of the code for a repeated single character, but I haven't found a + nice way of commoning these up that doesn't require a test of the + positive/negative option for each character match. Maybe that wouldn't add + very much to the time taken, but character matching *is* what this is all + about... */ - case OP_BRAZERO: - next_ecode = ecode + 1; - RMATCH(eptr, next_ecode, offset_top, mb, eptrb, RM10); - if (rrc != MATCH_NOMATCH) RRETURN(rrc); - do next_ecode += GET(next_ecode, 1); while (*next_ecode == OP_ALT); - ecode = next_ecode + 1 + LINK_SIZE; - break; +#define Lstart_eptr F->temp_sptr[0] +#define Lmin F->temp_32[0] +#define Lmax F->temp_32[1] +#define Lc F->temp_32[2] +#define Loc F->temp_32[3] - case OP_BRAMINZERO: - next_ecode = ecode + 1; - do next_ecode += GET(next_ecode, 1); while (*next_ecode == OP_ALT); - RMATCH(eptr, next_ecode + 1+LINK_SIZE, offset_top, mb, eptrb, RM11); - if (rrc != MATCH_NOMATCH) RRETURN(rrc); - ecode++; - break; + case OP_NOTEXACT: + case OP_NOTEXACTI: + Lmin = Lmax = GET2(Fecode, 1); + Fecode += 1 + IMM2_SIZE; + goto REPEATNOTCHAR; - case OP_SKIPZERO: - next_ecode = ecode+1; - do next_ecode += GET(next_ecode,1); while (*next_ecode == OP_ALT); - ecode = next_ecode + 1 + LINK_SIZE; - break; + case OP_NOTUPTO: + case OP_NOTUPTOI: + Lmin = 0; + Lmax = GET2(Fecode, 1); + reptype = REPTYPE_MAX; + Fecode += 1 + IMM2_SIZE; + goto REPEATNOTCHAR; - /* BRAPOSZERO occurs before a possessive bracket group. Don't do anything - here; just jump to the group, with allow_zero set TRUE. */ + case OP_NOTMINUPTO: + case OP_NOTMINUPTOI: + Lmin = 0; + Lmax = GET2(Fecode, 1); + reptype = REPTYPE_MIN; + Fecode += 1 + IMM2_SIZE; + goto REPEATNOTCHAR; - case OP_BRAPOSZERO: - op = *(++ecode); - allow_zero = TRUE; - if (op == OP_CBRAPOS || op == OP_SCBRAPOS) goto POSSESSIVE_CAPTURE; - goto POSSESSIVE_NON_CAPTURE; + case OP_NOTPOSSTAR: + case OP_NOTPOSSTARI: + reptype = REPTYPE_POS; + Lmin = 0; + Lmax = UINT32_MAX; + Fecode++; + goto REPEATNOTCHAR; - /* End of a group, repeated or non-repeating. */ + case OP_NOTPOSPLUS: + case OP_NOTPOSPLUSI: + reptype = REPTYPE_POS; + Lmin = 1; + Lmax = UINT32_MAX; + Fecode++; + goto REPEATNOTCHAR; - case OP_KET: - case OP_KETRMIN: - case OP_KETRMAX: - case OP_KETRPOS: - prev = ecode - GET(ecode, 1); + case OP_NOTPOSQUERY: + case OP_NOTPOSQUERYI: + reptype = REPTYPE_POS; + Lmin = 0; + Lmax = 1; + Fecode++; + goto REPEATNOTCHAR; - /* If this was a group that remembered the subject start, in order to break - infinite repeats of empty string matches, retrieve the subject start from - the chain. Otherwise, set it NULL. */ + case OP_NOTPOSUPTO: + case OP_NOTPOSUPTOI: + reptype = REPTYPE_POS; + Lmin = 0; + Lmax = GET2(Fecode, 1); + Fecode += 1 + IMM2_SIZE; + goto REPEATNOTCHAR; - if (*prev >= OP_SBRA || *prev == OP_ONCE) - { - saved_eptr = eptrb->epb_saved_eptr; /* Value at start of group */ - eptrb = eptrb->epb_prev; /* Backup to previous group */ - } - else saved_eptr = NULL; + case OP_NOTSTAR: + case OP_NOTSTARI: + case OP_NOTMINSTAR: + case OP_NOTMINSTARI: + case OP_NOTPLUS: + case OP_NOTPLUSI: + case OP_NOTMINPLUS: + case OP_NOTMINPLUSI: + case OP_NOTQUERY: + case OP_NOTQUERYI: + case OP_NOTMINQUERY: + case OP_NOTMINQUERYI: + fc = *Fecode++ - ((Fop >= OP_NOTSTARI)? OP_NOTSTARI: OP_NOTSTAR); + Lmin = rep_min[fc]; + Lmax = rep_max[fc]; + reptype = rep_typ[fc]; - /* If we are at the end of an assertion group or a non-capturing atomic - group, stop matching and return MATCH_MATCH, but record the current high - water mark for use by positive assertions. We also need to record the match - start in case it was changed by \K. */ + /* Common code for all repeated single-character non-matches. */ - if ((*prev >= OP_ASSERT && *prev <= OP_ASSERTBACK_NOT) || - *prev == OP_ONCE_NC) - { - mb->end_match_ptr = eptr; /* For ONCE_NC */ - mb->end_offset_top = offset_top; - mb->start_match_ptr = mstart; - if (eptr > mb->last_used_ptr) mb->last_used_ptr = eptr; - RRETURN(MATCH_MATCH); /* Sets mb->mark */ - } + REPEATNOTCHAR: + GETCHARINCTEST(Lc, Fecode); - /* For capturing groups we have to check the group number back at the start - and if necessary complete handling an extraction by setting the offsets and - bumping the high water mark. Whole-pattern recursion is coded as a recurse - into group 0, so it won't be picked up here. Instead, we catch it when the - OP_END is reached. Other recursion is handled here. We just have to record - the current subject position and start match pointer and give a MATCH - return. */ + /* The code is duplicated for the caseless and caseful cases, for speed, + since matching characters is likely to be quite common. First, ensure the + minimum number of matches are present. If Lmin = Lmax, we are done. + Otherwise, if minimizing, keep trying the rest of the expression and + advancing one matching character if failing, up to the maximum. + Alternatively, if maximizing, find the maximum number of characters and + work backwards. */ - if (*prev == OP_CBRA || *prev == OP_SCBRA || - *prev == OP_CBRAPOS || *prev == OP_SCBRAPOS) + if (Fop >= OP_NOTSTARI) /* Caseless */ { - number = GET2(prev, 1+LINK_SIZE); - offset = number << 1; - - /* Handle a recursively called group. */ - - if (mb->recursive != NULL && mb->recursive->group_num == number) - { - mb->end_match_ptr = eptr; - mb->start_match_ptr = mstart; - if (eptr > mb->last_used_ptr) mb->last_used_ptr = eptr; - RRETURN(MATCH_MATCH); - } +#ifdef SUPPORT_UNICODE + if (utf && Lc > 127) + Loc = UCD_OTHERCASE(Lc); + else +#endif /* SUPPORT_UNICODE */ - /* Deal with capturing */ + Loc = TABLE_GET(Lc, mb->fcc, Lc); /* Other case from table */ - mb->capture_last = (mb->capture_last & OVFLMASK) | number; - if (offset >= mb->offset_max) mb->capture_last |= OVFLBIT; else +#ifdef SUPPORT_UNICODE + if (utf) { - /* If offset is greater than offset_top, it means that we are - "skipping" a capturing group, and that group's offsets must be marked - unset. In earlier versions of PCRE, all the offsets were unset at the - start of matching, but this doesn't work because atomic groups and - assertions can cause a value to be set that should later be unset. - Example: matching /(?>(a))b|(a)c/ against "ac". This sets group 1 as - part of the atomic group, but this is not on the final matching path, - so must be unset when 2 is set. (If there is no group 2, there is no - problem, because offset_top will then be 2, indicating no capture.) */ - - if (offset > offset_top) + uint32_t d; + for (i = 1; i <= Lmin; i++) { - PCRE2_SIZE *iptr = mb->ovector + offset_top; - PCRE2_SIZE *iend = mb->ovector + offset; - while (iptr < iend) *iptr++ = PCRE2_UNSET; + if (Feptr >= mb->end_subject) + { + SCHECK_PARTIAL(); + RRETURN(MATCH_NOMATCH); + } + GETCHARINC(d, Feptr); + if (Lc == d || Loc == d) RRETURN(MATCH_NOMATCH); } - - /* Now make the extraction */ - - mb->ovector[offset] = mb->ovector[mb->offset_end - number]; - mb->ovector[offset+1] = eptr - mb->start_subject; - if (offset_top <= offset) offset_top = offset + 2; - } - } - - /* OP_KETRPOS is a possessive repeating ket. Remember the current position, - and return the MATCH_KETRPOS. This makes it possible to do the repeats one - at a time from the outer level, thus saving stack. This must precede the - empty string test - in this case that test is done at the outer level. */ - - if (*ecode == OP_KETRPOS) - { - mb->start_match_ptr = mstart; /* In case \K reset it */ - mb->end_match_ptr = eptr; - mb->end_offset_top = offset_top; - if (eptr > mb->last_used_ptr) mb->last_used_ptr = eptr; - RRETURN(MATCH_KETRPOS); - } - - /* For an ordinary non-repeating ket, just continue at this level. This - also happens for a repeating ket if no characters were matched in the - group. This is the forcible breaking of infinite loops as implemented in - Perl 5.005. For a non-repeating atomic group that includes captures, - establish a backup point by processing the rest of the pattern at a lower - level. If this results in a NOMATCH return, pass MATCH_ONCE back to the - original OP_ONCE level, thereby bypassing intermediate backup points, but - resetting any captures that happened along the way. */ - - if (*ecode == OP_KET || eptr == saved_eptr) - { - if (*prev == OP_ONCE) - { - RMATCH(eptr, ecode + 1 + LINK_SIZE, offset_top, mb, eptrb, RM12); - if (rrc != MATCH_NOMATCH) RRETURN(rrc); - mb->once_target = prev; /* Level at which to change to MATCH_NOMATCH */ - RRETURN(MATCH_ONCE); - } - ecode += 1 + LINK_SIZE; /* Carry on at this level */ - break; - } - - /* The normal repeating kets try the rest of the pattern or restart from - the preceding bracket, in the appropriate order. In the second case, we can - use tail recursion to avoid using another stack frame, unless we have an - an atomic group or an unlimited repeat of a group that can match an empty - string. */ - - if (*ecode == OP_KETRMIN) - { - RMATCH(eptr, ecode + 1 + LINK_SIZE, offset_top, mb, eptrb, RM7); - if (rrc != MATCH_NOMATCH) RRETURN(rrc); - if (*prev == OP_ONCE) - { - RMATCH(eptr, prev, offset_top, mb, eptrb, RM8); - if (rrc != MATCH_NOMATCH) RRETURN(rrc); - mb->once_target = prev; /* Level at which to change to MATCH_NOMATCH */ - RRETURN(MATCH_ONCE); - } - if (*prev >= OP_SBRA) /* Could match an empty string */ - { - RMATCH(eptr, prev, offset_top, mb, eptrb, RM50); - RRETURN(rrc); - } - ecode = prev; - goto TAIL_RECURSE; - } - else /* OP_KETRMAX */ - { - RMATCH(eptr, prev, offset_top, mb, eptrb, RM13); - if (rrc == MATCH_ONCE && mb->once_target == prev) rrc = MATCH_NOMATCH; - if (rrc != MATCH_NOMATCH) RRETURN(rrc); - if (*prev == OP_ONCE) - { - RMATCH(eptr, ecode + 1 + LINK_SIZE, offset_top, mb, eptrb, RM9); - if (rrc != MATCH_NOMATCH) RRETURN(rrc); - mb->once_target = prev; - RRETURN(MATCH_ONCE); } - ecode += 1 + LINK_SIZE; - goto TAIL_RECURSE; - } - /* Control never gets here */ - - /* Not multiline mode: start of subject assertion, unless notbol. */ - - case OP_CIRC: - if ((mb->moptions & PCRE2_NOTBOL) != 0 && eptr == mb->start_subject) - RRETURN(MATCH_NOMATCH); - - /* Start of subject assertion */ - - case OP_SOD: - if (eptr != mb->start_subject) RRETURN(MATCH_NOMATCH); - ecode++; - break; - - /* Multiline mode: start of subject unless notbol, or after any newline - except for one at the very end, unless PCRE2_ALT_CIRCUMFLEX is set. */ - - case OP_CIRCM: - if ((mb->moptions & PCRE2_NOTBOL) != 0 && eptr == mb->start_subject) - RRETURN(MATCH_NOMATCH); - if (eptr != mb->start_subject && - ((eptr == mb->end_subject && - (mb->poptions & PCRE2_ALT_CIRCUMFLEX) == 0) || - !WAS_NEWLINE(eptr))) - RRETURN(MATCH_NOMATCH); - ecode++; - break; - - /* Start of match assertion */ - - case OP_SOM: - if (eptr != mb->start_subject + mb->start_offset) RRETURN(MATCH_NOMATCH); - ecode++; - break; - - /* Reset the start of match point */ - - case OP_SET_SOM: - mstart = eptr; - ecode++; - break; - - /* Multiline mode: assert before any newline, or before end of subject - unless noteol is set. */ + else +#endif /* SUPPORT_UNICODE */ - case OP_DOLLM: - if (eptr < mb->end_subject) - { - if (!IS_NEWLINE(eptr)) + /* Not UTF mode */ { - if (mb->partial != 0 && - eptr + 1 >= mb->end_subject && - NLBLOCK->nltype == NLTYPE_FIXED && - NLBLOCK->nllen == 2 && - UCHAR21TEST(eptr) == NLBLOCK->nl[0]) + for (i = 1; i <= Lmin; i++) { - mb->hitend = TRUE; - if (mb->partial > 1) RRETURN(PCRE2_ERROR_PARTIAL); + if (Feptr >= mb->end_subject) + { + SCHECK_PARTIAL(); + RRETURN(MATCH_NOMATCH); + } + if (Lc == *Feptr || Loc == *Feptr) RRETURN(MATCH_NOMATCH); + Feptr++; } - RRETURN(MATCH_NOMATCH); } - } - else - { - if ((mb->moptions & PCRE2_NOTEOL) != 0) RRETURN(MATCH_NOMATCH); - SCHECK_PARTIAL(); - } - ecode++; - break; - - /* Not multiline mode: assert before a terminating newline or before end of - subject unless noteol is set. */ - - case OP_DOLL: - if ((mb->moptions & PCRE2_NOTEOL) != 0) RRETURN(MATCH_NOMATCH); - if ((mb->poptions & PCRE2_DOLLAR_ENDONLY) == 0) goto ASSERT_NL_OR_EOS; - /* ... else fall through for endonly */ + if (Lmin == Lmax) continue; /* Finished for exact count */ - /* End of subject assertion (\z) */ - - case OP_EOD: - if (eptr < mb->end_subject) RRETURN(MATCH_NOMATCH); - SCHECK_PARTIAL(); - ecode++; - break; - - /* End of subject or ending \n assertion (\Z) */ - - case OP_EODN: - ASSERT_NL_OR_EOS: - if (eptr < mb->end_subject && - (!IS_NEWLINE(eptr) || eptr != mb->end_subject - mb->nllen)) - { - if (mb->partial != 0 && - eptr + 1 >= mb->end_subject && - NLBLOCK->nltype == NLTYPE_FIXED && - NLBLOCK->nllen == 2 && - UCHAR21TEST(eptr) == NLBLOCK->nl[0]) + if (reptype == REPTYPE_MIN) { - mb->hitend = TRUE; - if (mb->partial > 1) RRETURN(PCRE2_ERROR_PARTIAL); - } - RRETURN(MATCH_NOMATCH); - } - - /* Either at end of string or \n before end. */ - - SCHECK_PARTIAL(); - ecode++; - break; - - /* Word boundary assertions */ - - case OP_NOT_WORD_BOUNDARY: - case OP_WORD_BOUNDARY: - { - - /* Find out if the previous and current characters are "word" characters. - It takes a bit more work in UTF-8 mode. Characters > 255 are assumed to - be "non-word" characters. Remember the earliest consulted character for - partial matching. */ - #ifdef SUPPORT_UNICODE - if (utf) - { - /* Get status of previous character */ - - if (eptr == mb->start_subject) prev_is_word = FALSE; else + if (utf) { - PCRE2_SPTR lastptr = eptr - 1; - BACKCHAR(lastptr); - if (lastptr < mb->start_used_ptr) mb->start_used_ptr = lastptr; - GETCHAR(c, lastptr); - if ((mb->poptions & PCRE2_UCP) != 0) + uint32_t d; + for (;;) { - if (c == '_') prev_is_word = TRUE; else + RMATCH(Fecode, RM204); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + if (Lmin++ >= Lmax) RRETURN(MATCH_NOMATCH); + if (Feptr >= mb->end_subject) { - int cat = UCD_CATEGORY(c); - prev_is_word = (cat == ucp_L || cat == ucp_N); + SCHECK_PARTIAL(); + RRETURN(MATCH_NOMATCH); } + GETCHARINC(d, Feptr); + if (Lc == d || Loc == d) RRETURN(MATCH_NOMATCH); } - else - prev_is_word = c < 256 && (mb->ctypes[c] & ctype_word) != 0; - } - - /* Get status of next character */ - - if (eptr >= mb->end_subject) - { - SCHECK_PARTIAL(); - cur_is_word = FALSE; } else +#endif /*SUPPORT_UNICODE */ + + /* Not UTF mode */ { - PCRE2_SPTR nextptr = eptr + 1; - FORWARDCHARTEST(nextptr, mb->end_subject); - if (nextptr > mb->last_used_ptr) mb->last_used_ptr = nextptr; - GETCHAR(c, eptr); - if ((mb->poptions & PCRE2_UCP) != 0) + for (;;) { - if (c == '_') cur_is_word = TRUE; else + RMATCH(Fecode, RM29); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + if (Lmin++ >= Lmax) RRETURN(MATCH_NOMATCH); + if (Feptr >= mb->end_subject) { - int cat = UCD_CATEGORY(c); - cur_is_word = (cat == ucp_L || cat == ucp_N); + SCHECK_PARTIAL(); + RRETURN(MATCH_NOMATCH); } + if (Lc == *Feptr || Loc == *Feptr) RRETURN(MATCH_NOMATCH); + Feptr++; } - else - cur_is_word = c < 256 && (mb->ctypes[c] & ctype_word) != 0; } + /* Control never gets here */ } - else -#endif /* SUPPORT UTF */ - /* Not in UTF-8 mode, but we may still have PCRE2_UCP set, and for - consistency with the behaviour of \w we do use it in this case. */ + /* Maximize case */ + else { - /* Get status of previous character */ + Lstart_eptr = Feptr; - if (eptr == mb->start_subject) prev_is_word = FALSE; else - { - if (eptr <= mb->start_used_ptr) mb->start_used_ptr = eptr - 1; #ifdef SUPPORT_UNICODE - if ((mb->poptions & PCRE2_UCP) != 0) + if (utf) + { + uint32_t d; + for (i = Lmin; i < Lmax; i++) { - c = eptr[-1]; - if (c == '_') prev_is_word = TRUE; else + int len = 1; + if (Feptr >= mb->end_subject) { - int cat = UCD_CATEGORY(c); - prev_is_word = (cat == ucp_L || cat == ucp_N); + SCHECK_PARTIAL(); + break; } + GETCHARLEN(d, Feptr, len); + if (Lc == d || Loc == d) break; + Feptr += len; } - else -#endif - prev_is_word = MAX_255(eptr[-1]) - && ((mb->ctypes[eptr[-1]] & ctype_word) != 0); - } - /* Get status of next character */ + /* After \C in UTF mode, Lstart_eptr might be in the middle of a + Unicode character. Use <= Lstart_eptr to ensure backtracking doesn't + go too far. */ - if (eptr >= mb->end_subject) - { - SCHECK_PARTIAL(); - cur_is_word = FALSE; + if (reptype != REPTYPE_POS) for(;;) + { + if (Feptr <= Lstart_eptr) break; + RMATCH(Fecode, RM205); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + Feptr--; + BACKCHAR(Feptr); + } } else +#endif /* SUPPORT_UNICODE */ + + /* Not UTF mode */ { - if (eptr >= mb->last_used_ptr) mb->last_used_ptr = eptr + 1; -#ifdef SUPPORT_UNICODE - if ((mb->poptions & PCRE2_UCP) != 0) + for (i = Lmin; i < Lmax; i++) { - c = *eptr; - if (c == '_') cur_is_word = TRUE; else + if (Feptr >= mb->end_subject) { - int cat = UCD_CATEGORY(c); - cur_is_word = (cat == ucp_L || cat == ucp_N); + SCHECK_PARTIAL(); + break; } + if (Lc == *Feptr || Loc == *Feptr) break; + Feptr++; + } + if (reptype != REPTYPE_POS) for (;;) + { + if (Feptr == Lstart_eptr) break; + RMATCH(Fecode, RM30); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + Feptr--; } - else -#endif - cur_is_word = MAX_255(*eptr) - && ((mb->ctypes[*eptr] & ctype_word) != 0); } } - - /* Now see if the situation is what we want */ - - if ((*ecode++ == OP_WORD_BOUNDARY)? - cur_is_word == prev_is_word : cur_is_word != prev_is_word) - RRETURN(MATCH_NOMATCH); - } - break; - - /* Match any single character type except newline; have to take care with - CRLF newlines and partial matching. */ - - case OP_ANY: - if (IS_NEWLINE(eptr)) RRETURN(MATCH_NOMATCH); - if (mb->partial != 0 && - eptr == mb->end_subject - 1 && - NLBLOCK->nltype == NLTYPE_FIXED && - NLBLOCK->nllen == 2 && - UCHAR21TEST(eptr) == NLBLOCK->nl[0]) - { - mb->hitend = TRUE; - if (mb->partial > 1) RRETURN(PCRE2_ERROR_PARTIAL); - } - - /* Fall through */ - - /* Match any single character whatsoever. */ - - case OP_ALLANY: - if (eptr >= mb->end_subject) /* DO NOT merge the eptr++ here; it must */ - { /* not be updated before SCHECK_PARTIAL. */ - SCHECK_PARTIAL(); - RRETURN(MATCH_NOMATCH); } - eptr++; -#ifdef SUPPORT_UNICODE - if (utf) ACROSSCHAR(eptr < mb->end_subject, *eptr, eptr++); -#endif - ecode++; - break; - - /* Match a single code unit, even in UTF-8 mode. This opcode really does - match any code unit, even newline. (It really should be called ANYCODEUNIT, - of course - the byte name is from pre-16 bit days.) */ - - case OP_ANYBYTE: - if (eptr >= mb->end_subject) /* DO NOT merge the eptr++ here; it must */ - { /* not be updated before SCHECK_PARTIAL. */ - SCHECK_PARTIAL(); - RRETURN(MATCH_NOMATCH); - } - eptr++; - ecode++; - break; - - case OP_NOT_DIGIT: - if (eptr >= mb->end_subject) - { - SCHECK_PARTIAL(); - RRETURN(MATCH_NOMATCH); - } - GETCHARINCTEST(c, eptr); - if ( -#ifdef SUPPORT_WIDE_CHARS - c < 256 && -#endif - (mb->ctypes[c] & ctype_digit) != 0 - ) - RRETURN(MATCH_NOMATCH); - ecode++; - break; - case OP_DIGIT: - if (eptr >= mb->end_subject) - { - SCHECK_PARTIAL(); - RRETURN(MATCH_NOMATCH); - } - GETCHARINCTEST(c, eptr); - if ( -#ifdef SUPPORT_WIDE_CHARS - c > 255 || -#endif - (mb->ctypes[c] & ctype_digit) == 0 - ) - RRETURN(MATCH_NOMATCH); - ecode++; - break; - - case OP_NOT_WHITESPACE: - if (eptr >= mb->end_subject) - { - SCHECK_PARTIAL(); - RRETURN(MATCH_NOMATCH); - } - GETCHARINCTEST(c, eptr); - if ( -#ifdef SUPPORT_WIDE_CHARS - c < 256 && -#endif - (mb->ctypes[c] & ctype_space) != 0 - ) - RRETURN(MATCH_NOMATCH); - ecode++; - break; - - case OP_WHITESPACE: - if (eptr >= mb->end_subject) - { - SCHECK_PARTIAL(); - RRETURN(MATCH_NOMATCH); - } - GETCHARINCTEST(c, eptr); - if ( -#ifdef SUPPORT_WIDE_CHARS - c > 255 || -#endif - (mb->ctypes[c] & ctype_space) == 0 - ) - RRETURN(MATCH_NOMATCH); - ecode++; - break; - - case OP_NOT_WORDCHAR: - if (eptr >= mb->end_subject) - { - SCHECK_PARTIAL(); - RRETURN(MATCH_NOMATCH); - } - GETCHARINCTEST(c, eptr); - if ( -#ifdef SUPPORT_WIDE_CHARS - c < 256 && -#endif - (mb->ctypes[c] & ctype_word) != 0 - ) - RRETURN(MATCH_NOMATCH); - ecode++; - break; - - case OP_WORDCHAR: - if (eptr >= mb->end_subject) - { - SCHECK_PARTIAL(); - RRETURN(MATCH_NOMATCH); - } - GETCHARINCTEST(c, eptr); - if ( -#ifdef SUPPORT_WIDE_CHARS - c > 255 || -#endif - (mb->ctypes[c] & ctype_word) == 0 - ) - RRETURN(MATCH_NOMATCH); - ecode++; - break; - - case OP_ANYNL: - if (eptr >= mb->end_subject) - { - SCHECK_PARTIAL(); - RRETURN(MATCH_NOMATCH); - } - GETCHARINCTEST(c, eptr); - switch(c) - { - default: RRETURN(MATCH_NOMATCH); - - case CHAR_CR: - if (eptr >= mb->end_subject) - { - SCHECK_PARTIAL(); - } - else if (UCHAR21TEST(eptr) == CHAR_LF) eptr++; - break; - - case CHAR_LF: - break; - - case CHAR_VT: - case CHAR_FF: - case CHAR_NEL: -#ifndef EBCDIC - case 0x2028: - case 0x2029: -#endif /* Not EBCDIC */ - if (mb->bsr_convention == PCRE2_BSR_ANYCRLF) RRETURN(MATCH_NOMATCH); - break; - } - ecode++; - break; - - case OP_NOT_HSPACE: - if (eptr >= mb->end_subject) - { - SCHECK_PARTIAL(); - RRETURN(MATCH_NOMATCH); - } - GETCHARINCTEST(c, eptr); - switch(c) - { - HSPACE_CASES: RRETURN(MATCH_NOMATCH); /* Byte and multibyte cases */ - default: break; - } - ecode++; - break; - - case OP_HSPACE: - if (eptr >= mb->end_subject) - { - SCHECK_PARTIAL(); - RRETURN(MATCH_NOMATCH); - } - GETCHARINCTEST(c, eptr); - switch(c) - { - HSPACE_CASES: break; /* Byte and multibyte cases */ - default: RRETURN(MATCH_NOMATCH); - } - ecode++; - break; - - case OP_NOT_VSPACE: - if (eptr >= mb->end_subject) - { - SCHECK_PARTIAL(); - RRETURN(MATCH_NOMATCH); - } - GETCHARINCTEST(c, eptr); - switch(c) - { - VSPACE_CASES: RRETURN(MATCH_NOMATCH); - default: break; - } - ecode++; - break; + /* Caseful comparisons */ - case OP_VSPACE: - if (eptr >= mb->end_subject) - { - SCHECK_PARTIAL(); - RRETURN(MATCH_NOMATCH); - } - GETCHARINCTEST(c, eptr); - switch(c) + else { - VSPACE_CASES: break; - default: RRETURN(MATCH_NOMATCH); - } - ecode++; - break; - #ifdef SUPPORT_UNICODE - /* Check the next character by Unicode property. We will get here only - if the support is in the binary; otherwise a compile-time error occurs. */ - - case OP_PROP: - case OP_NOTPROP: - if (eptr >= mb->end_subject) - { - SCHECK_PARTIAL(); - RRETURN(MATCH_NOMATCH); - } - GETCHARINCTEST(c, eptr); - { - const uint32_t *cp; - const ucd_record *prop = GET_UCD(c); - - switch(ecode[1]) + if (utf) { - case PT_ANY: - if (op == OP_NOTPROP) RRETURN(MATCH_NOMATCH); - break; - - case PT_LAMP: - if ((prop->chartype == ucp_Lu || - prop->chartype == ucp_Ll || - prop->chartype == ucp_Lt) == (op == OP_NOTPROP)) - RRETURN(MATCH_NOMATCH); - break; - - case PT_GC: - if ((ecode[2] != PRIV(ucp_gentype)[prop->chartype]) == (op == OP_PROP)) - RRETURN(MATCH_NOMATCH); - break; - - case PT_PC: - if ((ecode[2] != prop->chartype) == (op == OP_PROP)) - RRETURN(MATCH_NOMATCH); - break; - - case PT_SC: - if ((ecode[2] != prop->script) == (op == OP_PROP)) - RRETURN(MATCH_NOMATCH); - break; - - /* These are specials */ - - case PT_ALNUM: - if ((PRIV(ucp_gentype)[prop->chartype] == ucp_L || - PRIV(ucp_gentype)[prop->chartype] == ucp_N) == (op == OP_NOTPROP)) - RRETURN(MATCH_NOMATCH); - break; - - /* Perl space used to exclude VT, but from Perl 5.18 it is included, - which means that Perl space and POSIX space are now identical. PCRE - was changed at release 8.34. */ - - case PT_SPACE: /* Perl space */ - case PT_PXSPACE: /* POSIX space */ - switch(c) - { - HSPACE_CASES: - VSPACE_CASES: - if (op == OP_NOTPROP) RRETURN(MATCH_NOMATCH); - break; - - default: - if ((PRIV(ucp_gentype)[prop->chartype] == ucp_Z) == - (op == OP_NOTPROP)) RRETURN(MATCH_NOMATCH); - break; - } - break; - - case PT_WORD: - if ((PRIV(ucp_gentype)[prop->chartype] == ucp_L || - PRIV(ucp_gentype)[prop->chartype] == ucp_N || - c == CHAR_UNDERSCORE) == (op == OP_NOTPROP)) - RRETURN(MATCH_NOMATCH); - break; - - case PT_CLIST: - cp = PRIV(ucd_caseless_sets) + ecode[2]; - for (;;) + uint32_t d; + for (i = 1; i <= Lmin; i++) { - if (c < *cp) - { if (op == OP_PROP) { RRETURN(MATCH_NOMATCH); } else break; } - if (c == *cp++) - { if (op == OP_PROP) break; else { RRETURN(MATCH_NOMATCH); } } + if (Feptr >= mb->end_subject) + { + SCHECK_PARTIAL(); + RRETURN(MATCH_NOMATCH); + } + GETCHARINC(d, Feptr); + if (Lc == d) RRETURN(MATCH_NOMATCH); } - break; - - case PT_UCNC: - if ((c == CHAR_DOLLAR_SIGN || c == CHAR_COMMERCIAL_AT || - c == CHAR_GRAVE_ACCENT || (c >= 0xa0 && c <= 0xd7ff) || - c >= 0xe000) == (op == OP_NOTPROP)) - RRETURN(MATCH_NOMATCH); - break; - - /* This should never occur */ - - default: - RRETURN(PCRE2_ERROR_INTERNAL); - } - - ecode += 3; - } - break; - - /* Match an extended Unicode sequence. We will get here only if the support - is in the binary; otherwise a compile-time error occurs. */ - - case OP_EXTUNI: - if (eptr >= mb->end_subject) - { - SCHECK_PARTIAL(); - RRETURN(MATCH_NOMATCH); - } - else - { - int lgb, rgb; - GETCHARINCTEST(c, eptr); - lgb = UCD_GRAPHBREAK(c); - while (eptr < mb->end_subject) - { - int len = 1; - if (!utf) c = *eptr; else { GETCHARLEN(c, eptr, len); } - rgb = UCD_GRAPHBREAK(c); - if ((PRIV(ucp_gbtable)[lgb] & (1 << rgb)) == 0) break; - lgb = rgb; - eptr += len; - } - } - CHECK_PARTIAL(); - ecode++; - break; -#endif /* SUPPORT_UNICODE */ - - - /* Match a back reference, possibly repeatedly. Look past the end of the - item to see if there is repeat information following. - - The OP_REF and OP_REFI opcodes are used for a reference to a numbered group - or to a non-duplicated named group. For a duplicated named group, OP_DNREF - and OP_DNREFI are used. In this case we must scan the list of groups to - which the name refers, and use the first one that is set. */ - - case OP_DNREF: - case OP_DNREFI: - caseless = op == OP_DNREFI; - { - int count = GET2(ecode, 1+IMM2_SIZE); - PCRE2_SPTR slot = mb->name_table + GET2(ecode, 1) * mb->name_entry_size; - ecode += 1 + 2*IMM2_SIZE; - - /* Initializing 'offset' avoids a compiler warning in the REF_REPEAT - code. */ - - offset = 0; - while (count-- > 0) - { - offset = GET2(slot, 0) << 1; - if (offset < offset_top && mb->ovector[offset] != PCRE2_UNSET) break; - slot += mb->name_entry_size; } - } - goto REF_REPEAT; - - case OP_REF: - case OP_REFI: - caseless = op == OP_REFI; - offset = GET2(ecode, 1) << 1; /* Doubled ref number */ - ecode += 1 + IMM2_SIZE; - - /* Set up for repetition, or handle the non-repeated case */ - - REF_REPEAT: - switch (*ecode) - { - case OP_CRSTAR: - case OP_CRMINSTAR: - case OP_CRPLUS: - case OP_CRMINPLUS: - case OP_CRQUERY: - case OP_CRMINQUERY: - c = *ecode++ - OP_CRSTAR; - minimize = (c & 1) != 0; - min = rep_min[c]; /* Pick up values from tables; */ - max = rep_max[c]; /* zero for max => infinity */ - if (max == 0) max = INT_MAX; - break; - - case OP_CRRANGE: - case OP_CRMINRANGE: - minimize = (*ecode == OP_CRMINRANGE); - min = GET2(ecode, 1); - max = GET2(ecode, 1 + IMM2_SIZE); - if (max == 0) max = INT_MAX; - ecode += 1 + 2 * IMM2_SIZE; - break; - - default: /* No repeat follows */ + else +#endif + /* Not UTF mode */ { - int rc = match_ref(offset, offset_top, eptr, mb, caseless, &length); - if (rc != 0) + for (i = 1; i <= Lmin; i++) { - if (rc > 0) eptr = mb->end_subject; /* Partial match */ - CHECK_PARTIAL(); - RRETURN(MATCH_NOMATCH); + if (Feptr >= mb->end_subject) + { + SCHECK_PARTIAL(); + RRETURN(MATCH_NOMATCH); + } + if (Lc == *Feptr++) RRETURN(MATCH_NOMATCH); } } - eptr += length; - continue; /* With the main loop */ - } - - /* Handle repeated back references. If a set group has length zero, just - continue with the main loop, because it matches however many times. For an - unset reference, if the minimum is zero, we can also just continue. We an - also continue if PCRE2_MATCH_UNSET_BACKREF is set, because this makes unset - group be have as a zero-length group. For any other unset cases, carrying - on will result in NOMATCH. */ - - if (offset < offset_top && mb->ovector[offset] != PCRE2_UNSET) - { - if (mb->ovector[offset] == mb->ovector[offset + 1]) continue; - } - else /* Group is not set */ - { - if (min == 0 || (mb->poptions & PCRE2_MATCH_UNSET_BACKREF) != 0) - continue; - } - - /* First, ensure the minimum number of matches are present. */ - - for (i = 1; i <= min; i++) - { - PCRE2_SIZE slength; - int rc = match_ref(offset, offset_top, eptr, mb, caseless, &slength); - if (rc != 0) - { - if (rc > 0) eptr = mb->end_subject; /* Partial match */ - CHECK_PARTIAL(); - RRETURN(MATCH_NOMATCH); - } - eptr += slength; - } - /* If min = max, continue at the same level without recursion. - They are not both allowed to be zero. */ + if (Lmin == Lmax) continue; - if (min == max) continue; - - /* If minimizing, keep trying and advancing the pointer */ - - if (minimize) - { - for (fi = min;; fi++) + if (reptype == REPTYPE_MIN) { - int rc; - PCRE2_SIZE slength; - RMATCH(eptr, ecode, offset_top, mb, eptrb, RM14); - if (rrc != MATCH_NOMATCH) RRETURN(rrc); - if (fi >= max) RRETURN(MATCH_NOMATCH); - rc = match_ref(offset, offset_top, eptr, mb, caseless, &slength); - if (rc != 0) +#ifdef SUPPORT_UNICODE + if (utf) { - if (rc > 0) eptr = mb->end_subject; /* Partial match */ - CHECK_PARTIAL(); - RRETURN(MATCH_NOMATCH); + uint32_t d; + for (;;) + { + RMATCH(Fecode, RM206); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + if (Lmin++ >= Lmax) RRETURN(MATCH_NOMATCH); + if (Feptr >= mb->end_subject) + { + SCHECK_PARTIAL(); + RRETURN(MATCH_NOMATCH); + } + GETCHARINC(d, Feptr); + if (Lc == d) RRETURN(MATCH_NOMATCH); + } } - eptr += slength; - } - /* Control never gets here */ - } - - /* If maximizing, find the longest string and work backwards, as long as - the matched lengths for each iteration are the same. */ - - else - { - BOOL samelengths = TRUE; - pp = eptr; - length = mb->ovector[offset+1] - mb->ovector[offset]; - - for (i = min; i < max; i++) - { - PCRE2_SIZE slength; - int rc = match_ref(offset, offset_top, eptr, mb, caseless, &slength); - - if (rc != 0) + else +#endif + /* Not UTF mode */ { - /* Can't use CHECK_PARTIAL because we don't want to update eptr in - the soft partial matching case. */ - - if (rc > 0 && mb->partial != 0 && - mb->end_subject > mb->start_used_ptr) + for (;;) { - mb->hitend = TRUE; - if (mb->partial > 1) RRETURN(PCRE2_ERROR_PARTIAL); + RMATCH(Fecode, RM31); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + if (Lmin++ >= Lmax) RRETURN(MATCH_NOMATCH); + if (Feptr >= mb->end_subject) + { + SCHECK_PARTIAL(); + RRETURN(MATCH_NOMATCH); + } + if (Lc == *Feptr++) RRETURN(MATCH_NOMATCH); } - break; } - - if (slength != length) samelengths = FALSE; - eptr += slength; + /* Control never gets here */ } - /* If the length matched for each repetition is the same as the length of - the captured group, we can easily work backwards. This is the normal - case. However, in caseless UTF-8 mode there are pairs of case-equivalent - characters whose lengths (in terms of code units) differ. However, this - is very rare, so we handle it by re-matching fewer and fewer times. */ + /* Maximize case */ - if (samelengths) + else { - while (eptr >= pp) + Lstart_eptr = Feptr; + +#ifdef SUPPORT_UNICODE + if (utf) { - RMATCH(eptr, ecode, offset_top, mb, eptrb, RM15); - if (rrc != MATCH_NOMATCH) RRETURN(rrc); - eptr -= length; - } - } + uint32_t d; + for (i = Lmin; i < Lmax; i++) + { + int len = 1; + if (Feptr >= mb->end_subject) + { + SCHECK_PARTIAL(); + break; + } + GETCHARLEN(d, Feptr, len); + if (Lc == d) break; + Feptr += len; + } - /* The rare case of non-matching lengths. Re-scan the repetition for each - iteration. We know that match_ref() will succeed every time. */ + /* After \C in UTF mode, Lstart_eptr might be in the middle of a + Unicode character. Use <= Lstart_eptr to ensure backtracking doesn't + go too far. */ - else - { - max = i; - for (;;) + if (reptype != REPTYPE_POS) for(;;) + { + if (Feptr <= Lstart_eptr) break; + RMATCH(Fecode, RM207); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + Feptr--; + BACKCHAR(Feptr); + } + } + else +#endif + /* Not UTF mode */ { - RMATCH(eptr, ecode, offset_top, mb, eptrb, RM68); - if (rrc != MATCH_NOMATCH) RRETURN(rrc); - if (eptr == pp) break; /* Failed after minimal repetition */ - eptr = pp; - max--; - for (i = min; i < max; i++) + for (i = Lmin; i < Lmax; i++) { - PCRE2_SIZE slength; - (void)match_ref(offset, offset_top, eptr, mb, caseless, &slength); - eptr += slength; + if (Feptr >= mb->end_subject) + { + SCHECK_PARTIAL(); + break; + } + if (Lc == *Feptr) break; + Feptr++; + } + if (reptype != REPTYPE_POS) for (;;) + { + if (Feptr == Lstart_eptr) break; + RMATCH(Fecode, RM32); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + Feptr--; } } } - - RRETURN(MATCH_NOMATCH); } - /* Control never gets here */ + break; + +#undef Lstart_eptr +#undef Lmin +#undef Lmax +#undef Lc +#undef Loc - /* Match a bit-mapped character class, possibly repeatedly. This op code is - used when all the characters in the class have values in the range 0-255, - and either the matching is caseful, or the characters are in the range - 0-127 when UTF-8 processing is enabled. The only difference between + + /* ===================================================================== */ + /* Match a bit-mapped character class, possibly repeatedly. These op codes + are used when all the characters in the class have values in the range + 0-255, and either the matching is caseful, or the characters are in the + range 0-127 when UTF processing is enabled. The only difference between OP_CLASS and OP_NCLASS occurs when a data character outside the range is - encountered. + encountered. */ - First, look past the end of the item to see if there is repeat information - following. Then obey similar code to character type repeats - written out - again for speed. */ +#define Lmin F->temp_32[0] +#define Lmax F->temp_32[1] +#define Lstart_eptr F->temp_sptr[0] +#define Lbyte_map_address F->temp_sptr[1] +#define Lbyte_map ((unsigned char *)Lbyte_map_address) case OP_NCLASS: case OP_CLASS: { - /* The data variable is saved across frames, so the byte map needs to - be stored there. */ -#define BYTE_MAP ((uint8_t *)data) - data = ecode + 1; /* Save for matching */ - ecode += 1 + (32 / sizeof(PCRE2_UCHAR)); /* Advance past the item */ + Lbyte_map_address = Fecode + 1; /* Save for matching */ + Fecode += 1 + (32 / sizeof(PCRE2_UCHAR)); /* Advance past the item */ + + /* Look past the end of the item to see if there is repeat information + following. Then obey similar code to character type repeats. */ - switch (*ecode) + switch (*Fecode) { case OP_CRSTAR: case OP_CRMINSTAR: @@ -2994,27 +1809,24 @@ for (;;) case OP_CRPOSSTAR: case OP_CRPOSPLUS: case OP_CRPOSQUERY: - c = *ecode++ - OP_CRSTAR; - if (c < OP_CRPOSSTAR - OP_CRSTAR) minimize = (c & 1) != 0; - else possessive = TRUE; - min = rep_min[c]; /* Pick up values from tables; */ - max = rep_max[c]; /* zero for max => infinity */ - if (max == 0) max = INT_MAX; + fc = *Fecode++ - OP_CRSTAR; + Lmin = rep_min[fc]; + Lmax = rep_max[fc]; + reptype = rep_typ[fc]; break; case OP_CRRANGE: case OP_CRMINRANGE: case OP_CRPOSRANGE: - minimize = (*ecode == OP_CRMINRANGE); - possessive = (*ecode == OP_CRPOSRANGE); - min = GET2(ecode, 1); - max = GET2(ecode, 1 + IMM2_SIZE); - if (max == 0) max = INT_MAX; - ecode += 1 + 2 * IMM2_SIZE; + Lmin = GET2(Fecode, 1); + Lmax = GET2(Fecode, 1 + IMM2_SIZE); + if (Lmax == 0) Lmax = UINT32_MAX; /* Max 0 => infinity */ + reptype = rep_typ[*Fecode - OP_CRSTAR]; + Fecode += 1 + 2 * IMM2_SIZE; break; default: /* No repeat follows */ - min = max = 1; + Lmin = Lmax = 1; break; } @@ -3023,100 +1835,99 @@ for (;;) #ifdef SUPPORT_UNICODE if (utf) { - for (i = 1; i <= min; i++) + for (i = 1; i <= Lmin; i++) { - if (eptr >= mb->end_subject) + if (Feptr >= mb->end_subject) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } - GETCHARINC(c, eptr); - if (c > 255) + GETCHARINC(fc, Feptr); + if (fc > 255) { - if (op == OP_CLASS) RRETURN(MATCH_NOMATCH); + if (Fop == OP_CLASS) RRETURN(MATCH_NOMATCH); } else - if ((BYTE_MAP[c/8] & (1 << (c&7))) == 0) RRETURN(MATCH_NOMATCH); + if ((Lbyte_map[fc/8] & (1 << (fc&7))) == 0) RRETURN(MATCH_NOMATCH); } } else #endif /* Not UTF mode */ { - for (i = 1; i <= min; i++) + for (i = 1; i <= Lmin; i++) { - if (eptr >= mb->end_subject) + if (Feptr >= mb->end_subject) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } - c = *eptr++; + fc = *Feptr++; #if PCRE2_CODE_UNIT_WIDTH != 8 - if (c > 255) + if (fc > 255) { - if (op == OP_CLASS) RRETURN(MATCH_NOMATCH); + if (Fop == OP_CLASS) RRETURN(MATCH_NOMATCH); } else #endif - if ((BYTE_MAP[c/8] & (1 << (c&7))) == 0) RRETURN(MATCH_NOMATCH); + if ((Lbyte_map[fc/8] & (1 << (fc&7))) == 0) RRETURN(MATCH_NOMATCH); } } - /* If max == min we can continue with the main loop without the - need to recurse. */ + /* If Lmax == Lmin we are done. Continue with main loop. */ - if (min == max) continue; + if (Lmin == Lmax) continue; /* If minimizing, keep testing the rest of the expression and advancing the pointer while it matches the class. */ - if (minimize) + if (reptype == REPTYPE_MIN) { #ifdef SUPPORT_UNICODE if (utf) { - for (fi = min;; fi++) + for (;;) { - RMATCH(eptr, ecode, offset_top, mb, eptrb, RM16); + RMATCH(Fecode, RM200); if (rrc != MATCH_NOMATCH) RRETURN(rrc); - if (fi >= max) RRETURN(MATCH_NOMATCH); - if (eptr >= mb->end_subject) + if (Lmin++ >= Lmax) RRETURN(MATCH_NOMATCH); + if (Feptr >= mb->end_subject) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } - GETCHARINC(c, eptr); - if (c > 255) + GETCHARINC(fc, Feptr); + if (fc > 255) { - if (op == OP_CLASS) RRETURN(MATCH_NOMATCH); + if (Fop == OP_CLASS) RRETURN(MATCH_NOMATCH); } else - if ((BYTE_MAP[c/8] & (1 << (c&7))) == 0) RRETURN(MATCH_NOMATCH); + if ((Lbyte_map[fc/8] & (1 << (fc&7))) == 0) RRETURN(MATCH_NOMATCH); } } else #endif /* Not UTF mode */ { - for (fi = min;; fi++) + for (;;) { - RMATCH(eptr, ecode, offset_top, mb, eptrb, RM17); + RMATCH(Fecode, RM23); if (rrc != MATCH_NOMATCH) RRETURN(rrc); - if (fi >= max) RRETURN(MATCH_NOMATCH); - if (eptr >= mb->end_subject) + if (Lmin++ >= Lmax) RRETURN(MATCH_NOMATCH); + if (Feptr >= mb->end_subject) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } - c = *eptr++; + fc = *Feptr++; #if PCRE2_CODE_UNIT_WIDTH != 8 - if (c > 255) + if (fc > 255) { - if (op == OP_CLASS) RRETURN(MATCH_NOMATCH); + if (Fop == OP_CLASS) RRETURN(MATCH_NOMATCH); } else #endif - if ((BYTE_MAP[c/8] & (1 << (c&7))) == 0) RRETURN(MATCH_NOMATCH); + if ((Lbyte_map[fc/8] & (1 << (fc&7))) == 0) RRETURN(MATCH_NOMATCH); } } /* Control never gets here */ @@ -3126,91 +1937,102 @@ for (;;) else { - pp = eptr; + Lstart_eptr = Feptr; #ifdef SUPPORT_UNICODE if (utf) { - for (i = min; i < max; i++) + for (i = Lmin; i < Lmax; i++) { int len = 1; - if (eptr >= mb->end_subject) + if (Feptr >= mb->end_subject) { SCHECK_PARTIAL(); break; } - GETCHARLEN(c, eptr, len); - if (c > 255) + GETCHARLEN(fc, Feptr, len); + if (fc > 255) { - if (op == OP_CLASS) break; + if (Fop == OP_CLASS) break; } else - if ((BYTE_MAP[c/8] & (1 << (c&7))) == 0) break; - eptr += len; + if ((Lbyte_map[fc/8] & (1 << (fc&7))) == 0) break; + Feptr += len; } - if (possessive) continue; /* No backtracking */ + if (reptype == REPTYPE_POS) continue; /* No backtracking */ for (;;) { - RMATCH(eptr, ecode, offset_top, mb, eptrb, RM18); + RMATCH(Fecode, RM201); if (rrc != MATCH_NOMATCH) RRETURN(rrc); - if (eptr-- == pp) break; /* Stop if tried at original pos */ - BACKCHAR(eptr); + if (Feptr-- == Lstart_eptr) break; /* Tried at original position */ + BACKCHAR(Feptr); } } else #endif /* Not UTF mode */ { - for (i = min; i < max; i++) + for (i = Lmin; i < Lmax; i++) { - if (eptr >= mb->end_subject) + if (Feptr >= mb->end_subject) { SCHECK_PARTIAL(); break; } - c = *eptr; + fc = *Feptr; #if PCRE2_CODE_UNIT_WIDTH != 8 - if (c > 255) + if (fc > 255) { - if (op == OP_CLASS) break; + if (Fop == OP_CLASS) break; } else #endif - if ((BYTE_MAP[c/8] & (1 << (c&7))) == 0) break; - eptr++; + if ((Lbyte_map[fc/8] & (1 << (fc&7))) == 0) break; + Feptr++; } - if (possessive) continue; /* No backtracking */ + if (reptype == REPTYPE_POS) continue; /* No backtracking */ - while (eptr >= pp) + while (Feptr >= Lstart_eptr) { - RMATCH(eptr, ecode, offset_top, mb, eptrb, RM19); + RMATCH(Fecode, RM24); if (rrc != MATCH_NOMATCH) RRETURN(rrc); - eptr--; + Feptr--; } } RRETURN(MATCH_NOMATCH); } -#undef BYTE_MAP } /* Control never gets here */ +#undef Lbyte_map_address +#undef Lbyte_map +#undef Lstart_eptr +#undef Lmin +#undef Lmax + + /* ===================================================================== */ /* Match an extended character class. In the 8-bit library, this opcode is encountered only when UTF-8 mode mode is supported. In the 16-bit and 32-bit libraries, codepoints greater than 255 may be encountered even when UTF is not supported. */ +#define Lstart_eptr F->temp_sptr[0] +#define Lxclass_data F->temp_sptr[1] +#define Lmin F->temp_32[0] +#define Lmax F->temp_32[1] + #ifdef SUPPORT_WIDE_CHARS case OP_XCLASS: { - data = ecode + 1 + LINK_SIZE; /* Save for matching */ - ecode += GET(ecode, 1); /* Advance past the item */ + Lxclass_data = Fecode + 1 + LINK_SIZE; /* Save for matching */ + Fecode += GET(Fecode, 1); /* Advance past the item */ - switch (*ecode) + switch (*Fecode) { case OP_CRSTAR: case OP_CRMINSTAR: @@ -3221,65 +2043,61 @@ for (;;) case OP_CRPOSSTAR: case OP_CRPOSPLUS: case OP_CRPOSQUERY: - c = *ecode++ - OP_CRSTAR; - if (c < OP_CRPOSSTAR - OP_CRSTAR) minimize = (c & 1) != 0; - else possessive = TRUE; - min = rep_min[c]; /* Pick up values from tables; */ - max = rep_max[c]; /* zero for max => infinity */ - if (max == 0) max = INT_MAX; + fc = *Fecode++ - OP_CRSTAR; + Lmin = rep_min[fc]; + Lmax = rep_max[fc]; + reptype = rep_typ[fc]; break; case OP_CRRANGE: case OP_CRMINRANGE: case OP_CRPOSRANGE: - minimize = (*ecode == OP_CRMINRANGE); - possessive = (*ecode == OP_CRPOSRANGE); - min = GET2(ecode, 1); - max = GET2(ecode, 1 + IMM2_SIZE); - if (max == 0) max = INT_MAX; - ecode += 1 + 2 * IMM2_SIZE; + Lmin = GET2(Fecode, 1); + Lmax = GET2(Fecode, 1 + IMM2_SIZE); + if (Lmax == 0) Lmax = UINT32_MAX; /* Max 0 => infinity */ + reptype = rep_typ[*Fecode - OP_CRSTAR]; + Fecode += 1 + 2 * IMM2_SIZE; break; default: /* No repeat follows */ - min = max = 1; + Lmin = Lmax = 1; break; } /* First, ensure the minimum number of matches are present. */ - for (i = 1; i <= min; i++) + for (i = 1; i <= Lmin; i++) { - if (eptr >= mb->end_subject) + if (Feptr >= mb->end_subject) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } - GETCHARINCTEST(c, eptr); - if (!PRIV(xclass)(c, data, utf)) RRETURN(MATCH_NOMATCH); + GETCHARINCTEST(fc, Feptr); + if (!PRIV(xclass)(fc, Lxclass_data, utf)) RRETURN(MATCH_NOMATCH); } - /* If max == min we can continue with the main loop without the - need to recurse. */ + /* If Lmax == Lmin we can just continue with the main loop. */ - if (min == max) continue; + if (Lmin == Lmax) continue; /* If minimizing, keep testing the rest of the expression and advancing the pointer while it matches the class. */ - if (minimize) + if (reptype == REPTYPE_MIN) { - for (fi = min;; fi++) + for (;;) { - RMATCH(eptr, ecode, offset_top, mb, eptrb, RM20); + RMATCH(Fecode, RM100); if (rrc != MATCH_NOMATCH) RRETURN(rrc); - if (fi >= max) RRETURN(MATCH_NOMATCH); - if (eptr >= mb->end_subject) + if (Lmin++ >= Lmax) RRETURN(MATCH_NOMATCH); + if (Feptr >= mb->end_subject) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } - GETCHARINCTEST(c, eptr); - if (!PRIV(xclass)(c, data, utf)) RRETURN(MATCH_NOMATCH); + GETCHARINCTEST(fc, Feptr); + if (!PRIV(xclass)(fc, Lxclass_data, utf)) RRETURN(MATCH_NOMATCH); } /* Control never gets here */ } @@ -3288,33 +2106,33 @@ for (;;) else { - pp = eptr; - for (i = min; i < max; i++) + Lstart_eptr = Feptr; + for (i = Lmin; i < Lmax; i++) { int len = 1; - if (eptr >= mb->end_subject) + if (Feptr >= mb->end_subject) { SCHECK_PARTIAL(); break; } #ifdef SUPPORT_UNICODE - GETCHARLENTEST(c, eptr, len); + GETCHARLENTEST(fc, Feptr, len); #else - c = *eptr; + fc = *Feptr; #endif - if (!PRIV(xclass)(c, data, utf)) break; - eptr += len; + if (!PRIV(xclass)(fc, Lxclass_data, utf)) break; + Feptr += len; } - if (possessive) continue; /* No backtracking */ + if (reptype == REPTYPE_POS) continue; /* No backtracking */ for(;;) { - RMATCH(eptr, ecode, offset_top, mb, eptrb, RM21); + RMATCH(Fecode, RM101); if (rrc != MATCH_NOMATCH) RRETURN(rrc); - if (eptr-- == pp) break; /* Stop if tried at original pos */ + if (Feptr-- == Lstart_eptr) break; /* Tried at original position */ #ifdef SUPPORT_UNICODE - if (utf) BACKCHAR(eptr); + if (utf) BACKCHAR(Feptr); #endif } RRETURN(MATCH_NOMATCH); @@ -3322,887 +2140,370 @@ for (;;) /* Control never gets here */ } -#endif /* End of XCLASS */ +#endif /* SUPPORT_WIDE_CHARS: end of XCLASS */ - /* Match a single character, casefully */ +#undef Lstart_eptr +#undef Lxclass_data +#undef Lmin +#undef Lmax - case OP_CHAR: -#ifdef SUPPORT_UNICODE - if (utf) + + /* ===================================================================== */ + /* Match various character types when PCRE2_UCP is not set. These opcodes + are not generated when PCRE2_UCP is set - instead appropriate property + tests are compiled. */ + + case OP_NOT_DIGIT: + if (Feptr >= mb->end_subject) { - length = 1; - ecode++; - GETCHARLEN(fc, ecode, length); - if (length > (PCRE2_SIZE)(mb->end_subject - eptr)) - { - CHECK_PARTIAL(); /* Not SCHECK_PARTIAL() */ - RRETURN(MATCH_NOMATCH); - } - for (; length > 0; length--) - { - if (*ecode++ != UCHAR21INC(eptr)) RRETURN(MATCH_NOMATCH); - } + SCHECK_PARTIAL(); + RRETURN(MATCH_NOMATCH); } - else -#endif - /* Not UTF mode */ + GETCHARINCTEST(fc, Feptr); + if (CHMAX_255(fc) && (mb->ctypes[fc] & ctype_digit) != 0) + RRETURN(MATCH_NOMATCH); + Fecode++; + break; + + case OP_DIGIT: + if (Feptr >= mb->end_subject) { - if (mb->end_subject - eptr < 1) - { - SCHECK_PARTIAL(); /* This one can use SCHECK_PARTIAL() */ - RRETURN(MATCH_NOMATCH); - } - if (ecode[1] != *eptr++) RRETURN(MATCH_NOMATCH); - ecode += 2; + SCHECK_PARTIAL(); + RRETURN(MATCH_NOMATCH); } + GETCHARINCTEST(fc, Feptr); + if (!CHMAX_255(fc) || (mb->ctypes[fc] & ctype_digit) == 0) + RRETURN(MATCH_NOMATCH); + Fecode++; break; - /* Match a single character, caselessly. If we are at the end of the - subject, give up immediately. */ - - case OP_CHARI: - if (eptr >= mb->end_subject) + case OP_NOT_WHITESPACE: + if (Feptr >= mb->end_subject) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } + GETCHARINCTEST(fc, Feptr); + if (CHMAX_255(fc) && (mb->ctypes[fc] & ctype_space) != 0) + RRETURN(MATCH_NOMATCH); + Fecode++; + break; -#ifdef SUPPORT_UNICODE - if (utf) + case OP_WHITESPACE: + if (Feptr >= mb->end_subject) { - length = 1; - ecode++; - GETCHARLEN(fc, ecode, length); - - /* If the pattern character's value is < 128, we have only one byte, and - we know that its other case must also be one byte long, so we can use the - fast lookup table. We know that there is at least one byte left in the - subject. */ - - if (fc < 128) - { - uint32_t cc = UCHAR21(eptr); - if (mb->lcc[fc] != TABLE_GET(cc, mb->lcc, cc)) RRETURN(MATCH_NOMATCH); - ecode++; - eptr++; - } - - /* Otherwise we must pick up the subject character. Note that we cannot - use the value of "length" to check for sufficient bytes left, because the - other case of the character may have more or fewer bytes. */ - - else - { - uint32_t dc; - GETCHARINC(dc, eptr); - ecode += length; - - /* If we have Unicode property support, we can use it to test the other - case of the character, if there is one. */ - - if (fc != dc) - { -#ifdef SUPPORT_UNICODE - if (dc != UCD_OTHERCASE(fc)) -#endif - RRETURN(MATCH_NOMATCH); - } - } + SCHECK_PARTIAL(); + RRETURN(MATCH_NOMATCH); } - else -#endif /* SUPPORT_UNICODE */ + GETCHARINCTEST(fc, Feptr); + if (!CHMAX_255(fc) || (mb->ctypes[fc] & ctype_space) == 0) + RRETURN(MATCH_NOMATCH); + Fecode++; + break; - /* Not UTF mode */ + case OP_NOT_WORDCHAR: + if (Feptr >= mb->end_subject) { - if (TABLE_GET(ecode[1], mb->lcc, ecode[1]) - != TABLE_GET(*eptr, mb->lcc, *eptr)) RRETURN(MATCH_NOMATCH); - eptr++; - ecode += 2; + SCHECK_PARTIAL(); + RRETURN(MATCH_NOMATCH); } + GETCHARINCTEST(fc, Feptr); + if (CHMAX_255(fc) && (mb->ctypes[fc] & ctype_word) != 0) + RRETURN(MATCH_NOMATCH); + Fecode++; break; - /* Match a single character repeatedly. */ - - case OP_EXACT: - case OP_EXACTI: - min = max = GET2(ecode, 1); - ecode += 1 + IMM2_SIZE; - goto REPEATCHAR; - - case OP_POSUPTO: - case OP_POSUPTOI: - possessive = TRUE; - /* Fall through */ - - case OP_UPTO: - case OP_UPTOI: - case OP_MINUPTO: - case OP_MINUPTOI: - min = 0; - max = GET2(ecode, 1); - minimize = *ecode == OP_MINUPTO || *ecode == OP_MINUPTOI; - ecode += 1 + IMM2_SIZE; - goto REPEATCHAR; - - case OP_POSSTAR: - case OP_POSSTARI: - possessive = TRUE; - min = 0; - max = INT_MAX; - ecode++; - goto REPEATCHAR; - - case OP_POSPLUS: - case OP_POSPLUSI: - possessive = TRUE; - min = 1; - max = INT_MAX; - ecode++; - goto REPEATCHAR; - - case OP_POSQUERY: - case OP_POSQUERYI: - possessive = TRUE; - min = 0; - max = 1; - ecode++; - goto REPEATCHAR; - - case OP_STAR: - case OP_STARI: - case OP_MINSTAR: - case OP_MINSTARI: - case OP_PLUS: - case OP_PLUSI: - case OP_MINPLUS: - case OP_MINPLUSI: - case OP_QUERY: - case OP_QUERYI: - case OP_MINQUERY: - case OP_MINQUERYI: - c = *ecode++ - ((op < OP_STARI)? OP_STAR : OP_STARI); - minimize = (c & 1) != 0; - min = rep_min[c]; /* Pick up values from tables; */ - max = rep_max[c]; /* zero for max => infinity */ - if (max == 0) max = INT_MAX; - - /* Common code for all repeated single-character matches. We first check - for the minimum number of characters. If the minimum equals the maximum, we - are done. Otherwise, if minimizing, check the rest of the pattern for a - match; if there isn't one, advance up to the maximum, one character at a - time. - - If maximizing, advance up to the maximum number of matching characters, - until eptr is past the end of the maximum run. If possessive, we are - then done (no backing up). Otherwise, match at this position; anything - other than no match is immediately returned. For nomatch, back up one - character, unless we are matching \R and the last thing matched was - \r\n, in which case, back up two bytes. When we reach the first optional - character position, we can save stack by doing a tail recurse. - - The various UTF/non-UTF and caseful/caseless cases are handled separately, - for speed. */ - - REPEATCHAR: -#ifdef SUPPORT_UNICODE - if (utf) + case OP_WORDCHAR: + if (Feptr >= mb->end_subject) { - length = 1; - charptr = ecode; - GETCHARLEN(fc, ecode, length); - ecode += length; - - /* Handle multibyte character matching specially here. There is - support for caseless matching if UCP support is present. */ - - if (length > 1) - { - uint32_t othercase; - if (op >= OP_STARI && /* Caseless */ - (othercase = UCD_OTHERCASE(fc)) != fc) - oclength = PRIV(ord2utf)(othercase, occhars); - else oclength = 0; - - for (i = 1; i <= min; i++) - { - if (eptr <= mb->end_subject - length && - memcmp(eptr, charptr, CU2BYTES(length)) == 0) eptr += length; - else if (oclength > 0 && - eptr <= mb->end_subject - oclength && - memcmp(eptr, occhars, CU2BYTES(oclength)) == 0) eptr += oclength; - else - { - CHECK_PARTIAL(); - RRETURN(MATCH_NOMATCH); - } - } - - if (min == max) continue; - - if (minimize) - { - for (fi = min;; fi++) - { - RMATCH(eptr, ecode, offset_top, mb, eptrb, RM22); - if (rrc != MATCH_NOMATCH) RRETURN(rrc); - if (fi >= max) RRETURN(MATCH_NOMATCH); - if (eptr <= mb->end_subject - length && - memcmp(eptr, charptr, CU2BYTES(length)) == 0) eptr += length; - else if (oclength > 0 && - eptr <= mb->end_subject - oclength && - memcmp(eptr, occhars, CU2BYTES(oclength)) == 0) eptr += oclength; - else - { - CHECK_PARTIAL(); - RRETURN(MATCH_NOMATCH); - } - } - /* Control never gets here */ - } - - else /* Maximize */ - { - pp = eptr; - for (i = min; i < max; i++) - { - if (eptr <= mb->end_subject - length && - memcmp(eptr, charptr, CU2BYTES(length)) == 0) eptr += length; - else if (oclength > 0 && - eptr <= mb->end_subject - oclength && - memcmp(eptr, occhars, CU2BYTES(oclength)) == 0) eptr += oclength; - else - { - CHECK_PARTIAL(); - break; - } - } - - if (possessive) continue; /* No backtracking */ - - /* After \C in UTF mode, pp might be in the middle of a Unicode - character. Use <= pp to ensure backtracking doesn't go too far. */ - - for(;;) - { - if (eptr <= pp) goto TAIL_RECURSE; - RMATCH(eptr, ecode, offset_top, mb, eptrb, RM23); - if (rrc != MATCH_NOMATCH) RRETURN(rrc); - eptr--; - BACKCHAR(eptr); - } - } - /* Control never gets here */ - } - - /* If the length of a UTF-8 character is 1, we fall through here, and - obey the code as for non-UTF-8 characters below, though in this case the - value of fc will always be < 128. */ + SCHECK_PARTIAL(); + RRETURN(MATCH_NOMATCH); } - else -#endif /* SUPPORT_UNICODE */ - - /* When not in UTF-8 mode, load a single-byte character. */ - fc = *ecode++; - - /* The value of fc at this point is always one character, though we may - or may not be in UTF mode. The code is duplicated for the caseless and - caseful cases, for speed, since matching characters is likely to be quite - common. First, ensure the minimum number of matches are present. If min = - max, continue at the same level without recursing. Otherwise, if - minimizing, keep trying the rest of the expression and advancing one - matching character if failing, up to the maximum. Alternatively, if - maximizing, find the maximum number of characters and work backwards. */ + GETCHARINCTEST(fc, Feptr); + if (!CHMAX_255(fc) || (mb->ctypes[fc] & ctype_word) == 0) + RRETURN(MATCH_NOMATCH); + Fecode++; + break; - if (op >= OP_STARI) /* Caseless */ + case OP_ANYNL: + if (Feptr >= mb->end_subject) { -#if PCRE2_CODE_UNIT_WIDTH == 8 - /* fc must be < 128 if UTF is enabled. */ - foc = mb->fcc[fc]; -#else -#ifdef SUPPORT_UNICODE - if (utf && fc > 127) - foc = UCD_OTHERCASE(fc); - else -#endif /* SUPPORT_UNICODE */ - foc = TABLE_GET(fc, mb->fcc, fc); -#endif /* PCRE2_CODE_UNIT_WIDTH == 8 */ - - for (i = 1; i <= min; i++) - { - uint32_t cc; /* Faster than PCRE2_UCHAR */ - if (eptr >= mb->end_subject) - { - SCHECK_PARTIAL(); - RRETURN(MATCH_NOMATCH); - } - cc = UCHAR21TEST(eptr); - if (fc != cc && foc != cc) RRETURN(MATCH_NOMATCH); - eptr++; - } - if (min == max) continue; - if (minimize) - { - for (fi = min;; fi++) - { - uint32_t cc; /* Faster than PCRE2_UCHAR */ - RMATCH(eptr, ecode, offset_top, mb, eptrb, RM24); - if (rrc != MATCH_NOMATCH) RRETURN(rrc); - if (fi >= max) RRETURN(MATCH_NOMATCH); - if (eptr >= mb->end_subject) - { - SCHECK_PARTIAL(); - RRETURN(MATCH_NOMATCH); - } - cc = UCHAR21TEST(eptr); - if (fc != cc && foc != cc) RRETURN(MATCH_NOMATCH); - eptr++; - } - /* Control never gets here */ - } - else /* Maximize */ - { - pp = eptr; - for (i = min; i < max; i++) - { - uint32_t cc; /* Faster than PCRE2_UCHAR */ - if (eptr >= mb->end_subject) - { - SCHECK_PARTIAL(); - break; - } - cc = UCHAR21TEST(eptr); - if (fc != cc && foc != cc) break; - eptr++; - } - if (possessive) continue; /* No backtracking */ - for (;;) - { - if (eptr == pp) goto TAIL_RECURSE; - RMATCH(eptr, ecode, offset_top, mb, eptrb, RM25); - eptr--; - if (rrc != MATCH_NOMATCH) RRETURN(rrc); - } - /* Control never gets here */ - } + SCHECK_PARTIAL(); + RRETURN(MATCH_NOMATCH); } - - /* Caseful comparisons (includes all multi-byte characters) */ - - else + GETCHARINCTEST(fc, Feptr); + switch(fc) { - for (i = 1; i <= min; i++) + default: RRETURN(MATCH_NOMATCH); + + case CHAR_CR: + if (Feptr >= mb->end_subject) { - if (eptr >= mb->end_subject) - { - SCHECK_PARTIAL(); - RRETURN(MATCH_NOMATCH); - } - if (fc != UCHAR21INCTEST(eptr)) RRETURN(MATCH_NOMATCH); + SCHECK_PARTIAL(); } + else if (UCHAR21TEST(Feptr) == CHAR_LF) Feptr++; + break; - if (min == max) continue; + case CHAR_LF: + break; - if (minimize) - { - for (fi = min;; fi++) - { - RMATCH(eptr, ecode, offset_top, mb, eptrb, RM26); - if (rrc != MATCH_NOMATCH) RRETURN(rrc); - if (fi >= max) RRETURN(MATCH_NOMATCH); - if (eptr >= mb->end_subject) - { - SCHECK_PARTIAL(); - RRETURN(MATCH_NOMATCH); - } - if (fc != UCHAR21INCTEST(eptr)) RRETURN(MATCH_NOMATCH); - } - /* Control never gets here */ - } - else /* Maximize */ - { - pp = eptr; - for (i = min; i < max; i++) - { - if (eptr >= mb->end_subject) - { - SCHECK_PARTIAL(); - break; - } - if (fc != UCHAR21TEST(eptr)) break; - eptr++; - } - if (possessive) continue; /* No backtracking */ - for (;;) - { - if (eptr == pp) goto TAIL_RECURSE; - RMATCH(eptr, ecode, offset_top, mb, eptrb, RM27); - eptr--; - if (rrc != MATCH_NOMATCH) RRETURN(rrc); - } - /* Control never gets here */ - } + case CHAR_VT: + case CHAR_FF: + case CHAR_NEL: +#ifndef EBCDIC + case 0x2028: + case 0x2029: +#endif /* Not EBCDIC */ + if (mb->bsr_convention == PCRE2_BSR_ANYCRLF) RRETURN(MATCH_NOMATCH); + break; } - /* Control never gets here */ + Fecode++; + break; - /* Match a negated single one-byte character. The character we are - checking can be multibyte. */ + case OP_NOT_HSPACE: + if (Feptr >= mb->end_subject) + { + SCHECK_PARTIAL(); + RRETURN(MATCH_NOMATCH); + } + GETCHARINCTEST(fc, Feptr); + switch(fc) + { + HSPACE_CASES: RRETURN(MATCH_NOMATCH); /* Byte and multibyte cases */ + default: break; + } + Fecode++; + break; - case OP_NOT: - case OP_NOTI: - if (eptr >= mb->end_subject) + case OP_HSPACE: + if (Feptr >= mb->end_subject) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } -#ifdef SUPPORT_UNICODE - if (utf) + GETCHARINCTEST(fc, Feptr); + switch(fc) { - uint32_t ch, och; + HSPACE_CASES: break; /* Byte and multibyte cases */ + default: RRETURN(MATCH_NOMATCH); + } + Fecode++; + break; - ecode++; - GETCHARINC(ch, ecode); - GETCHARINC(c, eptr); + case OP_NOT_VSPACE: + if (Feptr >= mb->end_subject) + { + SCHECK_PARTIAL(); + RRETURN(MATCH_NOMATCH); + } + GETCHARINCTEST(fc, Feptr); + switch(fc) + { + VSPACE_CASES: RRETURN(MATCH_NOMATCH); + default: break; + } + Fecode++; + break; - if (op == OP_NOT) - { - if (ch == c) RRETURN(MATCH_NOMATCH); - } - else - { - if (ch > 127) - och = UCD_OTHERCASE(ch); - else - och = TABLE_GET(ch, mb->fcc, ch); - if (ch == c || och == c) RRETURN(MATCH_NOMATCH); - } + case OP_VSPACE: + if (Feptr >= mb->end_subject) + { + SCHECK_PARTIAL(); + RRETURN(MATCH_NOMATCH); } - else -#endif /* SUPPORT_UNICODE */ + GETCHARINCTEST(fc, Feptr); + switch(fc) { - uint32_t ch = ecode[1]; - c = *eptr++; - if (ch == c || (op == OP_NOTI && TABLE_GET(ch, mb->fcc, ch) == c)) - RRETURN(MATCH_NOMATCH); - ecode += 2; + VSPACE_CASES: break; + default: RRETURN(MATCH_NOMATCH); } + Fecode++; break; - /* Match a negated single one-byte character repeatedly. This is almost a - repeat of the code for a repeated single character, but I haven't found a - nice way of commoning these up that doesn't require a test of the - positive/negative option for each character match. Maybe that wouldn't add - very much to the time taken, but character matching *is* what this is all - about... */ - case OP_NOTEXACT: - case OP_NOTEXACTI: - min = max = GET2(ecode, 1); - ecode += 1 + IMM2_SIZE; - goto REPEATNOTCHAR; +#ifdef SUPPORT_UNICODE - case OP_NOTUPTO: - case OP_NOTUPTOI: - case OP_NOTMINUPTO: - case OP_NOTMINUPTOI: - min = 0; - max = GET2(ecode, 1); - minimize = *ecode == OP_NOTMINUPTO || *ecode == OP_NOTMINUPTOI; - ecode += 1 + IMM2_SIZE; - goto REPEATNOTCHAR; + /* ===================================================================== */ + /* Check the next character by Unicode property. We will get here only + if the support is in the binary; otherwise a compile-time error occurs. */ - case OP_NOTPOSSTAR: - case OP_NOTPOSSTARI: - possessive = TRUE; - min = 0; - max = INT_MAX; - ecode++; - goto REPEATNOTCHAR; + case OP_PROP: + case OP_NOTPROP: + if (Feptr >= mb->end_subject) + { + SCHECK_PARTIAL(); + RRETURN(MATCH_NOMATCH); + } + GETCHARINCTEST(fc, Feptr); + { + const uint32_t *cp; + const ucd_record *prop = GET_UCD(fc); - case OP_NOTPOSPLUS: - case OP_NOTPOSPLUSI: - possessive = TRUE; - min = 1; - max = INT_MAX; - ecode++; - goto REPEATNOTCHAR; + switch(Fecode[1]) + { + case PT_ANY: + if (Fop == OP_NOTPROP) RRETURN(MATCH_NOMATCH); + break; - case OP_NOTPOSQUERY: - case OP_NOTPOSQUERYI: - possessive = TRUE; - min = 0; - max = 1; - ecode++; - goto REPEATNOTCHAR; + case PT_LAMP: + if ((prop->chartype == ucp_Lu || + prop->chartype == ucp_Ll || + prop->chartype == ucp_Lt) == (Fop == OP_NOTPROP)) + RRETURN(MATCH_NOMATCH); + break; - case OP_NOTPOSUPTO: - case OP_NOTPOSUPTOI: - possessive = TRUE; - min = 0; - max = GET2(ecode, 1); - ecode += 1 + IMM2_SIZE; - goto REPEATNOTCHAR; + case PT_GC: + if ((Fecode[2] != PRIV(ucp_gentype)[prop->chartype]) == (Fop == OP_PROP)) + RRETURN(MATCH_NOMATCH); + break; - case OP_NOTSTAR: - case OP_NOTSTARI: - case OP_NOTMINSTAR: - case OP_NOTMINSTARI: - case OP_NOTPLUS: - case OP_NOTPLUSI: - case OP_NOTMINPLUS: - case OP_NOTMINPLUSI: - case OP_NOTQUERY: - case OP_NOTQUERYI: - case OP_NOTMINQUERY: - case OP_NOTMINQUERYI: - c = *ecode++ - ((op >= OP_NOTSTARI)? OP_NOTSTARI: OP_NOTSTAR); - minimize = (c & 1) != 0; - min = rep_min[c]; /* Pick up values from tables; */ - max = rep_max[c]; /* zero for max => infinity */ - if (max == 0) max = INT_MAX; + case PT_PC: + if ((Fecode[2] != prop->chartype) == (Fop == OP_PROP)) + RRETURN(MATCH_NOMATCH); + break; - /* Common code for all repeated single-byte matches. */ + case PT_SC: + if ((Fecode[2] != prop->script) == (Fop == OP_PROP)) + RRETURN(MATCH_NOMATCH); + break; - REPEATNOTCHAR: - GETCHARINCTEST(fc, ecode); + /* These are specials */ - /* The code is duplicated for the caseless and caseful cases, for speed, - since matching characters is likely to be quite common. First, ensure the - minimum number of matches are present. If min = max, continue at the same - level without recursing. Otherwise, if minimizing, keep trying the rest of - the expression and advancing one matching character if failing, up to the - maximum. Alternatively, if maximizing, find the maximum number of - characters and work backwards. */ + case PT_ALNUM: + if ((PRIV(ucp_gentype)[prop->chartype] == ucp_L || + PRIV(ucp_gentype)[prop->chartype] == ucp_N) == (Fop == OP_NOTPROP)) + RRETURN(MATCH_NOMATCH); + break; - if (op >= OP_NOTSTARI) /* Caseless */ - { -#ifdef SUPPORT_UNICODE - if (utf && fc > 127) - foc = UCD_OTHERCASE(fc); - else -#endif /* SUPPORT_UNICODE */ - foc = TABLE_GET(fc, mb->fcc, fc); + /* Perl space used to exclude VT, but from Perl 5.18 it is included, + which means that Perl space and POSIX space are now identical. PCRE + was changed at release 8.34. */ -#ifdef SUPPORT_UNICODE - if (utf) - { - uint32_t d; - for (i = 1; i <= min; i++) - { - if (eptr >= mb->end_subject) - { - SCHECK_PARTIAL(); - RRETURN(MATCH_NOMATCH); - } - GETCHARINC(d, eptr); - if (fc == d || (uint32_t)foc == d) RRETURN(MATCH_NOMATCH); - } - } - else -#endif /* SUPPORT_UNICODE */ - /* Not UTF mode */ - { - for (i = 1; i <= min; i++) + case PT_SPACE: /* Perl space */ + case PT_PXSPACE: /* POSIX space */ + switch(fc) { - if (eptr >= mb->end_subject) - { - SCHECK_PARTIAL(); - RRETURN(MATCH_NOMATCH); - } - if (fc == *eptr || foc == *eptr) RRETURN(MATCH_NOMATCH); - eptr++; + HSPACE_CASES: + VSPACE_CASES: + if (Fop == OP_NOTPROP) RRETURN(MATCH_NOMATCH); + break; + + default: + if ((PRIV(ucp_gentype)[prop->chartype] == ucp_Z) == + (Fop == OP_NOTPROP)) RRETURN(MATCH_NOMATCH); + break; } - } + break; - if (min == max) continue; + case PT_WORD: + if ((PRIV(ucp_gentype)[prop->chartype] == ucp_L || + PRIV(ucp_gentype)[prop->chartype] == ucp_N || + fc == CHAR_UNDERSCORE) == (Fop == OP_NOTPROP)) + RRETURN(MATCH_NOMATCH); + break; - if (minimize) - { -#ifdef SUPPORT_UNICODE - if (utf) - { - uint32_t d; - for (fi = min;; fi++) - { - RMATCH(eptr, ecode, offset_top, mb, eptrb, RM28); - if (rrc != MATCH_NOMATCH) RRETURN(rrc); - if (fi >= max) RRETURN(MATCH_NOMATCH); - if (eptr >= mb->end_subject) - { - SCHECK_PARTIAL(); - RRETURN(MATCH_NOMATCH); - } - GETCHARINC(d, eptr); - if (fc == d || (uint32_t)foc == d) RRETURN(MATCH_NOMATCH); - } - } - else -#endif /*SUPPORT_UNICODE */ - /* Not UTF mode */ + case PT_CLIST: + cp = PRIV(ucd_caseless_sets) + Fecode[2]; + for (;;) { - for (fi = min;; fi++) - { - RMATCH(eptr, ecode, offset_top, mb, eptrb, RM29); - if (rrc != MATCH_NOMATCH) RRETURN(rrc); - if (fi >= max) RRETURN(MATCH_NOMATCH); - if (eptr >= mb->end_subject) - { - SCHECK_PARTIAL(); - RRETURN(MATCH_NOMATCH); - } - if (fc == *eptr || foc == *eptr) RRETURN(MATCH_NOMATCH); - eptr++; - } + if (fc < *cp) + { if (Fop == OP_PROP) { RRETURN(MATCH_NOMATCH); } else break; } + if (fc == *cp++) + { if (Fop == OP_PROP) break; else { RRETURN(MATCH_NOMATCH); } } } - /* Control never gets here */ - } - - /* Maximize case */ - - else - { - pp = eptr; + break; -#ifdef SUPPORT_UNICODE - if (utf) - { - uint32_t d; - for (i = min; i < max; i++) - { - int len = 1; - if (eptr >= mb->end_subject) - { - SCHECK_PARTIAL(); - break; - } - GETCHARLEN(d, eptr, len); - if (fc == d || (uint32_t)foc == d) break; - eptr += len; - } - if (possessive) continue; /* No backtracking */ + case PT_UCNC: + if ((fc == CHAR_DOLLAR_SIGN || fc == CHAR_COMMERCIAL_AT || + fc == CHAR_GRAVE_ACCENT || (fc >= 0xa0 && fc <= 0xd7ff) || + fc >= 0xe000) == (Fop == OP_NOTPROP)) + RRETURN(MATCH_NOMATCH); + break; - /* After \C in UTF mode, pp might be in the middle of a Unicode - character. Use <= pp to ensure backtracking doesn't go too far. */ + /* This should never occur */ - for(;;) - { - if (eptr <= pp) goto TAIL_RECURSE; - RMATCH(eptr, ecode, offset_top, mb, eptrb, RM30); - if (rrc != MATCH_NOMATCH) RRETURN(rrc); - eptr--; - BACKCHAR(eptr); - } - } - else -#endif /* SUPPORT_UNICODE */ - /* Not UTF mode */ - { - for (i = min; i < max; i++) - { - if (eptr >= mb->end_subject) - { - SCHECK_PARTIAL(); - break; - } - if (fc == *eptr || foc == *eptr) break; - eptr++; - } - if (possessive) continue; /* No backtracking */ - for (;;) - { - if (eptr == pp) goto TAIL_RECURSE; - RMATCH(eptr, ecode, offset_top, mb, eptrb, RM31); - if (rrc != MATCH_NOMATCH) RRETURN(rrc); - eptr--; - } - } - /* Control never gets here */ + default: + return PCRE2_ERROR_INTERNAL; } + + Fecode += 3; } + break; - /* Caseful comparisons */ + /* ===================================================================== */ + /* Match an extended Unicode sequence. We will get here only if the support + is in the binary; otherwise a compile-time error occurs. */ + + case OP_EXTUNI: + if (Feptr >= mb->end_subject) + { + SCHECK_PARTIAL(); + RRETURN(MATCH_NOMATCH); + } else { -#ifdef SUPPORT_UNICODE - if (utf) - { - uint32_t d; - for (i = 1; i <= min; i++) - { - if (eptr >= mb->end_subject) - { - SCHECK_PARTIAL(); - RRETURN(MATCH_NOMATCH); - } - GETCHARINC(d, eptr); - if (fc == d) RRETURN(MATCH_NOMATCH); - } - } - else -#endif - /* Not UTF mode */ - { - for (i = 1; i <= min; i++) - { - if (eptr >= mb->end_subject) - { - SCHECK_PARTIAL(); - RRETURN(MATCH_NOMATCH); - } - if (fc == *eptr++) RRETURN(MATCH_NOMATCH); - } - } - - if (min == max) continue; - - if (minimize) - { -#ifdef SUPPORT_UNICODE - if (utf) - { - uint32_t d; - for (fi = min;; fi++) - { - RMATCH(eptr, ecode, offset_top, mb, eptrb, RM32); - if (rrc != MATCH_NOMATCH) RRETURN(rrc); - if (fi >= max) RRETURN(MATCH_NOMATCH); - if (eptr >= mb->end_subject) - { - SCHECK_PARTIAL(); - RRETURN(MATCH_NOMATCH); - } - GETCHARINC(d, eptr); - if (fc == d) RRETURN(MATCH_NOMATCH); - } - } - else -#endif - /* Not UTF mode */ - { - for (fi = min;; fi++) - { - RMATCH(eptr, ecode, offset_top, mb, eptrb, RM33); - if (rrc != MATCH_NOMATCH) RRETURN(rrc); - if (fi >= max) RRETURN(MATCH_NOMATCH); - if (eptr >= mb->end_subject) - { - SCHECK_PARTIAL(); - RRETURN(MATCH_NOMATCH); - } - if (fc == *eptr++) RRETURN(MATCH_NOMATCH); - } - } - /* Control never gets here */ - } - - /* Maximize case */ - - else - { - pp = eptr; + GETCHARINCTEST(fc, Feptr); + Feptr = PRIV(extuni)(fc, Feptr, mb->start_subject, mb->end_subject, utf, + NULL); + } + CHECK_PARTIAL(); + Fecode++; + break; -#ifdef SUPPORT_UNICODE - if (utf) - { - uint32_t d; - for (i = min; i < max; i++) - { - int len = 1; - if (eptr >= mb->end_subject) - { - SCHECK_PARTIAL(); - break; - } - GETCHARLEN(d, eptr, len); - if (fc == d) break; - eptr += len; - } - if (possessive) continue; /* No backtracking */ +#endif /* SUPPORT_UNICODE */ - /* After \C in UTF mode, pp might be in the middle of a Unicode - character. Use <= pp to ensure backtracking doesn't go too far. */ - for(;;) - { - if (eptr <= pp) goto TAIL_RECURSE; - RMATCH(eptr, ecode, offset_top, mb, eptrb, RM34); - if (rrc != MATCH_NOMATCH) RRETURN(rrc); - eptr--; - BACKCHAR(eptr); - } - } - else -#endif - /* Not UTF mode */ - { - for (i = min; i < max; i++) - { - if (eptr >= mb->end_subject) - { - SCHECK_PARTIAL(); - break; - } - if (fc == *eptr) break; - eptr++; - } - if (possessive) continue; /* No backtracking */ - for (;;) - { - if (eptr == pp) goto TAIL_RECURSE; - RMATCH(eptr, ecode, offset_top, mb, eptrb, RM35); - if (rrc != MATCH_NOMATCH) RRETURN(rrc); - eptr--; - } - } - /* Control never gets here */ - } - } - /* Control never gets here */ + /* ===================================================================== */ + /* Match a single character type repeatedly. Note that the property type + does not need to be in a stack frame as it not used within an RMATCH() + loop. */ - /* Match a single character type repeatedly; several different opcodes - share code. This is very similar to the code for single characters, but we - repeat it in the interests of efficiency. */ +#define Lstart_eptr F->temp_sptr[0] +#define Lmin F->temp_32[0] +#define Lmax F->temp_32[1] +#define Lctype F->temp_32[2] +#define Lpropvalue F->temp_32[3] case OP_TYPEEXACT: - min = max = GET2(ecode, 1); - minimize = TRUE; - ecode += 1 + IMM2_SIZE; + Lmin = Lmax = GET2(Fecode, 1); + Fecode += 1 + IMM2_SIZE; goto REPEATTYPE; case OP_TYPEUPTO: case OP_TYPEMINUPTO: - min = 0; - max = GET2(ecode, 1); - minimize = *ecode == OP_TYPEMINUPTO; - ecode += 1 + IMM2_SIZE; + Lmin = 0; + Lmax = GET2(Fecode, 1); + reptype = (*Fecode == OP_TYPEMINUPTO)? REPTYPE_MIN : REPTYPE_MAX; + Fecode += 1 + IMM2_SIZE; goto REPEATTYPE; case OP_TYPEPOSSTAR: - possessive = TRUE; - min = 0; - max = INT_MAX; - ecode++; + reptype = REPTYPE_POS; + Lmin = 0; + Lmax = UINT32_MAX; + Fecode++; goto REPEATTYPE; case OP_TYPEPOSPLUS: - possessive = TRUE; - min = 1; - max = INT_MAX; - ecode++; + reptype = REPTYPE_POS; + Lmin = 1; + Lmax = UINT32_MAX; + Fecode++; goto REPEATTYPE; case OP_TYPEPOSQUERY: - possessive = TRUE; - min = 0; - max = 1; - ecode++; + reptype = REPTYPE_POS; + Lmin = 0; + Lmax = 1; + Fecode++; goto REPEATTYPE; case OP_TYPEPOSUPTO: - possessive = TRUE; - min = 0; - max = GET2(ecode, 1); - ecode += 1 + IMM2_SIZE; + reptype = REPTYPE_POS; + Lmin = 0; + Lmax = GET2(Fecode, 1); + Fecode += 1 + IMM2_SIZE; goto REPEATTYPE; case OP_TYPESTAR: @@ -4211,127 +2512,122 @@ for (;;) case OP_TYPEMINPLUS: case OP_TYPEQUERY: case OP_TYPEMINQUERY: - c = *ecode++ - OP_TYPESTAR; - minimize = (c & 1) != 0; - min = rep_min[c]; /* Pick up values from tables; */ - max = rep_max[c]; /* zero for max => infinity */ - if (max == 0) max = INT_MAX; + fc = *Fecode++ - OP_TYPESTAR; + Lmin = rep_min[fc]; + Lmax = rep_max[fc]; + reptype = rep_typ[fc]; - /* Common code for all repeated single character type matches. Note that - in UTF-8 mode, '.' matches a character of any length, but for the other - character types, the valid characters are all one-byte long. */ + /* Common code for all repeated character type matches. */ REPEATTYPE: - ctype = *ecode++; /* Code for the character type */ + Lctype = *Fecode++; /* Code for the character type */ #ifdef SUPPORT_UNICODE - if (ctype == OP_PROP || ctype == OP_NOTPROP) + if (Lctype == OP_PROP || Lctype == OP_NOTPROP) { - prop_fail_result = ctype == OP_NOTPROP; - prop_type = *ecode++; - prop_value = *ecode++; + proptype = *Fecode++; + Lpropvalue = *Fecode++; } - else prop_type = -1; + else proptype = -1; #endif /* First, ensure the minimum number of matches are present. Use inline code for maximizing the speed, and do the type test once at the start - (i.e. keep it out of the loop). Separate the UTF-8 code completely as that - is tidier. Also separate the UCP code, which can be the same for both UTF-8 - and single-bytes. */ + (i.e. keep it out of the loop). The code for UTF mode is separated out for + tidiness, except for Unicode property tests. */ - if (min > 0) + if (Lmin > 0) { #ifdef SUPPORT_UNICODE - if (prop_type >= 0) + if (proptype >= 0) /* Property tests in all modes */ { - switch(prop_type) + switch(proptype) { case PT_ANY: - if (prop_fail_result) RRETURN(MATCH_NOMATCH); - for (i = 1; i <= min; i++) + if (Lctype == OP_NOTPROP) RRETURN(MATCH_NOMATCH); + for (i = 1; i <= Lmin; i++) { - if (eptr >= mb->end_subject) + if (Feptr >= mb->end_subject) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } - GETCHARINCTEST(c, eptr); + GETCHARINCTEST(fc, Feptr); } break; case PT_LAMP: - for (i = 1; i <= min; i++) + for (i = 1; i <= Lmin; i++) { int chartype; - if (eptr >= mb->end_subject) + if (Feptr >= mb->end_subject) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } - GETCHARINCTEST(c, eptr); - chartype = UCD_CHARTYPE(c); + GETCHARINCTEST(fc, Feptr); + chartype = UCD_CHARTYPE(fc); if ((chartype == ucp_Lu || chartype == ucp_Ll || - chartype == ucp_Lt) == prop_fail_result) + chartype == ucp_Lt) == (Lctype == OP_NOTPROP)) RRETURN(MATCH_NOMATCH); } break; case PT_GC: - for (i = 1; i <= min; i++) + for (i = 1; i <= Lmin; i++) { - if (eptr >= mb->end_subject) + if (Feptr >= mb->end_subject) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } - GETCHARINCTEST(c, eptr); - if ((UCD_CATEGORY(c) == prop_value) == prop_fail_result) + GETCHARINCTEST(fc, Feptr); + if ((UCD_CATEGORY(fc) == Lpropvalue) == (Lctype == OP_NOTPROP)) RRETURN(MATCH_NOMATCH); } break; case PT_PC: - for (i = 1; i <= min; i++) + for (i = 1; i <= Lmin; i++) { - if (eptr >= mb->end_subject) + if (Feptr >= mb->end_subject) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } - GETCHARINCTEST(c, eptr); - if ((UCD_CHARTYPE(c) == prop_value) == prop_fail_result) + GETCHARINCTEST(fc, Feptr); + if ((UCD_CHARTYPE(fc) == Lpropvalue) == (Lctype == OP_NOTPROP)) RRETURN(MATCH_NOMATCH); } break; case PT_SC: - for (i = 1; i <= min; i++) + for (i = 1; i <= Lmin; i++) { - if (eptr >= mb->end_subject) + if (Feptr >= mb->end_subject) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } - GETCHARINCTEST(c, eptr); - if ((UCD_SCRIPT(c) == prop_value) == prop_fail_result) + GETCHARINCTEST(fc, Feptr); + if ((UCD_SCRIPT(fc) == Lpropvalue) == (Lctype == OP_NOTPROP)) RRETURN(MATCH_NOMATCH); } break; case PT_ALNUM: - for (i = 1; i <= min; i++) + for (i = 1; i <= Lmin; i++) { int category; - if (eptr >= mb->end_subject) + if (Feptr >= mb->end_subject) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } - GETCHARINCTEST(c, eptr); - category = UCD_CATEGORY(c); - if ((category == ucp_L || category == ucp_N) == prop_fail_result) + GETCHARINCTEST(fc, Feptr); + category = UCD_CATEGORY(fc); + if ((category == ucp_L || category == ucp_N) == (Lctype == OP_NOTPROP)) RRETURN(MATCH_NOMATCH); } break; @@ -4342,23 +2638,23 @@ for (;;) case PT_SPACE: /* Perl space */ case PT_PXSPACE: /* POSIX space */ - for (i = 1; i <= min; i++) + for (i = 1; i <= Lmin; i++) { - if (eptr >= mb->end_subject) + if (Feptr >= mb->end_subject) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } - GETCHARINCTEST(c, eptr); - switch(c) + GETCHARINCTEST(fc, Feptr); + switch(fc) { HSPACE_CASES: VSPACE_CASES: - if (prop_fail_result) RRETURN(MATCH_NOMATCH); + if (Lctype == OP_NOTPROP) RRETURN(MATCH_NOMATCH); break; default: - if ((UCD_CATEGORY(c) == ucp_Z) == prop_fail_result) + if ((UCD_CATEGORY(fc) == ucp_Z) == (Lctype == OP_NOTPROP)) RRETURN(MATCH_NOMATCH); break; } @@ -4366,55 +2662,61 @@ for (;;) break; case PT_WORD: - for (i = 1; i <= min; i++) + for (i = 1; i <= Lmin; i++) { int category; - if (eptr >= mb->end_subject) + if (Feptr >= mb->end_subject) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } - GETCHARINCTEST(c, eptr); - category = UCD_CATEGORY(c); - if ((category == ucp_L || category == ucp_N || c == CHAR_UNDERSCORE) - == prop_fail_result) + GETCHARINCTEST(fc, Feptr); + category = UCD_CATEGORY(fc); + if ((category == ucp_L || category == ucp_N || + fc == CHAR_UNDERSCORE) == (Lctype == OP_NOTPROP)) RRETURN(MATCH_NOMATCH); } break; case PT_CLIST: - for (i = 1; i <= min; i++) + for (i = 1; i <= Lmin; i++) { const uint32_t *cp; - if (eptr >= mb->end_subject) + if (Feptr >= mb->end_subject) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } - GETCHARINCTEST(c, eptr); - cp = PRIV(ucd_caseless_sets) + prop_value; + GETCHARINCTEST(fc, Feptr); + cp = PRIV(ucd_caseless_sets) + Lpropvalue; for (;;) { - if (c < *cp) - { if (prop_fail_result) break; else { RRETURN(MATCH_NOMATCH); } } - if (c == *cp++) - { if (prop_fail_result) { RRETURN(MATCH_NOMATCH); } else break; } + if (fc < *cp) + { + if (Lctype == OP_NOTPROP) break; + RRETURN(MATCH_NOMATCH); + } + if (fc == *cp++) + { + if (Lctype == OP_NOTPROP) RRETURN(MATCH_NOMATCH); + break; + } } } break; case PT_UCNC: - for (i = 1; i <= min; i++) + for (i = 1; i <= Lmin; i++) { - if (eptr >= mb->end_subject) + if (Feptr >= mb->end_subject) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } - GETCHARINCTEST(c, eptr); - if ((c == CHAR_DOLLAR_SIGN || c == CHAR_COMMERCIAL_AT || - c == CHAR_GRAVE_ACCENT || (c >= 0xa0 && c <= 0xd7ff) || - c >= 0xe000) == prop_fail_result) + GETCHARINCTEST(fc, Feptr); + if ((fc == CHAR_DOLLAR_SIGN || fc == CHAR_COMMERCIAL_AT || + fc == CHAR_GRAVE_ACCENT || (fc >= 0xa0 && fc <= 0xd7ff) || + fc >= 0xe000) == (Lctype == OP_NOTPROP)) RRETURN(MATCH_NOMATCH); } break; @@ -4422,105 +2724,95 @@ for (;;) /* This should not occur */ default: - RRETURN(PCRE2_ERROR_INTERNAL); + return PCRE2_ERROR_INTERNAL; } } /* Match extended Unicode sequences. We will get here only if the support is in the binary; otherwise a compile-time error occurs. */ - else if (ctype == OP_EXTUNI) + else if (Lctype == OP_EXTUNI) { - for (i = 1; i <= min; i++) + for (i = 1; i <= Lmin; i++) { - if (eptr >= mb->end_subject) + if (Feptr >= mb->end_subject) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } else { - int lgb, rgb; - GETCHARINCTEST(c, eptr); - lgb = UCD_GRAPHBREAK(c); - while (eptr < mb->end_subject) - { - int len = 1; - if (!utf) c = *eptr; else { GETCHARLEN(c, eptr, len); } - rgb = UCD_GRAPHBREAK(c); - if ((PRIV(ucp_gbtable)[lgb] & (1 << rgb)) == 0) break; - lgb = rgb; - eptr += len; - } + GETCHARINCTEST(fc, Feptr); + Feptr = PRIV(extuni)(fc, Feptr, mb->start_subject, + mb->end_subject, utf, NULL); } CHECK_PARTIAL(); } } - else #endif /* SUPPORT_UNICODE */ -/* Handle all other cases when the coding is UTF-8 */ +/* Handle all other cases in UTF mode */ #ifdef SUPPORT_UNICODE - if (utf) switch(ctype) + if (utf) switch(Lctype) { case OP_ANY: - for (i = 1; i <= min; i++) + for (i = 1; i <= Lmin; i++) { - if (eptr >= mb->end_subject) + if (Feptr >= mb->end_subject) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } - if (IS_NEWLINE(eptr)) RRETURN(MATCH_NOMATCH); + if (IS_NEWLINE(Feptr)) RRETURN(MATCH_NOMATCH); if (mb->partial != 0 && - eptr + 1 >= mb->end_subject && + Feptr + 1 >= mb->end_subject && NLBLOCK->nltype == NLTYPE_FIXED && NLBLOCK->nllen == 2 && - UCHAR21(eptr) == NLBLOCK->nl[0]) + UCHAR21(Feptr) == NLBLOCK->nl[0]) { mb->hitend = TRUE; - if (mb->partial > 1) RRETURN(PCRE2_ERROR_PARTIAL); + if (mb->partial > 1) return PCRE2_ERROR_PARTIAL; } - eptr++; - ACROSSCHAR(eptr < mb->end_subject, *eptr, eptr++); + Feptr++; + ACROSSCHAR(Feptr < mb->end_subject, Feptr, Feptr++); } break; case OP_ALLANY: - for (i = 1; i <= min; i++) + for (i = 1; i <= Lmin; i++) { - if (eptr >= mb->end_subject) + if (Feptr >= mb->end_subject) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } - eptr++; - ACROSSCHAR(eptr < mb->end_subject, *eptr, eptr++); + Feptr++; + ACROSSCHAR(Feptr < mb->end_subject, Feptr, Feptr++); } break; case OP_ANYBYTE: - if (eptr > mb->end_subject - min) RRETURN(MATCH_NOMATCH); - eptr += min; + if (Feptr > mb->end_subject - Lmin) RRETURN(MATCH_NOMATCH); + Feptr += Lmin; break; case OP_ANYNL: - for (i = 1; i <= min; i++) + for (i = 1; i <= Lmin; i++) { - if (eptr >= mb->end_subject) + if (Feptr >= mb->end_subject) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } - GETCHARINC(c, eptr); - switch(c) + GETCHARINC(fc, Feptr); + switch(fc) { default: RRETURN(MATCH_NOMATCH); case CHAR_CR: - if (eptr < mb->end_subject && UCHAR21(eptr) == CHAR_LF) eptr++; + if (Feptr < mb->end_subject && UCHAR21(Feptr) == CHAR_LF) Feptr++; break; case CHAR_LF: @@ -4540,49 +2832,49 @@ for (;;) break; case OP_NOT_HSPACE: - for (i = 1; i <= min; i++) + for (i = 1; i <= Lmin; i++) { - if (eptr >= mb->end_subject) + if (Feptr >= mb->end_subject) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } - GETCHARINC(c, eptr); - switch(c) + GETCHARINC(fc, Feptr); + switch(fc) { - HSPACE_CASES: RRETURN(MATCH_NOMATCH); /* Byte and multibyte cases */ + HSPACE_CASES: RRETURN(MATCH_NOMATCH); default: break; } } break; case OP_HSPACE: - for (i = 1; i <= min; i++) + for (i = 1; i <= Lmin; i++) { - if (eptr >= mb->end_subject) + if (Feptr >= mb->end_subject) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } - GETCHARINC(c, eptr); - switch(c) + GETCHARINC(fc, Feptr); + switch(fc) { - HSPACE_CASES: break; /* Byte and multibyte cases */ + HSPACE_CASES: break; default: RRETURN(MATCH_NOMATCH); } } break; case OP_NOT_VSPACE: - for (i = 1; i <= min; i++) + for (i = 1; i <= Lmin; i++) { - if (eptr >= mb->end_subject) + if (Feptr >= mb->end_subject) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } - GETCHARINC(c, eptr); - switch(c) + GETCHARINC(fc, Feptr); + switch(fc) { VSPACE_CASES: RRETURN(MATCH_NOMATCH); default: break; @@ -4591,15 +2883,15 @@ for (;;) break; case OP_VSPACE: - for (i = 1; i <= min; i++) + for (i = 1; i <= Lmin; i++) { - if (eptr >= mb->end_subject) + if (Feptr >= mb->end_subject) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } - GETCHARINC(c, eptr); - switch(c) + GETCHARINC(fc, Feptr); + switch(fc) { VSPACE_CASES: break; default: RRETURN(MATCH_NOMATCH); @@ -4608,170 +2900,174 @@ for (;;) break; case OP_NOT_DIGIT: - for (i = 1; i <= min; i++) + for (i = 1; i <= Lmin; i++) { - if (eptr >= mb->end_subject) + if (Feptr >= mb->end_subject) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } - GETCHARINC(c, eptr); - if (c < 128 && (mb->ctypes[c] & ctype_digit) != 0) + GETCHARINC(fc, Feptr); + if (fc < 128 && (mb->ctypes[fc] & ctype_digit) != 0) RRETURN(MATCH_NOMATCH); } break; case OP_DIGIT: - for (i = 1; i <= min; i++) + for (i = 1; i <= Lmin; i++) { uint32_t cc; - if (eptr >= mb->end_subject) + if (Feptr >= mb->end_subject) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } - cc = UCHAR21(eptr); + cc = UCHAR21(Feptr); if (cc >= 128 || (mb->ctypes[cc] & ctype_digit) == 0) RRETURN(MATCH_NOMATCH); - eptr++; - /* No need to skip more bytes - we know it's a 1-byte character */ + Feptr++; + /* No need to skip more code units - we know it has only one. */ } break; case OP_NOT_WHITESPACE: - for (i = 1; i <= min; i++) + for (i = 1; i <= Lmin; i++) { uint32_t cc; - if (eptr >= mb->end_subject) + if (Feptr >= mb->end_subject) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } - cc = UCHAR21(eptr); + cc = UCHAR21(Feptr); if (cc < 128 && (mb->ctypes[cc] & ctype_space) != 0) RRETURN(MATCH_NOMATCH); - eptr++; - ACROSSCHAR(eptr < mb->end_subject, *eptr, eptr++); + Feptr++; + ACROSSCHAR(Feptr < mb->end_subject, Feptr, Feptr++); } break; case OP_WHITESPACE: - for (i = 1; i <= min; i++) + for (i = 1; i <= Lmin; i++) { uint32_t cc; - if (eptr >= mb->end_subject) + if (Feptr >= mb->end_subject) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } - cc = UCHAR21(eptr); + cc = UCHAR21(Feptr); if (cc >= 128 || (mb->ctypes[cc] & ctype_space) == 0) RRETURN(MATCH_NOMATCH); - eptr++; - /* No need to skip more bytes - we know it's a 1-byte character */ + Feptr++; + /* No need to skip more code units - we know it has only one. */ } break; case OP_NOT_WORDCHAR: - for (i = 1; i <= min; i++) + for (i = 1; i <= Lmin; i++) { uint32_t cc; - if (eptr >= mb->end_subject) + if (Feptr >= mb->end_subject) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } - cc = UCHAR21(eptr); + cc = UCHAR21(Feptr); if (cc < 128 && (mb->ctypes[cc] & ctype_word) != 0) RRETURN(MATCH_NOMATCH); - eptr++; - ACROSSCHAR(eptr < mb->end_subject, *eptr, eptr++); + Feptr++; + ACROSSCHAR(Feptr < mb->end_subject, Feptr, Feptr++); } break; case OP_WORDCHAR: - for (i = 1; i <= min; i++) + for (i = 1; i <= Lmin; i++) { uint32_t cc; - if (eptr >= mb->end_subject) + if (Feptr >= mb->end_subject) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } - cc = UCHAR21(eptr); + cc = UCHAR21(Feptr); if (cc >= 128 || (mb->ctypes[cc] & ctype_word) == 0) RRETURN(MATCH_NOMATCH); - eptr++; - /* No need to skip more bytes - we know it's a 1-byte character */ + Feptr++; + /* No need to skip more code units - we know it has only one. */ } break; default: - RRETURN(PCRE2_ERROR_INTERNAL); - } /* End switch(ctype) */ + return PCRE2_ERROR_INTERNAL; + } /* End switch(Lctype) */ else #endif /* SUPPORT_UNICODE */ - /* Code for the non-UTF-8 case for minimum matching of operators other + /* Code for the non-UTF case for minimum matching of operators other than OP_PROP and OP_NOTPROP. */ - switch(ctype) + switch(Lctype) { case OP_ANY: - for (i = 1; i <= min; i++) + for (i = 1; i <= Lmin; i++) { - if (eptr >= mb->end_subject) + if (Feptr >= mb->end_subject) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } - if (IS_NEWLINE(eptr)) RRETURN(MATCH_NOMATCH); + if (IS_NEWLINE(Feptr)) RRETURN(MATCH_NOMATCH); if (mb->partial != 0 && - eptr + 1 >= mb->end_subject && + Feptr + 1 >= mb->end_subject && NLBLOCK->nltype == NLTYPE_FIXED && NLBLOCK->nllen == 2 && - *eptr == NLBLOCK->nl[0]) + *Feptr == NLBLOCK->nl[0]) { mb->hitend = TRUE; - if (mb->partial > 1) RRETURN(PCRE2_ERROR_PARTIAL); + if (mb->partial > 1) return PCRE2_ERROR_PARTIAL; } - eptr++; + Feptr++; } break; case OP_ALLANY: - if (eptr > mb->end_subject - min) - { - SCHECK_PARTIAL(); - RRETURN(MATCH_NOMATCH); - } - eptr += min; - break; - - case OP_ANYBYTE: - if (eptr > mb->end_subject - min) + if (Feptr > mb->end_subject - Lmin) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } - eptr += min; + Feptr += Lmin; break; + /* This OP_ANYBYTE case will never be reached because \C gets turned + into OP_ALLANY in non-UTF mode. Cut out the code so that coverage + reports don't complain about it's never being used. */ + +/* case OP_ANYBYTE: +* if (Feptr > mb->end_subject - Lmin) +* { +* SCHECK_PARTIAL(); +* RRETURN(MATCH_NOMATCH); +* } +* Feptr += Lmin; +* break; +*/ case OP_ANYNL: - for (i = 1; i <= min; i++) + for (i = 1; i <= Lmin; i++) { - if (eptr >= mb->end_subject) + if (Feptr >= mb->end_subject) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } - switch(*eptr++) + switch(*Feptr++) { default: RRETURN(MATCH_NOMATCH); case CHAR_CR: - if (eptr < mb->end_subject && *eptr == CHAR_LF) eptr++; + if (Feptr < mb->end_subject && *Feptr == CHAR_LF) Feptr++; break; case CHAR_LF: @@ -4791,14 +3087,14 @@ for (;;) break; case OP_NOT_HSPACE: - for (i = 1; i <= min; i++) + for (i = 1; i <= Lmin; i++) { - if (eptr >= mb->end_subject) + if (Feptr >= mb->end_subject) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } - switch(*eptr++) + switch(*Feptr++) { default: break; HSPACE_BYTE_CASES: @@ -4811,14 +3107,14 @@ for (;;) break; case OP_HSPACE: - for (i = 1; i <= min; i++) + for (i = 1; i <= Lmin; i++) { - if (eptr >= mb->end_subject) + if (Feptr >= mb->end_subject) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } - switch(*eptr++) + switch(*Feptr++) { default: RRETURN(MATCH_NOMATCH); HSPACE_BYTE_CASES: @@ -4831,14 +3127,14 @@ for (;;) break; case OP_NOT_VSPACE: - for (i = 1; i <= min; i++) + for (i = 1; i <= Lmin; i++) { - if (eptr >= mb->end_subject) + if (Feptr >= mb->end_subject) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } - switch(*eptr++) + switch(*Feptr++) { VSPACE_BYTE_CASES: #if PCRE2_CODE_UNIT_WIDTH != 8 @@ -4851,14 +3147,14 @@ for (;;) break; case OP_VSPACE: - for (i = 1; i <= min; i++) + for (i = 1; i <= Lmin; i++) { - if (eptr >= mb->end_subject) + if (Feptr >= mb->end_subject) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } - switch(*eptr++) + switch(*Feptr++) { default: RRETURN(MATCH_NOMATCH); VSPACE_BYTE_CASES: @@ -4871,212 +3167,212 @@ for (;;) break; case OP_NOT_DIGIT: - for (i = 1; i <= min; i++) + for (i = 1; i <= Lmin; i++) { - if (eptr >= mb->end_subject) + if (Feptr >= mb->end_subject) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } - if (MAX_255(*eptr) && (mb->ctypes[*eptr] & ctype_digit) != 0) + if (MAX_255(*Feptr) && (mb->ctypes[*Feptr] & ctype_digit) != 0) RRETURN(MATCH_NOMATCH); - eptr++; + Feptr++; } break; case OP_DIGIT: - for (i = 1; i <= min; i++) + for (i = 1; i <= Lmin; i++) { - if (eptr >= mb->end_subject) + if (Feptr >= mb->end_subject) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } - if (!MAX_255(*eptr) || (mb->ctypes[*eptr] & ctype_digit) == 0) + if (!MAX_255(*Feptr) || (mb->ctypes[*Feptr] & ctype_digit) == 0) RRETURN(MATCH_NOMATCH); - eptr++; + Feptr++; } break; case OP_NOT_WHITESPACE: - for (i = 1; i <= min; i++) + for (i = 1; i <= Lmin; i++) { - if (eptr >= mb->end_subject) + if (Feptr >= mb->end_subject) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } - if (MAX_255(*eptr) && (mb->ctypes[*eptr] & ctype_space) != 0) + if (MAX_255(*Feptr) && (mb->ctypes[*Feptr] & ctype_space) != 0) RRETURN(MATCH_NOMATCH); - eptr++; + Feptr++; } break; case OP_WHITESPACE: - for (i = 1; i <= min; i++) + for (i = 1; i <= Lmin; i++) { - if (eptr >= mb->end_subject) + if (Feptr >= mb->end_subject) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } - if (!MAX_255(*eptr) || (mb->ctypes[*eptr] & ctype_space) == 0) + if (!MAX_255(*Feptr) || (mb->ctypes[*Feptr] & ctype_space) == 0) RRETURN(MATCH_NOMATCH); - eptr++; + Feptr++; } break; case OP_NOT_WORDCHAR: - for (i = 1; i <= min; i++) + for (i = 1; i <= Lmin; i++) { - if (eptr >= mb->end_subject) + if (Feptr >= mb->end_subject) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } - if (MAX_255(*eptr) && (mb->ctypes[*eptr] & ctype_word) != 0) + if (MAX_255(*Feptr) && (mb->ctypes[*Feptr] & ctype_word) != 0) RRETURN(MATCH_NOMATCH); - eptr++; + Feptr++; } break; case OP_WORDCHAR: - for (i = 1; i <= min; i++) + for (i = 1; i <= Lmin; i++) { - if (eptr >= mb->end_subject) + if (Feptr >= mb->end_subject) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } - if (!MAX_255(*eptr) || (mb->ctypes[*eptr] & ctype_word) == 0) + if (!MAX_255(*Feptr) || (mb->ctypes[*Feptr] & ctype_word) == 0) RRETURN(MATCH_NOMATCH); - eptr++; + Feptr++; } break; default: - RRETURN(PCRE2_ERROR_INTERNAL); + return PCRE2_ERROR_INTERNAL; } } - /* If min = max, continue at the same level without recursing */ + /* If Lmin = Lmax we are done. Continue with the main loop. */ - if (min == max) continue; + if (Lmin == Lmax) continue; /* If minimizing, we have to test the rest of the pattern before each - subsequent match. Again, separate the UTF-8 case for speed, and also - separate the UCP cases. */ + subsequent match. */ - if (minimize) + if (reptype == REPTYPE_MIN) { #ifdef SUPPORT_UNICODE - if (prop_type >= 0) + if (proptype >= 0) { - switch(prop_type) + switch(proptype) { case PT_ANY: - for (fi = min;; fi++) + for (;;) { - RMATCH(eptr, ecode, offset_top, mb, eptrb, RM36); + RMATCH(Fecode, RM208); if (rrc != MATCH_NOMATCH) RRETURN(rrc); - if (fi >= max) RRETURN(MATCH_NOMATCH); - if (eptr >= mb->end_subject) + if (Lmin++ >= Lmax) RRETURN(MATCH_NOMATCH); + if (Feptr >= mb->end_subject) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } - GETCHARINCTEST(c, eptr); - if (prop_fail_result) RRETURN(MATCH_NOMATCH); + GETCHARINCTEST(fc, Feptr); + if (Lctype == OP_NOTPROP) RRETURN(MATCH_NOMATCH); } /* Control never gets here */ case PT_LAMP: - for (fi = min;; fi++) + for (;;) { int chartype; - RMATCH(eptr, ecode, offset_top, mb, eptrb, RM37); + RMATCH(Fecode, RM209); if (rrc != MATCH_NOMATCH) RRETURN(rrc); - if (fi >= max) RRETURN(MATCH_NOMATCH); - if (eptr >= mb->end_subject) + if (Lmin++ >= Lmax) RRETURN(MATCH_NOMATCH); + if (Feptr >= mb->end_subject) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } - GETCHARINCTEST(c, eptr); - chartype = UCD_CHARTYPE(c); + GETCHARINCTEST(fc, Feptr); + chartype = UCD_CHARTYPE(fc); if ((chartype == ucp_Lu || chartype == ucp_Ll || - chartype == ucp_Lt) == prop_fail_result) + chartype == ucp_Lt) == (Lctype == OP_NOTPROP)) RRETURN(MATCH_NOMATCH); } /* Control never gets here */ case PT_GC: - for (fi = min;; fi++) + for (;;) { - RMATCH(eptr, ecode, offset_top, mb, eptrb, RM38); + RMATCH(Fecode, RM210); if (rrc != MATCH_NOMATCH) RRETURN(rrc); - if (fi >= max) RRETURN(MATCH_NOMATCH); - if (eptr >= mb->end_subject) + if (Lmin++ >= Lmax) RRETURN(MATCH_NOMATCH); + if (Feptr >= mb->end_subject) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } - GETCHARINCTEST(c, eptr); - if ((UCD_CATEGORY(c) == prop_value) == prop_fail_result) + GETCHARINCTEST(fc, Feptr); + if ((UCD_CATEGORY(fc) == Lpropvalue) == (Lctype == OP_NOTPROP)) RRETURN(MATCH_NOMATCH); } /* Control never gets here */ case PT_PC: - for (fi = min;; fi++) + for (;;) { - RMATCH(eptr, ecode, offset_top, mb, eptrb, RM39); + RMATCH(Fecode, RM211); if (rrc != MATCH_NOMATCH) RRETURN(rrc); - if (fi >= max) RRETURN(MATCH_NOMATCH); - if (eptr >= mb->end_subject) + if (Lmin++ >= Lmax) RRETURN(MATCH_NOMATCH); + if (Feptr >= mb->end_subject) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } - GETCHARINCTEST(c, eptr); - if ((UCD_CHARTYPE(c) == prop_value) == prop_fail_result) + GETCHARINCTEST(fc, Feptr); + if ((UCD_CHARTYPE(fc) == Lpropvalue) == (Lctype == OP_NOTPROP)) RRETURN(MATCH_NOMATCH); } /* Control never gets here */ case PT_SC: - for (fi = min;; fi++) + for (;;) { - RMATCH(eptr, ecode, offset_top, mb, eptrb, RM40); + RMATCH(Fecode, RM212); if (rrc != MATCH_NOMATCH) RRETURN(rrc); - if (fi >= max) RRETURN(MATCH_NOMATCH); - if (eptr >= mb->end_subject) + if (Lmin++ >= Lmax) RRETURN(MATCH_NOMATCH); + if (Feptr >= mb->end_subject) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } - GETCHARINCTEST(c, eptr); - if ((UCD_SCRIPT(c) == prop_value) == prop_fail_result) + GETCHARINCTEST(fc, Feptr); + if ((UCD_SCRIPT(fc) == Lpropvalue) == (Lctype == OP_NOTPROP)) RRETURN(MATCH_NOMATCH); } /* Control never gets here */ case PT_ALNUM: - for (fi = min;; fi++) + for (;;) { int category; - RMATCH(eptr, ecode, offset_top, mb, eptrb, RM59); + RMATCH(Fecode, RM213); if (rrc != MATCH_NOMATCH) RRETURN(rrc); - if (fi >= max) RRETURN(MATCH_NOMATCH); - if (eptr >= mb->end_subject) + if (Lmin++ >= Lmax) RRETURN(MATCH_NOMATCH); + if (Feptr >= mb->end_subject) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } - GETCHARINCTEST(c, eptr); - category = UCD_CATEGORY(c); - if ((category == ucp_L || category == ucp_N) == prop_fail_result) + GETCHARINCTEST(fc, Feptr); + category = UCD_CATEGORY(fc); + if ((category == ucp_L || category == ucp_N) == + (Lctype == OP_NOTPROP)) RRETURN(MATCH_NOMATCH); } /* Control never gets here */ @@ -5087,26 +3383,26 @@ for (;;) case PT_SPACE: /* Perl space */ case PT_PXSPACE: /* POSIX space */ - for (fi = min;; fi++) + for (;;) { - RMATCH(eptr, ecode, offset_top, mb, eptrb, RM61); + RMATCH(Fecode, RM214); if (rrc != MATCH_NOMATCH) RRETURN(rrc); - if (fi >= max) RRETURN(MATCH_NOMATCH); - if (eptr >= mb->end_subject) + if (Lmin++ >= Lmax) RRETURN(MATCH_NOMATCH); + if (Feptr >= mb->end_subject) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } - GETCHARINCTEST(c, eptr); - switch(c) + GETCHARINCTEST(fc, Feptr); + switch(fc) { HSPACE_CASES: VSPACE_CASES: - if (prop_fail_result) RRETURN(MATCH_NOMATCH); + if (Lctype == OP_NOTPROP) RRETURN(MATCH_NOMATCH); break; default: - if ((UCD_CATEGORY(c) == ucp_Z) == prop_fail_result) + if ((UCD_CATEGORY(fc) == ucp_Z) == (Lctype == OP_NOTPROP)) RRETURN(MATCH_NOMATCH); break; } @@ -5114,105 +3410,101 @@ for (;;) /* Control never gets here */ case PT_WORD: - for (fi = min;; fi++) + for (;;) { int category; - RMATCH(eptr, ecode, offset_top, mb, eptrb, RM62); + RMATCH(Fecode, RM215); if (rrc != MATCH_NOMATCH) RRETURN(rrc); - if (fi >= max) RRETURN(MATCH_NOMATCH); - if (eptr >= mb->end_subject) + if (Lmin++ >= Lmax) RRETURN(MATCH_NOMATCH); + if (Feptr >= mb->end_subject) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } - GETCHARINCTEST(c, eptr); - category = UCD_CATEGORY(c); + GETCHARINCTEST(fc, Feptr); + category = UCD_CATEGORY(fc); if ((category == ucp_L || category == ucp_N || - c == CHAR_UNDERSCORE) - == prop_fail_result) + fc == CHAR_UNDERSCORE) == (Lctype == OP_NOTPROP)) RRETURN(MATCH_NOMATCH); } /* Control never gets here */ case PT_CLIST: - for (fi = min;; fi++) + for (;;) { const uint32_t *cp; - RMATCH(eptr, ecode, offset_top, mb, eptrb, RM67); + RMATCH(Fecode, RM216); if (rrc != MATCH_NOMATCH) RRETURN(rrc); - if (fi >= max) RRETURN(MATCH_NOMATCH); - if (eptr >= mb->end_subject) + if (Lmin++ >= Lmax) RRETURN(MATCH_NOMATCH); + if (Feptr >= mb->end_subject) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } - GETCHARINCTEST(c, eptr); - cp = PRIV(ucd_caseless_sets) + prop_value; + GETCHARINCTEST(fc, Feptr); + cp = PRIV(ucd_caseless_sets) + Lpropvalue; for (;;) { - if (c < *cp) - { if (prop_fail_result) break; else { RRETURN(MATCH_NOMATCH); } } - if (c == *cp++) - { if (prop_fail_result) { RRETURN(MATCH_NOMATCH); } else break; } + if (fc < *cp) + { + if (Lctype == OP_NOTPROP) break; + RRETURN(MATCH_NOMATCH); + } + if (fc == *cp++) + { + if (Lctype == OP_NOTPROP) RRETURN(MATCH_NOMATCH); + break; + } } } /* Control never gets here */ case PT_UCNC: - for (fi = min;; fi++) + for (;;) { - RMATCH(eptr, ecode, offset_top, mb, eptrb, RM60); + RMATCH(Fecode, RM217); if (rrc != MATCH_NOMATCH) RRETURN(rrc); - if (fi >= max) RRETURN(MATCH_NOMATCH); - if (eptr >= mb->end_subject) + if (Lmin++ >= Lmax) RRETURN(MATCH_NOMATCH); + if (Feptr >= mb->end_subject) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } - GETCHARINCTEST(c, eptr); - if ((c == CHAR_DOLLAR_SIGN || c == CHAR_COMMERCIAL_AT || - c == CHAR_GRAVE_ACCENT || (c >= 0xa0 && c <= 0xd7ff) || - c >= 0xe000) == prop_fail_result) + GETCHARINCTEST(fc, Feptr); + if ((fc == CHAR_DOLLAR_SIGN || fc == CHAR_COMMERCIAL_AT || + fc == CHAR_GRAVE_ACCENT || (fc >= 0xa0 && fc <= 0xd7ff) || + fc >= 0xe000) == (Lctype == OP_NOTPROP)) RRETURN(MATCH_NOMATCH); } /* Control never gets here */ /* This should never occur */ default: - RRETURN(PCRE2_ERROR_INTERNAL); + return PCRE2_ERROR_INTERNAL; } } /* Match extended Unicode sequences. We will get here only if the support is in the binary; otherwise a compile-time error occurs. */ - else if (ctype == OP_EXTUNI) + else if (Lctype == OP_EXTUNI) { - for (fi = min;; fi++) + for (;;) { - RMATCH(eptr, ecode, offset_top, mb, eptrb, RM41); + RMATCH(Fecode, RM218); if (rrc != MATCH_NOMATCH) RRETURN(rrc); - if (fi >= max) RRETURN(MATCH_NOMATCH); - if (eptr >= mb->end_subject) + if (Lmin++ >= Lmax) RRETURN(MATCH_NOMATCH); + if (Feptr >= mb->end_subject) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } else { - int lgb, rgb; - GETCHARINCTEST(c, eptr); - lgb = UCD_GRAPHBREAK(c); - while (eptr < mb->end_subject) - { - int len = 1; - if (!utf) c = *eptr; else { GETCHARLEN(c, eptr, len); } - rgb = UCD_GRAPHBREAK(c); - if ((PRIV(ucp_gbtable)[lgb] & (1 << rgb)) == 0) break; - lgb = rgb; - eptr += len; - } + GETCHARINCTEST(fc, Feptr); + Feptr = PRIV(extuni)(fc, Feptr, mb->start_subject, mb->end_subject, + utf, NULL); } CHECK_PARTIAL(); } @@ -5220,33 +3512,34 @@ for (;;) else #endif /* SUPPORT_UNICODE */ + /* UTF mode for non-property testing character types. */ + #ifdef SUPPORT_UNICODE if (utf) { - for (fi = min;; fi++) + for (;;) { - RMATCH(eptr, ecode, offset_top, mb, eptrb, RM42); + RMATCH(Fecode, RM219); if (rrc != MATCH_NOMATCH) RRETURN(rrc); - if (fi >= max) RRETURN(MATCH_NOMATCH); - if (eptr >= mb->end_subject) + if (Lmin++ >= Lmax) RRETURN(MATCH_NOMATCH); + if (Feptr >= mb->end_subject) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } - if (ctype == OP_ANY && IS_NEWLINE(eptr)) - RRETURN(MATCH_NOMATCH); - GETCHARINC(c, eptr); - switch(ctype) + if (Lctype == OP_ANY && IS_NEWLINE(Feptr)) RRETURN(MATCH_NOMATCH); + GETCHARINC(fc, Feptr); + switch(Lctype) { case OP_ANY: /* This is the non-NL case */ if (mb->partial != 0 && /* Take care with CRLF partial */ - eptr >= mb->end_subject && + Feptr >= mb->end_subject && NLBLOCK->nltype == NLTYPE_FIXED && NLBLOCK->nllen == 2 && - c == NLBLOCK->nl[0]) + fc == NLBLOCK->nl[0]) { mb->hitend = TRUE; - if (mb->partial > 1) RRETURN(PCRE2_ERROR_PARTIAL); + if (mb->partial > 1) return PCRE2_ERROR_PARTIAL; } break; @@ -5255,11 +3548,12 @@ for (;;) break; case OP_ANYNL: - switch(c) + switch(fc) { default: RRETURN(MATCH_NOMATCH); + case CHAR_CR: - if (eptr < mb->end_subject && UCHAR21(eptr) == CHAR_LF) eptr++; + if (Feptr < mb->end_subject && UCHAR21(Feptr) == CHAR_LF) Feptr++; break; case CHAR_LF: @@ -5272,13 +3566,14 @@ for (;;) case 0x2028: case 0x2029: #endif /* Not EBCDIC */ - if (mb->bsr_convention == PCRE2_BSR_ANYCRLF) RRETURN(MATCH_NOMATCH); + if (mb->bsr_convention == PCRE2_BSR_ANYCRLF) + RRETURN(MATCH_NOMATCH); break; } break; case OP_NOT_HSPACE: - switch(c) + switch(fc) { HSPACE_CASES: RRETURN(MATCH_NOMATCH); default: break; @@ -5286,7 +3581,7 @@ for (;;) break; case OP_HSPACE: - switch(c) + switch(fc) { HSPACE_CASES: break; default: RRETURN(MATCH_NOMATCH); @@ -5294,7 +3589,7 @@ for (;;) break; case OP_NOT_VSPACE: - switch(c) + switch(fc) { VSPACE_CASES: RRETURN(MATCH_NOMATCH); default: break; @@ -5302,7 +3597,7 @@ for (;;) break; case OP_VSPACE: - switch(c) + switch(fc) { VSPACE_CASES: break; default: RRETURN(MATCH_NOMATCH); @@ -5310,68 +3605,69 @@ for (;;) break; case OP_NOT_DIGIT: - if (c < 256 && (mb->ctypes[c] & ctype_digit) != 0) + if (fc < 256 && (mb->ctypes[fc] & ctype_digit) != 0) RRETURN(MATCH_NOMATCH); break; case OP_DIGIT: - if (c >= 256 || (mb->ctypes[c] & ctype_digit) == 0) + if (fc >= 256 || (mb->ctypes[fc] & ctype_digit) == 0) RRETURN(MATCH_NOMATCH); break; case OP_NOT_WHITESPACE: - if (c < 256 && (mb->ctypes[c] & ctype_space) != 0) + if (fc < 256 && (mb->ctypes[fc] & ctype_space) != 0) RRETURN(MATCH_NOMATCH); break; case OP_WHITESPACE: - if (c >= 256 || (mb->ctypes[c] & ctype_space) == 0) + if (fc >= 256 || (mb->ctypes[fc] & ctype_space) == 0) RRETURN(MATCH_NOMATCH); break; case OP_NOT_WORDCHAR: - if (c < 256 && (mb->ctypes[c] & ctype_word) != 0) + if (fc < 256 && (mb->ctypes[fc] & ctype_word) != 0) RRETURN(MATCH_NOMATCH); break; case OP_WORDCHAR: - if (c >= 256 || (mb->ctypes[c] & ctype_word) == 0) + if (fc >= 256 || (mb->ctypes[fc] & ctype_word) == 0) RRETURN(MATCH_NOMATCH); break; default: - RRETURN(PCRE2_ERROR_INTERNAL); + return PCRE2_ERROR_INTERNAL; } } } else -#endif +#endif /* SUPPORT_UNICODE */ + /* Not UTF mode */ { - for (fi = min;; fi++) + for (;;) { - RMATCH(eptr, ecode, offset_top, mb, eptrb, RM43); + RMATCH(Fecode, RM33); if (rrc != MATCH_NOMATCH) RRETURN(rrc); - if (fi >= max) RRETURN(MATCH_NOMATCH); - if (eptr >= mb->end_subject) + if (Lmin++ >= Lmax) RRETURN(MATCH_NOMATCH); + if (Feptr >= mb->end_subject) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } - if (ctype == OP_ANY && IS_NEWLINE(eptr)) + if (Lctype == OP_ANY && IS_NEWLINE(Feptr)) RRETURN(MATCH_NOMATCH); - c = *eptr++; - switch(ctype) + fc = *Feptr++; + switch(Lctype) { case OP_ANY: /* This is the non-NL case */ if (mb->partial != 0 && /* Take care with CRLF partial */ - eptr >= mb->end_subject && + Feptr >= mb->end_subject && NLBLOCK->nltype == NLTYPE_FIXED && NLBLOCK->nllen == 2 && - c == NLBLOCK->nl[0]) + fc == NLBLOCK->nl[0]) { mb->hitend = TRUE; - if (mb->partial > 1) RRETURN(PCRE2_ERROR_PARTIAL); + if (mb->partial > 1) return PCRE2_ERROR_PARTIAL; } break; @@ -5380,11 +3676,12 @@ for (;;) break; case OP_ANYNL: - switch(c) + switch(fc) { default: RRETURN(MATCH_NOMATCH); + case CHAR_CR: - if (eptr < mb->end_subject && *eptr == CHAR_LF) eptr++; + if (Feptr < mb->end_subject && *Feptr == CHAR_LF) Feptr++; break; case CHAR_LF: @@ -5397,13 +3694,14 @@ for (;;) case 0x2028: case 0x2029: #endif - if (mb->bsr_convention == PCRE2_BSR_ANYCRLF) RRETURN(MATCH_NOMATCH); + if (mb->bsr_convention == PCRE2_BSR_ANYCRLF) + RRETURN(MATCH_NOMATCH); break; } break; case OP_NOT_HSPACE: - switch(c) + switch(fc) { default: break; HSPACE_BYTE_CASES: @@ -5415,7 +3713,7 @@ for (;;) break; case OP_HSPACE: - switch(c) + switch(fc) { default: RRETURN(MATCH_NOMATCH); HSPACE_BYTE_CASES: @@ -5427,7 +3725,7 @@ for (;;) break; case OP_NOT_VSPACE: - switch(c) + switch(fc) { default: break; VSPACE_BYTE_CASES: @@ -5439,7 +3737,7 @@ for (;;) break; case OP_VSPACE: - switch(c) + switch(fc) { default: RRETURN(MATCH_NOMATCH); VSPACE_BYTE_CASES: @@ -5451,31 +3749,37 @@ for (;;) break; case OP_NOT_DIGIT: - if (MAX_255(c) && (mb->ctypes[c] & ctype_digit) != 0) RRETURN(MATCH_NOMATCH); + if (MAX_255(fc) && (mb->ctypes[fc] & ctype_digit) != 0) + RRETURN(MATCH_NOMATCH); break; case OP_DIGIT: - if (!MAX_255(c) || (mb->ctypes[c] & ctype_digit) == 0) RRETURN(MATCH_NOMATCH); + if (!MAX_255(fc) || (mb->ctypes[fc] & ctype_digit) == 0) + RRETURN(MATCH_NOMATCH); break; case OP_NOT_WHITESPACE: - if (MAX_255(c) && (mb->ctypes[c] & ctype_space) != 0) RRETURN(MATCH_NOMATCH); + if (MAX_255(fc) && (mb->ctypes[fc] & ctype_space) != 0) + RRETURN(MATCH_NOMATCH); break; case OP_WHITESPACE: - if (!MAX_255(c) || (mb->ctypes[c] & ctype_space) == 0) RRETURN(MATCH_NOMATCH); + if (!MAX_255(fc) || (mb->ctypes[fc] & ctype_space) == 0) + RRETURN(MATCH_NOMATCH); break; case OP_NOT_WORDCHAR: - if (MAX_255(c) && (mb->ctypes[c] & ctype_word) != 0) RRETURN(MATCH_NOMATCH); + if (MAX_255(fc) && (mb->ctypes[fc] & ctype_word) != 0) + RRETURN(MATCH_NOMATCH); break; case OP_WORDCHAR: - if (!MAX_255(c) || (mb->ctypes[c] & ctype_word) == 0) RRETURN(MATCH_NOMATCH); + if (!MAX_255(fc) || (mb->ctypes[fc] & ctype_word) == 0) + RRETURN(MATCH_NOMATCH); break; default: - RRETURN(PCRE2_ERROR_INTERNAL); + return PCRE2_ERROR_INTERNAL; } } } @@ -5483,113 +3787,116 @@ for (;;) } /* If maximizing, it is worth using inline code for speed, doing the type - test once at the start (i.e. keep it out of the loop). Again, keep the - UTF-8 and UCP stuff separate. */ + test once at the start (i.e. keep it out of the loop). */ else { - pp = eptr; /* Remember where we started */ + Lstart_eptr = Feptr; /* Remember where we started */ #ifdef SUPPORT_UNICODE - if (prop_type >= 0) + if (proptype >= 0) { - switch(prop_type) + switch(proptype) { case PT_ANY: - for (i = min; i < max; i++) + for (i = Lmin; i < Lmax; i++) { int len = 1; - if (eptr >= mb->end_subject) + if (Feptr >= mb->end_subject) { SCHECK_PARTIAL(); break; } - GETCHARLENTEST(c, eptr, len); - if (prop_fail_result) break; - eptr+= len; + GETCHARLENTEST(fc, Feptr, len); + if (Lctype == OP_NOTPROP) break; + Feptr+= len; } break; case PT_LAMP: - for (i = min; i < max; i++) + for (i = Lmin; i < Lmax; i++) { int chartype; int len = 1; - if (eptr >= mb->end_subject) + if (Feptr >= mb->end_subject) { SCHECK_PARTIAL(); break; } - GETCHARLENTEST(c, eptr, len); - chartype = UCD_CHARTYPE(c); + GETCHARLENTEST(fc, Feptr, len); + chartype = UCD_CHARTYPE(fc); if ((chartype == ucp_Lu || chartype == ucp_Ll || - chartype == ucp_Lt) == prop_fail_result) + chartype == ucp_Lt) == (Lctype == OP_NOTPROP)) break; - eptr+= len; + Feptr+= len; } break; case PT_GC: - for (i = min; i < max; i++) + for (i = Lmin; i < Lmax; i++) { int len = 1; - if (eptr >= mb->end_subject) + if (Feptr >= mb->end_subject) { SCHECK_PARTIAL(); break; } - GETCHARLENTEST(c, eptr, len); - if ((UCD_CATEGORY(c) == prop_value) == prop_fail_result) break; - eptr+= len; + GETCHARLENTEST(fc, Feptr, len); + if ((UCD_CATEGORY(fc) == Lpropvalue) == (Lctype == OP_NOTPROP)) + break; + Feptr+= len; } break; case PT_PC: - for (i = min; i < max; i++) + for (i = Lmin; i < Lmax; i++) { int len = 1; - if (eptr >= mb->end_subject) + if (Feptr >= mb->end_subject) { SCHECK_PARTIAL(); break; } - GETCHARLENTEST(c, eptr, len); - if ((UCD_CHARTYPE(c) == prop_value) == prop_fail_result) break; - eptr+= len; + GETCHARLENTEST(fc, Feptr, len); + if ((UCD_CHARTYPE(fc) == Lpropvalue) == (Lctype == OP_NOTPROP)) + break; + Feptr+= len; } break; case PT_SC: - for (i = min; i < max; i++) + for (i = Lmin; i < Lmax; i++) { int len = 1; - if (eptr >= mb->end_subject) + if (Feptr >= mb->end_subject) { SCHECK_PARTIAL(); break; } - GETCHARLENTEST(c, eptr, len); - if ((UCD_SCRIPT(c) == prop_value) == prop_fail_result) break; - eptr+= len; + GETCHARLENTEST(fc, Feptr, len); + if ((UCD_SCRIPT(fc) == Lpropvalue) == (Lctype == OP_NOTPROP)) + break; + Feptr+= len; } break; case PT_ALNUM: - for (i = min; i < max; i++) + for (i = Lmin; i < Lmax; i++) { int category; int len = 1; - if (eptr >= mb->end_subject) + if (Feptr >= mb->end_subject) { SCHECK_PARTIAL(); break; } - GETCHARLENTEST(c, eptr, len); - category = UCD_CATEGORY(c); - if ((category == ucp_L || category == ucp_N) == prop_fail_result) + GETCHARLENTEST(fc, Feptr, len); + category = UCD_CATEGORY(fc); + if ((category == ucp_L || category == ucp_N) == + (Lctype == OP_NOTPROP)) break; - eptr+= len; + Feptr+= len; } break; @@ -5599,186 +3906,178 @@ for (;;) case PT_SPACE: /* Perl space */ case PT_PXSPACE: /* POSIX space */ - for (i = min; i < max; i++) + for (i = Lmin; i < Lmax; i++) { int len = 1; - if (eptr >= mb->end_subject) + if (Feptr >= mb->end_subject) { SCHECK_PARTIAL(); break; } - GETCHARLENTEST(c, eptr, len); - switch(c) + GETCHARLENTEST(fc, Feptr, len); + switch(fc) { HSPACE_CASES: VSPACE_CASES: - if (prop_fail_result) goto ENDLOOP99; /* Break the loop */ + if (Lctype == OP_NOTPROP) goto ENDLOOP99; /* Break the loop */ break; default: - if ((UCD_CATEGORY(c) == ucp_Z) == prop_fail_result) + if ((UCD_CATEGORY(fc) == ucp_Z) == (Lctype == OP_NOTPROP)) goto ENDLOOP99; /* Break the loop */ break; } - eptr+= len; + Feptr+= len; } ENDLOOP99: break; case PT_WORD: - for (i = min; i < max; i++) + for (i = Lmin; i < Lmax; i++) { int category; int len = 1; - if (eptr >= mb->end_subject) + if (Feptr >= mb->end_subject) { SCHECK_PARTIAL(); break; } - GETCHARLENTEST(c, eptr, len); - category = UCD_CATEGORY(c); + GETCHARLENTEST(fc, Feptr, len); + category = UCD_CATEGORY(fc); if ((category == ucp_L || category == ucp_N || - c == CHAR_UNDERSCORE) == prop_fail_result) + fc == CHAR_UNDERSCORE) == (Lctype == OP_NOTPROP)) break; - eptr+= len; + Feptr+= len; } break; case PT_CLIST: - for (i = min; i < max; i++) + for (i = Lmin; i < Lmax; i++) { const uint32_t *cp; int len = 1; - if (eptr >= mb->end_subject) + if (Feptr >= mb->end_subject) { SCHECK_PARTIAL(); break; } - GETCHARLENTEST(c, eptr, len); - cp = PRIV(ucd_caseless_sets) + prop_value; + GETCHARLENTEST(fc, Feptr, len); + cp = PRIV(ucd_caseless_sets) + Lpropvalue; for (;;) { - if (c < *cp) - { if (prop_fail_result) break; else goto GOT_MAX; } - if (c == *cp++) - { if (prop_fail_result) goto GOT_MAX; else break; } + if (fc < *cp) + { if (Lctype == OP_NOTPROP) break; else goto GOT_MAX; } + if (fc == *cp++) + { if (Lctype == OP_NOTPROP) goto GOT_MAX; else break; } } - eptr += len; + Feptr += len; } GOT_MAX: break; case PT_UCNC: - for (i = min; i < max; i++) + for (i = Lmin; i < Lmax; i++) { int len = 1; - if (eptr >= mb->end_subject) + if (Feptr >= mb->end_subject) { SCHECK_PARTIAL(); break; } - GETCHARLENTEST(c, eptr, len); - if ((c == CHAR_DOLLAR_SIGN || c == CHAR_COMMERCIAL_AT || - c == CHAR_GRAVE_ACCENT || (c >= 0xa0 && c <= 0xd7ff) || - c >= 0xe000) == prop_fail_result) + GETCHARLENTEST(fc, Feptr, len); + if ((fc == CHAR_DOLLAR_SIGN || fc == CHAR_COMMERCIAL_AT || + fc == CHAR_GRAVE_ACCENT || (fc >= 0xa0 && fc <= 0xd7ff) || + fc >= 0xe000) == (Lctype == OP_NOTPROP)) break; - eptr += len; + Feptr += len; } break; default: - RRETURN(PCRE2_ERROR_INTERNAL); + return PCRE2_ERROR_INTERNAL; } - /* eptr is now past the end of the maximum run */ + /* Feptr is now past the end of the maximum run */ - if (possessive) continue; /* No backtracking */ + if (reptype == REPTYPE_POS) continue; /* No backtracking */ - /* After \C in UTF mode, pp might be in the middle of a Unicode - character. Use <= pp to ensure backtracking doesn't go too far. */ + /* After \C in UTF mode, Lstart_eptr might be in the middle of a + Unicode character. Use <= pp to ensure backtracking doesn't go too far. + */ for(;;) { - if (eptr <= pp) goto TAIL_RECURSE; - RMATCH(eptr, ecode, offset_top, mb, eptrb, RM44); + if (Feptr <= Lstart_eptr) break; + RMATCH(Fecode, RM222); if (rrc != MATCH_NOMATCH) RRETURN(rrc); - eptr--; - if (utf) BACKCHAR(eptr); + Feptr--; + if (utf) BACKCHAR(Feptr); } } /* Match extended Unicode grapheme clusters. We will get here only if the support is in the binary; otherwise a compile-time error occurs. */ - else if (ctype == OP_EXTUNI) + else if (Lctype == OP_EXTUNI) { - for (i = min; i < max; i++) + for (i = Lmin; i < Lmax; i++) { - if (eptr >= mb->end_subject) + if (Feptr >= mb->end_subject) { SCHECK_PARTIAL(); break; } else { - int lgb, rgb; - GETCHARINCTEST(c, eptr); - lgb = UCD_GRAPHBREAK(c); - while (eptr < mb->end_subject) - { - int len = 1; - if (!utf) c = *eptr; else { GETCHARLEN(c, eptr, len); } - rgb = UCD_GRAPHBREAK(c); - if ((PRIV(ucp_gbtable)[lgb] & (1 << rgb)) == 0) break; - lgb = rgb; - eptr += len; - } + GETCHARINCTEST(fc, Feptr); + Feptr = PRIV(extuni)(fc, Feptr, mb->start_subject, mb->end_subject, + utf, NULL); } CHECK_PARTIAL(); } - /* eptr is now past the end of the maximum run */ + /* Feptr is now past the end of the maximum run */ - if (possessive) continue; /* No backtracking */ + if (reptype == REPTYPE_POS) continue; /* No backtracking */ - /* We use <= pp rather than == pp to detect the start of the run while - backtracking because the use of \C in UTF mode can cause BACKCHAR to - move back past pp. This is just palliative; the use of \C in UTF mode - is fraught with danger. */ + /* We use <= Lstart_eptr rather than == Lstart_eptr to detect the start + of the run while backtracking because the use of \C in UTF mode can + cause BACKCHAR to move back past Lstart_eptr. This is just palliative; + the use of \C in UTF mode is fraught with danger. */ for(;;) { int lgb, rgb; PCRE2_SPTR fptr; - if (eptr <= pp) goto TAIL_RECURSE; /* At start of char run */ - RMATCH(eptr, ecode, offset_top, mb, eptrb, RM45); + if (Feptr <= Lstart_eptr) break; /* At start of char run */ + RMATCH(Fecode, RM220); if (rrc != MATCH_NOMATCH) RRETURN(rrc); /* Backtracking over an extended grapheme cluster involves inspecting the previous two characters (if present) to see if a break is permitted between them. */ - eptr--; - if (!utf) c = *eptr; else + Feptr--; + if (!utf) fc = *Feptr; else { - BACKCHAR(eptr); - GETCHAR(c, eptr); + BACKCHAR(Feptr); + GETCHAR(fc, Feptr); } - rgb = UCD_GRAPHBREAK(c); + rgb = UCD_GRAPHBREAK(fc); for (;;) { - if (eptr <= pp) goto TAIL_RECURSE; /* At start of char run */ - fptr = eptr - 1; - if (!utf) c = *fptr; else + if (Feptr <= Lstart_eptr) break; /* At start of char run */ + fptr = Feptr - 1; + if (!utf) fc = *fptr; else { BACKCHAR(fptr); - GETCHAR(c, fptr); + GETCHAR(fc, fptr); } - lgb = UCD_GRAPHBREAK(c); + lgb = UCD_GRAPHBREAK(fc); if ((PRIV(ucp_gbtable)[lgb] & (1 << rgb)) == 0) break; - eptr = fptr; + Feptr = fptr; rgb = lgb; } } @@ -5790,325 +4089,328 @@ for (;;) #ifdef SUPPORT_UNICODE if (utf) { - switch(ctype) + switch(Lctype) { case OP_ANY: - for (i = min; i < max; i++) + for (i = Lmin; i < Lmax; i++) { - if (eptr >= mb->end_subject) + if (Feptr >= mb->end_subject) { SCHECK_PARTIAL(); break; } - if (IS_NEWLINE(eptr)) break; + if (IS_NEWLINE(Feptr)) break; if (mb->partial != 0 && /* Take care with CRLF partial */ - eptr + 1 >= mb->end_subject && + Feptr + 1 >= mb->end_subject && NLBLOCK->nltype == NLTYPE_FIXED && NLBLOCK->nllen == 2 && - UCHAR21(eptr) == NLBLOCK->nl[0]) + UCHAR21(Feptr) == NLBLOCK->nl[0]) { mb->hitend = TRUE; - if (mb->partial > 1) RRETURN(PCRE2_ERROR_PARTIAL); + if (mb->partial > 1) return PCRE2_ERROR_PARTIAL; } - eptr++; - ACROSSCHAR(eptr < mb->end_subject, *eptr, eptr++); + Feptr++; + ACROSSCHAR(Feptr < mb->end_subject, Feptr, Feptr++); } break; case OP_ALLANY: - if (max < INT_MAX) + if (Lmax < UINT32_MAX) { - for (i = min; i < max; i++) + for (i = Lmin; i < Lmax; i++) { - if (eptr >= mb->end_subject) + if (Feptr >= mb->end_subject) { SCHECK_PARTIAL(); break; } - eptr++; - ACROSSCHAR(eptr < mb->end_subject, *eptr, eptr++); + Feptr++; + ACROSSCHAR(Feptr < mb->end_subject, Feptr, Feptr++); } } else { - eptr = mb->end_subject; /* Unlimited UTF-8 repeat */ + Feptr = mb->end_subject; /* Unlimited UTF-8 repeat */ SCHECK_PARTIAL(); } break; - /* The byte case is the same as non-UTF8 */ + /* The "byte" (i.e. "code unit") case is the same as non-UTF */ case OP_ANYBYTE: - c = max - min; - if (c > (uint32_t)(mb->end_subject - eptr)) + fc = Lmax - Lmin; + if (fc > (uint32_t)(mb->end_subject - Feptr)) { - eptr = mb->end_subject; + Feptr = mb->end_subject; SCHECK_PARTIAL(); } - else eptr += c; + else Feptr += fc; break; case OP_ANYNL: - for (i = min; i < max; i++) + for (i = Lmin; i < Lmax; i++) { int len = 1; - if (eptr >= mb->end_subject) + if (Feptr >= mb->end_subject) { SCHECK_PARTIAL(); break; } - GETCHARLEN(c, eptr, len); - if (c == CHAR_CR) + GETCHARLEN(fc, Feptr, len); + if (fc == CHAR_CR) { - if (++eptr >= mb->end_subject) break; - if (UCHAR21(eptr) == CHAR_LF) eptr++; + if (++Feptr >= mb->end_subject) break; + if (UCHAR21(Feptr) == CHAR_LF) Feptr++; } else { - if (c != CHAR_LF && + if (fc != CHAR_LF && (mb->bsr_convention == PCRE2_BSR_ANYCRLF || - (c != CHAR_VT && c != CHAR_FF && c != CHAR_NEL + (fc != CHAR_VT && fc != CHAR_FF && fc != CHAR_NEL #ifndef EBCDIC - && c != 0x2028 && c != 0x2029 + && fc != 0x2028 && fc != 0x2029 #endif /* Not EBCDIC */ ))) break; - eptr += len; + Feptr += len; } } break; case OP_NOT_HSPACE: case OP_HSPACE: - for (i = min; i < max; i++) + for (i = Lmin; i < Lmax; i++) { BOOL gotspace; int len = 1; - if (eptr >= mb->end_subject) + if (Feptr >= mb->end_subject) { SCHECK_PARTIAL(); break; } - GETCHARLEN(c, eptr, len); - switch(c) + GETCHARLEN(fc, Feptr, len); + switch(fc) { HSPACE_CASES: gotspace = TRUE; break; default: gotspace = FALSE; break; } - if (gotspace == (ctype == OP_NOT_HSPACE)) break; - eptr += len; + if (gotspace == (Lctype == OP_NOT_HSPACE)) break; + Feptr += len; } break; case OP_NOT_VSPACE: case OP_VSPACE: - for (i = min; i < max; i++) + for (i = Lmin; i < Lmax; i++) { BOOL gotspace; int len = 1; - if (eptr >= mb->end_subject) + if (Feptr >= mb->end_subject) { SCHECK_PARTIAL(); break; } - GETCHARLEN(c, eptr, len); - switch(c) + GETCHARLEN(fc, Feptr, len); + switch(fc) { VSPACE_CASES: gotspace = TRUE; break; default: gotspace = FALSE; break; } - if (gotspace == (ctype == OP_NOT_VSPACE)) break; - eptr += len; + if (gotspace == (Lctype == OP_NOT_VSPACE)) break; + Feptr += len; } break; case OP_NOT_DIGIT: - for (i = min; i < max; i++) + for (i = Lmin; i < Lmax; i++) { int len = 1; - if (eptr >= mb->end_subject) + if (Feptr >= mb->end_subject) { SCHECK_PARTIAL(); break; } - GETCHARLEN(c, eptr, len); - if (c < 256 && (mb->ctypes[c] & ctype_digit) != 0) break; - eptr+= len; + GETCHARLEN(fc, Feptr, len); + if (fc < 256 && (mb->ctypes[fc] & ctype_digit) != 0) break; + Feptr+= len; } break; case OP_DIGIT: - for (i = min; i < max; i++) + for (i = Lmin; i < Lmax; i++) { int len = 1; - if (eptr >= mb->end_subject) + if (Feptr >= mb->end_subject) { SCHECK_PARTIAL(); break; } - GETCHARLEN(c, eptr, len); - if (c >= 256 ||(mb->ctypes[c] & ctype_digit) == 0) break; - eptr+= len; + GETCHARLEN(fc, Feptr, len); + if (fc >= 256 ||(mb->ctypes[fc] & ctype_digit) == 0) break; + Feptr+= len; } break; case OP_NOT_WHITESPACE: - for (i = min; i < max; i++) + for (i = Lmin; i < Lmax; i++) { int len = 1; - if (eptr >= mb->end_subject) + if (Feptr >= mb->end_subject) { SCHECK_PARTIAL(); break; } - GETCHARLEN(c, eptr, len); - if (c < 256 && (mb->ctypes[c] & ctype_space) != 0) break; - eptr+= len; + GETCHARLEN(fc, Feptr, len); + if (fc < 256 && (mb->ctypes[fc] & ctype_space) != 0) break; + Feptr+= len; } break; case OP_WHITESPACE: - for (i = min; i < max; i++) + for (i = Lmin; i < Lmax; i++) { int len = 1; - if (eptr >= mb->end_subject) + if (Feptr >= mb->end_subject) { SCHECK_PARTIAL(); break; } - GETCHARLEN(c, eptr, len); - if (c >= 256 ||(mb->ctypes[c] & ctype_space) == 0) break; - eptr+= len; + GETCHARLEN(fc, Feptr, len); + if (fc >= 256 ||(mb->ctypes[fc] & ctype_space) == 0) break; + Feptr+= len; } break; case OP_NOT_WORDCHAR: - for (i = min; i < max; i++) + for (i = Lmin; i < Lmax; i++) { int len = 1; - if (eptr >= mb->end_subject) + if (Feptr >= mb->end_subject) { SCHECK_PARTIAL(); break; } - GETCHARLEN(c, eptr, len); - if (c < 256 && (mb->ctypes[c] & ctype_word) != 0) break; - eptr+= len; + GETCHARLEN(fc, Feptr, len); + if (fc < 256 && (mb->ctypes[fc] & ctype_word) != 0) break; + Feptr+= len; } break; case OP_WORDCHAR: - for (i = min; i < max; i++) + for (i = Lmin; i < Lmax; i++) { int len = 1; - if (eptr >= mb->end_subject) + if (Feptr >= mb->end_subject) { SCHECK_PARTIAL(); break; } - GETCHARLEN(c, eptr, len); - if (c >= 256 || (mb->ctypes[c] & ctype_word) == 0) break; - eptr+= len; + GETCHARLEN(fc, Feptr, len); + if (fc >= 256 || (mb->ctypes[fc] & ctype_word) == 0) break; + Feptr+= len; } break; default: - RRETURN(PCRE2_ERROR_INTERNAL); + return PCRE2_ERROR_INTERNAL; } - if (possessive) continue; /* No backtracking */ + if (reptype == REPTYPE_POS) continue; /* No backtracking */ - /* After \C in UTF mode, pp might be in the middle of a Unicode - character. Use <= pp to ensure backtracking doesn't go too far. */ + /* After \C in UTF mode, Lstart_eptr might be in the middle of a + Unicode character. Use <= Lstart_eptr to ensure backtracking doesn't go + too far. */ for(;;) { - if (eptr <= pp) goto TAIL_RECURSE; - RMATCH(eptr, ecode, offset_top, mb, eptrb, RM46); + if (Feptr <= Lstart_eptr) break; + RMATCH(Fecode, RM221); if (rrc != MATCH_NOMATCH) RRETURN(rrc); - eptr--; - BACKCHAR(eptr); - if (ctype == OP_ANYNL && eptr > pp && UCHAR21(eptr) == CHAR_NL && - UCHAR21(eptr - 1) == CHAR_CR) eptr--; + Feptr--; + BACKCHAR(Feptr); + if (Lctype == OP_ANYNL && Feptr > Lstart_eptr && + UCHAR21(Feptr) == CHAR_NL && UCHAR21(Feptr - 1) == CHAR_CR) + Feptr--; } } else #endif /* SUPPORT_UNICODE */ + /* Not UTF mode */ { - switch(ctype) + switch(Lctype) { case OP_ANY: - for (i = min; i < max; i++) + for (i = Lmin; i < Lmax; i++) { - if (eptr >= mb->end_subject) + if (Feptr >= mb->end_subject) { SCHECK_PARTIAL(); break; } - if (IS_NEWLINE(eptr)) break; + if (IS_NEWLINE(Feptr)) break; if (mb->partial != 0 && /* Take care with CRLF partial */ - eptr + 1 >= mb->end_subject && + Feptr + 1 >= mb->end_subject && NLBLOCK->nltype == NLTYPE_FIXED && NLBLOCK->nllen == 2 && - *eptr == NLBLOCK->nl[0]) + *Feptr == NLBLOCK->nl[0]) { mb->hitend = TRUE; - if (mb->partial > 1) RRETURN(PCRE2_ERROR_PARTIAL); + if (mb->partial > 1) return PCRE2_ERROR_PARTIAL; } - eptr++; + Feptr++; } break; case OP_ALLANY: case OP_ANYBYTE: - c = max - min; - if (c > (uint32_t)(mb->end_subject - eptr)) + fc = Lmax - Lmin; + if (fc > (uint32_t)(mb->end_subject - Feptr)) { - eptr = mb->end_subject; + Feptr = mb->end_subject; SCHECK_PARTIAL(); } - else eptr += c; + else Feptr += fc; break; case OP_ANYNL: - for (i = min; i < max; i++) + for (i = Lmin; i < Lmax; i++) { - if (eptr >= mb->end_subject) + if (Feptr >= mb->end_subject) { SCHECK_PARTIAL(); break; } - c = *eptr; - if (c == CHAR_CR) + fc = *Feptr; + if (fc == CHAR_CR) { - if (++eptr >= mb->end_subject) break; - if (*eptr == CHAR_LF) eptr++; + if (++Feptr >= mb->end_subject) break; + if (*Feptr == CHAR_LF) Feptr++; } else { - if (c != CHAR_LF && (mb->bsr_convention == PCRE2_BSR_ANYCRLF || - (c != CHAR_VT && c != CHAR_FF && c != CHAR_NEL + if (fc != CHAR_LF && (mb->bsr_convention == PCRE2_BSR_ANYCRLF || + (fc != CHAR_VT && fc != CHAR_FF && fc != CHAR_NEL #if PCRE2_CODE_UNIT_WIDTH != 8 - && c != 0x2028 && c != 0x2029 + && fc != 0x2028 && fc != 0x2029 #endif ))) break; - eptr++; + Feptr++; } } break; case OP_NOT_HSPACE: - for (i = min; i < max; i++) + for (i = Lmin; i < Lmax; i++) { - if (eptr >= mb->end_subject) + if (Feptr >= mb->end_subject) { SCHECK_PARTIAL(); break; } - switch(*eptr) + switch(*Feptr) { - default: eptr++; break; + default: Feptr++; break; HSPACE_BYTE_CASES: #if PCRE2_CODE_UNIT_WIDTH != 8 HSPACE_MULTIBYTE_CASES: @@ -6120,37 +4422,37 @@ for (;;) break; case OP_HSPACE: - for (i = min; i < max; i++) + for (i = Lmin; i < Lmax; i++) { - if (eptr >= mb->end_subject) + if (Feptr >= mb->end_subject) { SCHECK_PARTIAL(); break; } - switch(*eptr) + switch(*Feptr) { default: goto ENDLOOP01; HSPACE_BYTE_CASES: #if PCRE2_CODE_UNIT_WIDTH != 8 HSPACE_MULTIBYTE_CASES: #endif - eptr++; break; + Feptr++; break; } } ENDLOOP01: break; case OP_NOT_VSPACE: - for (i = min; i < max; i++) + for (i = Lmin; i < Lmax; i++) { - if (eptr >= mb->end_subject) + if (Feptr >= mb->end_subject) { SCHECK_PARTIAL(); break; } - switch(*eptr) + switch(*Feptr) { - default: eptr++; break; + default: Feptr++; break; VSPACE_BYTE_CASES: #if PCRE2_CODE_UNIT_WIDTH != 8 VSPACE_MULTIBYTE_CASES: @@ -6162,251 +4464,1494 @@ for (;;) break; case OP_VSPACE: - for (i = min; i < max; i++) + for (i = Lmin; i < Lmax; i++) { - if (eptr >= mb->end_subject) + if (Feptr >= mb->end_subject) { SCHECK_PARTIAL(); break; } - switch(*eptr) + switch(*Feptr) { default: goto ENDLOOP03; VSPACE_BYTE_CASES: #if PCRE2_CODE_UNIT_WIDTH != 8 VSPACE_MULTIBYTE_CASES: #endif - eptr++; break; + Feptr++; break; } } ENDLOOP03: break; case OP_NOT_DIGIT: - for (i = min; i < max; i++) + for (i = Lmin; i < Lmax; i++) { - if (eptr >= mb->end_subject) + if (Feptr >= mb->end_subject) { SCHECK_PARTIAL(); break; } - if (MAX_255(*eptr) && (mb->ctypes[*eptr] & ctype_digit) != 0) break; - eptr++; + if (MAX_255(*Feptr) && (mb->ctypes[*Feptr] & ctype_digit) != 0) + break; + Feptr++; } break; case OP_DIGIT: - for (i = min; i < max; i++) + for (i = Lmin; i < Lmax; i++) { - if (eptr >= mb->end_subject) + if (Feptr >= mb->end_subject) { SCHECK_PARTIAL(); break; } - if (!MAX_255(*eptr) || (mb->ctypes[*eptr] & ctype_digit) == 0) break; - eptr++; + if (!MAX_255(*Feptr) || (mb->ctypes[*Feptr] & ctype_digit) == 0) + break; + Feptr++; } break; case OP_NOT_WHITESPACE: - for (i = min; i < max; i++) + for (i = Lmin; i < Lmax; i++) { - if (eptr >= mb->end_subject) + if (Feptr >= mb->end_subject) { SCHECK_PARTIAL(); break; } - if (MAX_255(*eptr) && (mb->ctypes[*eptr] & ctype_space) != 0) break; - eptr++; + if (MAX_255(*Feptr) && (mb->ctypes[*Feptr] & ctype_space) != 0) + break; + Feptr++; } break; case OP_WHITESPACE: - for (i = min; i < max; i++) + for (i = Lmin; i < Lmax; i++) { - if (eptr >= mb->end_subject) + if (Feptr >= mb->end_subject) { SCHECK_PARTIAL(); break; } - if (!MAX_255(*eptr) || (mb->ctypes[*eptr] & ctype_space) == 0) break; - eptr++; + if (!MAX_255(*Feptr) || (mb->ctypes[*Feptr] & ctype_space) == 0) + break; + Feptr++; } break; case OP_NOT_WORDCHAR: - for (i = min; i < max; i++) + for (i = Lmin; i < Lmax; i++) { - if (eptr >= mb->end_subject) + if (Feptr >= mb->end_subject) { SCHECK_PARTIAL(); break; } - if (MAX_255(*eptr) && (mb->ctypes[*eptr] & ctype_word) != 0) break; - eptr++; + if (MAX_255(*Feptr) && (mb->ctypes[*Feptr] & ctype_word) != 0) + break; + Feptr++; } break; case OP_WORDCHAR: - for (i = min; i < max; i++) + for (i = Lmin; i < Lmax; i++) { - if (eptr >= mb->end_subject) + if (Feptr >= mb->end_subject) { SCHECK_PARTIAL(); break; } - if (!MAX_255(*eptr) || (mb->ctypes[*eptr] & ctype_word) == 0) break; - eptr++; + if (!MAX_255(*Feptr) || (mb->ctypes[*Feptr] & ctype_word) == 0) + break; + Feptr++; } break; default: - RRETURN(PCRE2_ERROR_INTERNAL); + return PCRE2_ERROR_INTERNAL; } - if (possessive) continue; /* No backtracking */ + if (reptype == REPTYPE_POS) continue; /* No backtracking */ + for (;;) { - if (eptr == pp) goto TAIL_RECURSE; - RMATCH(eptr, ecode, offset_top, mb, eptrb, RM47); + if (Feptr == Lstart_eptr) break; + RMATCH(Fecode, RM34); if (rrc != MATCH_NOMATCH) RRETURN(rrc); - eptr--; - if (ctype == OP_ANYNL && eptr > pp && *eptr == CHAR_LF && - eptr[-1] == CHAR_CR) eptr--; + Feptr--; + if (Lctype == OP_ANYNL && Feptr > Lstart_eptr && *Feptr == CHAR_LF && + Feptr[-1] == CHAR_CR) Feptr--; } } + } + break; /* End of repeat character type processing */ + +#undef Lstart_eptr +#undef Lmin +#undef Lmax +#undef Lctype +#undef Lpropvalue + + + /* ===================================================================== */ + /* Match a back reference, possibly repeatedly. Look past the end of the + item to see if there is repeat information following. The OP_REF and + OP_REFI opcodes are used for a reference to a numbered group or to a + non-duplicated named group. For a duplicated named group, OP_DNREF and + OP_DNREFI are used. In this case we must scan the list of groups to which + the name refers, and use the first one that is set. */ + +#define Lmin F->temp_32[0] +#define Lmax F->temp_32[1] +#define Lcaseless F->temp_32[2] +#define Lstart F->temp_sptr[0] +#define Loffset F->temp_size + + case OP_DNREF: + case OP_DNREFI: + Lcaseless = (Fop == OP_DNREFI); + { + int count = GET2(Fecode, 1+IMM2_SIZE); + PCRE2_SPTR slot = mb->name_table + GET2(Fecode, 1) * mb->name_entry_size; + Fecode += 1 + 2*IMM2_SIZE; + + while (count-- > 0) + { + Loffset = (GET2(slot, 0) << 1) - 2; + if (Loffset < Foffset_top && Fovector[Loffset] != PCRE2_UNSET) break; + slot += mb->name_entry_size; + } + } + goto REF_REPEAT; + case OP_REF: + case OP_REFI: + Lcaseless = (Fop == OP_REFI); + Loffset = (GET2(Fecode, 1) << 1) - 2; + Fecode += 1 + IMM2_SIZE; + + /* Set up for repetition, or handle the non-repeated case. The maximum and + minimum must be in the heap frame, but as they are short-term values, we + use temporary fields. */ + + REF_REPEAT: + switch (*Fecode) + { + case OP_CRSTAR: + case OP_CRMINSTAR: + case OP_CRPLUS: + case OP_CRMINPLUS: + case OP_CRQUERY: + case OP_CRMINQUERY: + fc = *Fecode++ - OP_CRSTAR; + Lmin = rep_min[fc]; + Lmax = rep_max[fc]; + reptype = rep_typ[fc]; + break; + + case OP_CRRANGE: + case OP_CRMINRANGE: + Lmin = GET2(Fecode, 1); + Lmax = GET2(Fecode, 1 + IMM2_SIZE); + reptype = rep_typ[*Fecode - OP_CRSTAR]; + if (Lmax == 0) Lmax = UINT32_MAX; /* Max 0 => infinity */ + Fecode += 1 + 2 * IMM2_SIZE; + break; + + default: /* No repeat follows */ + { + rrc = match_ref(Loffset, Lcaseless, F, mb, &length); + if (rrc != 0) + { + if (rrc > 0) Feptr = mb->end_subject; /* Partial match */ + CHECK_PARTIAL(); + RRETURN(MATCH_NOMATCH); + } + } + Feptr += length; + continue; /* With the main loop */ + } + + /* Handle repeated back references. If a set group has length zero, just + continue with the main loop, because it matches however many times. For an + unset reference, if the minimum is zero, we can also just continue. We can + also continue if PCRE2_MATCH_UNSET_BACKREF is set, because this makes unset + group behave as a zero-length group. For any other unset cases, carrying + on will result in NOMATCH. */ + + if (Loffset < Foffset_top && Fovector[Loffset] != PCRE2_UNSET) + { + if (Fovector[Loffset] == Fovector[Loffset + 1]) continue; + } + else /* Group is not set */ + { + if (Lmin == 0 || (mb->poptions & PCRE2_MATCH_UNSET_BACKREF) != 0) + continue; + } + + /* First, ensure the minimum number of matches are present. */ + + for (i = 1; i <= Lmin; i++) + { + PCRE2_SIZE slength; + rrc = match_ref(Loffset, Lcaseless, F, mb, &slength); + if (rrc != 0) + { + if (rrc > 0) Feptr = mb->end_subject; /* Partial match */ + CHECK_PARTIAL(); + RRETURN(MATCH_NOMATCH); + } + Feptr += slength; + } + + /* If min = max, we are done. They are not both allowed to be zero. */ + + if (Lmin == Lmax) continue; + + /* If minimizing, keep trying and advancing the pointer. */ + + if (reptype == REPTYPE_MIN) + { + for (;;) + { + PCRE2_SIZE slength; + RMATCH(Fecode, RM20); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + if (Lmin++ >= Lmax) RRETURN(MATCH_NOMATCH); + rrc = match_ref(Loffset, Lcaseless, F, mb, &slength); + if (rrc != 0) + { + if (rrc > 0) Feptr = mb->end_subject; /* Partial match */ + CHECK_PARTIAL(); + RRETURN(MATCH_NOMATCH); + } + Feptr += slength; + } /* Control never gets here */ } - /* There's been some horrible disaster. Arrival here can only mean there is - something seriously wrong in the code above or the OP_xxx definitions. */ + /* If maximizing, find the longest string and work backwards, as long as + the matched lengths for each iteration are the same. */ - default: - RRETURN(PCRE2_ERROR_INTERNAL); - } + else + { + BOOL samelengths = TRUE; + Lstart = Feptr; /* Starting position */ + Flength = Fovector[Loffset+1] - Fovector[Loffset]; - /* Do not stick any code in here without much thought; it is assumed - that "continue" in the code above comes out to here to repeat the main - loop. */ + for (i = Lmin; i < Lmax; i++) + { + PCRE2_SIZE slength; + rrc = match_ref(Loffset, Lcaseless, F, mb, &slength); + if (rrc != 0) + { + /* Can't use CHECK_PARTIAL because we don't want to update Feptr in + the soft partial matching case. */ - } /* End of main loop */ -/* Control never reaches here */ + if (rrc > 0 && mb->partial != 0 && + mb->end_subject > mb->start_used_ptr) + { + mb->hitend = TRUE; + if (mb->partial > 1) return PCRE2_ERROR_PARTIAL; + } + break; + } + if (slength != Flength) samelengths = FALSE; + Feptr += slength; + } -/* When compiling to use the heap rather than the stack for recursive calls to -match(), the RRETURN() macro jumps here. The number that is saved in -frame->Xwhere indicates which label we actually want to return to. */ + /* If the length matched for each repetition is the same as the length of + the captured group, we can easily work backwards. This is the normal + case. However, in caseless UTF-8 mode there are pairs of case-equivalent + characters whose lengths (in terms of code units) differ. However, this + is very rare, so we handle it by re-matching fewer and fewer times. */ -#ifdef HEAP_MATCH_RECURSE -#define LBL(val) case val: goto L_RM##val; -HEAP_RETURN: -switch (frame->Xwhere) - { - LBL( 1) LBL( 2) LBL( 3) LBL( 4) LBL( 5) LBL( 6) LBL( 7) LBL( 8) - LBL( 9) LBL(10) LBL(11) LBL(12) LBL(13) LBL(14) LBL(15) LBL(17) - LBL(19) LBL(24) LBL(25) LBL(26) LBL(27) LBL(29) LBL(31) LBL(33) - LBL(35) LBL(43) LBL(47) LBL(48) LBL(49) LBL(50) LBL(51) LBL(52) - LBL(53) LBL(54) LBL(55) LBL(56) LBL(57) LBL(58) LBL(63) LBL(64) - LBL(65) LBL(66) LBL(68) -#ifdef SUPPORT_WIDE_CHARS - LBL(20) LBL(21) + if (samelengths) + { + while (Feptr >= Lstart) + { + RMATCH(Fecode, RM21); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + Feptr -= Flength; + } + } + + /* The rare case of non-matching lengths. Re-scan the repetition for each + iteration. We know that match_ref() will succeed every time. */ + + else + { + Lmax = i; + for (;;) + { + RMATCH(Fecode, RM22); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + if (Feptr == Lstart) break; /* Failed after minimal repetition */ + Feptr = Lstart; + Lmax--; + for (i = Lmin; i < Lmax; i++) + { + PCRE2_SIZE slength; + (void)match_ref(Loffset, Lcaseless, F, mb, &slength); + Feptr += slength; + } + } + } + + RRETURN(MATCH_NOMATCH); + } + /* Control never gets here */ + +#undef Lcaseless +#undef Lmin +#undef Lmax +#undef Lstart +#undef Loffset + + + +/* ========================================================================= */ +/* Opcodes for the start of various parenthesized items */ +/* ========================================================================= */ + + /* In all cases, if the result of RMATCH() is MATCH_THEN, check whether the + (*THEN) is within the current branch by comparing the address of OP_THEN + that is passed back with the end of the branch. If (*THEN) is within the + current branch, and the branch is one of two or more alternatives (it + either starts or ends with OP_ALT), we have reached the limit of THEN's + action, so convert the return code to NOMATCH, which will cause normal + backtracking to happen from now on. Otherwise, THEN is passed back to an + outer alternative. This implements Perl's treatment of parenthesized + groups, where a group not containing | does not affect the current + alternative, that is, (X) is NOT the same as (X|(*F)). */ + + + /* ===================================================================== */ + /* BRAZERO, BRAMINZERO and SKIPZERO occur just before a non-possessive + bracket group, indicating that it may occur zero times. It may repeat + infinitely, or not at all - i.e. it could be ()* or ()? or even (){0} in + the pattern. Brackets with fixed upper repeat limits are compiled as a + number of copies, with the optional ones preceded by BRAZERO or BRAMINZERO. + Possessive groups with possible zero repeats are preceded by BRAPOSZERO. */ + +#define Lnext_ecode F->temp_sptr[0] + + case OP_BRAZERO: + Lnext_ecode = Fecode + 1; + RMATCH(Lnext_ecode, RM9); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + do Lnext_ecode += GET(Lnext_ecode, 1); while (*Lnext_ecode == OP_ALT); + Fecode = Lnext_ecode + 1 + LINK_SIZE; + break; + + case OP_BRAMINZERO: + Lnext_ecode = Fecode + 1; + do Lnext_ecode += GET(Lnext_ecode, 1); while (*Lnext_ecode == OP_ALT); + RMATCH(Lnext_ecode + 1 + LINK_SIZE, RM10); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + Fecode++; + break; + +#undef Lnext_ecode + + case OP_SKIPZERO: + Fecode++; + do Fecode += GET(Fecode,1); while (*Fecode == OP_ALT); + Fecode += 1 + LINK_SIZE; + break; + + + /* ===================================================================== */ + /* Handle possessive brackets with an unlimited repeat. The end of these + brackets will always be OP_KETRPOS, which returns MATCH_KETRPOS without + going further in the pattern. */ + +#define Lframe_type F->temp_32[0] +#define Lmatched_once F->temp_32[1] +#define Lzero_allowed F->temp_32[2] +#define Lstart_eptr F->temp_sptr[0] +#define Lstart_group F->temp_sptr[1] + + case OP_BRAPOSZERO: + Lzero_allowed = TRUE; /* Zero repeat is allowed */ + Fecode += 1; + if (*Fecode == OP_CBRAPOS || *Fecode == OP_SCBRAPOS) + goto POSSESSIVE_CAPTURE; + goto POSSESSIVE_NON_CAPTURE; + + case OP_BRAPOS: + case OP_SBRAPOS: + Lzero_allowed = FALSE; /* Zero repeat not allowed */ + + POSSESSIVE_NON_CAPTURE: + Lframe_type = GF_NOCAPTURE; /* Remembered frame type */ + goto POSSESSIVE_GROUP; + + case OP_CBRAPOS: + case OP_SCBRAPOS: + Lzero_allowed = FALSE; /* Zero repeat not allowed */ + + POSSESSIVE_CAPTURE: + number = GET2(Fecode, 1+LINK_SIZE); + Lframe_type = GF_CAPTURE | number; /* Remembered frame type */ + + POSSESSIVE_GROUP: + Lmatched_once = FALSE; /* Never matched */ + Lstart_group = Fecode; /* Start of this group */ + + for (;;) + { + Lstart_eptr = Feptr; /* Position at group start */ + group_frame_type = Lframe_type; + RMATCH(Fecode + PRIV(OP_lengths)[*Fecode], RM8); + if (rrc == MATCH_KETRPOS) + { + Lmatched_once = TRUE; /* Matched at least once */ + if (Feptr == Lstart_eptr) /* Empty match; skip to end */ + { + do Fecode += GET(Fecode, 1); while (*Fecode == OP_ALT); + break; + } + + Fecode = Lstart_group; + continue; + } + + /* See comment above about handling THEN. */ + + if (rrc == MATCH_THEN) + { + PCRE2_SPTR next_ecode = Fecode + GET(Fecode,1); + if (mb->verb_ecode_ptr < next_ecode && + (*Fecode == OP_ALT || *next_ecode == OP_ALT)) + rrc = MATCH_NOMATCH; + } + + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + Fecode += GET(Fecode, 1); + if (*Fecode != OP_ALT) break; + } + + /* Success if matched something or zero repeat allowed */ + + if (Lmatched_once || Lzero_allowed) + { + Fecode += 1 + LINK_SIZE; + break; + } + + RRETURN(MATCH_NOMATCH); + +#undef Lmatched_once +#undef Lzero_allowed +#undef Lframe_type +#undef Lstart_eptr +#undef Lstart_group + + + /* ===================================================================== */ + /* Handle non-capturing brackets that cannot match an empty string. When we + get to the final alternative within the brackets, as long as there are no + THEN's in the pattern, we can optimize by not recording a new backtracking + point. (Ideally we should test for a THEN within this group, but we don't + have that information.) Don't do this if we are at the very top level, + however, because that would make handling assertions and once-only brackets + messier when there is nothing to go back to. */ + +#define Lframe_type F->temp_32[0] /* Set for all that use GROUPLOOP */ +#define Lnext_branch F->temp_sptr[0] /* Used only in OP_BRA handling */ + + case OP_BRA: + if (mb->hasthen || Frdepth == 0) + { + Lframe_type = 0; + goto GROUPLOOP; + } + + for (;;) + { + Lnext_branch = Fecode + GET(Fecode, 1); + if (*Lnext_branch != OP_ALT) break; + + /* This is never the final branch. We do not need to test for MATCH_THEN + here because this code is not used when there is a THEN in the pattern. */ + + RMATCH(Fecode + PRIV(OP_lengths)[*Fecode], RM1); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + Fecode = Lnext_branch; + } + + /* Hit the start of the final branch. Continue at this level. */ + + Fecode += PRIV(OP_lengths)[*Fecode]; + break; + +#undef Lnext_branch + + + /* ===================================================================== */ + /* Handle a capturing bracket, other than those that are possessive with an + unlimited repeat. */ + + case OP_CBRA: + case OP_SCBRA: + Lframe_type = GF_CAPTURE | GET2(Fecode, 1+LINK_SIZE); + goto GROUPLOOP; + + + /* ===================================================================== */ + /* Atomic groups and non-capturing brackets that can match an empty string + must record a backtracking point and also set up a chained frame. */ + + case OP_ONCE: + case OP_SBRA: + Lframe_type = GF_NOCAPTURE | Fop; + + GROUPLOOP: + for (;;) + { + group_frame_type = Lframe_type; + RMATCH(Fecode + PRIV(OP_lengths)[*Fecode], RM2); + if (rrc == MATCH_THEN) + { + PCRE2_SPTR next_ecode = Fecode + GET(Fecode,1); + if (mb->verb_ecode_ptr < next_ecode && + (*Fecode == OP_ALT || *next_ecode == OP_ALT)) + rrc = MATCH_NOMATCH; + } + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + Fecode += GET(Fecode, 1); + if (*Fecode != OP_ALT) RRETURN(MATCH_NOMATCH); + } + /* Control never reaches here. */ + +#undef Lframe_type + + + /* ===================================================================== */ + /* Recursion either matches the current regex, or some subexpression. The + offset data is the offset to the starting bracket from the start of the + whole pattern. (This is so that it works from duplicated subpatterns.) */ + +#define Lframe_type F->temp_32[0] +#define Lstart_branch F->temp_sptr[0] + + case OP_RECURSE: + bracode = mb->start_code + GET(Fecode, 1); + number = (bracode == mb->start_code)? 0 : GET2(bracode, 1 + LINK_SIZE); + + /* If we are already in a recursion, check for repeating the same one + without advancing the subject pointer. This should catch convoluted mutual + recursions. (Some simple cases are caught at compile time.) */ + + if (Fcurrent_recurse != RECURSE_UNSET) + { + offset = Flast_group_offset; + while (offset != PCRE2_UNSET) + { + N = (heapframe *)((char *)mb->match_frames + offset); + P = (heapframe *)((char *)N - frame_size); + if (N->group_frame_type == (GF_RECURSE | number)) + { + if (Feptr == P->eptr) return PCRE2_ERROR_RECURSELOOP; + break; + } + offset = P->last_group_offset; + } + } + + /* Now run the recursion, branch by branch. */ + + Lstart_branch = bracode; + Lframe_type = GF_RECURSE | number; + + for (;;) + { + PCRE2_SPTR next_ecode; + + group_frame_type = Lframe_type; + RMATCH(Lstart_branch + PRIV(OP_lengths)[*Lstart_branch], RM11); + next_ecode = Lstart_branch + GET(Lstart_branch,1); + + /* Handle backtracking verbs, which are defined in a range that can + easily be tested for. PCRE does not allow THEN, SKIP, PRUNE or COMMIT to + escape beyond a recursion; they cause a NOMATCH for the entire recursion. + + When one of these verbs triggers, the current recursion group number is + recorded. If it matches the recursion we are processing, the verb + happened within the recursion and we must deal with it. Otherwise it must + have happened after the recursion completed, and so has to be passed + back. See comment above about handling THEN. */ + + if (rrc >= MATCH_BACKTRACK_MIN && rrc <= MATCH_BACKTRACK_MAX && + mb->verb_current_recurse == (Lframe_type ^ GF_RECURSE)) + { + if (rrc == MATCH_THEN && mb->verb_ecode_ptr < next_ecode && + (*Lstart_branch == OP_ALT || *next_ecode == OP_ALT)) + rrc = MATCH_NOMATCH; + else RRETURN(MATCH_NOMATCH); + } + + /* Note that carrying on after (*ACCEPT) in a recursion is handled in the + OP_ACCEPT code. Nothing needs to be done here. */ + + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + Lstart_branch = next_ecode; + if (*Lstart_branch != OP_ALT) RRETURN(MATCH_NOMATCH); + } + /* Control never reaches here. */ + +#undef Lframe_type +#undef Lstart_branch + + + /* ===================================================================== */ + /* Positive assertions are like other groups except that PCRE doesn't allow + the effect of (*THEN) to escape beyond an assertion; it is therefore + treated as NOMATCH. (*ACCEPT) is treated as successful assertion, with its + captures retained. Any other return is an error. */ + +#define Lframe_type F->temp_32[0] + + case OP_ASSERT: + case OP_ASSERTBACK: + Lframe_type = GF_NOCAPTURE | Fop; + for (;;) + { + group_frame_type = Lframe_type; + RMATCH(Fecode + PRIV(OP_lengths)[*Fecode], RM3); + if (rrc == MATCH_ACCEPT) + { + memcpy(Fovector, + (char *)assert_accept_frame + offsetof(heapframe, ovector), + assert_accept_frame->offset_top * sizeof(PCRE2_SIZE)); + Foffset_top = assert_accept_frame->offset_top; + break; + } + if (rrc != MATCH_NOMATCH && rrc != MATCH_THEN) RRETURN(rrc); + Fecode += GET(Fecode, 1); + if (*Fecode != OP_ALT) RRETURN(MATCH_NOMATCH); + } + + do Fecode += GET(Fecode, 1); while (*Fecode == OP_ALT); + Fecode += 1 + LINK_SIZE; + break; + +#undef Lframe_type + + + /* ===================================================================== */ + /* Handle negative assertions. Loop for each non-matching branch as for + positive assertions. */ + +#define Lframe_type F->temp_32[0] + + case OP_ASSERT_NOT: + case OP_ASSERTBACK_NOT: + Lframe_type = GF_NOCAPTURE | Fop; + + for (;;) + { + group_frame_type = Lframe_type; + RMATCH(Fecode + PRIV(OP_lengths)[*Fecode], RM4); + switch(rrc) + { + case MATCH_ACCEPT: /* Assertion matched, therefore it fails. */ + case MATCH_MATCH: + RRETURN (MATCH_NOMATCH); + + case MATCH_NOMATCH: /* Branch failed, try next if present. */ + case MATCH_THEN: + Fecode += GET(Fecode, 1); + if (*Fecode != OP_ALT) goto ASSERT_NOT_FAILED; + break; + + case MATCH_COMMIT: /* Assertion forced to fail, therefore continue. */ + case MATCH_SKIP: + case MATCH_PRUNE: + do Fecode += GET(Fecode, 1); while (*Fecode == OP_ALT); + goto ASSERT_NOT_FAILED; + + default: /* Pass back any other return */ + RRETURN(rrc); + } + } + + /* None of the branches have matched or there was a backtrack to (*COMMIT), + (*SKIP), (*PRUNE), or (*THEN) in the last branch. This is success for a + negative assertion, so carry on. */ + + ASSERT_NOT_FAILED: + Fecode += 1 + LINK_SIZE; + break; + +#undef Lframe_type + + + /* ===================================================================== */ + /* The callout item calls an external function, if one is provided, passing + details of the match so far. This is mainly for debugging, though the + function is able to force a failure. */ + + case OP_CALLOUT: + case OP_CALLOUT_STR: + rrc = do_callout(F, mb, &length); + if (rrc > 0) RRETURN(MATCH_NOMATCH); + if (rrc < 0) RRETURN(rrc); + Fecode += length; + break; + + + /* ===================================================================== */ + /* Conditional group: compilation checked that there are no more than two + branches. If the condition is false, skipping the first branch takes us + past the end of the item if there is only one branch, but that's exactly + what we want. */ + + case OP_COND: + case OP_SCOND: + + /* The variable Flength will be added to Fecode when the condition is + false, to get to the second branch. Setting it to the offset to the ALT or + KET, then incrementing Fecode achieves this effect. However, if the second + branch is non-existent, we must point to the KET so that the end of the + group is correctly processed. We now have Fecode pointing to the condition + or callout. */ + + Flength = GET(Fecode, 1); /* Offset to the second branch */ + if (Fecode[Flength] != OP_ALT) Flength -= 1 + LINK_SIZE; + Fecode += 1 + LINK_SIZE; /* From this opcode */ + + /* Because of the way auto-callout works during compile, a callout item is + inserted between OP_COND and an assertion condition. Such a callout can + also be inserted manually. */ + + if (*Fecode == OP_CALLOUT || *Fecode == OP_CALLOUT_STR) + { + rrc = do_callout(F, mb, &length); + if (rrc > 0) RRETURN(MATCH_NOMATCH); + if (rrc < 0) RRETURN(rrc); + + /* Advance Fecode past the callout, so it now points to the condition. We + must adjust Flength so that the value of Fecode+Flength is unchanged. */ + + Fecode += length; + Flength -= length; + } + + /* Test the various possible conditions */ + + condition = FALSE; + switch(*Fecode) + { + case OP_RREF: /* Group recursion test */ + if (Fcurrent_recurse != RECURSE_UNSET) + { + number = GET2(Fecode, 1); + condition = (number == RREF_ANY || number == Fcurrent_recurse); + } + break; + + case OP_DNRREF: /* Duplicate named group recursion test */ + if (Fcurrent_recurse != RECURSE_UNSET) + { + int count = GET2(Fecode, 1 + IMM2_SIZE); + PCRE2_SPTR slot = mb->name_table + GET2(Fecode, 1) * mb->name_entry_size; + while (count-- > 0) + { + number = GET2(slot, 0); + condition = number == Fcurrent_recurse; + if (condition) break; + slot += mb->name_entry_size; + } + } + break; + + case OP_CREF: /* Numbered group used test */ + offset = (GET2(Fecode, 1) << 1) - 2; /* Doubled ref number */ + condition = offset < Foffset_top && Fovector[offset] != PCRE2_UNSET; + break; + + case OP_DNCREF: /* Duplicate named group used test */ + { + int count = GET2(Fecode, 1 + IMM2_SIZE); + PCRE2_SPTR slot = mb->name_table + GET2(Fecode, 1) * mb->name_entry_size; + while (count-- > 0) + { + offset = (GET2(slot, 0) << 1) - 2; + condition = offset < Foffset_top && Fovector[offset] != PCRE2_UNSET; + if (condition) break; + slot += mb->name_entry_size; + } + } + break; + + case OP_FALSE: + case OP_FAIL: /* The assertion (?!) becomes OP_FAIL */ + break; + + case OP_TRUE: + condition = TRUE; + break; + + /* The condition is an assertion. Run code similar to the assertion code + above. */ + +#define Lpositive F->temp_32[0] +#define Lstart_branch F->temp_sptr[0] + + default: + Lpositive = (*Fecode == OP_ASSERT || *Fecode == OP_ASSERTBACK); + Lstart_branch = Fecode; + + for (;;) + { + group_frame_type = GF_CONDASSERT | *Fecode; + RMATCH(Lstart_branch + PRIV(OP_lengths)[*Lstart_branch], RM5); + + switch(rrc) + { + case MATCH_ACCEPT: /* Save captures */ + memcpy(Fovector, + (char *)assert_accept_frame + offsetof(heapframe, ovector), + assert_accept_frame->offset_top * sizeof(PCRE2_SIZE)); + Foffset_top = assert_accept_frame->offset_top; + + /* Fall through */ + /* In the case of a match, the captures have already been put into + the current frame. */ + + case MATCH_MATCH: + condition = Lpositive; /* TRUE for positive assertion */ + break; + + /* PCRE doesn't allow the effect of (*THEN) to escape beyond an + assertion; it is therefore always treated as NOMATCH. */ + + case MATCH_NOMATCH: + case MATCH_THEN: + Lstart_branch += GET(Lstart_branch, 1); + if (*Lstart_branch == OP_ALT) continue; /* Try next branch */ + condition = !Lpositive; /* TRUE for negative assertion */ + break; + + /* These force no match without checking other branches. */ + + case MATCH_COMMIT: + case MATCH_SKIP: + case MATCH_PRUNE: + condition = !Lpositive; + break; + + default: + RRETURN(rrc); + } + break; /* Out of the branch loop */ + } + + /* If the condition is true, find the end of the assertion so that + advancing past it gets us to the start of the first branch. */ + + if (condition) + { + do Fecode += GET(Fecode, 1); while (*Fecode == OP_ALT); + } + break; /* End of assertion condition */ + } + +#undef Lpositive +#undef Lstart_branch + + /* Choose branch according to the condition. */ + + Fecode += condition? PRIV(OP_lengths)[*Fecode] : Flength; + + /* If the opcode is OP_SCOND it means we are at a repeated conditional + group that might match an empty string. We must therefore descend a level + so that the start is remembered for checking. For OP_COND we can just + continue at this level. */ + + if (Fop == OP_SCOND) + { + group_frame_type = GF_NOCAPTURE | Fop; + RMATCH(Fecode, RM35); + RRETURN(rrc); + } + break; + + + +/* ========================================================================= */ +/* End of start of parenthesis opcodes */ +/* ========================================================================= */ + + + /* ===================================================================== */ + /* Move the subject pointer back. This occurs only at the start of each + branch of a lookbehind assertion. If we are too close to the start to move + back, fail. When working with UTF-8 we move back a number of characters, + not bytes. */ + + case OP_REVERSE: + number = GET(Fecode, 1); +#ifdef SUPPORT_UNICODE + if (utf) + { + while (number-- > 0) + { + if (Feptr <= mb->start_subject) RRETURN(MATCH_NOMATCH); + Feptr--; + BACKCHAR(Feptr); + } + } + else +#endif + + /* No UTF-8 support, or not in UTF-8 mode: count is byte count */ + + { + if ((ptrdiff_t)number > Feptr - mb->start_subject) RRETURN(MATCH_NOMATCH); + Feptr -= number; + } + + /* Save the earliest consulted character, then skip to next op code */ + + if (Feptr < mb->start_used_ptr) mb->start_used_ptr = Feptr; + Fecode += 1 + LINK_SIZE; + break; + + + /* ===================================================================== */ + /* An alternation is the end of a branch; scan along to find the end of the + bracketed group. */ + + case OP_ALT: + do Fecode += GET(Fecode,1); while (*Fecode == OP_ALT); + break; + + + /* ===================================================================== */ + /* The end of a parenthesized group. For all but OP_BRA and OP_COND, the + starting frame was added to the chained frames in order to remember the + starting subject position for the group. */ + + case OP_KET: + case OP_KETRMIN: + case OP_KETRMAX: + case OP_KETRPOS: + + bracode = Fecode - GET(Fecode, 1); + + /* Point N to the frame at the start of the most recent group. + Remember the subject pointer at the start of the group. */ + + if (*bracode != OP_BRA && *bracode != OP_COND) + { + N = (heapframe *)((char *)mb->match_frames + Flast_group_offset); + P = (heapframe *)((char *)N - frame_size); + Flast_group_offset = P->last_group_offset; + +#ifdef DEBUG_SHOW_RMATCH + fprintf(stderr, "++ KET for frame=%d type=%x prev char offset=%lu\n", + N->rdepth, N->group_frame_type, + (char *)P->eptr - (char *)mb->start_subject); #endif + + /* If we are at the end of an assertion that is a condition, return a + match, discarding any intermediate backtracking points. Copy back the + captures into the frame before N so that they are set on return. Doing + this for all assertions, both positive and negative, seems to match what + Perl does. */ + + if (GF_IDMASK(N->group_frame_type) == GF_CONDASSERT) + { + memcpy((char *)P + offsetof(heapframe, ovector), Fovector, + Foffset_top * sizeof(PCRE2_SIZE)); + P->offset_top = Foffset_top; + Fback_frame = (char *)F - (char *)P; + RRETURN(MATCH_MATCH); + } + } + else P = NULL; /* Indicates starting frame not recorded */ + + /* The group was not a conditional assertion. */ + + switch (*bracode) + { + case OP_BRA: /* No need to do anything for these */ + case OP_COND: + case OP_SCOND: + break; + + /* Positive assertions are like OP_ONCE, except that in addition the + subject pointer must be put back to where it was at the start of the + assertion. */ + + case OP_ASSERT: + case OP_ASSERTBACK: + if (Feptr > mb->last_used_ptr) mb->last_used_ptr = Feptr; + Feptr = P->eptr; + /* Fall through */ + + /* For an atomic group, discard internal backtracking points. We must + also ensure that any remaining branches within the top-level of the group + are not tried. Do this by adjusting the code pointer within the backtrack + frame so that it points to the final branch. */ + + case OP_ONCE: + Fback_frame = ((char *)F - (char *)P) + frame_size; + for (;;) + { + uint32_t y = GET(P->ecode,1); + if ((P->ecode)[y] != OP_ALT) break; + P->ecode += y; + } + break; + + /* A matching negative assertion returns MATCH, which is turned into + NOMATCH at the assertion level. */ + + case OP_ASSERT_NOT: + case OP_ASSERTBACK_NOT: + RRETURN(MATCH_MATCH); + + /* Whole-pattern recursion is coded as a recurse into group 0, so it + won't be picked up here. Instead, we catch it when the OP_END is reached. + Other recursion is handled here. */ + + case OP_CBRA: + case OP_CBRAPOS: + case OP_SCBRA: + case OP_SCBRAPOS: + number = GET2(bracode, 1+LINK_SIZE); + + /* Handle a recursively called group. We reinstate the previous set of + captures and then carry on after the recursion call. */ + + if (Fcurrent_recurse == number) + { + P = (heapframe *)((char *)N - frame_size); + memcpy((char *)F + offsetof(heapframe, ovector), P->ovector, + P->offset_top * sizeof(PCRE2_SIZE)); + Foffset_top = P->offset_top; + Fcapture_last = P->capture_last; + Fcurrent_recurse = P->current_recurse; + Fecode = P->ecode + 1 + LINK_SIZE; + continue; /* With next opcode */ + } + + /* Deal with actual capturing. */ + + offset = (number << 1) - 2; + Fcapture_last = number; + Fovector[offset] = P->eptr - mb->start_subject; + Fovector[offset+1] = Feptr - mb->start_subject; + if (offset >= Foffset_top) Foffset_top = offset + 2; + break; + } /* End actions relating to the starting opcode */ + + /* OP_KETRPOS is a possessive repeating ket. Remember the current position, + and return the MATCH_KETRPOS. This makes it possible to do the repeats one + at a time from the outer level. This must precede the empty string test - + in this case that test is done at the outer level. */ + + if (*Fecode == OP_KETRPOS) + { + memcpy((char *)P + offsetof(heapframe, eptr), + (char *)F + offsetof(heapframe, eptr), + frame_copy_size); + RRETURN(MATCH_KETRPOS); + } + + /* Handle the different kinds of closing brackets. A non-repeating ket + needs no special action, just continuing at this level. This also happens + for the repeating kets if the group matched no characters, in order to + forcibly break infinite loops. Otherwise, the repeating kets try the rest + of the pattern or restart from the preceding bracket, in the appropriate + order. */ + + if (Fop != OP_KET && (P == NULL || Feptr != P->eptr)) + { + if (Fop == OP_KETRMIN) + { + RMATCH(Fecode + 1 + LINK_SIZE, RM6); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + Fecode -= GET(Fecode, 1); + break; /* End of ket processing */ + } + + /* Repeat the maximum number of times (KETRMAX) */ + + RMATCH(bracode, RM7); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + } + + /* Carry on at this level for a non-repeating ket, or after matching an + empty string, or after repeating for a maximum number of times. */ + + Fecode += 1 + LINK_SIZE; + break; + + + /* ===================================================================== */ + /* Start and end of line assertions, not multiline mode. */ + + case OP_CIRC: /* Start of line, unless PCRE2_NOTBOL is set. */ + if (Feptr != mb->start_subject || (mb->moptions & PCRE2_NOTBOL) != 0) + RRETURN(MATCH_NOMATCH); + Fecode++; + break; + + case OP_SOD: /* Unconditional start of subject */ + if (Feptr != mb->start_subject) RRETURN(MATCH_NOMATCH); + Fecode++; + break; + + /* When PCRE2_NOTEOL is unset, assert before the subject end, or a + terminating newline unless PCRE2_DOLLAR_ENDONLY is set. */ + + case OP_DOLL: + if ((mb->moptions & PCRE2_NOTEOL) != 0) RRETURN(MATCH_NOMATCH); + if ((mb->poptions & PCRE2_DOLLAR_ENDONLY) == 0) goto ASSERT_NL_OR_EOS; + + /* Fall through */ + /* Unconditional end of subject assertion (\z) */ + + case OP_EOD: + if (Feptr < mb->end_subject) RRETURN(MATCH_NOMATCH); + SCHECK_PARTIAL(); + Fecode++; + break; + + /* End of subject or ending \n assertion (\Z) */ + + case OP_EODN: + ASSERT_NL_OR_EOS: + if (Feptr < mb->end_subject && + (!IS_NEWLINE(Feptr) || Feptr != mb->end_subject - mb->nllen)) + { + if (mb->partial != 0 && + Feptr + 1 >= mb->end_subject && + NLBLOCK->nltype == NLTYPE_FIXED && + NLBLOCK->nllen == 2 && + UCHAR21TEST(Feptr) == NLBLOCK->nl[0]) + { + mb->hitend = TRUE; + if (mb->partial > 1) return PCRE2_ERROR_PARTIAL; + } + RRETURN(MATCH_NOMATCH); + } + + /* Either at end of string or \n before end. */ + + SCHECK_PARTIAL(); + Fecode++; + break; + + + /* ===================================================================== */ + /* Start and end of line assertions, multiline mode. */ + + /* Start of subject unless notbol, or after any newline except for one at + the very end, unless PCRE2_ALT_CIRCUMFLEX is set. */ + + case OP_CIRCM: + if ((mb->moptions & PCRE2_NOTBOL) != 0 && Feptr == mb->start_subject) + RRETURN(MATCH_NOMATCH); + if (Feptr != mb->start_subject && + ((Feptr == mb->end_subject && + (mb->poptions & PCRE2_ALT_CIRCUMFLEX) == 0) || + !WAS_NEWLINE(Feptr))) + RRETURN(MATCH_NOMATCH); + Fecode++; + break; + + /* Assert before any newline, or before end of subject unless noteol is + set. */ + + case OP_DOLLM: + if (Feptr < mb->end_subject) + { + if (!IS_NEWLINE(Feptr)) + { + if (mb->partial != 0 && + Feptr + 1 >= mb->end_subject && + NLBLOCK->nltype == NLTYPE_FIXED && + NLBLOCK->nllen == 2 && + UCHAR21TEST(Feptr) == NLBLOCK->nl[0]) + { + mb->hitend = TRUE; + if (mb->partial > 1) return PCRE2_ERROR_PARTIAL; + } + RRETURN(MATCH_NOMATCH); + } + } + else + { + if ((mb->moptions & PCRE2_NOTEOL) != 0) RRETURN(MATCH_NOMATCH); + SCHECK_PARTIAL(); + } + Fecode++; + break; + + + /* ===================================================================== */ + /* Start of match assertion */ + + case OP_SOM: + if (Feptr != mb->start_subject + mb->start_offset) RRETURN(MATCH_NOMATCH); + Fecode++; + break; + + + /* ===================================================================== */ + /* Reset the start of match point */ + + case OP_SET_SOM: + Fstart_match = Feptr; + Fecode++; + break; + + + /* ===================================================================== */ + /* Word boundary assertions. Find out if the previous and current + characters are "word" characters. It takes a bit more work in UTF mode. + Characters > 255 are assumed to be "non-word" characters when PCRE2_UCP is + not set. When it is set, use Unicode properties if available, even when not + in UTF mode. Remember the earliest and latest consulted characters. */ + + case OP_NOT_WORD_BOUNDARY: + case OP_WORD_BOUNDARY: + if (Feptr == mb->start_subject) prev_is_word = FALSE; else + { + PCRE2_SPTR lastptr = Feptr - 1; #ifdef SUPPORT_UNICODE - LBL(16) LBL(18) - LBL(22) LBL(23) LBL(28) LBL(30) - LBL(32) LBL(34) LBL(42) LBL(46) - LBL(36) LBL(37) LBL(38) LBL(39) LBL(40) LBL(41) LBL(44) LBL(45) - LBL(59) LBL(60) LBL(61) LBL(62) LBL(67) + if (utf) + { + BACKCHAR(lastptr); + GETCHAR(fc, lastptr); + } + else #endif /* SUPPORT_UNICODE */ - default: - return PCRE2_ERROR_INTERNAL; - } -#undef LBL -#endif /* HEAP_MATCH_RECURSE */ -} + fc = *lastptr; + if (lastptr < mb->start_used_ptr) mb->start_used_ptr = lastptr; +#ifdef SUPPORT_UNICODE + if ((mb->poptions & PCRE2_UCP) != 0) + { + if (fc == '_') prev_is_word = TRUE; else + { + int cat = UCD_CATEGORY(fc); + prev_is_word = (cat == ucp_L || cat == ucp_N); + } + } + else +#endif /* SUPPORT_UNICODE */ + prev_is_word = CHMAX_255(fc) && (mb->ctypes[fc] & ctype_word) != 0; + } + /* Get status of next character */ -/*************************************************************************** -**************************************************************************** - RECURSION IN THE match() FUNCTION + if (Feptr >= mb->end_subject) + { + SCHECK_PARTIAL(); + cur_is_word = FALSE; + } + else + { + PCRE2_SPTR nextptr = Feptr + 1; +#ifdef SUPPORT_UNICODE + if (utf) + { + FORWARDCHARTEST(nextptr, mb->end_subject); + GETCHAR(fc, Feptr); + } + else +#endif /* SUPPORT_UNICODE */ + fc = *Feptr; + if (nextptr > mb->last_used_ptr) mb->last_used_ptr = nextptr; +#ifdef SUPPORT_UNICODE + if ((mb->poptions & PCRE2_UCP) != 0) + { + if (fc == '_') cur_is_word = TRUE; else + { + int cat = UCD_CATEGORY(fc); + cur_is_word = (cat == ucp_L || cat == ucp_N); + } + } + else +#endif /* SUPPORT_UNICODE */ + cur_is_word = CHMAX_255(fc) && (mb->ctypes[fc] & ctype_word) != 0; + } -Undefine all the macros that were defined above to handle this. */ + /* Now see if the situation is what we want */ -#ifdef HEAP_MATCH_RECURSE -#undef eptr -#undef ecode -#undef mstart -#undef offset_top -#undef eptrb -#undef flags + if ((*Fecode++ == OP_WORD_BOUNDARY)? + cur_is_word == prev_is_word : cur_is_word != prev_is_word) + RRETURN(MATCH_NOMATCH); + break; -#undef callpat -#undef charptr -#undef data -#undef next_ecode -#undef pp -#undef prev -#undef saved_eptr -#undef new_recursive + /* ===================================================================== */ + /* Backtracking (*VERB)s, with and without arguments. Note that if the + pattern is successfully matched, we do not come back from RMATCH. */ -#undef cur_is_word -#undef condition -#undef prev_is_word + case OP_MARK: + Fmark = mb->nomatch_mark = Fecode + 2; + RMATCH(Fecode + PRIV(OP_lengths)[*Fecode] + Fecode[1], RM12); -#undef ctype -#undef length -#undef max -#undef min -#undef number -#undef offset -#undef op -#undef save_capture_last -#undef save_offset1 -#undef save_offset2 -#undef save_offset3 + /* A return of MATCH_SKIP_ARG means that matching failed at SKIP with an + argument, and we must check whether that argument matches this MARK's + argument. It is passed back in mb->verb_skip_ptr. If it does match, we + return MATCH_SKIP with mb->verb_skip_ptr now pointing to the subject + position that corresponds to this mark. Otherwise, pass back the return + code unaltered. */ -#undef newptrb -#endif /* HEAP_MATCH_RECURSE */ + if (rrc == MATCH_SKIP_ARG && + PRIV(strcmp)(Fecode + 2, mb->verb_skip_ptr) == 0) + { + mb->verb_skip_ptr = Feptr; /* Pass back current position */ + RRETURN(MATCH_SKIP); + } + RRETURN(rrc); -/* These two are defined as macros in both cases */ + case OP_FAIL: + RRETURN(MATCH_NOMATCH); -#undef fc -#undef fi + /* Record the current recursing group number in mb->verb_current_recurse + when a backtracking return such as MATCH_COMMIT is given. This enables the + recurse processing to catch verbs from within the recursion. */ -/*************************************************************************** -***************************************************************************/ + case OP_COMMIT: + RMATCH(Fecode + PRIV(OP_lengths)[*Fecode], RM13); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + mb->verb_current_recurse = Fcurrent_recurse; + RRETURN(MATCH_COMMIT); + case OP_PRUNE: + RMATCH(Fecode + PRIV(OP_lengths)[*Fecode], RM14); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + mb->verb_current_recurse = Fcurrent_recurse; + RRETURN(MATCH_PRUNE); -#ifdef HEAP_MATCH_RECURSE -/************************************************* -* Release allocated heap frames * -*************************************************/ + case OP_PRUNE_ARG: + Fmark = mb->nomatch_mark = Fecode + 2; + RMATCH(Fecode + PRIV(OP_lengths)[*Fecode] + Fecode[1], RM15); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + mb->verb_current_recurse = Fcurrent_recurse; + RRETURN(MATCH_PRUNE); -/* This function releases all the allocated frames. The base frame is on the -machine stack, and so must not be freed. + case OP_SKIP: + RMATCH(Fecode + PRIV(OP_lengths)[*Fecode], RM16); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + mb->verb_skip_ptr = Feptr; /* Pass back current position */ + mb->verb_current_recurse = Fcurrent_recurse; + RRETURN(MATCH_SKIP); -Argument: - frame_base the address of the base frame - mb the match block + /* Note that, for Perl compatibility, SKIP with an argument does NOT set + nomatch_mark. When a pattern match ends with a SKIP_ARG for which there was + not a matching mark, we have to re-run the match, ignoring the SKIP_ARG + that failed and any that precede it (either they also failed, or were not + triggered). To do this, we maintain a count of executed SKIP_ARGs. If a + SKIP_ARG gets to top level, the match is re-run with mb->ignore_skip_arg + set to the count of the one that failed. */ -Returns: nothing -*/ + case OP_SKIP_ARG: + mb->skip_arg_count++; + if (mb->skip_arg_count <= mb->ignore_skip_arg) + { + Fecode += PRIV(OP_lengths)[*Fecode] + Fecode[1]; + break; + } + RMATCH(Fecode + PRIV(OP_lengths)[*Fecode] + Fecode[1], RM17); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); -static void -release_match_heapframes (heapframe *frame_base, match_block *mb) -{ -heapframe *nextframe = frame_base->Xnextframe; -while (nextframe != NULL) + /* Pass back the current skip name and return the special MATCH_SKIP_ARG + return code. This will either be caught by a matching MARK, or get to the + top, where it causes a rematch with mb->ignore_skip_arg set to the value of + mb->skip_arg_count. */ + + mb->verb_skip_ptr = Fecode + 2; + mb->verb_current_recurse = Fcurrent_recurse; + RRETURN(MATCH_SKIP_ARG); + + /* For THEN (and THEN_ARG) we pass back the address of the opcode, so that + the branch in which it occurs can be determined. */ + + case OP_THEN: + RMATCH(Fecode + PRIV(OP_lengths)[*Fecode], RM18); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + mb->verb_ecode_ptr = Fecode; + mb->verb_current_recurse = Fcurrent_recurse; + RRETURN(MATCH_THEN); + + case OP_THEN_ARG: + Fmark = mb->nomatch_mark = Fecode + 2; + RMATCH(Fecode + PRIV(OP_lengths)[*Fecode] + Fecode[1], RM19); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + mb->verb_ecode_ptr = Fecode; + mb->verb_current_recurse = Fcurrent_recurse; + RRETURN(MATCH_THEN); + + + /* ===================================================================== */ + /* There's been some horrible disaster. Arrival here can only mean there is + something seriously wrong in the code above or the OP_xxx definitions. */ + + default: + return PCRE2_ERROR_INTERNAL; + } + + /* Do not insert any code in here without much thought; it is assumed + that "continue" in the code above comes out to here to repeat the main + loop. */ + + } /* End of main loop */ +/* Control never reaches here */ + + +/* ========================================================================= */ +/* The RRETURN() macro jumps here. The number that is saved in Freturn_id +indicates which label we actually want to return to. The value in Frdepth is +the index number of the frame in the vector. The return value has been placed +in rrc. */ + +#define LBL(val) case val: goto L_RM##val; + +RETURN_SWITCH: +if (Frdepth == 0) return rrc; /* Exit from the top level */ +F = (heapframe *)((char *)F - Fback_frame); /* Back track */ +mb->cb->callout_flags |= PCRE2_CALLOUT_BACKTRACK; /* Note for callouts */ + +#ifdef DEBUG_SHOW_RMATCH +fprintf(stderr, "++ RETURN %d to %d\n", rrc, Freturn_id); +#endif + +switch (Freturn_id) { - heapframe *oldframe = nextframe; - nextframe = nextframe->Xnextframe; - mb->stack_memctl.free(oldframe, mb->stack_memctl.memory_data); + LBL( 1) LBL( 2) LBL( 3) LBL( 4) LBL( 5) LBL( 6) LBL( 7) LBL( 8) + LBL( 9) LBL(10) LBL(11) LBL(12) LBL(13) LBL(14) LBL(15) LBL(16) + LBL(17) LBL(18) LBL(19) LBL(20) LBL(21) LBL(22) LBL(23) LBL(24) + LBL(25) LBL(26) LBL(27) LBL(28) LBL(29) LBL(30) LBL(31) LBL(32) + LBL(33) LBL(34) LBL(35) + +#ifdef SUPPORT_WIDE_CHARS + LBL(100) LBL(101) +#endif + +#ifdef SUPPORT_UNICODE + LBL(200) LBL(201) LBL(202) LBL(203) LBL(204) LBL(205) LBL(206) + LBL(207) LBL(208) LBL(209) LBL(210) LBL(211) LBL(212) LBL(213) + LBL(214) LBL(215) LBL(216) LBL(217) LBL(218) LBL(219) LBL(220) + LBL(221) LBL(222) +#endif + + default: + return PCRE2_ERROR_INTERNAL; } +#undef LBL } -#endif /* HEAP_MATCH_RECURSE */ - /************************************************* @@ -6439,8 +5984,6 @@ pcre2_match(const pcre2_code *code, PCRE2_SPTR subject, PCRE2_SIZE length, pcre2_match_context *mcontext) { int rc; -int ocount; - const uint8_t *start_bits = NULL; const pcre2_real_code *re = (const pcre2_real_code *)code; @@ -6450,7 +5993,6 @@ BOOL firstline; BOOL has_first_cu = FALSE; BOOL has_req_cu = FALSE; BOOL startline; -BOOL using_temporary_offsets = FALSE; BOOL utf; PCRE2_UCHAR first_cu = 0; @@ -6465,18 +6007,22 @@ PCRE2_SPTR req_cu_ptr = start_match - 1; PCRE2_SPTR start_partial = NULL; PCRE2_SPTR match_partial = NULL; -/* We need to have mb pointing to a match block, because the IS_NEWLINE macro -is used below, and it expects NLBLOCK to be defined as a pointer. */ +PCRE2_SIZE frame_size; + +/* We need to have mb as a pointer to a match block, because the IS_NEWLINE +macro is used below, and it expects NLBLOCK to be defined as a pointer. */ +pcre2_callout_block cb; match_block actual_match_block; match_block *mb = &actual_match_block; -#ifdef HEAP_MATCH_RECURSE -heapframe frame_zero; -frame_zero.Xprevframe = NULL; /* Marks the top level */ -frame_zero.Xnextframe = NULL; /* None are allocated yet */ -mb->match_frames_base = &frame_zero; -#endif +/* Allocate an initial vector of backtracking frames on the stack. If this +proves to be too small, it is replaced by a larger one on the heap. To get a +vector of the size required that is aligned for pointers, allocate it as a +vector of pointers. */ + +PCRE2_SPTR stack_frames_vector[START_FRAMES_SIZE/sizeof(PCRE2_SPTR)]; +mb->stack_frames = (heapframe *)stack_frames_vector; /* A length equal to PCRE2_ZERO_TERMINATED implies a zero-terminated subject string. */ @@ -6505,8 +6051,8 @@ options variable for this function. Users of PCRE2 who are not calling the function directly would like to have a way of setting these flags, in the same way that they can set pcre2_compile() flags like PCRE2_NO_AUTOPOSSESS with constructions like (*NO_AUTOPOSSESS). To enable this, (*NOTEMPTY) and -(*NOTEMPTY_ATSTART) set bits in the pattern's "flag" function which can now be -transferred to the options for this function. The bits are guaranteed to be +(*NOTEMPTY_ATSTART) set bits in the pattern's "flag" function which we now +transfer to the options for this function. The bits are guaranteed to be adjacent, but do not have the same values. This bit of Boolean trickery assumes that the match-time bits are not more significant than the flag bits. If by accident this is not the case, a compile-time division by zero error will @@ -6518,20 +6064,22 @@ options |= (re->flags & FF) / ((FF & (~FF+1)) / (OO & (~OO+1))); #undef FF #undef OO -/* A NULL match context means "use a default context" */ - -if (mcontext == NULL) - mcontext = (pcre2_match_context *)(&PRIV(default_match_context)); - /* These two settings are used in the code for checking a UTF string that follows immediately afterwards. Other values in the mb block are used only -during interpretive pcre_match() processing, not when the JIT support is in -use, so they are set up later. */ +during interpretive processing, not when the JIT support is in use, so they are +set up later. */ utf = (re->overall_options & PCRE2_UTF) != 0; mb->partial = ((options & PCRE2_PARTIAL_HARD) != 0)? 2 : ((options & PCRE2_PARTIAL_SOFT) != 0)? 1 : 0; +/* Partial matching and PCRE2_ENDANCHORED are currently not allowed at the same +time. */ + +if (mb->partial != 0 && + ((re->overall_options | options) & PCRE2_ENDANCHORED) != 0) + return PCRE2_ERROR_BADOPTION; + /* Check a UTF string for validity if required. For 8-bit and 16-bit strings, we must also check that a starting offset does not point into the middle of a multiunit character. We check only the portion of the subject that is going to @@ -6590,7 +6138,7 @@ if (utf && (options & PCRE2_NO_UTF_CHECK) == 0) /* It is an error to set an offset limit without setting the flag at compile time. */ -if (mcontext->offset_limit != PCRE2_UNSET && +if (mcontext != NULL && mcontext->offset_limit != PCRE2_UNSET && (re->overall_options & PCRE2_USE_OFFSET_LIMIT) == 0) return PCRE2_ERROR_BADOFFSETLIMIT; @@ -6609,7 +6157,15 @@ if (re->executable_jit != NULL && (options & ~PUBLIC_JIT_MATCH_OPTIONS) == 0) } #endif -/* Carry on with non-JIT matching. */ +/* Carry on with non-JIT matching. A NULL match context means "use a default +context", but we take the memory control functions from the pattern. */ + +if (mcontext == NULL) + { + mcontext = (pcre2_match_context *)(&PRIV(default_match_context)); + mb->memctl = re->memctl; + } +else mb->memctl = mcontext->memctl; anchored = ((re->overall_options | options) & PCRE2_ANCHORED) != 0; firstline = (re->overall_options & PCRE2_FIRSTLINE) != 0; @@ -6617,14 +6173,19 @@ startline = (re->flags & PCRE2_STARTLINE) != 0; bumpalong_limit = (mcontext->offset_limit == PCRE2_UNSET)? end_subject : subject + mcontext->offset_limit; -/* Fill in the fields in the match block. */ +/* Initialize and set up the fixed fields in the callout block, with a pointer +in the match block. */ + +mb->cb = &cb; +cb.version = 2; +cb.subject = subject; +cb.subject_length = (PCRE2_SIZE)(end_subject - subject); +cb.callout_flags = 0; + +/* Fill in the remaining fields in the match block. */ mb->callout = mcontext->callout; mb->callout_data = mcontext->callout_data; -mb->memctl = mcontext->memctl; -#ifdef HEAP_MATCH_RECURSE -mb->stack_memctl = mcontext->stack_memctl; -#endif mb->start_subject = subject; mb->start_offset = start_offset; @@ -6636,8 +6197,6 @@ mb->poptions = re->overall_options; /* Pattern options */ mb->ignore_skip_arg = 0; mb->mark = mb->nomatch_mark = NULL; /* In case never set */ -mb->recursive = NULL; /* No recursion at top level */ -mb->ovecsave_chain = NULL; /* No ovecsave blocks yet */ mb->hitend = FALSE; /* The name table is needed for finding all the numbers associated with a @@ -6648,20 +6207,6 @@ mb->name_count = re->name_count; mb->name_entry_size = re->name_entry_size; mb->start_code = mb->name_table + re->name_count * re->name_entry_size; -/* Limits set in the pattern override the match context only if they are -smaller. */ - -mb->match_limit = (mcontext->match_limit < re->limit_match)? - mcontext->match_limit : re->limit_match; -mb->match_limit_recursion = (mcontext->recursion_limit < re->limit_recursion)? - mcontext->recursion_limit : re->limit_recursion; - -/* Pointers to the individual character tables */ - -mb->lcc = re->tables + lcc_offset; -mb->fcc = re->tables + fcc_offset; -mb->ctypes = re->tables + ctypes_offset; - /* Process the \R and newline settings. */ mb->bsr_convention = re->bsr_convention; @@ -6678,6 +6223,11 @@ switch(re->newline_convention) mb->nl[0] = CHAR_NL; break; + case PCRE2_NEWLINE_NUL: + mb->nllen = 1; + mb->nl[0] = CHAR_NUL; + break; + case PCRE2_NEWLINE_CRLF: mb->nllen = 2; mb->nl[0] = CHAR_CR; @@ -6695,71 +6245,91 @@ switch(re->newline_convention) default: return PCRE2_ERROR_INTERNAL; } -/* If the expression has got more back references than the offsets supplied can -hold, we get a temporary chunk of memory to use during the matching. Otherwise, -we can use the vector supplied. The size of the ovector is three times the -value in the oveccount field. Two-thirds of it is pairs for storing matching -offsets, and the top third is working space. */ +/* The backtracking frames have fixed data at the front, and a PCRE2_SIZE +vector at the end, whose size depends on the number of capturing parentheses in +the pattern. It is not used at all if there are no capturing parentheses. + + frame_size is the total size of each frame + mb->frame_vector_size is the total usable size of the vector (rounded down + to a whole number of frames) -if (re->top_backref >= match_data->oveccount) +The last of these is changed within the match() function if the frame vector +has to be expanded. We therefore put it into the match block so that it is +correct when calling match() more than once for non-anchored patterns. */ + +frame_size = offsetof(heapframe, ovector) + + re->top_bracket * 2 * sizeof(PCRE2_SIZE); + +/* Limits set in the pattern override the match context only if they are +smaller. */ + +mb->heap_limit = (mcontext->heap_limit < re->limit_heap)? + mcontext->heap_limit : re->limit_heap; + +mb->match_limit = (mcontext->match_limit < re->limit_match)? + mcontext->match_limit : re->limit_match; + +mb->match_limit_depth = (mcontext->depth_limit < re->limit_depth)? + mcontext->depth_limit : re->limit_depth; + +/* If a pattern has very many capturing parentheses, the frame size may be very +large. Ensure that there are at least 10 available frames by getting an initial +vector on the heap if necessary, except when the heap limit prevents this. Get +fewer if possible. (The heap limit is in kilobytes.) */ + +if (frame_size <= START_FRAMES_SIZE/10) { - ocount = re->top_backref * 3 + 3; - mb->ovector = (PCRE2_SIZE *)(mb->memctl.malloc(ocount * sizeof(PCRE2_SIZE), - mb->memctl.memory_data)); - if (mb->ovector == NULL) return PCRE2_ERROR_NOMEMORY; - using_temporary_offsets = TRUE; + mb->match_frames = mb->stack_frames; /* Initial frame vector on the stack */ + mb->frame_vector_size = ((START_FRAMES_SIZE/frame_size) * frame_size); } else { - ocount = 3 * match_data->oveccount; - mb->ovector = match_data->ovector; + mb->frame_vector_size = frame_size * 10; + if ((mb->frame_vector_size / 1024) > mb->heap_limit) + { + if (frame_size > mb->heap_limit * 1024) return PCRE2_ERROR_HEAPLIMIT; + mb->frame_vector_size = ((mb->heap_limit * 1024)/frame_size) * frame_size; + } + mb->match_frames = mb->memctl.malloc(mb->frame_vector_size, + mb->memctl.memory_data); + if (mb->match_frames == NULL) return PCRE2_ERROR_NOMEMORY; } -mb->offset_end = ocount; -mb->offset_max = (2*ocount)/3; +mb->match_frames_top = + (heapframe *)((char *)mb->match_frames + mb->frame_vector_size); -/* Reset the working variable associated with each extraction. These should -never be used unless previously set, but they get saved and restored, and so we -initialize them to avoid reading uninitialized locations. Also, unset the -offsets for the matched string. This is really just for tidiness with callouts, -in case they inspect these fields. */ +/* Write to the ovector within the first frame to mark every capture unset and +to avoid uninitialized memory read errors when it is copied to a new frame. */ -if (ocount > 0) - { - PCRE2_SIZE *iptr = mb->ovector + ocount; - PCRE2_SIZE *iend = iptr - re->top_bracket; - if (iend < mb->ovector + 2) iend = mb->ovector + 2; - while (--iptr >= iend) *iptr = PCRE2_UNSET; - mb->ovector[0] = mb->ovector[1] = PCRE2_UNSET; - } +memset((char *)(mb->match_frames) + offsetof(heapframe, ovector), 0xff, + re->top_bracket * 2 * sizeof(PCRE2_SIZE)); -/* Set up the first code unit to match, if available. The first_codeunit value -is never set for an anchored regular expression, but the anchoring may be -forced at run time, so we have to test for anchoring. The first code unit may -be unset for an unanchored pattern, of course. If there's no first code unit -there may be a bitmap of possible first characters. */ +/* Pointers to the individual character tables */ + +mb->lcc = re->tables + lcc_offset; +mb->fcc = re->tables + fcc_offset; +mb->ctypes = re->tables + ctypes_offset; + +/* Set up the first code unit to match, if available. If there's no first code +unit there may be a bitmap of possible first characters. */ -if (!anchored) +if ((re->flags & PCRE2_FIRSTSET) != 0) { - if ((re->flags & PCRE2_FIRSTSET) != 0) + has_first_cu = TRUE; + first_cu = first_cu2 = (PCRE2_UCHAR)(re->first_codeunit); + if ((re->flags & PCRE2_FIRSTCASELESS) != 0) { - has_first_cu = TRUE; - first_cu = first_cu2 = (PCRE2_UCHAR)(re->first_codeunit); - if ((re->flags & PCRE2_FIRSTCASELESS) != 0) - { - first_cu2 = TABLE_GET(first_cu, mb->fcc, first_cu); + first_cu2 = TABLE_GET(first_cu, mb->fcc, first_cu); #if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 8 - if (utf && first_cu > 127) first_cu2 = UCD_OTHERCASE(first_cu); + if (utf && first_cu > 127) first_cu2 = UCD_OTHERCASE(first_cu); #endif - } } - else - if (!startline && (re->flags & PCRE2_FIRSTMAPSET) != 0) - start_bits = re->start_bitmap; } +else + if (!startline && (re->flags & PCRE2_FIRSTMAPSET) != 0) + start_bits = re->start_bitmap; -/* For anchored or unanchored matches, there may be a "last known required -character" set. */ +/* There may also be a "last known required character" set. */ if ((re->flags & PCRE2_LASTSET) != 0) { @@ -6783,7 +6353,6 @@ the loop runs just once. */ for(;;) { PCRE2_SPTR new_start_match; - mb->capture_last = 0; /* ----------------- Start of match optimizations ---------------- */ @@ -6794,13 +6363,11 @@ for(;;) if ((re->overall_options & PCRE2_NO_START_OPTIMIZE) == 0) { - PCRE2_SPTR save_end_subject = end_subject; - /* If firstline is TRUE, the start of the match is constrained to the first line of a multiline string. That is, the match must be before or at the - first newline. Implement this by temporarily adjusting end_subject so that - we stop the optimization scans at a newline. If the match fails at the - newline, later code breaks this loop. */ + first newline following the start of matching. Temporarily adjust + end_subject so that we stop the scans for a first code unit at a newline. + If the match fails at the newline, later code breaks the loop. */ if (firstline) { @@ -6808,102 +6375,179 @@ for(;;) #ifdef SUPPORT_UNICODE if (utf) { - while (t < mb->end_subject && !IS_NEWLINE(t)) + while (t < end_subject && !IS_NEWLINE(t)) { t++; - ACROSSCHAR(t < end_subject, *t, t++); + ACROSSCHAR(t < end_subject, t, t++); } } else #endif - while (t < mb->end_subject && !IS_NEWLINE(t)) t++; + while (t < end_subject && !IS_NEWLINE(t)) t++; end_subject = t; } - /* Advance to a unique first code unit if there is one. In 8-bit mode, the - use of memchr() gives a big speed up. */ + /* Anchored: check the first code unit if one is recorded. This may seem + pointless but it can help in detecting a no match case without scanning for + the required code unit. */ - if (has_first_cu) + if (anchored) { - PCRE2_UCHAR smc; - if (first_cu != first_cu2) - while (start_match < end_subject && - (smc = UCHAR21TEST(start_match)) != first_cu && smc != first_cu2) - start_match++; - else + if (has_first_cu || start_bits != NULL) { + BOOL ok = start_match < end_subject; + if (ok) + { + PCRE2_UCHAR c = UCHAR21TEST(start_match); + ok = has_first_cu && (c == first_cu || c == first_cu2); + if (!ok && start_bits != NULL) + { #if PCRE2_CODE_UNIT_WIDTH != 8 - while (start_match < end_subject && UCHAR21TEST(start_match) != first_cu) - start_match++; -#else - start_match = memchr(start_match, first_cu, end_subject - start_match); - if (start_match == NULL) start_match = end_subject; + if (c > 255) c = 255; #endif + ok = (start_bits[c/8] & (1 << (c&7))) != 0; + } + } + if (!ok) + { + rc = MATCH_NOMATCH; + break; + } } } - /* Or to just after a linebreak for a multiline match */ + /* Not anchored. Advance to a unique first code unit if there is one. In + 8-bit mode, the use of memchr() gives a big speed up, even though we have + to call it twice in caseless mode, in order to find the earliest occurrence + of the character in either of its cases. */ - else if (startline) + else { - if (start_match > mb->start_subject + start_offset) + if (has_first_cu) { -#ifdef SUPPORT_UNICODE - if (utf) + if (first_cu != first_cu2) /* Caseless */ { - while (start_match < end_subject && !WAS_NEWLINE(start_match)) - { +#if PCRE2_CODE_UNIT_WIDTH != 8 + PCRE2_UCHAR smc; + while (start_match < end_subject && + (smc = UCHAR21TEST(start_match)) != first_cu && + smc != first_cu2) start_match++; - ACROSSCHAR(start_match < end_subject, *start_match, - start_match++); - } +#else /* 8-bit code units */ + PCRE2_SPTR pp1 = + memchr(start_match, first_cu, end_subject-start_match); + PCRE2_SPTR pp2 = + memchr(start_match, first_cu2, end_subject-start_match); + if (pp1 == NULL) + start_match = (pp2 == NULL)? end_subject : pp2; + else + start_match = (pp2 == NULL || pp1 < pp2)? pp1 : pp2; +#endif } + + /* The caseful case */ + else + { +#if PCRE2_CODE_UNIT_WIDTH != 8 + while (start_match < end_subject && UCHAR21TEST(start_match) != + first_cu) + start_match++; +#else + start_match = memchr(start_match, first_cu, end_subject - start_match); + if (start_match == NULL) start_match = end_subject; #endif - while (start_match < end_subject && !WAS_NEWLINE(start_match)) - start_match++; + } - /* If we have just passed a CR and the newline option is ANY or - ANYCRLF, and we are now at a LF, advance the match position by one more - code unit. */ + /* If we can't find the required code unit, having reached the true end + of the subject, break the bumpalong loop, to force a match failure, + except when doing partial matching, when we let the next cycle run at + the end of the subject. To see why, consider the pattern /(?<=abc)def/, + which partially matches "abc", even though the string does not contain + the starting character "d". If we have not reached the true end of the + subject (PCRE2_FIRSTLINE caused end_subject to be temporarily modified) + we also let the cycle run, because the matching string is legitimately + allowed to start with the first code unit of a newline. */ + + if (!mb->partial && start_match >= mb->end_subject) + { + rc = MATCH_NOMATCH; + break; + } + } - if (start_match[-1] == CHAR_CR && - (mb->nltype == NLTYPE_ANY || mb->nltype == NLTYPE_ANYCRLF) && - start_match < end_subject && - UCHAR21TEST(start_match) == CHAR_NL) - start_match++; + /* If there's no first code unit, advance to just after a linebreak for a + multiline match if required. */ + + else if (startline) + { + if (start_match > mb->start_subject + start_offset) + { +#ifdef SUPPORT_UNICODE + if (utf) + { + while (start_match < end_subject && !WAS_NEWLINE(start_match)) + { + start_match++; + ACROSSCHAR(start_match < end_subject, start_match, start_match++); + } + } + else +#endif + while (start_match < end_subject && !WAS_NEWLINE(start_match)) + start_match++; + + /* If we have just passed a CR and the newline option is ANY or + ANYCRLF, and we are now at a LF, advance the match position by one + more code unit. */ + + if (start_match[-1] == CHAR_CR && + (mb->nltype == NLTYPE_ANY || mb->nltype == NLTYPE_ANYCRLF) && + start_match < end_subject && + UCHAR21TEST(start_match) == CHAR_NL) + start_match++; + } } - } - /* Or to a non-unique first code unit if any have been identified. The - bitmap contains only 256 bits. When code units are 16 or 32 bits wide, all - code units greater than 254 set the 255 bit. */ + /* If there's no first code unit or a requirement for a multiline line + start, advance to a non-unique first code unit if any have been + identified. The bitmap contains only 256 bits. When code units are 16 or + 32 bits wide, all code units greater than 254 set the 255 bit. */ - else if (start_bits != NULL) - { - while (start_match < end_subject) + else if (start_bits != NULL) { - uint32_t c = UCHAR21TEST(start_match); + while (start_match < end_subject) + { + uint32_t c = UCHAR21TEST(start_match); #if PCRE2_CODE_UNIT_WIDTH != 8 - if (c > 255) c = 255; + if (c > 255) c = 255; #endif - if ((start_bits[c/8] & (1 << (c&7))) != 0) break; - start_match++; + if ((start_bits[c/8] & (1 << (c&7))) != 0) break; + start_match++; + } + + /* See comment above in first_cu checking about the next few lines. */ + + if (!mb->partial && start_match >= mb->end_subject) + { + rc = MATCH_NOMATCH; + break; + } } - } + } /* End first code unit handling */ /* Restore fudged end_subject */ - end_subject = save_end_subject; + end_subject = mb->end_subject; - /* The following two optimizations are disabled for partial matching. */ + /* The following two optimizations must be disabled for partial matching. */ if (!mb->partial) { - /* The minimum matching length is a lower bound; no actual string of that - length may actually match the pattern. Although the value is, strictly, - in characters, we treat it as code units to avoid spending too much time - in this optimization. */ + /* The minimum matching length is a lower bound; no string of that length + may actually match the pattern. Although the value is, strictly, in + characters, we treat it as code units to avoid spending too much time in + this optimization. */ if (end_subject - start_match < re->minlength) { @@ -6912,12 +6556,16 @@ for(;;) } /* If req_cu is set, we know that that code unit must appear in the - subject for the match to succeed. If the first code unit is set, req_cu - must be later in the subject; otherwise the test starts at the match - point. This optimization can save a huge amount of backtracking in - patterns with nested unlimited repeats that aren't going to match. - Writing separate code for cased/caseless versions makes it go faster, as - does using an autoincrement and backing off on a match. + subject for the (non-partial) match to succeed. If the first code unit is + set, req_cu must be later in the subject; otherwise the test starts at + the match point. This optimization can save a huge amount of backtracking + in patterns with nested unlimited repeats that aren't going to match. + Writing separate code for caseful/caseless versions makes it go faster, + as does using an autoincrement and backing off on a match. As in the case + of the first code unit, using memchr() in the 8-bit library gives a big + speed up. Unlike the first_cu check above, we do not need to call + memchr() twice in the caseless case because we only need to check for the + presence of the character in either case, not find the first occurrence. HOWEVER: when the subject string is very, very long, searching to its end can take a long time, and give bad performance on quite ordinary @@ -6930,27 +6578,52 @@ for(;;) PCRE2_SPTR p = start_match + (has_first_cu? 1:0); /* We don't need to repeat the search if we haven't yet reached the - place we found it at last time. */ + place we found it last time round the bumpalong loop. */ if (p > req_cu_ptr) { - if (req_cu != req_cu2) + if (p < end_subject) { - while (p < end_subject) + if (req_cu != req_cu2) /* Caseless */ { - uint32_t pp = UCHAR21INCTEST(p); - if (pp == req_cu || pp == req_cu2) { p--; break; } +#if PCRE2_CODE_UNIT_WIDTH != 8 + do + { + uint32_t pp = UCHAR21INCTEST(p); + if (pp == req_cu || pp == req_cu2) { p--; break; } + } + while (p < end_subject); + +#else /* 8-bit code units */ + PCRE2_SPTR pp = p; + p = memchr(pp, req_cu, end_subject - pp); + if (p == NULL) + { + p = memchr(pp, req_cu2, end_subject - pp); + if (p == NULL) p = end_subject; + } +#endif /* PCRE2_CODE_UNIT_WIDTH != 8 */ } - } - else - { - while (p < end_subject) + + /* The caseful case */ + + else { - if (UCHAR21INCTEST(p) == req_cu) { p--; break; } +#if PCRE2_CODE_UNIT_WIDTH != 8 + do + { + if (UCHAR21INCTEST(p) == req_cu) { p--; break; } + } + while (p < end_subject); + +#else /* 8-bit code units */ + p = memchr(p, req_cu, end_subject - p); + if (p == NULL) p = end_subject; +#endif } } - /* If we can't find the required code unit, break the matching loop, + /* If we can't find the required code unit, break the bumpalong loop, forcing a match failure. */ if (p >= end_subject) @@ -6960,8 +6633,8 @@ for(;;) } /* If we have found the required code unit, save the point where we - found it, so that we don't search again next time round the loop if - the start hasn't passed this code unit yet. */ + found it, so that we don't search again next time round the bumpalong + loop if the start hasn't yet passed this code unit. */ req_cu_ptr = p; } @@ -6982,14 +6655,17 @@ for(;;) /* OK, we can now run the match. If "hitend" is set afterwards, remember the first starting point for which a partial match was found. */ - mb->start_match_ptr = start_match; + cb.start_match = (PCRE2_SIZE)(start_match - subject); + cb.callout_flags |= PCRE2_CALLOUT_STARTMATCH; + mb->start_used_ptr = start_match; mb->last_used_ptr = start_match; mb->match_call_count = 0; - mb->match_function_type = 0; mb->end_offset_top = 0; mb->skip_arg_count = 0; - rc = match(start_match, mb->start_code, start_match, 2, mb, NULL, 0); + + rc = match(start_match, mb->start_code, match_data->ovector, + match_data->oveccount, re->top_bracket, frame_size, mb); if (mb->hitend && start_partial == NULL) { @@ -7015,9 +6691,9 @@ for(;;) greater than the match we have just done, treat it as NOMATCH. */ case MATCH_SKIP: - if (mb->start_match_ptr > start_match) + if (mb->verb_skip_ptr > start_match) { - new_start_match = mb->start_match_ptr; + new_start_match = mb->verb_skip_ptr; break; } /* Fall through */ @@ -7032,7 +6708,7 @@ for(;;) new_start_match = start_match + 1; #ifdef SUPPORT_UNICODE if (utf) - ACROSSCHAR(new_start_match < end_subject, *new_start_match, + ACROSSCHAR(new_start_match < end_subject, new_start_match, new_start_match++); #endif break; @@ -7091,11 +6767,11 @@ for(;;) /* ==========================================================================*/ -/* When we reach here, one of the stopping conditions is true: +/* When we reach here, one of the following stopping conditions is true: (1) The match succeeded, either completely, or partially; -(2) The pattern is anchored or the match was failed by (*COMMIT); +(2) The pattern is anchored or the match was failed after (*COMMIT); (3) We are past the end of the subject or the bumpalong limit; @@ -7109,18 +6785,10 @@ for(;;) ENDLOOP: -#ifdef HEAP_MATCH_RECURSE -release_match_heapframes(&frame_zero, mb); -#endif - -/* Release any frames that were saved from recursions. */ +/* Release an enlarged frame vector that is on the heap. */ -while (mb->ovecsave_chain != NULL) - { - ovecsave_frame *this = mb->ovecsave_chain; - mb->ovecsave_chain = this->next; - mb->memctl.free(this, mb->memctl.memory_data); - } +if (mb->match_frames != mb->stack_frames) + mb->memctl.free(mb->match_frames, mb->memctl.memory_data); /* Fill in fields that are always returned in the match data. */ @@ -7129,68 +6797,14 @@ match_data->subject = subject; match_data->mark = mb->mark; match_data->matchedby = PCRE2_MATCHEDBY_INTERPRETER; -/* Handle a fully successful match. */ +/* Handle a fully successful match. Set the return code to the number of +captured strings, or 0 if there were too many to fit into the ovector, and then +set the remaining returned values before returning. */ -if (rc == MATCH_MATCH || rc == MATCH_ACCEPT) +if (rc == MATCH_MATCH) { - uint32_t arg_offset_max = 2 * match_data->oveccount; - - /* When the offset vector is big enough to deal with any backreferences, - captured substring offsets will already be set up. In the case where we had - to get some local memory to hold offsets for backreference processing, copy - those that we can. In this case there need not be overflow if certain parts - of the pattern were not used, even though there are more capturing - parentheses than vector slots. */ - - if (using_temporary_offsets) - { - if (arg_offset_max >= 4) - { - memcpy(match_data->ovector + 2, mb->ovector + 2, - (arg_offset_max - 2) * sizeof(PCRE2_SIZE)); - } - if (mb->end_offset_top > arg_offset_max) mb->capture_last |= OVFLBIT; - mb->memctl.free(mb->ovector, mb->memctl.memory_data); - } - - /* Set the return code to the number of captured strings, or 0 if there were - too many to fit into the ovector. */ - - match_data->rc = ((mb->capture_last & OVFLBIT) != 0)? - 0 : (int)mb->end_offset_top/2; - - /* If there is space in the offset vector, set any pairs that follow the - highest-numbered captured string but are less than the number of capturing - groups in the pattern (and are within the ovector) to PCRE2_UNSET. It is - documented that this happens. In earlier versions, the whole set of potential - capturing offsets was initialized each time round the loop, but this is - handled differently now. "Gaps" are set to PCRE2_UNSET dynamically instead - (this fixed a bug). Thus, it is only those at the end that need setting here. - We can't just mark them all unset at the start of the whole thing because - they may get set in one branch that is not the final matching branch. */ - - if (mb->end_offset_top/2 <= re->top_bracket) - { - PCRE2_SIZE *iptr, *iend; - int resetcount = re->top_bracket + 1; - if (resetcount > match_data->oveccount) resetcount = match_data->oveccount; - iptr = match_data->ovector + mb->end_offset_top; - iend = match_data->ovector + 2 * resetcount; - while (iptr < iend) *iptr++ = PCRE2_UNSET; - } - - /* If there is space, set up the whole thing as substring 0. The value of - mb->start_match_ptr might be modified if \K was encountered on the success - matching path. */ - - if (match_data->oveccount < 1) rc = 0; else - { - match_data->ovector[0] = mb->start_match_ptr - mb->start_subject; - match_data->ovector[1] = mb->end_match_ptr - mb->start_subject; - } - - /* Set the remaining returned values */ - + match_data->rc = ((int)mb->end_offset_top >= 2 * match_data->oveccount)? + 0 : (int)mb->end_offset_top/2 + 1; match_data->startchar = start_match - subject; match_data->leftchar = mb->start_used_ptr - subject; match_data->rightchar = ((mb->last_used_ptr > mb->end_match_ptr)? @@ -7206,18 +6820,14 @@ match_data->mark = mb->nomatch_mark; /* For anything other than nomatch or partial match, just return the code. */ -if (rc != MATCH_NOMATCH && rc != PCRE2_ERROR_PARTIAL) - match_data->rc = rc; +if (rc != MATCH_NOMATCH && rc != PCRE2_ERROR_PARTIAL) match_data->rc = rc; -/* Else handle a partial match. */ +/* Handle a partial match. */ else if (match_partial != NULL) { - if (match_data->oveccount > 0) - { - match_data->ovector[0] = match_partial - subject; - match_data->ovector[1] = end_subject - subject; - } + match_data->ovector[0] = match_partial - subject; + match_data->ovector[1] = end_subject - subject; match_data->startchar = match_partial - subject; match_data->leftchar = start_partial - subject; match_data->rightchar = end_subject - subject; @@ -7228,10 +6838,6 @@ else if (match_partial != NULL) else match_data->rc = PCRE2_ERROR_NOMATCH; -/* Free any temporary offsets. */ - -if (using_temporary_offsets) - mb->memctl.free(mb->ovector, mb->memctl.memory_data); return match_data->rc; } diff --git a/thirdparty/pcre2/src/pcre2_match_data.c b/thirdparty/pcre2/src/pcre2_match_data.c index 85ac998348..b297f326b5 100644 --- a/thirdparty/pcre2/src/pcre2_match_data.c +++ b/thirdparty/pcre2/src/pcre2_match_data.c @@ -7,7 +7,7 @@ and semantics are as close as possible to those of the Perl 5 language. Written by Philip Hazel Original API code Copyright (c) 1997-2012 University of Cambridge - New API code Copyright (c) 2016 University of Cambridge + New API code Copyright (c) 2016-2017 University of Cambridge ----------------------------------------------------------------------------- Redistribution and use in source and binary forms, with or without @@ -51,7 +51,7 @@ POSSIBILITY OF SUCH DAMAGE. * Create a match data block given ovector size * *************************************************/ -/* A minimum of 1 is imposed on the number of ovector triplets. */ +/* A minimum of 1 is imposed on the number of ovector pairs. */ PCRE2_EXP_DEFN pcre2_match_data * PCRE2_CALL_CONVENTION pcre2_match_data_create(uint32_t oveccount, pcre2_general_context *gcontext) @@ -59,7 +59,7 @@ pcre2_match_data_create(uint32_t oveccount, pcre2_general_context *gcontext) pcre2_match_data *yield; if (oveccount < 1) oveccount = 1; yield = PRIV(memctl_malloc)( - sizeof(pcre2_match_data) + 3*oveccount*sizeof(PCRE2_SIZE), + offsetof(pcre2_match_data, ovector) + 2*oveccount*sizeof(PCRE2_SIZE), (pcre2_memctl *)gcontext); if (yield == NULL) return NULL; yield->oveccount = oveccount; diff --git a/thirdparty/pcre2/src/pcre2_pattern_info.c b/thirdparty/pcre2/src/pcre2_pattern_info.c index 5b32a905b0..906e9198f5 100644 --- a/thirdparty/pcre2/src/pcre2_pattern_info.c +++ b/thirdparty/pcre2/src/pcre2_pattern_info.c @@ -7,7 +7,7 @@ and semantics are as close as possible to those of the Perl 5 language. Written by Philip Hazel Original API code Copyright (c) 1997-2012 University of Cambridge - New API code Copyright (c) 2016 University of Cambridge + New API code Copyright (c) 2016-2017 University of Cambridge ----------------------------------------------------------------------------- Redistribution and use in source and binary forms, with or without @@ -75,10 +75,13 @@ if (where == NULL) /* Requests field length */ case PCRE2_INFO_BACKREFMAX: case PCRE2_INFO_BSR: case PCRE2_INFO_CAPTURECOUNT: + case PCRE2_INFO_DEPTHLIMIT: + case PCRE2_INFO_EXTRAOPTIONS: case PCRE2_INFO_FIRSTCODETYPE: case PCRE2_INFO_FIRSTCODEUNIT: case PCRE2_INFO_HASBACKSLASHC: case PCRE2_INFO_HASCRORLF: + case PCRE2_INFO_HEAPLIMIT: case PCRE2_INFO_JCHANGED: case PCRE2_INFO_LASTCODETYPE: case PCRE2_INFO_LASTCODEUNIT: @@ -89,7 +92,6 @@ if (where == NULL) /* Requests field length */ case PCRE2_INFO_NAMEENTRYSIZE: case PCRE2_INFO_NAMECOUNT: case PCRE2_INFO_NEWLINE: - case PCRE2_INFO_RECURSIONLIMIT: return sizeof(uint32_t); case PCRE2_INFO_FIRSTBITMAP: @@ -97,6 +99,7 @@ if (where == NULL) /* Requests field length */ case PCRE2_INFO_JITSIZE: case PCRE2_INFO_SIZE: + case PCRE2_INFO_FRAMESIZE: return sizeof(size_t); case PCRE2_INFO_NAMETABLE: @@ -137,6 +140,15 @@ switch(what) *((uint32_t *)where) = re->top_bracket; break; + case PCRE2_INFO_DEPTHLIMIT: + *((uint32_t *)where) = re->limit_depth; + if (re->limit_depth == UINT32_MAX) return PCRE2_ERROR_UNSET; + break; + + case PCRE2_INFO_EXTRAOPTIONS: + *((uint32_t *)where) = re->extra_options; + break; + case PCRE2_INFO_FIRSTCODETYPE: *((uint32_t *)where) = ((re->flags & PCRE2_FIRSTSET) != 0)? 1 : ((re->flags & PCRE2_STARTLINE) != 0)? 2 : 0; @@ -152,6 +164,11 @@ switch(what) &(re->start_bitmap[0]) : NULL; break; + case PCRE2_INFO_FRAMESIZE: + *((size_t *)where) = offsetof(heapframe, ovector) + + re->top_bracket * 2 * sizeof(PCRE2_SIZE); + break; + case PCRE2_INFO_HASBACKSLASHC: *((uint32_t *)where) = (re->flags & PCRE2_HASBKC) != 0; break; @@ -160,6 +177,11 @@ switch(what) *((uint32_t *)where) = (re->flags & PCRE2_HASCRORLF) != 0; break; + case PCRE2_INFO_HEAPLIMIT: + *((uint32_t *)where) = re->limit_heap; + if (re->limit_heap == UINT32_MAX) return PCRE2_ERROR_UNSET; + break; + case PCRE2_INFO_JCHANGED: *((uint32_t *)where) = (re->flags & PCRE2_JCHANGED) != 0; break; @@ -215,11 +237,6 @@ switch(what) *((uint32_t *)where) = re->newline_convention; break; - case PCRE2_INFO_RECURSIONLIMIT: - *((uint32_t *)where) = re->limit_recursion; - if (re->limit_recursion == UINT32_MAX) return PCRE2_ERROR_UNSET; - break; - case PCRE2_INFO_SIZE: *((size_t *)where) = re->blocksize; break; @@ -255,11 +272,15 @@ pcre2_real_code *re = (pcre2_real_code *)code; pcre2_callout_enumerate_block cb; PCRE2_SPTR cc; #ifdef SUPPORT_UNICODE -BOOL utf = (re->overall_options & PCRE2_UTF) != 0; +BOOL utf; #endif if (re == NULL) return PCRE2_ERROR_NULL; +#ifdef SUPPORT_UNICODE +utf = (re->overall_options & PCRE2_UTF) != 0; +#endif + /* Check that the first field in the block is the magic number. If it is not, return with PCRE2_ERROR_BADMAGIC. */ diff --git a/thirdparty/pcre2/src/pcre2_printint.c b/thirdparty/pcre2/src/pcre2_printint.c deleted file mode 100644 index 6207497648..0000000000 --- a/thirdparty/pcre2/src/pcre2_printint.c +++ /dev/null @@ -1,832 +0,0 @@ -/************************************************* -* Perl-Compatible Regular Expressions * -*************************************************/ - -/* PCRE is a library of functions to support regular expressions whose syntax -and semantics are as close as possible to those of the Perl 5 language. - - Written by Philip Hazel - Original API code Copyright (c) 1997-2012 University of Cambridge - New API code Copyright (c) 2016 University of Cambridge - ------------------------------------------------------------------------------ -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - * Neither the name of the University of Cambridge nor the names of its - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. ------------------------------------------------------------------------------ -*/ - - -/* This module contains a PCRE private debugging function for printing out the -internal form of a compiled regular expression, along with some supporting -local functions. This source file is #included in pcre2test.c at each supported -code unit width, with PCRE2_SUFFIX set appropriately, just like the functions -that comprise the library. It can also optionally be included in -pcre2_compile.c for detailed debugging in error situations. */ - - -/* Tables of operator names. The same 8-bit table is used for all code unit -widths, so it must be defined only once. The list itself is defined in -pcre2_internal.h, which is #included by pcre2test before this file. */ - -#ifndef OP_LISTS_DEFINED -static const char *OP_names[] = { OP_NAME_LIST }; -#define OP_LISTS_DEFINED -#endif - -/* The functions and tables herein must all have mode-dependent names. */ - -#define OP_lengths PCRE2_SUFFIX(OP_lengths_) -#define get_ucpname PCRE2_SUFFIX(get_ucpname_) -#define pcre2_printint PCRE2_SUFFIX(pcre2_printint_) -#define print_char PCRE2_SUFFIX(print_char_) -#define print_custring PCRE2_SUFFIX(print_custring_) -#define print_custring_bylen PCRE2_SUFFIX(print_custring_bylen_) -#define print_prop PCRE2_SUFFIX(print_prop_) - -/* Table of sizes for the fixed-length opcodes. It's defined in a macro so that -the definition is next to the definition of the opcodes in pcre2_internal.h. -The contents of the table are, however, mode-dependent. */ - -static const uint8_t OP_lengths[] = { OP_LENGTHS }; - - - -/************************************************* -* Print one character from a string * -*************************************************/ - -/* In UTF mode the character may occupy more than one code unit. - -Arguments: - f file to write to - ptr pointer to first code unit of the character - utf TRUE if string is UTF (will be FALSE if UTF is not supported) - -Returns: number of additional code units used -*/ - -static unsigned int -print_char(FILE *f, PCRE2_SPTR ptr, BOOL utf) -{ -uint32_t c = *ptr; -BOOL one_code_unit = !utf; - -/* If UTF is supported and requested, check for a valid single code unit. */ - -#ifdef SUPPORT_UNICODE -if (utf) - { -#if PCRE2_CODE_UNIT_WIDTH == 8 - one_code_unit = c < 0x80; -#elif PCRE2_CODE_UNIT_WIDTH == 16 - one_code_unit = (c & 0xfc00) != 0xd800; -#else - one_code_unit = (c & 0xfffff800u) != 0xd800u; -#endif /* CODE_UNIT_WIDTH */ - } -#endif /* SUPPORT_UNICODE */ - -/* Handle a valid one-code-unit character at any width. */ - -if (one_code_unit) - { - if (PRINTABLE(c)) fprintf(f, "%c", (char)c); - else if (c < 0x80) fprintf(f, "\\x%02x", c); - else fprintf(f, "\\x{%02x}", c); - return 0; - } - -/* Code for invalid UTF code units and multi-unit UTF characters is different -for each width. If UTF is not supported, control should never get here, but we -need a return statement to keep the compiler happy. */ - -#ifndef SUPPORT_UNICODE -return 0; -#else - -/* Malformed UTF-8 should occur only if the sanity check has been turned off. -Rather than swallow random bytes, just stop if we hit a bad one. Print it with -\X instead of \x as an indication. */ - -#if PCRE2_CODE_UNIT_WIDTH == 8 -if ((c & 0xc0) != 0xc0) - { - fprintf(f, "\\X{%x}", c); /* Invalid starting byte */ - return 0; - } -else - { - int i; - int a = PRIV(utf8_table4)[c & 0x3f]; /* Number of additional bytes */ - int s = 6*a; - c = (c & PRIV(utf8_table3)[a]) << s; - for (i = 1; i <= a; i++) - { - if ((ptr[i] & 0xc0) != 0x80) - { - fprintf(f, "\\X{%x}", c); /* Invalid secondary byte */ - return i - 1; - } - s -= 6; - c |= (ptr[i] & 0x3f) << s; - } - fprintf(f, "\\x{%x}", c); - return a; -} -#endif /* PCRE2_CODE_UNIT_WIDTH == 8 */ - -/* UTF-16: rather than swallow a low surrogate, just stop if we hit a bad one. -Print it with \X instead of \x as an indication. */ - -#if PCRE2_CODE_UNIT_WIDTH == 16 -if ((ptr[1] & 0xfc00) != 0xdc00) - { - fprintf(f, "\\X{%x}", c); - return 0; - } -c = (((c & 0x3ff) << 10) | (ptr[1] & 0x3ff)) + 0x10000; -fprintf(f, "\\x{%x}", c); -return 1; -#endif /* PCRE2_CODE_UNIT_WIDTH == 16 */ - -/* For UTF-32 we get here only for a malformed code unit, which should only -occur if the sanity check has been turned off. Print it with \X instead of \x -as an indication. */ - -#if PCRE2_CODE_UNIT_WIDTH == 32 -fprintf(f, "\\X{%x}", c); -return 0; -#endif /* PCRE2_CODE_UNIT_WIDTH == 32 */ -#endif /* SUPPORT_UNICODE */ -} - - - -/************************************************* -* Print string as a list of code units * -*************************************************/ - -/* These take no account of UTF as they always print each individual code unit. -The string is zero-terminated for print_custring(); the length is given for -print_custring_bylen(). - -Arguments: - f file to write to - ptr point to the string - len length for print_custring_bylen() - -Returns: nothing -*/ - -static void -print_custring(FILE *f, PCRE2_SPTR ptr) -{ -while (*ptr != '\0') - { - uint32_t c = *ptr++; - if (PRINTABLE(c)) fprintf(f, "%c", c); else fprintf(f, "\\x{%x}", c); - } -} - -static void -print_custring_bylen(FILE *f, PCRE2_SPTR ptr, PCRE2_UCHAR len) -{ -for (; len > 0; len--) - { - uint32_t c = *ptr++; - if (PRINTABLE(c)) fprintf(f, "%c", c); else fprintf(f, "\\x{%x}", c); - } -} - - - -/************************************************* -* Find Unicode property name * -*************************************************/ - -/* When there is no UTF/UCP support, the table of names does not exist. This -function should not be called in such configurations, because a pattern that -tries to use Unicode properties won't compile. Rather than put lots of #ifdefs -into the main code, however, we just put one into this function. */ - -static const char * -get_ucpname(unsigned int ptype, unsigned int pvalue) -{ -#ifdef SUPPORT_UNICODE -int i; -for (i = PRIV(utt_size) - 1; i >= 0; i--) - { - if (ptype == PRIV(utt)[i].type && pvalue == PRIV(utt)[i].value) break; - } -return (i >= 0)? PRIV(utt_names) + PRIV(utt)[i].name_offset : "??"; -#else /* No UTF support */ -(void)ptype; -(void)pvalue; -return "??"; -#endif /* SUPPORT_UNICODE */ -} - - - -/************************************************* -* Print Unicode property value * -*************************************************/ - -/* "Normal" properties can be printed from tables. The PT_CLIST property is a -pseudo-property that contains a pointer to a list of case-equivalent -characters. - -Arguments: - f file to write to - code pointer in the compiled code - before text to print before - after text to print after - -Returns: nothing -*/ - -static void -print_prop(FILE *f, PCRE2_SPTR code, const char *before, const char *after) -{ -if (code[1] != PT_CLIST) - { - fprintf(f, "%s%s %s%s", before, OP_names[*code], get_ucpname(code[1], - code[2]), after); - } -else - { - const char *not = (*code == OP_PROP)? "" : "not "; - const uint32_t *p = PRIV(ucd_caseless_sets) + code[2]; - fprintf (f, "%s%sclist", before, not); - while (*p < NOTACHAR) fprintf(f, " %04x", *p++); - fprintf(f, "%s", after); - } -} - - - -/************************************************* -* Print compiled pattern * -*************************************************/ - -/* The print_lengths flag controls whether offsets and lengths of items are -printed. Lenths can be turned off from pcre2test so that automatic tests on -bytecode can be written that do not depend on the value of LINK_SIZE. - -Arguments: - re a compiled pattern - f the file to write to - print_lengths show various lengths - -Returns: nothing -*/ - -static void -pcre2_printint(pcre2_code *re, FILE *f, BOOL print_lengths) -{ -PCRE2_SPTR codestart, nametable, code; -uint32_t nesize = re->name_entry_size; -BOOL utf = (re->overall_options & PCRE2_UTF) != 0; - -nametable = (PCRE2_SPTR)((uint8_t *)re + sizeof(pcre2_real_code)); -code = codestart = nametable + re->name_count * re->name_entry_size; - -for(;;) - { - PCRE2_SPTR ccode; - uint32_t c; - int i; - const char *flag = " "; - unsigned int extra = 0; - - if (print_lengths) - fprintf(f, "%3d ", (int)(code - codestart)); - else - fprintf(f, " "); - - switch(*code) - { -/* ========================================================================== */ - /* These cases are never obeyed. This is a fudge that causes a compile- - time error if the vectors OP_names or OP_lengths, which are indexed - by opcode, are not the correct length. It seems to be the only way to do - such a check at compile time, as the sizeof() operator does not work in - the C preprocessor. */ - - case OP_TABLE_LENGTH: - case OP_TABLE_LENGTH + - ((sizeof(OP_names)/sizeof(const char *) == OP_TABLE_LENGTH) && - (sizeof(OP_lengths) == OP_TABLE_LENGTH)): - break; -/* ========================================================================== */ - - case OP_END: - fprintf(f, " %s\n", OP_names[*code]); - fprintf(f, "------------------------------------------------------------------\n"); - return; - - case OP_CHAR: - fprintf(f, " "); - do - { - code++; - code += 1 + print_char(f, code, utf); - } - while (*code == OP_CHAR); - fprintf(f, "\n"); - continue; - - case OP_CHARI: - fprintf(f, " /i "); - do - { - code++; - code += 1 + print_char(f, code, utf); - } - while (*code == OP_CHARI); - fprintf(f, "\n"); - continue; - - case OP_CBRA: - case OP_CBRAPOS: - case OP_SCBRA: - case OP_SCBRAPOS: - if (print_lengths) fprintf(f, "%3d ", GET(code, 1)); - else fprintf(f, " "); - fprintf(f, "%s %d", OP_names[*code], GET2(code, 1+LINK_SIZE)); - break; - - case OP_BRA: - case OP_BRAPOS: - case OP_SBRA: - case OP_SBRAPOS: - case OP_KETRMAX: - case OP_KETRMIN: - case OP_KETRPOS: - case OP_ALT: - case OP_KET: - case OP_ASSERT: - case OP_ASSERT_NOT: - case OP_ASSERTBACK: - case OP_ASSERTBACK_NOT: - case OP_ONCE: - case OP_ONCE_NC: - case OP_COND: - case OP_SCOND: - case OP_REVERSE: - if (print_lengths) fprintf(f, "%3d ", GET(code, 1)); - else fprintf(f, " "); - fprintf(f, "%s", OP_names[*code]); - break; - - case OP_CLOSE: - fprintf(f, " %s %d", OP_names[*code], GET2(code, 1)); - break; - - case OP_CREF: - fprintf(f, "%3d %s", GET2(code,1), OP_names[*code]); - break; - - case OP_DNCREF: - { - PCRE2_SPTR entry = nametable + (GET2(code, 1) * nesize) + IMM2_SIZE; - fprintf(f, " %s Cond ref <", flag); - print_custring(f, entry); - fprintf(f, ">%d", GET2(code, 1 + IMM2_SIZE)); - } - break; - - case OP_RREF: - c = GET2(code, 1); - if (c == RREF_ANY) - fprintf(f, " Cond recurse any"); - else - fprintf(f, " Cond recurse %d", c); - break; - - case OP_DNRREF: - { - PCRE2_SPTR entry = nametable + (GET2(code, 1) * nesize) + IMM2_SIZE; - fprintf(f, " %s Cond recurse <", flag); - print_custring(f, entry); - fprintf(f, ">%d", GET2(code, 1 + IMM2_SIZE)); - } - break; - - case OP_FALSE: - fprintf(f, " Cond false"); - break; - - case OP_TRUE: - fprintf(f, " Cond true"); - break; - - case OP_STARI: - case OP_MINSTARI: - case OP_POSSTARI: - case OP_PLUSI: - case OP_MINPLUSI: - case OP_POSPLUSI: - case OP_QUERYI: - case OP_MINQUERYI: - case OP_POSQUERYI: - flag = "/i"; - /* Fall through */ - case OP_STAR: - case OP_MINSTAR: - case OP_POSSTAR: - case OP_PLUS: - case OP_MINPLUS: - case OP_POSPLUS: - case OP_QUERY: - case OP_MINQUERY: - case OP_POSQUERY: - case OP_TYPESTAR: - case OP_TYPEMINSTAR: - case OP_TYPEPOSSTAR: - case OP_TYPEPLUS: - case OP_TYPEMINPLUS: - case OP_TYPEPOSPLUS: - case OP_TYPEQUERY: - case OP_TYPEMINQUERY: - case OP_TYPEPOSQUERY: - fprintf(f, " %s ", flag); - - if (*code >= OP_TYPESTAR) - { - if (code[1] == OP_PROP || code[1] == OP_NOTPROP) - { - print_prop(f, code + 1, "", " "); - extra = 2; - } - else fprintf(f, "%s", OP_names[code[1]]); - } - else extra = print_char(f, code+1, utf); - fprintf(f, "%s", OP_names[*code]); - break; - - case OP_EXACTI: - case OP_UPTOI: - case OP_MINUPTOI: - case OP_POSUPTOI: - flag = "/i"; - /* Fall through */ - case OP_EXACT: - case OP_UPTO: - case OP_MINUPTO: - case OP_POSUPTO: - fprintf(f, " %s ", flag); - extra = print_char(f, code + 1 + IMM2_SIZE, utf); - fprintf(f, "{"); - if (*code != OP_EXACT && *code != OP_EXACTI) fprintf(f, "0,"); - fprintf(f, "%d}", GET2(code,1)); - if (*code == OP_MINUPTO || *code == OP_MINUPTOI) fprintf(f, "?"); - else if (*code == OP_POSUPTO || *code == OP_POSUPTOI) fprintf(f, "+"); - break; - - case OP_TYPEEXACT: - case OP_TYPEUPTO: - case OP_TYPEMINUPTO: - case OP_TYPEPOSUPTO: - if (code[1 + IMM2_SIZE] == OP_PROP || code[1 + IMM2_SIZE] == OP_NOTPROP) - { - print_prop(f, code + IMM2_SIZE + 1, " ", " "); - extra = 2; - } - else fprintf(f, " %s", OP_names[code[1 + IMM2_SIZE]]); - fprintf(f, "{"); - if (*code != OP_TYPEEXACT) fprintf(f, "0,"); - fprintf(f, "%d}", GET2(code,1)); - if (*code == OP_TYPEMINUPTO) fprintf(f, "?"); - else if (*code == OP_TYPEPOSUPTO) fprintf(f, "+"); - break; - - case OP_NOTI: - flag = "/i"; - /* Fall through */ - case OP_NOT: - fprintf(f, " %s [^", flag); - extra = print_char(f, code + 1, utf); - fprintf(f, "]"); - break; - - case OP_NOTSTARI: - case OP_NOTMINSTARI: - case OP_NOTPOSSTARI: - case OP_NOTPLUSI: - case OP_NOTMINPLUSI: - case OP_NOTPOSPLUSI: - case OP_NOTQUERYI: - case OP_NOTMINQUERYI: - case OP_NOTPOSQUERYI: - flag = "/i"; - /* Fall through */ - - case OP_NOTSTAR: - case OP_NOTMINSTAR: - case OP_NOTPOSSTAR: - case OP_NOTPLUS: - case OP_NOTMINPLUS: - case OP_NOTPOSPLUS: - case OP_NOTQUERY: - case OP_NOTMINQUERY: - case OP_NOTPOSQUERY: - fprintf(f, " %s [^", flag); - extra = print_char(f, code + 1, utf); - fprintf(f, "]%s", OP_names[*code]); - break; - - case OP_NOTEXACTI: - case OP_NOTUPTOI: - case OP_NOTMINUPTOI: - case OP_NOTPOSUPTOI: - flag = "/i"; - /* Fall through */ - - case OP_NOTEXACT: - case OP_NOTUPTO: - case OP_NOTMINUPTO: - case OP_NOTPOSUPTO: - fprintf(f, " %s [^", flag); - extra = print_char(f, code + 1 + IMM2_SIZE, utf); - fprintf(f, "]{"); - if (*code != OP_NOTEXACT && *code != OP_NOTEXACTI) fprintf(f, "0,"); - fprintf(f, "%d}", GET2(code,1)); - if (*code == OP_NOTMINUPTO || *code == OP_NOTMINUPTOI) fprintf(f, "?"); - else - if (*code == OP_NOTPOSUPTO || *code == OP_NOTPOSUPTOI) fprintf(f, "+"); - break; - - case OP_RECURSE: - if (print_lengths) fprintf(f, "%3d ", GET(code, 1)); - else fprintf(f, " "); - fprintf(f, "%s", OP_names[*code]); - break; - - case OP_REFI: - flag = "/i"; - /* Fall through */ - case OP_REF: - fprintf(f, " %s \\%d", flag, GET2(code,1)); - ccode = code + OP_lengths[*code]; - goto CLASS_REF_REPEAT; - - case OP_DNREFI: - flag = "/i"; - /* Fall through */ - case OP_DNREF: - { - PCRE2_SPTR entry = nametable + (GET2(code, 1) * nesize) + IMM2_SIZE; - fprintf(f, " %s \\k<", flag); - print_custring(f, entry); - fprintf(f, ">%d", GET2(code, 1 + IMM2_SIZE)); - } - ccode = code + OP_lengths[*code]; - goto CLASS_REF_REPEAT; - - case OP_CALLOUT: - fprintf(f, " %s %d %d %d", OP_names[*code], code[1 + 2*LINK_SIZE], - GET(code, 1), GET(code, 1 + LINK_SIZE)); - break; - - case OP_CALLOUT_STR: - c = code[1 + 4*LINK_SIZE]; - fprintf(f, " %s %c", OP_names[*code], c); - extra = GET(code, 1 + 2*LINK_SIZE); - print_custring_bylen(f, code + 2 + 4*LINK_SIZE, extra - 3 - 4*LINK_SIZE); - for (i = 0; PRIV(callout_start_delims)[i] != 0; i++) - if (c == PRIV(callout_start_delims)[i]) - { - c = PRIV(callout_end_delims)[i]; - break; - } - fprintf(f, "%c %d %d %d", c, GET(code, 1 + 3*LINK_SIZE), GET(code, 1), - GET(code, 1 + LINK_SIZE)); - break; - - case OP_PROP: - case OP_NOTPROP: - print_prop(f, code, " ", ""); - break; - - /* OP_XCLASS cannot occur in 8-bit, non-UTF mode. However, there's no harm - in having this code always here, and it makes it less messy without all - those #ifdefs. */ - - case OP_CLASS: - case OP_NCLASS: - case OP_XCLASS: - { - unsigned int min, max; - BOOL printmap; - BOOL invertmap = FALSE; - uint8_t *map; - uint8_t inverted_map[32]; - - fprintf(f, " ["); - - if (*code == OP_XCLASS) - { - extra = GET(code, 1); - ccode = code + LINK_SIZE + 1; - printmap = (*ccode & XCL_MAP) != 0; - if ((*ccode & XCL_NOT) != 0) - { - invertmap = (*ccode & XCL_HASPROP) == 0; - fprintf(f, "^"); - } - ccode++; - } - else - { - printmap = TRUE; - ccode = code + 1; - } - - /* Print a bit map */ - - if (printmap) - { - map = (uint8_t *)ccode; - if (invertmap) - { - for (i = 0; i < 32; i++) inverted_map[i] = ~map[i]; - map = inverted_map; - } - - for (i = 0; i < 256; i++) - { - if ((map[i/8] & (1 << (i&7))) != 0) - { - int j; - for (j = i+1; j < 256; j++) - if ((map[j/8] & (1 << (j&7))) == 0) break; - if (i == '-' || i == ']') fprintf(f, "\\"); - if (PRINTABLE(i)) fprintf(f, "%c", i); - else fprintf(f, "\\x%02x", i); - if (--j > i) - { - if (j != i + 1) fprintf(f, "-"); - if (j == '-' || j == ']') fprintf(f, "\\"); - if (PRINTABLE(j)) fprintf(f, "%c", j); - else fprintf(f, "\\x%02x", j); - } - i = j; - } - } - ccode += 32 / sizeof(PCRE2_UCHAR); - } - - /* For an XCLASS there is always some additional data */ - - if (*code == OP_XCLASS) - { - PCRE2_UCHAR ch; - while ((ch = *ccode++) != XCL_END) - { - BOOL not = FALSE; - const char *notch = ""; - - switch(ch) - { - case XCL_NOTPROP: - not = TRUE; - notch = "^"; - /* Fall through */ - - case XCL_PROP: - { - unsigned int ptype = *ccode++; - unsigned int pvalue = *ccode++; - - switch(ptype) - { - case PT_PXGRAPH: - fprintf(f, "[:%sgraph:]", notch); - break; - - case PT_PXPRINT: - fprintf(f, "[:%sprint:]", notch); - break; - - case PT_PXPUNCT: - fprintf(f, "[:%spunct:]", notch); - break; - - default: - fprintf(f, "\\%c{%s}", (not? 'P':'p'), - get_ucpname(ptype, pvalue)); - break; - } - } - break; - - default: - ccode += 1 + print_char(f, ccode, utf); - if (ch == XCL_RANGE) - { - fprintf(f, "-"); - ccode += 1 + print_char(f, ccode, utf); - } - break; - } - } - } - - /* Indicate a non-UTF class which was created by negation */ - - fprintf(f, "]%s", (*code == OP_NCLASS)? " (neg)" : ""); - - /* Handle repeats after a class or a back reference */ - - CLASS_REF_REPEAT: - switch(*ccode) - { - case OP_CRSTAR: - case OP_CRMINSTAR: - case OP_CRPLUS: - case OP_CRMINPLUS: - case OP_CRQUERY: - case OP_CRMINQUERY: - case OP_CRPOSSTAR: - case OP_CRPOSPLUS: - case OP_CRPOSQUERY: - fprintf(f, "%s", OP_names[*ccode]); - extra += OP_lengths[*ccode]; - break; - - case OP_CRRANGE: - case OP_CRMINRANGE: - case OP_CRPOSRANGE: - min = GET2(ccode,1); - max = GET2(ccode,1 + IMM2_SIZE); - if (max == 0) fprintf(f, "{%u,}", min); - else fprintf(f, "{%u,%u}", min, max); - if (*ccode == OP_CRMINRANGE) fprintf(f, "?"); - else if (*ccode == OP_CRPOSRANGE) fprintf(f, "+"); - extra += OP_lengths[*ccode]; - break; - - /* Do nothing if it's not a repeat; this code stops picky compilers - warning about the lack of a default code path. */ - - default: - break; - } - } - break; - - case OP_MARK: - case OP_PRUNE_ARG: - case OP_SKIP_ARG: - case OP_THEN_ARG: - fprintf(f, " %s ", OP_names[*code]); - print_custring_bylen(f, code + 2, code[1]); - extra += code[1]; - break; - - case OP_THEN: - fprintf(f, " %s", OP_names[*code]); - break; - - case OP_CIRCM: - case OP_DOLLM: - flag = "/m"; - /* Fall through */ - - /* Anything else is just an item with no data, but possibly a flag. */ - - default: - fprintf(f, " %s %s", flag, OP_names[*code]); - break; - } - - code += OP_lengths[*code] + extra; - fprintf(f, "\n"); - } -} - -/* End of pcre2_printint.c */ diff --git a/thirdparty/pcre2/src/pcre2_serialize.c b/thirdparty/pcre2/src/pcre2_serialize.c index 0af26d8fc3..d2cc603cbb 100644 --- a/thirdparty/pcre2/src/pcre2_serialize.c +++ b/thirdparty/pcre2/src/pcre2_serialize.c @@ -7,7 +7,7 @@ and semantics are as close as possible to those of the Perl 5 language. Written by Philip Hazel Original API code Copyright (c) 1997-2012 University of Cambridge - New API code Copyright (c) 2016 University of Cambridge + New API code Copyright (c) 2016-2017 University of Cambridge ----------------------------------------------------------------------------- Redistribution and use in source and binary forms, with or without @@ -214,7 +214,10 @@ for (i = 0; i < number_of_codes; i++) if (dst_re->magic_number != MAGIC_NUMBER || dst_re->name_entry_size > MAX_NAME_SIZE + IMM2_SIZE + 1 || dst_re->name_count > MAX_NAME_COUNT) + { + memctl->free(dst_re, memctl->memory_data); return PCRE2_ERROR_BADSERIALIZEDDATA; + } /* At the moment only one table is supported. */ diff --git a/thirdparty/pcre2/src/pcre2_study.c b/thirdparty/pcre2/src/pcre2_study.c index 5a4d520c09..b92686759d 100644 --- a/thirdparty/pcre2/src/pcre2_study.c +++ b/thirdparty/pcre2/src/pcre2_study.c @@ -7,7 +7,7 @@ and semantics are as close as possible to those of the Perl 5 language. Written by Philip Hazel Original API code Copyright (c) 1997-2012 University of Cambridge - New API code Copyright (c) 2016 University of Cambridge + New API code Copyright (c) 2016-2017 University of Cambridge ----------------------------------------------------------------------------- Redistribution and use in source and binary forms, with or without @@ -46,10 +46,8 @@ collecting data (e.g. minimum matching length). */ #include "config.h" #endif - #include "pcre2_internal.h" - /* The maximum remembered capturing brackets minimum. */ #define MAX_CACHE_BACKREF 128 @@ -158,12 +156,12 @@ for (;;) } goto PROCESS_NON_CAPTURE; - /* There's a special case of OP_ONCE, when it is wrapped round an + case OP_BRA: + /* There's a special case of OP_BRA, when it is wrapped round a repeated OP_RECURSE. We'd like to process the latter at this level so that remembering the value works for repeated cases. So we do nothing, but set a fudge value to skip over the OP_KET after the recurse. */ - case OP_ONCE: if (cc[1+LINK_SIZE] == OP_RECURSE && cc[2*(1+LINK_SIZE)] == OP_KET) { once_fudge = 1 + LINK_SIZE; @@ -172,8 +170,7 @@ for (;;) } /* Fall through */ - case OP_ONCE_NC: - case OP_BRA: + case OP_ONCE: case OP_SBRA: case OP_BRAPOS: case OP_SBRAPOS: @@ -789,6 +786,7 @@ if (utf) if (caseless) { +#ifdef SUPPORT_UNICODE if (utf) { #if PCRE2_CODE_UNIT_WIDTH == 8 @@ -801,10 +799,12 @@ if (caseless) if (c > 0xff) SET_BIT(0xff); else SET_BIT(c); #endif } + else +#endif /* SUPPORT_UNICODE */ /* Not UTF */ - else if (MAX_255(c)) SET_BIT(re->tables[fcc_offset + c]); + if (MAX_255(c)) SET_BIT(re->tables[fcc_offset + c]); } return p; @@ -953,7 +953,6 @@ do case OP_ALLANY: case OP_ANY: case OP_ANYBYTE: - case OP_CIRC: case OP_CIRCM: case OP_CLOSE: case OP_COMMIT: @@ -1021,6 +1020,13 @@ do case OP_THEN_ARG: return SSB_FAIL; + /* OP_CIRC happens only at the start of an anchored branch (multiline ^ + uses OP_CIRCM). Skip over it. */ + + case OP_CIRC: + tcode += PRIV(OP_lengths)[OP_CIRC]; + break; + /* A "real" property test implies no starting bits, but the fake property PT_CLIST identifies a list of characters. These lists are short, as they are used for characters with more than one "other case", so there is no @@ -1067,7 +1073,6 @@ do case OP_CBRAPOS: case OP_SCBRAPOS: case OP_ONCE: - case OP_ONCE_NC: case OP_ASSERT: rc = set_start_bits(re, tcode, utf); if (rc == SSB_FAIL || rc == SSB_UNKNOWN) return rc; @@ -1449,6 +1454,10 @@ do classmap = ((tcode[1 + LINK_SIZE] & XCL_MAP) == 0)? NULL : (uint8_t *)(tcode + 1 + LINK_SIZE + 1); #endif + /* It seems that the fall through comment must be outside the #ifdef if + it is to avoid the gcc compiler warning. */ + + /* Fall through */ /* Enter here for a negative non-XCLASS. In the 8-bit library, if we are in UTF mode, any byte with a value >= 0xc4 is a potentially valid starter @@ -1576,12 +1585,11 @@ BOOL utf = (re->overall_options & PCRE2_UTF) != 0; code = (PCRE2_UCHAR *)((uint8_t *)re + sizeof(pcre2_real_code)) + re->name_entry_size * re->name_count; -/* For an anchored pattern, or an unanchored pattern that has a first code -unit, or a multiline pattern that matches only at "line start", there is no -point in seeking a list of starting code units. */ +/* For a pattern that has a first code unit, or a multiline pattern that +matches only at "line start", there is no point in seeking a list of starting +code units. */ -if ((re->overall_options & PCRE2_ANCHORED) == 0 && - (re->flags & (PCRE2_FIRSTSET|PCRE2_STARTLINE)) == 0) +if ((re->flags & (PCRE2_FIRSTSET|PCRE2_STARTLINE)) == 0) { int rc = set_start_bits(re, code, utf); if (rc == SSB_UNKNOWN) return 1; diff --git a/thirdparty/pcre2/src/pcre2_substring.c b/thirdparty/pcre2/src/pcre2_substring.c index f6d7c39722..ddf5774e15 100644 --- a/thirdparty/pcre2/src/pcre2_substring.c +++ b/thirdparty/pcre2/src/pcre2_substring.c @@ -7,7 +7,7 @@ and semantics are as close as possible to those of the Perl 5 language. Written by Philip Hazel Original API code Copyright (c) 1997-2012 University of Cambridge - New API code Copyright (c) 2016 University of Cambridge + New API code Copyright (c) 2016-2018 University of Cambridge ----------------------------------------------------------------------------- Redistribution and use in source and binary forms, with or without @@ -414,7 +414,12 @@ else for (i = 0; i < count2; i += 2) { size = (ovector[i+1] > ovector[i])? (ovector[i+1] - ovector[i]) : 0; - memcpy(sp, match_data->subject + ovector[i], CU2BYTES(size)); + + /* Size == 0 includes the case when the capture is unset. Avoid adding + PCRE2_UNSET to match_data->subject because it overflows, even though with + zero size calling memcpy() is harmless. */ + + if (size != 0) memcpy(sp, match_data->subject + ovector[i], CU2BYTES(size)); *listp++ = sp; if (lensp != NULL) *lensp++ = size; sp += size; diff --git a/thirdparty/pcre2/src/pcre2_tables.c b/thirdparty/pcre2/src/pcre2_tables.c index b945ed7a7f..9f8dc293aa 100644 --- a/thirdparty/pcre2/src/pcre2_tables.c +++ b/thirdparty/pcre2/src/pcre2_tables.c @@ -7,7 +7,7 @@ and semantics are as close as possible to those of the Perl 5 language. Written by Philip Hazel Original API code Copyright (c) 1997-2012 University of Cambridge - New API code Copyright (c) 2016 University of Cambridge + New API code Copyright (c) 2016-2017 University of Cambridge ----------------------------------------------------------------------------- Redistribution and use in source and binary forms, with or without @@ -39,7 +39,7 @@ POSSIBILITY OF SUCH DAMAGE. */ /* This module contains some fixed tables that are used by more than one of the -PCRE code modules. The tables are also #included by the pcre2test program, +PCRE2 code modules. The tables are also #included by the pcre2test program, which uses macros to change their names from _pcre2_xxx to xxxx, thereby avoiding name clashes with the library. In this case, PCRE2_PCRE2TEST is defined. */ @@ -148,7 +148,7 @@ two code points. The breaking rules are as follows: 1. Break at the start and end of text (pretty obviously). -2. Do not break between a CR and LF; otherwise, break before and after +2. Do not break between a CR and LF; otherwise, break before and after controls. 3. Do not break Hangul syllable sequences, the rules for which are: @@ -157,44 +157,62 @@ two code points. The breaking rules are as follows: LV or V may be followed by V or T LVT or T may be followed by T -4. Do not break before extending characters. +4. Do not break before extending characters or zero-width-joiner (ZWJ). -The next two rules are only for extended grapheme clusters (but that's what we +The following rules are only for extended grapheme clusters (but that's what we are implementing). 5. Do not break before SpacingMarks. 6. Do not break after Prepend characters. -7. Otherwise, break everywhere. +7. Do not break within emoji modifier sequences (E_Base or E_Base_GAZ followed + by E_Modifier). Extend characters are allowed before the modifier; this + cannot be represented in this table, the code has to deal with it. + +8. Do not break within emoji zwj sequences (ZWJ followed by Glue_After_Zwj or + E_Base_GAZ). + +9. Do not break within emoji flag sequences. That is, do not break between + regional indicator (RI) symbols if there are an odd number of RI characters + before the break point. This table encodes "join RI characters"; the code + has to deal with checking for previous adjoining RIs. + +10. Otherwise, break everywhere. */ +#define ESZ (1<<ucp_gbExtend)|(1<<ucp_gbSpacingMark)|(1<<ucp_gbZWJ) + const uint32_t PRIV(ucp_gbtable)[] = { (1<<ucp_gbLF), /* 0 CR */ 0, /* 1 LF */ 0, /* 2 Control */ - (1<<ucp_gbExtend)|(1<<ucp_gbSpacingMark), /* 3 Extend */ - (1<<ucp_gbExtend)|(1<<ucp_gbPrepend)| /* 4 Prepend */ - (1<<ucp_gbSpacingMark)|(1<<ucp_gbL)| - (1<<ucp_gbV)|(1<<ucp_gbT)|(1<<ucp_gbLV)| - (1<<ucp_gbLVT)|(1<<ucp_gbOther), - - (1<<ucp_gbExtend)|(1<<ucp_gbSpacingMark), /* 5 SpacingMark */ - (1<<ucp_gbExtend)|(1<<ucp_gbSpacingMark)|(1<<ucp_gbL)| /* 6 L */ - (1<<ucp_gbL)|(1<<ucp_gbV)|(1<<ucp_gbLV)|(1<<ucp_gbLVT), - - (1<<ucp_gbExtend)|(1<<ucp_gbSpacingMark)|(1<<ucp_gbV)| /* 7 V */ - (1<<ucp_gbT), - - (1<<ucp_gbExtend)|(1<<ucp_gbSpacingMark)|(1<<ucp_gbT), /* 8 T */ - (1<<ucp_gbExtend)|(1<<ucp_gbSpacingMark)|(1<<ucp_gbV)| /* 9 LV */ - (1<<ucp_gbT), - - (1<<ucp_gbExtend)|(1<<ucp_gbSpacingMark)|(1<<ucp_gbT), /* 10 LVT */ + ESZ, /* 3 Extend */ + ESZ|(1<<ucp_gbPrepend)| /* 4 Prepend */ + (1<<ucp_gbL)|(1<<ucp_gbV)|(1<<ucp_gbT)| + (1<<ucp_gbLV)|(1<<ucp_gbLVT)|(1<<ucp_gbOther)| + (1<<ucp_gbRegionalIndicator)| + (1<<ucp_gbE_Base)|(1<<ucp_gbE_Modifier)| + (1<<ucp_gbE_Base_GAZ)| + (1<<ucp_gbZWJ)|(1<<ucp_gbGlue_After_Zwj), + ESZ, /* 5 SpacingMark */ + ESZ|(1<<ucp_gbL)|(1<<ucp_gbV)|(1<<ucp_gbLV)| /* 6 L */ + (1<<ucp_gbLVT), + ESZ|(1<<ucp_gbV)|(1<<ucp_gbT), /* 7 V */ + ESZ|(1<<ucp_gbT), /* 8 T */ + ESZ|(1<<ucp_gbV)|(1<<ucp_gbT), /* 9 LV */ + ESZ|(1<<ucp_gbT), /* 10 LVT */ (1<<ucp_gbRegionalIndicator), /* 11 RegionalIndicator */ - (1<<ucp_gbExtend)|(1<<ucp_gbSpacingMark) /* 12 Other */ + ESZ, /* 12 Other */ + ESZ|(1<<ucp_gbE_Modifier), /* 13 E_Base */ + ESZ, /* 14 E_Modifier */ + ESZ|(1<<ucp_gbE_Modifier), /* 15 E_Base_GAZ */ + ESZ|(1<<ucp_gbGlue_After_Zwj)|(1<<ucp_gbE_Base_GAZ), /* 16 ZWJ */ + ESZ /* 12 Glue_After_Zwj */ }; +#undef ESZ + #ifdef SUPPORT_JIT /* This table reverses PRIV(ucp_gentype). We can save the cost of a memory load. */ @@ -227,6 +245,7 @@ version. Like all other character and string literals that are compared against the regular expression pattern, we must use STR_ macros instead of literal strings to make sure that UTF-8 support works on EBCDIC platforms. */ +#define STRING_Adlam0 STR_A STR_d STR_l STR_a STR_m "\0" #define STRING_Ahom0 STR_A STR_h STR_o STR_m "\0" #define STRING_Anatolian_Hieroglyphs0 STR_A STR_n STR_a STR_t STR_o STR_l STR_i STR_a STR_n STR_UNDERSCORE STR_H STR_i STR_e STR_r STR_o STR_g STR_l STR_y STR_p STR_h STR_s "\0" #define STRING_Any0 STR_A STR_n STR_y "\0" @@ -238,6 +257,7 @@ strings to make sure that UTF-8 support works on EBCDIC platforms. */ #define STRING_Bassa_Vah0 STR_B STR_a STR_s STR_s STR_a STR_UNDERSCORE STR_V STR_a STR_h "\0" #define STRING_Batak0 STR_B STR_a STR_t STR_a STR_k "\0" #define STRING_Bengali0 STR_B STR_e STR_n STR_g STR_a STR_l STR_i "\0" +#define STRING_Bhaiksuki0 STR_B STR_h STR_a STR_i STR_k STR_s STR_u STR_k STR_i "\0" #define STRING_Bopomofo0 STR_B STR_o STR_p STR_o STR_m STR_o STR_f STR_o "\0" #define STRING_Brahmi0 STR_B STR_r STR_a STR_h STR_m STR_i "\0" #define STRING_Braille0 STR_B STR_r STR_a STR_i STR_l STR_l STR_e "\0" @@ -313,6 +333,8 @@ strings to make sure that UTF-8 support works on EBCDIC platforms. */ #define STRING_Malayalam0 STR_M STR_a STR_l STR_a STR_y STR_a STR_l STR_a STR_m "\0" #define STRING_Mandaic0 STR_M STR_a STR_n STR_d STR_a STR_i STR_c "\0" #define STRING_Manichaean0 STR_M STR_a STR_n STR_i STR_c STR_h STR_a STR_e STR_a STR_n "\0" +#define STRING_Marchen0 STR_M STR_a STR_r STR_c STR_h STR_e STR_n "\0" +#define STRING_Masaram_Gondi0 STR_M STR_a STR_s STR_a STR_r STR_a STR_m STR_UNDERSCORE STR_G STR_o STR_n STR_d STR_i "\0" #define STRING_Mc0 STR_M STR_c "\0" #define STRING_Me0 STR_M STR_e "\0" #define STRING_Meetei_Mayek0 STR_M STR_e STR_e STR_t STR_e STR_i STR_UNDERSCORE STR_M STR_a STR_y STR_e STR_k "\0" @@ -330,9 +352,11 @@ strings to make sure that UTF-8 support works on EBCDIC platforms. */ #define STRING_Nabataean0 STR_N STR_a STR_b STR_a STR_t STR_a STR_e STR_a STR_n "\0" #define STRING_Nd0 STR_N STR_d "\0" #define STRING_New_Tai_Lue0 STR_N STR_e STR_w STR_UNDERSCORE STR_T STR_a STR_i STR_UNDERSCORE STR_L STR_u STR_e "\0" +#define STRING_Newa0 STR_N STR_e STR_w STR_a "\0" #define STRING_Nko0 STR_N STR_k STR_o "\0" #define STRING_Nl0 STR_N STR_l "\0" #define STRING_No0 STR_N STR_o "\0" +#define STRING_Nushu0 STR_N STR_u STR_s STR_h STR_u "\0" #define STRING_Ogham0 STR_O STR_g STR_h STR_a STR_m "\0" #define STRING_Ol_Chiki0 STR_O STR_l STR_UNDERSCORE STR_C STR_h STR_i STR_k STR_i "\0" #define STRING_Old_Hungarian0 STR_O STR_l STR_d STR_UNDERSCORE STR_H STR_u STR_n STR_g STR_a STR_r STR_i STR_a STR_n "\0" @@ -343,6 +367,7 @@ strings to make sure that UTF-8 support works on EBCDIC platforms. */ #define STRING_Old_South_Arabian0 STR_O STR_l STR_d STR_UNDERSCORE STR_S STR_o STR_u STR_t STR_h STR_UNDERSCORE STR_A STR_r STR_a STR_b STR_i STR_a STR_n "\0" #define STRING_Old_Turkic0 STR_O STR_l STR_d STR_UNDERSCORE STR_T STR_u STR_r STR_k STR_i STR_c "\0" #define STRING_Oriya0 STR_O STR_r STR_i STR_y STR_a "\0" +#define STRING_Osage0 STR_O STR_s STR_a STR_g STR_e "\0" #define STRING_Osmanya0 STR_O STR_s STR_m STR_a STR_n STR_y STR_a "\0" #define STRING_P0 STR_P "\0" #define STRING_Pahawh_Hmong0 STR_P STR_a STR_h STR_a STR_w STR_h STR_UNDERSCORE STR_H STR_m STR_o STR_n STR_g "\0" @@ -373,6 +398,7 @@ strings to make sure that UTF-8 support works on EBCDIC platforms. */ #define STRING_Sm0 STR_S STR_m "\0" #define STRING_So0 STR_S STR_o "\0" #define STRING_Sora_Sompeng0 STR_S STR_o STR_r STR_a STR_UNDERSCORE STR_S STR_o STR_m STR_p STR_e STR_n STR_g "\0" +#define STRING_Soyombo0 STR_S STR_o STR_y STR_o STR_m STR_b STR_o "\0" #define STRING_Sundanese0 STR_S STR_u STR_n STR_d STR_a STR_n STR_e STR_s STR_e "\0" #define STRING_Syloti_Nagri0 STR_S STR_y STR_l STR_o STR_t STR_i STR_UNDERSCORE STR_N STR_a STR_g STR_r STR_i "\0" #define STRING_Syriac0 STR_S STR_y STR_r STR_i STR_a STR_c "\0" @@ -383,6 +409,7 @@ strings to make sure that UTF-8 support works on EBCDIC platforms. */ #define STRING_Tai_Viet0 STR_T STR_a STR_i STR_UNDERSCORE STR_V STR_i STR_e STR_t "\0" #define STRING_Takri0 STR_T STR_a STR_k STR_r STR_i "\0" #define STRING_Tamil0 STR_T STR_a STR_m STR_i STR_l "\0" +#define STRING_Tangut0 STR_T STR_a STR_n STR_g STR_u STR_t "\0" #define STRING_Telugu0 STR_T STR_e STR_l STR_u STR_g STR_u "\0" #define STRING_Thaana0 STR_T STR_h STR_a STR_a STR_n STR_a "\0" #define STRING_Thai0 STR_T STR_h STR_a STR_i "\0" @@ -399,11 +426,13 @@ strings to make sure that UTF-8 support works on EBCDIC platforms. */ #define STRING_Xwd0 STR_X STR_w STR_d "\0" #define STRING_Yi0 STR_Y STR_i "\0" #define STRING_Z0 STR_Z "\0" +#define STRING_Zanabazar_Square0 STR_Z STR_a STR_n STR_a STR_b STR_a STR_z STR_a STR_r STR_UNDERSCORE STR_S STR_q STR_u STR_a STR_r STR_e "\0" #define STRING_Zl0 STR_Z STR_l "\0" #define STRING_Zp0 STR_Z STR_p "\0" #define STRING_Zs0 STR_Z STR_s "\0" const char PRIV(utt_names)[] = + STRING_Adlam0 STRING_Ahom0 STRING_Anatolian_Hieroglyphs0 STRING_Any0 @@ -415,6 +444,7 @@ const char PRIV(utt_names)[] = STRING_Bassa_Vah0 STRING_Batak0 STRING_Bengali0 + STRING_Bhaiksuki0 STRING_Bopomofo0 STRING_Brahmi0 STRING_Braille0 @@ -490,6 +520,8 @@ const char PRIV(utt_names)[] = STRING_Malayalam0 STRING_Mandaic0 STRING_Manichaean0 + STRING_Marchen0 + STRING_Masaram_Gondi0 STRING_Mc0 STRING_Me0 STRING_Meetei_Mayek0 @@ -507,9 +539,11 @@ const char PRIV(utt_names)[] = STRING_Nabataean0 STRING_Nd0 STRING_New_Tai_Lue0 + STRING_Newa0 STRING_Nko0 STRING_Nl0 STRING_No0 + STRING_Nushu0 STRING_Ogham0 STRING_Ol_Chiki0 STRING_Old_Hungarian0 @@ -520,6 +554,7 @@ const char PRIV(utt_names)[] = STRING_Old_South_Arabian0 STRING_Old_Turkic0 STRING_Oriya0 + STRING_Osage0 STRING_Osmanya0 STRING_P0 STRING_Pahawh_Hmong0 @@ -550,6 +585,7 @@ const char PRIV(utt_names)[] = STRING_Sm0 STRING_So0 STRING_Sora_Sompeng0 + STRING_Soyombo0 STRING_Sundanese0 STRING_Syloti_Nagri0 STRING_Syriac0 @@ -560,6 +596,7 @@ const char PRIV(utt_names)[] = STRING_Tai_Viet0 STRING_Takri0 STRING_Tamil0 + STRING_Tangut0 STRING_Telugu0 STRING_Thaana0 STRING_Thai0 @@ -576,186 +613,197 @@ const char PRIV(utt_names)[] = STRING_Xwd0 STRING_Yi0 STRING_Z0 + STRING_Zanabazar_Square0 STRING_Zl0 STRING_Zp0 STRING_Zs0; const ucp_type_table PRIV(utt)[] = { - { 0, PT_SC, ucp_Ahom }, - { 5, PT_SC, ucp_Anatolian_Hieroglyphs }, - { 27, PT_ANY, 0 }, - { 31, PT_SC, ucp_Arabic }, - { 38, PT_SC, ucp_Armenian }, - { 47, PT_SC, ucp_Avestan }, - { 55, PT_SC, ucp_Balinese }, - { 64, PT_SC, ucp_Bamum }, - { 70, PT_SC, ucp_Bassa_Vah }, - { 80, PT_SC, ucp_Batak }, - { 86, PT_SC, ucp_Bengali }, - { 94, PT_SC, ucp_Bopomofo }, - { 103, PT_SC, ucp_Brahmi }, - { 110, PT_SC, ucp_Braille }, - { 118, PT_SC, ucp_Buginese }, - { 127, PT_SC, ucp_Buhid }, - { 133, PT_GC, ucp_C }, - { 135, PT_SC, ucp_Canadian_Aboriginal }, - { 155, PT_SC, ucp_Carian }, - { 162, PT_SC, ucp_Caucasian_Albanian }, - { 181, PT_PC, ucp_Cc }, - { 184, PT_PC, ucp_Cf }, - { 187, PT_SC, ucp_Chakma }, - { 194, PT_SC, ucp_Cham }, - { 199, PT_SC, ucp_Cherokee }, - { 208, PT_PC, ucp_Cn }, - { 211, PT_PC, ucp_Co }, - { 214, PT_SC, ucp_Common }, - { 221, PT_SC, ucp_Coptic }, - { 228, PT_PC, ucp_Cs }, - { 231, PT_SC, ucp_Cuneiform }, - { 241, PT_SC, ucp_Cypriot }, - { 249, PT_SC, ucp_Cyrillic }, - { 258, PT_SC, ucp_Deseret }, - { 266, PT_SC, ucp_Devanagari }, - { 277, PT_SC, ucp_Duployan }, - { 286, PT_SC, ucp_Egyptian_Hieroglyphs }, - { 307, PT_SC, ucp_Elbasan }, - { 315, PT_SC, ucp_Ethiopic }, - { 324, PT_SC, ucp_Georgian }, - { 333, PT_SC, ucp_Glagolitic }, - { 344, PT_SC, ucp_Gothic }, - { 351, PT_SC, ucp_Grantha }, - { 359, PT_SC, ucp_Greek }, - { 365, PT_SC, ucp_Gujarati }, - { 374, PT_SC, ucp_Gurmukhi }, - { 383, PT_SC, ucp_Han }, - { 387, PT_SC, ucp_Hangul }, - { 394, PT_SC, ucp_Hanunoo }, - { 402, PT_SC, ucp_Hatran }, - { 409, PT_SC, ucp_Hebrew }, - { 416, PT_SC, ucp_Hiragana }, - { 425, PT_SC, ucp_Imperial_Aramaic }, - { 442, PT_SC, ucp_Inherited }, - { 452, PT_SC, ucp_Inscriptional_Pahlavi }, - { 474, PT_SC, ucp_Inscriptional_Parthian }, - { 497, PT_SC, ucp_Javanese }, - { 506, PT_SC, ucp_Kaithi }, - { 513, PT_SC, ucp_Kannada }, - { 521, PT_SC, ucp_Katakana }, - { 530, PT_SC, ucp_Kayah_Li }, - { 539, PT_SC, ucp_Kharoshthi }, - { 550, PT_SC, ucp_Khmer }, - { 556, PT_SC, ucp_Khojki }, - { 563, PT_SC, ucp_Khudawadi }, - { 573, PT_GC, ucp_L }, - { 575, PT_LAMP, 0 }, - { 578, PT_SC, ucp_Lao }, - { 582, PT_SC, ucp_Latin }, - { 588, PT_SC, ucp_Lepcha }, - { 595, PT_SC, ucp_Limbu }, - { 601, PT_SC, ucp_Linear_A }, - { 610, PT_SC, ucp_Linear_B }, - { 619, PT_SC, ucp_Lisu }, - { 624, PT_PC, ucp_Ll }, - { 627, PT_PC, ucp_Lm }, - { 630, PT_PC, ucp_Lo }, - { 633, PT_PC, ucp_Lt }, - { 636, PT_PC, ucp_Lu }, - { 639, PT_SC, ucp_Lycian }, - { 646, PT_SC, ucp_Lydian }, - { 653, PT_GC, ucp_M }, - { 655, PT_SC, ucp_Mahajani }, - { 664, PT_SC, ucp_Malayalam }, - { 674, PT_SC, ucp_Mandaic }, - { 682, PT_SC, ucp_Manichaean }, - { 693, PT_PC, ucp_Mc }, - { 696, PT_PC, ucp_Me }, - { 699, PT_SC, ucp_Meetei_Mayek }, - { 712, PT_SC, ucp_Mende_Kikakui }, - { 726, PT_SC, ucp_Meroitic_Cursive }, - { 743, PT_SC, ucp_Meroitic_Hieroglyphs }, - { 764, PT_SC, ucp_Miao }, - { 769, PT_PC, ucp_Mn }, - { 772, PT_SC, ucp_Modi }, - { 777, PT_SC, ucp_Mongolian }, - { 787, PT_SC, ucp_Mro }, - { 791, PT_SC, ucp_Multani }, - { 799, PT_SC, ucp_Myanmar }, - { 807, PT_GC, ucp_N }, - { 809, PT_SC, ucp_Nabataean }, - { 819, PT_PC, ucp_Nd }, - { 822, PT_SC, ucp_New_Tai_Lue }, - { 834, PT_SC, ucp_Nko }, - { 838, PT_PC, ucp_Nl }, - { 841, PT_PC, ucp_No }, - { 844, PT_SC, ucp_Ogham }, - { 850, PT_SC, ucp_Ol_Chiki }, - { 859, PT_SC, ucp_Old_Hungarian }, - { 873, PT_SC, ucp_Old_Italic }, - { 884, PT_SC, ucp_Old_North_Arabian }, - { 902, PT_SC, ucp_Old_Permic }, - { 913, PT_SC, ucp_Old_Persian }, - { 925, PT_SC, ucp_Old_South_Arabian }, - { 943, PT_SC, ucp_Old_Turkic }, - { 954, PT_SC, ucp_Oriya }, - { 960, PT_SC, ucp_Osmanya }, - { 968, PT_GC, ucp_P }, - { 970, PT_SC, ucp_Pahawh_Hmong }, - { 983, PT_SC, ucp_Palmyrene }, - { 993, PT_SC, ucp_Pau_Cin_Hau }, - { 1005, PT_PC, ucp_Pc }, - { 1008, PT_PC, ucp_Pd }, - { 1011, PT_PC, ucp_Pe }, - { 1014, PT_PC, ucp_Pf }, - { 1017, PT_SC, ucp_Phags_Pa }, - { 1026, PT_SC, ucp_Phoenician }, - { 1037, PT_PC, ucp_Pi }, - { 1040, PT_PC, ucp_Po }, - { 1043, PT_PC, ucp_Ps }, - { 1046, PT_SC, ucp_Psalter_Pahlavi }, - { 1062, PT_SC, ucp_Rejang }, - { 1069, PT_SC, ucp_Runic }, - { 1075, PT_GC, ucp_S }, - { 1077, PT_SC, ucp_Samaritan }, - { 1087, PT_SC, ucp_Saurashtra }, - { 1098, PT_PC, ucp_Sc }, - { 1101, PT_SC, ucp_Sharada }, - { 1109, PT_SC, ucp_Shavian }, - { 1117, PT_SC, ucp_Siddham }, - { 1125, PT_SC, ucp_SignWriting }, - { 1137, PT_SC, ucp_Sinhala }, - { 1145, PT_PC, ucp_Sk }, - { 1148, PT_PC, ucp_Sm }, - { 1151, PT_PC, ucp_So }, - { 1154, PT_SC, ucp_Sora_Sompeng }, - { 1167, PT_SC, ucp_Sundanese }, - { 1177, PT_SC, ucp_Syloti_Nagri }, - { 1190, PT_SC, ucp_Syriac }, - { 1197, PT_SC, ucp_Tagalog }, - { 1205, PT_SC, ucp_Tagbanwa }, - { 1214, PT_SC, ucp_Tai_Le }, - { 1221, PT_SC, ucp_Tai_Tham }, - { 1230, PT_SC, ucp_Tai_Viet }, - { 1239, PT_SC, ucp_Takri }, - { 1245, PT_SC, ucp_Tamil }, - { 1251, PT_SC, ucp_Telugu }, - { 1258, PT_SC, ucp_Thaana }, - { 1265, PT_SC, ucp_Thai }, - { 1270, PT_SC, ucp_Tibetan }, - { 1278, PT_SC, ucp_Tifinagh }, - { 1287, PT_SC, ucp_Tirhuta }, - { 1295, PT_SC, ucp_Ugaritic }, - { 1304, PT_SC, ucp_Vai }, - { 1308, PT_SC, ucp_Warang_Citi }, - { 1320, PT_ALNUM, 0 }, - { 1324, PT_PXSPACE, 0 }, - { 1328, PT_SPACE, 0 }, - { 1332, PT_UCNC, 0 }, - { 1336, PT_WORD, 0 }, - { 1340, PT_SC, ucp_Yi }, - { 1343, PT_GC, ucp_Z }, - { 1345, PT_PC, ucp_Zl }, - { 1348, PT_PC, ucp_Zp }, - { 1351, PT_PC, ucp_Zs } + { 0, PT_SC, ucp_Adlam }, + { 6, PT_SC, ucp_Ahom }, + { 11, PT_SC, ucp_Anatolian_Hieroglyphs }, + { 33, PT_ANY, 0 }, + { 37, PT_SC, ucp_Arabic }, + { 44, PT_SC, ucp_Armenian }, + { 53, PT_SC, ucp_Avestan }, + { 61, PT_SC, ucp_Balinese }, + { 70, PT_SC, ucp_Bamum }, + { 76, PT_SC, ucp_Bassa_Vah }, + { 86, PT_SC, ucp_Batak }, + { 92, PT_SC, ucp_Bengali }, + { 100, PT_SC, ucp_Bhaiksuki }, + { 110, PT_SC, ucp_Bopomofo }, + { 119, PT_SC, ucp_Brahmi }, + { 126, PT_SC, ucp_Braille }, + { 134, PT_SC, ucp_Buginese }, + { 143, PT_SC, ucp_Buhid }, + { 149, PT_GC, ucp_C }, + { 151, PT_SC, ucp_Canadian_Aboriginal }, + { 171, PT_SC, ucp_Carian }, + { 178, PT_SC, ucp_Caucasian_Albanian }, + { 197, PT_PC, ucp_Cc }, + { 200, PT_PC, ucp_Cf }, + { 203, PT_SC, ucp_Chakma }, + { 210, PT_SC, ucp_Cham }, + { 215, PT_SC, ucp_Cherokee }, + { 224, PT_PC, ucp_Cn }, + { 227, PT_PC, ucp_Co }, + { 230, PT_SC, ucp_Common }, + { 237, PT_SC, ucp_Coptic }, + { 244, PT_PC, ucp_Cs }, + { 247, PT_SC, ucp_Cuneiform }, + { 257, PT_SC, ucp_Cypriot }, + { 265, PT_SC, ucp_Cyrillic }, + { 274, PT_SC, ucp_Deseret }, + { 282, PT_SC, ucp_Devanagari }, + { 293, PT_SC, ucp_Duployan }, + { 302, PT_SC, ucp_Egyptian_Hieroglyphs }, + { 323, PT_SC, ucp_Elbasan }, + { 331, PT_SC, ucp_Ethiopic }, + { 340, PT_SC, ucp_Georgian }, + { 349, PT_SC, ucp_Glagolitic }, + { 360, PT_SC, ucp_Gothic }, + { 367, PT_SC, ucp_Grantha }, + { 375, PT_SC, ucp_Greek }, + { 381, PT_SC, ucp_Gujarati }, + { 390, PT_SC, ucp_Gurmukhi }, + { 399, PT_SC, ucp_Han }, + { 403, PT_SC, ucp_Hangul }, + { 410, PT_SC, ucp_Hanunoo }, + { 418, PT_SC, ucp_Hatran }, + { 425, PT_SC, ucp_Hebrew }, + { 432, PT_SC, ucp_Hiragana }, + { 441, PT_SC, ucp_Imperial_Aramaic }, + { 458, PT_SC, ucp_Inherited }, + { 468, PT_SC, ucp_Inscriptional_Pahlavi }, + { 490, PT_SC, ucp_Inscriptional_Parthian }, + { 513, PT_SC, ucp_Javanese }, + { 522, PT_SC, ucp_Kaithi }, + { 529, PT_SC, ucp_Kannada }, + { 537, PT_SC, ucp_Katakana }, + { 546, PT_SC, ucp_Kayah_Li }, + { 555, PT_SC, ucp_Kharoshthi }, + { 566, PT_SC, ucp_Khmer }, + { 572, PT_SC, ucp_Khojki }, + { 579, PT_SC, ucp_Khudawadi }, + { 589, PT_GC, ucp_L }, + { 591, PT_LAMP, 0 }, + { 594, PT_SC, ucp_Lao }, + { 598, PT_SC, ucp_Latin }, + { 604, PT_SC, ucp_Lepcha }, + { 611, PT_SC, ucp_Limbu }, + { 617, PT_SC, ucp_Linear_A }, + { 626, PT_SC, ucp_Linear_B }, + { 635, PT_SC, ucp_Lisu }, + { 640, PT_PC, ucp_Ll }, + { 643, PT_PC, ucp_Lm }, + { 646, PT_PC, ucp_Lo }, + { 649, PT_PC, ucp_Lt }, + { 652, PT_PC, ucp_Lu }, + { 655, PT_SC, ucp_Lycian }, + { 662, PT_SC, ucp_Lydian }, + { 669, PT_GC, ucp_M }, + { 671, PT_SC, ucp_Mahajani }, + { 680, PT_SC, ucp_Malayalam }, + { 690, PT_SC, ucp_Mandaic }, + { 698, PT_SC, ucp_Manichaean }, + { 709, PT_SC, ucp_Marchen }, + { 717, PT_SC, ucp_Masaram_Gondi }, + { 731, PT_PC, ucp_Mc }, + { 734, PT_PC, ucp_Me }, + { 737, PT_SC, ucp_Meetei_Mayek }, + { 750, PT_SC, ucp_Mende_Kikakui }, + { 764, PT_SC, ucp_Meroitic_Cursive }, + { 781, PT_SC, ucp_Meroitic_Hieroglyphs }, + { 802, PT_SC, ucp_Miao }, + { 807, PT_PC, ucp_Mn }, + { 810, PT_SC, ucp_Modi }, + { 815, PT_SC, ucp_Mongolian }, + { 825, PT_SC, ucp_Mro }, + { 829, PT_SC, ucp_Multani }, + { 837, PT_SC, ucp_Myanmar }, + { 845, PT_GC, ucp_N }, + { 847, PT_SC, ucp_Nabataean }, + { 857, PT_PC, ucp_Nd }, + { 860, PT_SC, ucp_New_Tai_Lue }, + { 872, PT_SC, ucp_Newa }, + { 877, PT_SC, ucp_Nko }, + { 881, PT_PC, ucp_Nl }, + { 884, PT_PC, ucp_No }, + { 887, PT_SC, ucp_Nushu }, + { 893, PT_SC, ucp_Ogham }, + { 899, PT_SC, ucp_Ol_Chiki }, + { 908, PT_SC, ucp_Old_Hungarian }, + { 922, PT_SC, ucp_Old_Italic }, + { 933, PT_SC, ucp_Old_North_Arabian }, + { 951, PT_SC, ucp_Old_Permic }, + { 962, PT_SC, ucp_Old_Persian }, + { 974, PT_SC, ucp_Old_South_Arabian }, + { 992, PT_SC, ucp_Old_Turkic }, + { 1003, PT_SC, ucp_Oriya }, + { 1009, PT_SC, ucp_Osage }, + { 1015, PT_SC, ucp_Osmanya }, + { 1023, PT_GC, ucp_P }, + { 1025, PT_SC, ucp_Pahawh_Hmong }, + { 1038, PT_SC, ucp_Palmyrene }, + { 1048, PT_SC, ucp_Pau_Cin_Hau }, + { 1060, PT_PC, ucp_Pc }, + { 1063, PT_PC, ucp_Pd }, + { 1066, PT_PC, ucp_Pe }, + { 1069, PT_PC, ucp_Pf }, + { 1072, PT_SC, ucp_Phags_Pa }, + { 1081, PT_SC, ucp_Phoenician }, + { 1092, PT_PC, ucp_Pi }, + { 1095, PT_PC, ucp_Po }, + { 1098, PT_PC, ucp_Ps }, + { 1101, PT_SC, ucp_Psalter_Pahlavi }, + { 1117, PT_SC, ucp_Rejang }, + { 1124, PT_SC, ucp_Runic }, + { 1130, PT_GC, ucp_S }, + { 1132, PT_SC, ucp_Samaritan }, + { 1142, PT_SC, ucp_Saurashtra }, + { 1153, PT_PC, ucp_Sc }, + { 1156, PT_SC, ucp_Sharada }, + { 1164, PT_SC, ucp_Shavian }, + { 1172, PT_SC, ucp_Siddham }, + { 1180, PT_SC, ucp_SignWriting }, + { 1192, PT_SC, ucp_Sinhala }, + { 1200, PT_PC, ucp_Sk }, + { 1203, PT_PC, ucp_Sm }, + { 1206, PT_PC, ucp_So }, + { 1209, PT_SC, ucp_Sora_Sompeng }, + { 1222, PT_SC, ucp_Soyombo }, + { 1230, PT_SC, ucp_Sundanese }, + { 1240, PT_SC, ucp_Syloti_Nagri }, + { 1253, PT_SC, ucp_Syriac }, + { 1260, PT_SC, ucp_Tagalog }, + { 1268, PT_SC, ucp_Tagbanwa }, + { 1277, PT_SC, ucp_Tai_Le }, + { 1284, PT_SC, ucp_Tai_Tham }, + { 1293, PT_SC, ucp_Tai_Viet }, + { 1302, PT_SC, ucp_Takri }, + { 1308, PT_SC, ucp_Tamil }, + { 1314, PT_SC, ucp_Tangut }, + { 1321, PT_SC, ucp_Telugu }, + { 1328, PT_SC, ucp_Thaana }, + { 1335, PT_SC, ucp_Thai }, + { 1340, PT_SC, ucp_Tibetan }, + { 1348, PT_SC, ucp_Tifinagh }, + { 1357, PT_SC, ucp_Tirhuta }, + { 1365, PT_SC, ucp_Ugaritic }, + { 1374, PT_SC, ucp_Vai }, + { 1378, PT_SC, ucp_Warang_Citi }, + { 1390, PT_ALNUM, 0 }, + { 1394, PT_PXSPACE, 0 }, + { 1398, PT_SPACE, 0 }, + { 1402, PT_UCNC, 0 }, + { 1406, PT_WORD, 0 }, + { 1410, PT_SC, ucp_Yi }, + { 1413, PT_GC, ucp_Z }, + { 1415, PT_SC, ucp_Zanabazar_Square }, + { 1432, PT_PC, ucp_Zl }, + { 1435, PT_PC, ucp_Zp }, + { 1438, PT_PC, ucp_Zs } }; const size_t PRIV(utt_size) = sizeof(PRIV(utt)) / sizeof(ucp_type_table); diff --git a/thirdparty/pcre2/src/pcre2_ucd.c b/thirdparty/pcre2/src/pcre2_ucd.c index 116f537b38..ac7649b99e 100644 --- a/thirdparty/pcre2/src/pcre2_ucd.c +++ b/thirdparty/pcre2/src/pcre2_ucd.c @@ -20,7 +20,7 @@ needed. */ /* Unicode character database. */ /* This file was autogenerated by the MultiStage2.py script. */ -/* Total size: 75072 bytes, block size: 128. */ +/* Total size: 80808 bytes, block size: 128. */ /* The tables herein are needed only when UCP support is built, and in PCRE2 that happens automatically with UTF support. @@ -39,7 +39,21 @@ const uint16_t PRIV(ucd_stage2)[] = {0}; const uint32_t PRIV(ucd_caseless_sets)[] = {0}; #else -const char *PRIV(unicode_version) = "8.0.0"; +const char *PRIV(unicode_version) = "10.0.0"; + +/* If the 32-bit library is run in non-32-bit mode, character values +greater than 0x10ffff may be encountered. For these we set up a +special record. */ + +#if PCRE2_CODE_UNIT_WIDTH == 32 +const ucd_record PRIV(dummy_ucd_record)[] = {{ + ucp_Common, /* script */ + ucp_Cn, /* type unassigned */ + ucp_gbOther, /* grapheme break property */ + 0, /* case set */ + 0, /* other case */ + }}; +#endif /* When recompiling tables with a new Unicode version, please check the types in this structure definition from pcre2_internal.h (the actual @@ -72,17 +86,25 @@ const uint32_t PRIV(ucd_caseless_sets)[] = { 0x039a, 0x03ba, 0x03f0, NOTACHAR, 0x03a1, 0x03c1, 0x03f1, NOTACHAR, 0x0395, 0x03b5, 0x03f5, NOTACHAR, + 0x0412, 0x0432, 0x1c80, NOTACHAR, + 0x0414, 0x0434, 0x1c81, NOTACHAR, + 0x041e, 0x043e, 0x1c82, NOTACHAR, + 0x0421, 0x0441, 0x1c83, NOTACHAR, + 0x0422, 0x0442, 0x1c84, 0x1c85, NOTACHAR, + 0x042a, 0x044a, 0x1c86, NOTACHAR, + 0x0462, 0x0463, 0x1c87, NOTACHAR, 0x1e60, 0x1e61, 0x1e9b, NOTACHAR, 0x03a9, 0x03c9, 0x2126, NOTACHAR, 0x004b, 0x006b, 0x212a, NOTACHAR, 0x00c5, 0x00e5, 0x212b, NOTACHAR, + 0x1c88, 0xa64a, 0xa64b, NOTACHAR, }; /* When #included in pcre2test, we don't need this large table. */ #ifndef PCRE2_PCRE2TEST -const ucd_record PRIV(ucd_records)[] = { /* 5952 bytes, record size 8 */ +const ucd_record PRIV(ucd_records)[] = { /* 6568 bytes, record size 8 */ { 9, 0, 2, 0, 0, }, /* 0 */ { 9, 0, 1, 0, 0, }, /* 1 */ { 9, 0, 0, 0, 0, }, /* 2 */ @@ -95,12 +117,12 @@ const ucd_record PRIV(ucd_records)[] = { /* 5952 bytes, record size 8 */ { 9, 17, 12, 0, 0, }, /* 9 */ { 9, 13, 12, 0, 0, }, /* 10 */ { 33, 9, 12, 0, 32, }, /* 11 */ - { 33, 9, 12, 71, 32, }, /* 12 */ + { 33, 9, 12, 100, 32, }, /* 12 */ { 33, 9, 12, 1, 32, }, /* 13 */ { 9, 24, 12, 0, 0, }, /* 14 */ { 9, 16, 12, 0, 0, }, /* 15 */ { 33, 5, 12, 0, -32, }, /* 16 */ - { 33, 5, 12, 71, -32, }, /* 17 */ + { 33, 5, 12, 100, -32, }, /* 17 */ { 33, 5, 12, 1, -32, }, /* 18 */ { 9, 26, 12, 0, 0, }, /* 19 */ { 33, 7, 12, 0, 0, }, /* 20 */ @@ -109,9 +131,9 @@ const ucd_record PRIV(ucd_records)[] = { /* 5952 bytes, record size 8 */ { 9, 15, 12, 0, 0, }, /* 23 */ { 9, 5, 12, 26, 775, }, /* 24 */ { 9, 19, 12, 0, 0, }, /* 25 */ - { 33, 9, 12, 75, 32, }, /* 26 */ + { 33, 9, 12, 104, 32, }, /* 26 */ { 33, 5, 12, 0, 7615, }, /* 27 */ - { 33, 5, 12, 75, -32, }, /* 28 */ + { 33, 5, 12, 104, -32, }, /* 28 */ { 33, 5, 12, 0, 121, }, /* 29 */ { 33, 9, 12, 0, 1, }, /* 30 */ { 33, 5, 12, 0, -1, }, /* 31 */ @@ -218,7 +240,7 @@ const ucd_record PRIV(ucd_records)[] = { /* 5952 bytes, record size 8 */ { 19, 9, 12, 55, 32, }, /* 132 */ { 19, 9, 12, 30, 32, }, /* 133 */ { 19, 9, 12, 43, 32, }, /* 134 */ - { 19, 9, 12, 67, 32, }, /* 135 */ + { 19, 9, 12, 96, 32, }, /* 135 */ { 19, 5, 12, 0, -38, }, /* 136 */ { 19, 5, 12, 0, -37, }, /* 137 */ { 19, 5, 12, 0, -32, }, /* 138 */ @@ -233,7 +255,7 @@ const ucd_record PRIV(ucd_records)[] = { /* 5952 bytes, record size 8 */ { 19, 5, 12, 30, 1, }, /* 147 */ { 19, 5, 12, 30, -32, }, /* 148 */ { 19, 5, 12, 43, -32, }, /* 149 */ - { 19, 5, 12, 67, -32, }, /* 150 */ + { 19, 5, 12, 96, -32, }, /* 150 */ { 19, 5, 12, 0, -64, }, /* 151 */ { 19, 5, 12, 0, -63, }, /* 152 */ { 19, 9, 12, 0, 8, }, /* 153 */ @@ -256,577 +278,654 @@ const ucd_record PRIV(ucd_records)[] = { /* 5952 bytes, record size 8 */ { 19, 9, 12, 0, -130, }, /* 170 */ { 12, 9, 12, 0, 80, }, /* 171 */ { 12, 9, 12, 0, 32, }, /* 172 */ - { 12, 5, 12, 0, -32, }, /* 173 */ - { 12, 5, 12, 0, -80, }, /* 174 */ - { 12, 9, 12, 0, 1, }, /* 175 */ - { 12, 5, 12, 0, -1, }, /* 176 */ - { 12, 26, 12, 0, 0, }, /* 177 */ - { 12, 12, 3, 0, 0, }, /* 178 */ - { 12, 11, 3, 0, 0, }, /* 179 */ - { 12, 9, 12, 0, 15, }, /* 180 */ - { 12, 5, 12, 0, -15, }, /* 181 */ - { 1, 9, 12, 0, 48, }, /* 182 */ - { 1, 6, 12, 0, 0, }, /* 183 */ - { 1, 21, 12, 0, 0, }, /* 184 */ - { 1, 5, 12, 0, -48, }, /* 185 */ - { 1, 5, 12, 0, 0, }, /* 186 */ - { 1, 17, 12, 0, 0, }, /* 187 */ - { 1, 26, 12, 0, 0, }, /* 188 */ - { 1, 23, 12, 0, 0, }, /* 189 */ - { 25, 12, 3, 0, 0, }, /* 190 */ - { 25, 17, 12, 0, 0, }, /* 191 */ - { 25, 21, 12, 0, 0, }, /* 192 */ - { 25, 7, 12, 0, 0, }, /* 193 */ - { 0, 1, 2, 0, 0, }, /* 194 */ - { 0, 25, 12, 0, 0, }, /* 195 */ - { 0, 21, 12, 0, 0, }, /* 196 */ - { 0, 23, 12, 0, 0, }, /* 197 */ - { 0, 26, 12, 0, 0, }, /* 198 */ - { 0, 12, 3, 0, 0, }, /* 199 */ - { 0, 7, 12, 0, 0, }, /* 200 */ - { 0, 13, 12, 0, 0, }, /* 201 */ - { 0, 6, 12, 0, 0, }, /* 202 */ - { 49, 21, 12, 0, 0, }, /* 203 */ - { 49, 1, 2, 0, 0, }, /* 204 */ - { 49, 7, 12, 0, 0, }, /* 205 */ - { 49, 12, 3, 0, 0, }, /* 206 */ - { 55, 7, 12, 0, 0, }, /* 207 */ - { 55, 12, 3, 0, 0, }, /* 208 */ - { 63, 13, 12, 0, 0, }, /* 209 */ - { 63, 7, 12, 0, 0, }, /* 210 */ - { 63, 12, 3, 0, 0, }, /* 211 */ - { 63, 6, 12, 0, 0, }, /* 212 */ - { 63, 26, 12, 0, 0, }, /* 213 */ - { 63, 21, 12, 0, 0, }, /* 214 */ - { 89, 7, 12, 0, 0, }, /* 215 */ - { 89, 12, 3, 0, 0, }, /* 216 */ - { 89, 6, 12, 0, 0, }, /* 217 */ - { 89, 21, 12, 0, 0, }, /* 218 */ - { 94, 7, 12, 0, 0, }, /* 219 */ - { 94, 12, 3, 0, 0, }, /* 220 */ - { 94, 21, 12, 0, 0, }, /* 221 */ - { 14, 12, 3, 0, 0, }, /* 222 */ - { 14, 10, 5, 0, 0, }, /* 223 */ - { 14, 7, 12, 0, 0, }, /* 224 */ - { 14, 13, 12, 0, 0, }, /* 225 */ - { 14, 21, 12, 0, 0, }, /* 226 */ - { 14, 6, 12, 0, 0, }, /* 227 */ - { 2, 7, 12, 0, 0, }, /* 228 */ - { 2, 12, 3, 0, 0, }, /* 229 */ - { 2, 10, 5, 0, 0, }, /* 230 */ - { 2, 10, 3, 0, 0, }, /* 231 */ - { 2, 13, 12, 0, 0, }, /* 232 */ - { 2, 23, 12, 0, 0, }, /* 233 */ - { 2, 15, 12, 0, 0, }, /* 234 */ - { 2, 26, 12, 0, 0, }, /* 235 */ - { 21, 12, 3, 0, 0, }, /* 236 */ - { 21, 10, 5, 0, 0, }, /* 237 */ - { 21, 7, 12, 0, 0, }, /* 238 */ - { 21, 13, 12, 0, 0, }, /* 239 */ - { 20, 12, 3, 0, 0, }, /* 240 */ - { 20, 10, 5, 0, 0, }, /* 241 */ - { 20, 7, 12, 0, 0, }, /* 242 */ - { 20, 13, 12, 0, 0, }, /* 243 */ - { 20, 21, 12, 0, 0, }, /* 244 */ - { 20, 23, 12, 0, 0, }, /* 245 */ - { 43, 12, 3, 0, 0, }, /* 246 */ - { 43, 10, 5, 0, 0, }, /* 247 */ - { 43, 7, 12, 0, 0, }, /* 248 */ - { 43, 10, 3, 0, 0, }, /* 249 */ - { 43, 13, 12, 0, 0, }, /* 250 */ - { 43, 26, 12, 0, 0, }, /* 251 */ - { 43, 15, 12, 0, 0, }, /* 252 */ - { 53, 12, 3, 0, 0, }, /* 253 */ - { 53, 7, 12, 0, 0, }, /* 254 */ - { 53, 10, 3, 0, 0, }, /* 255 */ - { 53, 10, 5, 0, 0, }, /* 256 */ - { 53, 13, 12, 0, 0, }, /* 257 */ - { 53, 15, 12, 0, 0, }, /* 258 */ - { 53, 26, 12, 0, 0, }, /* 259 */ - { 53, 23, 12, 0, 0, }, /* 260 */ - { 54, 12, 3, 0, 0, }, /* 261 */ - { 54, 10, 5, 0, 0, }, /* 262 */ - { 54, 7, 12, 0, 0, }, /* 263 */ - { 54, 13, 12, 0, 0, }, /* 264 */ - { 54, 15, 12, 0, 0, }, /* 265 */ - { 54, 26, 12, 0, 0, }, /* 266 */ - { 28, 12, 3, 0, 0, }, /* 267 */ - { 28, 10, 5, 0, 0, }, /* 268 */ - { 28, 7, 12, 0, 0, }, /* 269 */ - { 28, 10, 3, 0, 0, }, /* 270 */ - { 28, 13, 12, 0, 0, }, /* 271 */ - { 36, 12, 3, 0, 0, }, /* 272 */ - { 36, 10, 5, 0, 0, }, /* 273 */ - { 36, 7, 12, 0, 0, }, /* 274 */ - { 36, 10, 3, 0, 0, }, /* 275 */ - { 36, 13, 12, 0, 0, }, /* 276 */ - { 36, 15, 12, 0, 0, }, /* 277 */ - { 36, 26, 12, 0, 0, }, /* 278 */ - { 47, 10, 5, 0, 0, }, /* 279 */ - { 47, 7, 12, 0, 0, }, /* 280 */ - { 47, 12, 3, 0, 0, }, /* 281 */ - { 47, 10, 3, 0, 0, }, /* 282 */ - { 47, 13, 12, 0, 0, }, /* 283 */ - { 47, 21, 12, 0, 0, }, /* 284 */ - { 56, 7, 12, 0, 0, }, /* 285 */ - { 56, 12, 3, 0, 0, }, /* 286 */ - { 56, 7, 5, 0, 0, }, /* 287 */ - { 56, 6, 12, 0, 0, }, /* 288 */ - { 56, 21, 12, 0, 0, }, /* 289 */ - { 56, 13, 12, 0, 0, }, /* 290 */ - { 32, 7, 12, 0, 0, }, /* 291 */ - { 32, 12, 3, 0, 0, }, /* 292 */ - { 32, 7, 5, 0, 0, }, /* 293 */ - { 32, 6, 12, 0, 0, }, /* 294 */ - { 32, 13, 12, 0, 0, }, /* 295 */ - { 57, 7, 12, 0, 0, }, /* 296 */ - { 57, 26, 12, 0, 0, }, /* 297 */ - { 57, 21, 12, 0, 0, }, /* 298 */ - { 57, 12, 3, 0, 0, }, /* 299 */ - { 57, 13, 12, 0, 0, }, /* 300 */ - { 57, 15, 12, 0, 0, }, /* 301 */ - { 57, 22, 12, 0, 0, }, /* 302 */ - { 57, 18, 12, 0, 0, }, /* 303 */ - { 57, 10, 5, 0, 0, }, /* 304 */ - { 38, 7, 12, 0, 0, }, /* 305 */ - { 38, 10, 12, 0, 0, }, /* 306 */ - { 38, 12, 3, 0, 0, }, /* 307 */ - { 38, 10, 5, 0, 0, }, /* 308 */ - { 38, 13, 12, 0, 0, }, /* 309 */ - { 38, 21, 12, 0, 0, }, /* 310 */ - { 38, 26, 12, 0, 0, }, /* 311 */ - { 16, 9, 12, 0, 7264, }, /* 312 */ - { 16, 7, 12, 0, 0, }, /* 313 */ - { 16, 6, 12, 0, 0, }, /* 314 */ - { 23, 7, 6, 0, 0, }, /* 315 */ - { 23, 7, 7, 0, 0, }, /* 316 */ - { 23, 7, 8, 0, 0, }, /* 317 */ - { 15, 7, 12, 0, 0, }, /* 318 */ - { 15, 12, 3, 0, 0, }, /* 319 */ - { 15, 21, 12, 0, 0, }, /* 320 */ - { 15, 15, 12, 0, 0, }, /* 321 */ - { 15, 26, 12, 0, 0, }, /* 322 */ - { 8, 9, 12, 0, 38864, }, /* 323 */ - { 8, 9, 12, 0, 8, }, /* 324 */ - { 8, 5, 12, 0, -8, }, /* 325 */ - { 7, 17, 12, 0, 0, }, /* 326 */ - { 7, 7, 12, 0, 0, }, /* 327 */ - { 7, 21, 12, 0, 0, }, /* 328 */ - { 40, 29, 12, 0, 0, }, /* 329 */ - { 40, 7, 12, 0, 0, }, /* 330 */ - { 40, 22, 12, 0, 0, }, /* 331 */ - { 40, 18, 12, 0, 0, }, /* 332 */ - { 45, 7, 12, 0, 0, }, /* 333 */ - { 45, 14, 12, 0, 0, }, /* 334 */ - { 50, 7, 12, 0, 0, }, /* 335 */ - { 50, 12, 3, 0, 0, }, /* 336 */ - { 24, 7, 12, 0, 0, }, /* 337 */ - { 24, 12, 3, 0, 0, }, /* 338 */ - { 6, 7, 12, 0, 0, }, /* 339 */ - { 6, 12, 3, 0, 0, }, /* 340 */ - { 51, 7, 12, 0, 0, }, /* 341 */ - { 51, 12, 3, 0, 0, }, /* 342 */ - { 31, 7, 12, 0, 0, }, /* 343 */ - { 31, 12, 3, 0, 0, }, /* 344 */ - { 31, 10, 5, 0, 0, }, /* 345 */ - { 31, 21, 12, 0, 0, }, /* 346 */ - { 31, 6, 12, 0, 0, }, /* 347 */ - { 31, 23, 12, 0, 0, }, /* 348 */ - { 31, 13, 12, 0, 0, }, /* 349 */ - { 31, 15, 12, 0, 0, }, /* 350 */ - { 37, 21, 12, 0, 0, }, /* 351 */ - { 37, 17, 12, 0, 0, }, /* 352 */ - { 37, 12, 3, 0, 0, }, /* 353 */ - { 37, 1, 2, 0, 0, }, /* 354 */ - { 37, 13, 12, 0, 0, }, /* 355 */ - { 37, 7, 12, 0, 0, }, /* 356 */ - { 37, 6, 12, 0, 0, }, /* 357 */ - { 34, 7, 12, 0, 0, }, /* 358 */ - { 34, 12, 3, 0, 0, }, /* 359 */ - { 34, 10, 5, 0, 0, }, /* 360 */ - { 34, 26, 12, 0, 0, }, /* 361 */ - { 34, 21, 12, 0, 0, }, /* 362 */ - { 34, 13, 12, 0, 0, }, /* 363 */ - { 52, 7, 12, 0, 0, }, /* 364 */ - { 39, 7, 12, 0, 0, }, /* 365 */ - { 39, 13, 12, 0, 0, }, /* 366 */ - { 39, 15, 12, 0, 0, }, /* 367 */ - { 39, 26, 12, 0, 0, }, /* 368 */ - { 31, 26, 12, 0, 0, }, /* 369 */ - { 5, 7, 12, 0, 0, }, /* 370 */ - { 5, 12, 3, 0, 0, }, /* 371 */ - { 5, 10, 5, 0, 0, }, /* 372 */ - { 5, 21, 12, 0, 0, }, /* 373 */ - { 90, 7, 12, 0, 0, }, /* 374 */ - { 90, 10, 5, 0, 0, }, /* 375 */ - { 90, 12, 3, 0, 0, }, /* 376 */ - { 90, 10, 12, 0, 0, }, /* 377 */ - { 90, 13, 12, 0, 0, }, /* 378 */ - { 90, 21, 12, 0, 0, }, /* 379 */ - { 90, 6, 12, 0, 0, }, /* 380 */ - { 27, 11, 3, 0, 0, }, /* 381 */ - { 61, 12, 3, 0, 0, }, /* 382 */ - { 61, 10, 5, 0, 0, }, /* 383 */ - { 61, 7, 12, 0, 0, }, /* 384 */ - { 61, 13, 12, 0, 0, }, /* 385 */ - { 61, 21, 12, 0, 0, }, /* 386 */ - { 61, 26, 12, 0, 0, }, /* 387 */ - { 75, 12, 3, 0, 0, }, /* 388 */ - { 75, 10, 5, 0, 0, }, /* 389 */ - { 75, 7, 12, 0, 0, }, /* 390 */ - { 75, 13, 12, 0, 0, }, /* 391 */ - { 92, 7, 12, 0, 0, }, /* 392 */ - { 92, 12, 3, 0, 0, }, /* 393 */ - { 92, 10, 5, 0, 0, }, /* 394 */ - { 92, 21, 12, 0, 0, }, /* 395 */ - { 69, 7, 12, 0, 0, }, /* 396 */ - { 69, 10, 5, 0, 0, }, /* 397 */ - { 69, 12, 3, 0, 0, }, /* 398 */ - { 69, 21, 12, 0, 0, }, /* 399 */ - { 69, 13, 12, 0, 0, }, /* 400 */ - { 72, 13, 12, 0, 0, }, /* 401 */ - { 72, 7, 12, 0, 0, }, /* 402 */ - { 72, 6, 12, 0, 0, }, /* 403 */ - { 72, 21, 12, 0, 0, }, /* 404 */ - { 75, 21, 12, 0, 0, }, /* 405 */ - { 9, 10, 5, 0, 0, }, /* 406 */ - { 9, 7, 12, 0, 0, }, /* 407 */ - { 12, 5, 12, 0, 0, }, /* 408 */ - { 12, 6, 12, 0, 0, }, /* 409 */ - { 33, 5, 12, 0, 35332, }, /* 410 */ - { 33, 5, 12, 0, 3814, }, /* 411 */ - { 33, 9, 12, 63, 1, }, /* 412 */ - { 33, 5, 12, 63, -1, }, /* 413 */ - { 33, 5, 12, 63, -58, }, /* 414 */ - { 33, 9, 12, 0, -7615, }, /* 415 */ - { 19, 5, 12, 0, 8, }, /* 416 */ - { 19, 9, 12, 0, -8, }, /* 417 */ - { 19, 5, 12, 0, 74, }, /* 418 */ - { 19, 5, 12, 0, 86, }, /* 419 */ - { 19, 5, 12, 0, 100, }, /* 420 */ - { 19, 5, 12, 0, 128, }, /* 421 */ - { 19, 5, 12, 0, 112, }, /* 422 */ - { 19, 5, 12, 0, 126, }, /* 423 */ - { 19, 8, 12, 0, -8, }, /* 424 */ - { 19, 5, 12, 0, 9, }, /* 425 */ - { 19, 9, 12, 0, -74, }, /* 426 */ - { 19, 8, 12, 0, -9, }, /* 427 */ - { 19, 5, 12, 21, -7173, }, /* 428 */ - { 19, 9, 12, 0, -86, }, /* 429 */ - { 19, 9, 12, 0, -100, }, /* 430 */ - { 19, 9, 12, 0, -112, }, /* 431 */ - { 19, 9, 12, 0, -128, }, /* 432 */ - { 19, 9, 12, 0, -126, }, /* 433 */ - { 27, 1, 3, 0, 0, }, /* 434 */ - { 9, 27, 2, 0, 0, }, /* 435 */ - { 9, 28, 2, 0, 0, }, /* 436 */ - { 9, 2, 2, 0, 0, }, /* 437 */ - { 9, 9, 12, 0, 0, }, /* 438 */ - { 9, 5, 12, 0, 0, }, /* 439 */ - { 19, 9, 12, 67, -7517, }, /* 440 */ - { 33, 9, 12, 71, -8383, }, /* 441 */ - { 33, 9, 12, 75, -8262, }, /* 442 */ - { 33, 9, 12, 0, 28, }, /* 443 */ - { 33, 5, 12, 0, -28, }, /* 444 */ - { 33, 14, 12, 0, 16, }, /* 445 */ - { 33, 14, 12, 0, -16, }, /* 446 */ - { 33, 14, 12, 0, 0, }, /* 447 */ - { 9, 26, 12, 0, 26, }, /* 448 */ - { 9, 26, 12, 0, -26, }, /* 449 */ - { 4, 26, 12, 0, 0, }, /* 450 */ - { 17, 9, 12, 0, 48, }, /* 451 */ - { 17, 5, 12, 0, -48, }, /* 452 */ - { 33, 9, 12, 0, -10743, }, /* 453 */ - { 33, 9, 12, 0, -3814, }, /* 454 */ - { 33, 9, 12, 0, -10727, }, /* 455 */ - { 33, 5, 12, 0, -10795, }, /* 456 */ - { 33, 5, 12, 0, -10792, }, /* 457 */ - { 33, 9, 12, 0, -10780, }, /* 458 */ - { 33, 9, 12, 0, -10749, }, /* 459 */ - { 33, 9, 12, 0, -10783, }, /* 460 */ - { 33, 9, 12, 0, -10782, }, /* 461 */ - { 33, 9, 12, 0, -10815, }, /* 462 */ - { 10, 5, 12, 0, 0, }, /* 463 */ - { 10, 26, 12, 0, 0, }, /* 464 */ - { 10, 12, 3, 0, 0, }, /* 465 */ - { 10, 21, 12, 0, 0, }, /* 466 */ - { 10, 15, 12, 0, 0, }, /* 467 */ - { 16, 5, 12, 0, -7264, }, /* 468 */ - { 58, 7, 12, 0, 0, }, /* 469 */ - { 58, 6, 12, 0, 0, }, /* 470 */ - { 58, 21, 12, 0, 0, }, /* 471 */ - { 58, 12, 3, 0, 0, }, /* 472 */ - { 22, 26, 12, 0, 0, }, /* 473 */ - { 22, 6, 12, 0, 0, }, /* 474 */ - { 22, 14, 12, 0, 0, }, /* 475 */ - { 23, 10, 3, 0, 0, }, /* 476 */ - { 26, 7, 12, 0, 0, }, /* 477 */ - { 26, 6, 12, 0, 0, }, /* 478 */ - { 29, 7, 12, 0, 0, }, /* 479 */ - { 29, 6, 12, 0, 0, }, /* 480 */ - { 3, 7, 12, 0, 0, }, /* 481 */ - { 23, 7, 12, 0, 0, }, /* 482 */ - { 23, 26, 12, 0, 0, }, /* 483 */ - { 29, 26, 12, 0, 0, }, /* 484 */ - { 22, 7, 12, 0, 0, }, /* 485 */ - { 60, 7, 12, 0, 0, }, /* 486 */ - { 60, 6, 12, 0, 0, }, /* 487 */ - { 60, 26, 12, 0, 0, }, /* 488 */ - { 85, 7, 12, 0, 0, }, /* 489 */ - { 85, 6, 12, 0, 0, }, /* 490 */ - { 85, 21, 12, 0, 0, }, /* 491 */ - { 76, 7, 12, 0, 0, }, /* 492 */ - { 76, 6, 12, 0, 0, }, /* 493 */ - { 76, 21, 12, 0, 0, }, /* 494 */ - { 76, 13, 12, 0, 0, }, /* 495 */ - { 12, 7, 12, 0, 0, }, /* 496 */ - { 12, 21, 12, 0, 0, }, /* 497 */ - { 78, 7, 12, 0, 0, }, /* 498 */ - { 78, 14, 12, 0, 0, }, /* 499 */ - { 78, 12, 3, 0, 0, }, /* 500 */ - { 78, 21, 12, 0, 0, }, /* 501 */ - { 33, 9, 12, 0, -35332, }, /* 502 */ - { 33, 9, 12, 0, -42280, }, /* 503 */ - { 33, 9, 12, 0, -42308, }, /* 504 */ - { 33, 9, 12, 0, -42319, }, /* 505 */ - { 33, 9, 12, 0, -42315, }, /* 506 */ - { 33, 9, 12, 0, -42305, }, /* 507 */ - { 33, 9, 12, 0, -42258, }, /* 508 */ - { 33, 9, 12, 0, -42282, }, /* 509 */ - { 33, 9, 12, 0, -42261, }, /* 510 */ - { 33, 9, 12, 0, 928, }, /* 511 */ - { 48, 7, 12, 0, 0, }, /* 512 */ - { 48, 12, 3, 0, 0, }, /* 513 */ - { 48, 10, 5, 0, 0, }, /* 514 */ - { 48, 26, 12, 0, 0, }, /* 515 */ - { 64, 7, 12, 0, 0, }, /* 516 */ - { 64, 21, 12, 0, 0, }, /* 517 */ - { 74, 10, 5, 0, 0, }, /* 518 */ - { 74, 7, 12, 0, 0, }, /* 519 */ - { 74, 12, 3, 0, 0, }, /* 520 */ - { 74, 21, 12, 0, 0, }, /* 521 */ - { 74, 13, 12, 0, 0, }, /* 522 */ - { 68, 13, 12, 0, 0, }, /* 523 */ - { 68, 7, 12, 0, 0, }, /* 524 */ - { 68, 12, 3, 0, 0, }, /* 525 */ - { 68, 21, 12, 0, 0, }, /* 526 */ - { 73, 7, 12, 0, 0, }, /* 527 */ - { 73, 12, 3, 0, 0, }, /* 528 */ - { 73, 10, 5, 0, 0, }, /* 529 */ - { 73, 21, 12, 0, 0, }, /* 530 */ - { 83, 12, 3, 0, 0, }, /* 531 */ - { 83, 10, 5, 0, 0, }, /* 532 */ - { 83, 7, 12, 0, 0, }, /* 533 */ - { 83, 21, 12, 0, 0, }, /* 534 */ - { 83, 13, 12, 0, 0, }, /* 535 */ - { 38, 6, 12, 0, 0, }, /* 536 */ - { 67, 7, 12, 0, 0, }, /* 537 */ - { 67, 12, 3, 0, 0, }, /* 538 */ - { 67, 10, 5, 0, 0, }, /* 539 */ - { 67, 13, 12, 0, 0, }, /* 540 */ - { 67, 21, 12, 0, 0, }, /* 541 */ - { 91, 7, 12, 0, 0, }, /* 542 */ - { 91, 12, 3, 0, 0, }, /* 543 */ - { 91, 6, 12, 0, 0, }, /* 544 */ - { 91, 21, 12, 0, 0, }, /* 545 */ - { 86, 7, 12, 0, 0, }, /* 546 */ - { 86, 10, 5, 0, 0, }, /* 547 */ - { 86, 12, 3, 0, 0, }, /* 548 */ - { 86, 21, 12, 0, 0, }, /* 549 */ - { 86, 6, 12, 0, 0, }, /* 550 */ - { 33, 5, 12, 0, -928, }, /* 551 */ - { 8, 5, 12, 0, -38864, }, /* 552 */ - { 86, 13, 12, 0, 0, }, /* 553 */ - { 23, 7, 9, 0, 0, }, /* 554 */ - { 23, 7, 10, 0, 0, }, /* 555 */ - { 9, 4, 2, 0, 0, }, /* 556 */ - { 9, 3, 12, 0, 0, }, /* 557 */ - { 25, 25, 12, 0, 0, }, /* 558 */ - { 0, 24, 12, 0, 0, }, /* 559 */ - { 9, 6, 3, 0, 0, }, /* 560 */ - { 35, 7, 12, 0, 0, }, /* 561 */ - { 19, 14, 12, 0, 0, }, /* 562 */ - { 19, 15, 12, 0, 0, }, /* 563 */ - { 19, 26, 12, 0, 0, }, /* 564 */ - { 70, 7, 12, 0, 0, }, /* 565 */ - { 66, 7, 12, 0, 0, }, /* 566 */ - { 41, 7, 12, 0, 0, }, /* 567 */ - { 41, 15, 12, 0, 0, }, /* 568 */ - { 18, 7, 12, 0, 0, }, /* 569 */ - { 18, 14, 12, 0, 0, }, /* 570 */ - { 117, 7, 12, 0, 0, }, /* 571 */ - { 117, 12, 3, 0, 0, }, /* 572 */ - { 59, 7, 12, 0, 0, }, /* 573 */ - { 59, 21, 12, 0, 0, }, /* 574 */ - { 42, 7, 12, 0, 0, }, /* 575 */ - { 42, 21, 12, 0, 0, }, /* 576 */ - { 42, 14, 12, 0, 0, }, /* 577 */ - { 13, 9, 12, 0, 40, }, /* 578 */ - { 13, 5, 12, 0, -40, }, /* 579 */ - { 46, 7, 12, 0, 0, }, /* 580 */ - { 44, 7, 12, 0, 0, }, /* 581 */ - { 44, 13, 12, 0, 0, }, /* 582 */ - { 105, 7, 12, 0, 0, }, /* 583 */ - { 103, 7, 12, 0, 0, }, /* 584 */ - { 103, 21, 12, 0, 0, }, /* 585 */ - { 109, 7, 12, 0, 0, }, /* 586 */ - { 11, 7, 12, 0, 0, }, /* 587 */ - { 80, 7, 12, 0, 0, }, /* 588 */ - { 80, 21, 12, 0, 0, }, /* 589 */ - { 80, 15, 12, 0, 0, }, /* 590 */ - { 119, 7, 12, 0, 0, }, /* 591 */ - { 119, 26, 12, 0, 0, }, /* 592 */ - { 119, 15, 12, 0, 0, }, /* 593 */ - { 115, 7, 12, 0, 0, }, /* 594 */ - { 115, 15, 12, 0, 0, }, /* 595 */ - { 127, 7, 12, 0, 0, }, /* 596 */ - { 127, 15, 12, 0, 0, }, /* 597 */ - { 65, 7, 12, 0, 0, }, /* 598 */ - { 65, 15, 12, 0, 0, }, /* 599 */ - { 65, 21, 12, 0, 0, }, /* 600 */ - { 71, 7, 12, 0, 0, }, /* 601 */ - { 71, 21, 12, 0, 0, }, /* 602 */ - { 97, 7, 12, 0, 0, }, /* 603 */ - { 96, 7, 12, 0, 0, }, /* 604 */ - { 96, 15, 12, 0, 0, }, /* 605 */ - { 30, 7, 12, 0, 0, }, /* 606 */ - { 30, 12, 3, 0, 0, }, /* 607 */ - { 30, 15, 12, 0, 0, }, /* 608 */ - { 30, 21, 12, 0, 0, }, /* 609 */ - { 87, 7, 12, 0, 0, }, /* 610 */ - { 87, 15, 12, 0, 0, }, /* 611 */ - { 87, 21, 12, 0, 0, }, /* 612 */ - { 116, 7, 12, 0, 0, }, /* 613 */ - { 116, 15, 12, 0, 0, }, /* 614 */ - { 111, 7, 12, 0, 0, }, /* 615 */ - { 111, 26, 12, 0, 0, }, /* 616 */ - { 111, 12, 3, 0, 0, }, /* 617 */ - { 111, 15, 12, 0, 0, }, /* 618 */ - { 111, 21, 12, 0, 0, }, /* 619 */ - { 77, 7, 12, 0, 0, }, /* 620 */ - { 77, 21, 12, 0, 0, }, /* 621 */ - { 82, 7, 12, 0, 0, }, /* 622 */ - { 82, 15, 12, 0, 0, }, /* 623 */ - { 81, 7, 12, 0, 0, }, /* 624 */ - { 81, 15, 12, 0, 0, }, /* 625 */ - { 120, 7, 12, 0, 0, }, /* 626 */ - { 120, 21, 12, 0, 0, }, /* 627 */ - { 120, 15, 12, 0, 0, }, /* 628 */ - { 88, 7, 12, 0, 0, }, /* 629 */ - { 129, 9, 12, 0, 64, }, /* 630 */ - { 129, 5, 12, 0, -64, }, /* 631 */ - { 129, 15, 12, 0, 0, }, /* 632 */ - { 0, 15, 12, 0, 0, }, /* 633 */ - { 93, 10, 5, 0, 0, }, /* 634 */ - { 93, 12, 3, 0, 0, }, /* 635 */ - { 93, 7, 12, 0, 0, }, /* 636 */ - { 93, 21, 12, 0, 0, }, /* 637 */ - { 93, 15, 12, 0, 0, }, /* 638 */ - { 93, 13, 12, 0, 0, }, /* 639 */ - { 84, 12, 3, 0, 0, }, /* 640 */ - { 84, 10, 5, 0, 0, }, /* 641 */ - { 84, 7, 12, 0, 0, }, /* 642 */ - { 84, 21, 12, 0, 0, }, /* 643 */ - { 84, 1, 2, 0, 0, }, /* 644 */ - { 100, 7, 12, 0, 0, }, /* 645 */ - { 100, 13, 12, 0, 0, }, /* 646 */ - { 95, 12, 3, 0, 0, }, /* 647 */ - { 95, 7, 12, 0, 0, }, /* 648 */ - { 95, 10, 5, 0, 0, }, /* 649 */ - { 95, 13, 12, 0, 0, }, /* 650 */ - { 95, 21, 12, 0, 0, }, /* 651 */ - { 110, 7, 12, 0, 0, }, /* 652 */ - { 110, 12, 3, 0, 0, }, /* 653 */ - { 110, 21, 12, 0, 0, }, /* 654 */ - { 99, 12, 3, 0, 0, }, /* 655 */ - { 99, 10, 5, 0, 0, }, /* 656 */ - { 99, 7, 12, 0, 0, }, /* 657 */ - { 99, 21, 12, 0, 0, }, /* 658 */ - { 99, 13, 12, 0, 0, }, /* 659 */ - { 47, 15, 12, 0, 0, }, /* 660 */ - { 107, 7, 12, 0, 0, }, /* 661 */ - { 107, 10, 5, 0, 0, }, /* 662 */ - { 107, 12, 3, 0, 0, }, /* 663 */ - { 107, 21, 12, 0, 0, }, /* 664 */ - { 128, 7, 12, 0, 0, }, /* 665 */ - { 128, 21, 12, 0, 0, }, /* 666 */ - { 108, 7, 12, 0, 0, }, /* 667 */ - { 108, 12, 3, 0, 0, }, /* 668 */ - { 108, 10, 5, 0, 0, }, /* 669 */ - { 108, 13, 12, 0, 0, }, /* 670 */ - { 106, 12, 3, 0, 0, }, /* 671 */ - { 106, 10, 5, 0, 0, }, /* 672 */ - { 106, 7, 12, 0, 0, }, /* 673 */ - { 106, 10, 3, 0, 0, }, /* 674 */ - { 123, 7, 12, 0, 0, }, /* 675 */ - { 123, 10, 3, 0, 0, }, /* 676 */ - { 123, 10, 5, 0, 0, }, /* 677 */ - { 123, 12, 3, 0, 0, }, /* 678 */ - { 123, 21, 12, 0, 0, }, /* 679 */ - { 123, 13, 12, 0, 0, }, /* 680 */ - { 122, 7, 12, 0, 0, }, /* 681 */ - { 122, 10, 3, 0, 0, }, /* 682 */ - { 122, 10, 5, 0, 0, }, /* 683 */ - { 122, 12, 3, 0, 0, }, /* 684 */ - { 122, 21, 12, 0, 0, }, /* 685 */ - { 113, 7, 12, 0, 0, }, /* 686 */ - { 113, 10, 5, 0, 0, }, /* 687 */ - { 113, 12, 3, 0, 0, }, /* 688 */ - { 113, 21, 12, 0, 0, }, /* 689 */ - { 113, 13, 12, 0, 0, }, /* 690 */ - { 101, 7, 12, 0, 0, }, /* 691 */ - { 101, 12, 3, 0, 0, }, /* 692 */ - { 101, 10, 5, 0, 0, }, /* 693 */ - { 101, 13, 12, 0, 0, }, /* 694 */ - { 125, 7, 12, 0, 0, }, /* 695 */ - { 125, 12, 3, 0, 0, }, /* 696 */ - { 125, 10, 5, 0, 0, }, /* 697 */ - { 125, 13, 12, 0, 0, }, /* 698 */ - { 125, 15, 12, 0, 0, }, /* 699 */ - { 125, 21, 12, 0, 0, }, /* 700 */ - { 125, 26, 12, 0, 0, }, /* 701 */ - { 124, 9, 12, 0, 32, }, /* 702 */ - { 124, 5, 12, 0, -32, }, /* 703 */ - { 124, 13, 12, 0, 0, }, /* 704 */ - { 124, 15, 12, 0, 0, }, /* 705 */ - { 124, 7, 12, 0, 0, }, /* 706 */ - { 121, 7, 12, 0, 0, }, /* 707 */ - { 62, 7, 12, 0, 0, }, /* 708 */ - { 62, 14, 12, 0, 0, }, /* 709 */ - { 62, 21, 12, 0, 0, }, /* 710 */ - { 79, 7, 12, 0, 0, }, /* 711 */ - { 126, 7, 12, 0, 0, }, /* 712 */ - { 114, 7, 12, 0, 0, }, /* 713 */ - { 114, 13, 12, 0, 0, }, /* 714 */ - { 114, 21, 12, 0, 0, }, /* 715 */ - { 102, 7, 12, 0, 0, }, /* 716 */ - { 102, 12, 3, 0, 0, }, /* 717 */ - { 102, 21, 12, 0, 0, }, /* 718 */ - { 118, 7, 12, 0, 0, }, /* 719 */ - { 118, 12, 3, 0, 0, }, /* 720 */ - { 118, 21, 12, 0, 0, }, /* 721 */ - { 118, 26, 12, 0, 0, }, /* 722 */ - { 118, 6, 12, 0, 0, }, /* 723 */ - { 118, 13, 12, 0, 0, }, /* 724 */ - { 118, 15, 12, 0, 0, }, /* 725 */ - { 98, 7, 12, 0, 0, }, /* 726 */ - { 98, 10, 5, 0, 0, }, /* 727 */ - { 98, 12, 3, 0, 0, }, /* 728 */ - { 98, 6, 12, 0, 0, }, /* 729 */ - { 104, 7, 12, 0, 0, }, /* 730 */ - { 104, 26, 12, 0, 0, }, /* 731 */ - { 104, 12, 3, 0, 0, }, /* 732 */ - { 104, 21, 12, 0, 0, }, /* 733 */ - { 9, 10, 3, 0, 0, }, /* 734 */ - { 19, 12, 3, 0, 0, }, /* 735 */ - { 130, 26, 12, 0, 0, }, /* 736 */ - { 130, 12, 3, 0, 0, }, /* 737 */ - { 130, 21, 12, 0, 0, }, /* 738 */ - { 112, 7, 12, 0, 0, }, /* 739 */ - { 112, 15, 12, 0, 0, }, /* 740 */ - { 112, 12, 3, 0, 0, }, /* 741 */ - { 9, 26, 11, 0, 0, }, /* 742 */ - { 26, 26, 12, 0, 0, }, /* 743 */ + { 12, 9, 12, 63, 32, }, /* 173 */ + { 12, 9, 12, 67, 32, }, /* 174 */ + { 12, 9, 12, 71, 32, }, /* 175 */ + { 12, 9, 12, 75, 32, }, /* 176 */ + { 12, 9, 12, 79, 32, }, /* 177 */ + { 12, 9, 12, 84, 32, }, /* 178 */ + { 12, 5, 12, 0, -32, }, /* 179 */ + { 12, 5, 12, 63, -32, }, /* 180 */ + { 12, 5, 12, 67, -32, }, /* 181 */ + { 12, 5, 12, 71, -32, }, /* 182 */ + { 12, 5, 12, 75, -32, }, /* 183 */ + { 12, 5, 12, 79, -32, }, /* 184 */ + { 12, 5, 12, 84, -32, }, /* 185 */ + { 12, 5, 12, 0, -80, }, /* 186 */ + { 12, 9, 12, 0, 1, }, /* 187 */ + { 12, 5, 12, 0, -1, }, /* 188 */ + { 12, 9, 12, 88, 1, }, /* 189 */ + { 12, 5, 12, 88, -1, }, /* 190 */ + { 12, 26, 12, 0, 0, }, /* 191 */ + { 12, 12, 3, 0, 0, }, /* 192 */ + { 12, 11, 3, 0, 0, }, /* 193 */ + { 12, 9, 12, 0, 15, }, /* 194 */ + { 12, 5, 12, 0, -15, }, /* 195 */ + { 1, 9, 12, 0, 48, }, /* 196 */ + { 1, 6, 12, 0, 0, }, /* 197 */ + { 1, 21, 12, 0, 0, }, /* 198 */ + { 1, 5, 12, 0, -48, }, /* 199 */ + { 1, 5, 12, 0, 0, }, /* 200 */ + { 1, 17, 12, 0, 0, }, /* 201 */ + { 1, 26, 12, 0, 0, }, /* 202 */ + { 1, 23, 12, 0, 0, }, /* 203 */ + { 25, 12, 3, 0, 0, }, /* 204 */ + { 25, 17, 12, 0, 0, }, /* 205 */ + { 25, 21, 12, 0, 0, }, /* 206 */ + { 25, 7, 12, 0, 0, }, /* 207 */ + { 0, 1, 4, 0, 0, }, /* 208 */ + { 9, 1, 4, 0, 0, }, /* 209 */ + { 0, 25, 12, 0, 0, }, /* 210 */ + { 0, 21, 12, 0, 0, }, /* 211 */ + { 0, 23, 12, 0, 0, }, /* 212 */ + { 0, 26, 12, 0, 0, }, /* 213 */ + { 0, 12, 3, 0, 0, }, /* 214 */ + { 0, 1, 2, 0, 0, }, /* 215 */ + { 0, 7, 12, 0, 0, }, /* 216 */ + { 0, 13, 12, 0, 0, }, /* 217 */ + { 0, 6, 12, 0, 0, }, /* 218 */ + { 49, 21, 12, 0, 0, }, /* 219 */ + { 49, 1, 4, 0, 0, }, /* 220 */ + { 49, 7, 12, 0, 0, }, /* 221 */ + { 49, 12, 3, 0, 0, }, /* 222 */ + { 55, 7, 12, 0, 0, }, /* 223 */ + { 55, 12, 3, 0, 0, }, /* 224 */ + { 63, 13, 12, 0, 0, }, /* 225 */ + { 63, 7, 12, 0, 0, }, /* 226 */ + { 63, 12, 3, 0, 0, }, /* 227 */ + { 63, 6, 12, 0, 0, }, /* 228 */ + { 63, 26, 12, 0, 0, }, /* 229 */ + { 63, 21, 12, 0, 0, }, /* 230 */ + { 89, 7, 12, 0, 0, }, /* 231 */ + { 89, 12, 3, 0, 0, }, /* 232 */ + { 89, 6, 12, 0, 0, }, /* 233 */ + { 89, 21, 12, 0, 0, }, /* 234 */ + { 94, 7, 12, 0, 0, }, /* 235 */ + { 94, 12, 3, 0, 0, }, /* 236 */ + { 94, 21, 12, 0, 0, }, /* 237 */ + { 14, 12, 3, 0, 0, }, /* 238 */ + { 14, 10, 5, 0, 0, }, /* 239 */ + { 14, 7, 12, 0, 0, }, /* 240 */ + { 14, 13, 12, 0, 0, }, /* 241 */ + { 14, 21, 12, 0, 0, }, /* 242 */ + { 14, 6, 12, 0, 0, }, /* 243 */ + { 2, 7, 12, 0, 0, }, /* 244 */ + { 2, 12, 3, 0, 0, }, /* 245 */ + { 2, 10, 5, 0, 0, }, /* 246 */ + { 2, 10, 3, 0, 0, }, /* 247 */ + { 2, 13, 12, 0, 0, }, /* 248 */ + { 2, 23, 12, 0, 0, }, /* 249 */ + { 2, 15, 12, 0, 0, }, /* 250 */ + { 2, 26, 12, 0, 0, }, /* 251 */ + { 2, 21, 12, 0, 0, }, /* 252 */ + { 21, 12, 3, 0, 0, }, /* 253 */ + { 21, 10, 5, 0, 0, }, /* 254 */ + { 21, 7, 12, 0, 0, }, /* 255 */ + { 21, 13, 12, 0, 0, }, /* 256 */ + { 20, 12, 3, 0, 0, }, /* 257 */ + { 20, 10, 5, 0, 0, }, /* 258 */ + { 20, 7, 12, 0, 0, }, /* 259 */ + { 20, 13, 12, 0, 0, }, /* 260 */ + { 20, 21, 12, 0, 0, }, /* 261 */ + { 20, 23, 12, 0, 0, }, /* 262 */ + { 43, 12, 3, 0, 0, }, /* 263 */ + { 43, 10, 5, 0, 0, }, /* 264 */ + { 43, 7, 12, 0, 0, }, /* 265 */ + { 43, 10, 3, 0, 0, }, /* 266 */ + { 43, 13, 12, 0, 0, }, /* 267 */ + { 43, 26, 12, 0, 0, }, /* 268 */ + { 43, 15, 12, 0, 0, }, /* 269 */ + { 53, 12, 3, 0, 0, }, /* 270 */ + { 53, 7, 12, 0, 0, }, /* 271 */ + { 53, 10, 3, 0, 0, }, /* 272 */ + { 53, 10, 5, 0, 0, }, /* 273 */ + { 53, 13, 12, 0, 0, }, /* 274 */ + { 53, 15, 12, 0, 0, }, /* 275 */ + { 53, 26, 12, 0, 0, }, /* 276 */ + { 53, 23, 12, 0, 0, }, /* 277 */ + { 54, 12, 3, 0, 0, }, /* 278 */ + { 54, 10, 5, 0, 0, }, /* 279 */ + { 54, 7, 12, 0, 0, }, /* 280 */ + { 54, 13, 12, 0, 0, }, /* 281 */ + { 54, 15, 12, 0, 0, }, /* 282 */ + { 54, 26, 12, 0, 0, }, /* 283 */ + { 28, 7, 12, 0, 0, }, /* 284 */ + { 28, 12, 3, 0, 0, }, /* 285 */ + { 28, 10, 5, 0, 0, }, /* 286 */ + { 28, 10, 3, 0, 0, }, /* 287 */ + { 28, 13, 12, 0, 0, }, /* 288 */ + { 36, 12, 3, 0, 0, }, /* 289 */ + { 36, 10, 5, 0, 0, }, /* 290 */ + { 36, 7, 12, 0, 0, }, /* 291 */ + { 36, 10, 3, 0, 0, }, /* 292 */ + { 36, 7, 4, 0, 0, }, /* 293 */ + { 36, 26, 12, 0, 0, }, /* 294 */ + { 36, 15, 12, 0, 0, }, /* 295 */ + { 36, 13, 12, 0, 0, }, /* 296 */ + { 47, 10, 5, 0, 0, }, /* 297 */ + { 47, 7, 12, 0, 0, }, /* 298 */ + { 47, 12, 3, 0, 0, }, /* 299 */ + { 47, 10, 3, 0, 0, }, /* 300 */ + { 47, 13, 12, 0, 0, }, /* 301 */ + { 47, 21, 12, 0, 0, }, /* 302 */ + { 56, 7, 12, 0, 0, }, /* 303 */ + { 56, 12, 3, 0, 0, }, /* 304 */ + { 56, 7, 5, 0, 0, }, /* 305 */ + { 56, 6, 12, 0, 0, }, /* 306 */ + { 56, 21, 12, 0, 0, }, /* 307 */ + { 56, 13, 12, 0, 0, }, /* 308 */ + { 32, 7, 12, 0, 0, }, /* 309 */ + { 32, 12, 3, 0, 0, }, /* 310 */ + { 32, 7, 5, 0, 0, }, /* 311 */ + { 32, 6, 12, 0, 0, }, /* 312 */ + { 32, 13, 12, 0, 0, }, /* 313 */ + { 57, 7, 12, 0, 0, }, /* 314 */ + { 57, 26, 12, 0, 0, }, /* 315 */ + { 57, 21, 12, 0, 0, }, /* 316 */ + { 57, 12, 3, 0, 0, }, /* 317 */ + { 57, 13, 12, 0, 0, }, /* 318 */ + { 57, 15, 12, 0, 0, }, /* 319 */ + { 57, 22, 12, 0, 0, }, /* 320 */ + { 57, 18, 12, 0, 0, }, /* 321 */ + { 57, 10, 5, 0, 0, }, /* 322 */ + { 38, 7, 12, 0, 0, }, /* 323 */ + { 38, 10, 12, 0, 0, }, /* 324 */ + { 38, 12, 3, 0, 0, }, /* 325 */ + { 38, 10, 5, 0, 0, }, /* 326 */ + { 38, 13, 12, 0, 0, }, /* 327 */ + { 38, 21, 12, 0, 0, }, /* 328 */ + { 38, 26, 12, 0, 0, }, /* 329 */ + { 16, 9, 12, 0, 7264, }, /* 330 */ + { 16, 7, 12, 0, 0, }, /* 331 */ + { 16, 6, 12, 0, 0, }, /* 332 */ + { 23, 7, 6, 0, 0, }, /* 333 */ + { 23, 7, 7, 0, 0, }, /* 334 */ + { 23, 7, 8, 0, 0, }, /* 335 */ + { 15, 7, 12, 0, 0, }, /* 336 */ + { 15, 12, 3, 0, 0, }, /* 337 */ + { 15, 21, 12, 0, 0, }, /* 338 */ + { 15, 15, 12, 0, 0, }, /* 339 */ + { 15, 26, 12, 0, 0, }, /* 340 */ + { 8, 9, 12, 0, 38864, }, /* 341 */ + { 8, 9, 12, 0, 8, }, /* 342 */ + { 8, 5, 12, 0, -8, }, /* 343 */ + { 7, 17, 12, 0, 0, }, /* 344 */ + { 7, 7, 12, 0, 0, }, /* 345 */ + { 7, 21, 12, 0, 0, }, /* 346 */ + { 40, 29, 12, 0, 0, }, /* 347 */ + { 40, 7, 12, 0, 0, }, /* 348 */ + { 40, 22, 12, 0, 0, }, /* 349 */ + { 40, 18, 12, 0, 0, }, /* 350 */ + { 45, 7, 12, 0, 0, }, /* 351 */ + { 45, 14, 12, 0, 0, }, /* 352 */ + { 50, 7, 12, 0, 0, }, /* 353 */ + { 50, 12, 3, 0, 0, }, /* 354 */ + { 24, 7, 12, 0, 0, }, /* 355 */ + { 24, 12, 3, 0, 0, }, /* 356 */ + { 6, 7, 12, 0, 0, }, /* 357 */ + { 6, 12, 3, 0, 0, }, /* 358 */ + { 51, 7, 12, 0, 0, }, /* 359 */ + { 51, 12, 3, 0, 0, }, /* 360 */ + { 31, 7, 12, 0, 0, }, /* 361 */ + { 31, 12, 3, 0, 0, }, /* 362 */ + { 31, 10, 5, 0, 0, }, /* 363 */ + { 31, 21, 12, 0, 0, }, /* 364 */ + { 31, 6, 12, 0, 0, }, /* 365 */ + { 31, 23, 12, 0, 0, }, /* 366 */ + { 31, 13, 12, 0, 0, }, /* 367 */ + { 31, 15, 12, 0, 0, }, /* 368 */ + { 37, 21, 12, 0, 0, }, /* 369 */ + { 37, 17, 12, 0, 0, }, /* 370 */ + { 37, 12, 3, 0, 0, }, /* 371 */ + { 37, 1, 2, 0, 0, }, /* 372 */ + { 37, 13, 12, 0, 0, }, /* 373 */ + { 37, 7, 12, 0, 0, }, /* 374 */ + { 37, 6, 12, 0, 0, }, /* 375 */ + { 34, 7, 12, 0, 0, }, /* 376 */ + { 34, 12, 3, 0, 0, }, /* 377 */ + { 34, 10, 5, 0, 0, }, /* 378 */ + { 34, 26, 12, 0, 0, }, /* 379 */ + { 34, 21, 12, 0, 0, }, /* 380 */ + { 34, 13, 12, 0, 0, }, /* 381 */ + { 52, 7, 12, 0, 0, }, /* 382 */ + { 39, 7, 12, 0, 0, }, /* 383 */ + { 39, 13, 12, 0, 0, }, /* 384 */ + { 39, 15, 12, 0, 0, }, /* 385 */ + { 39, 26, 12, 0, 0, }, /* 386 */ + { 31, 26, 12, 0, 0, }, /* 387 */ + { 5, 7, 12, 0, 0, }, /* 388 */ + { 5, 12, 3, 0, 0, }, /* 389 */ + { 5, 10, 5, 0, 0, }, /* 390 */ + { 5, 21, 12, 0, 0, }, /* 391 */ + { 90, 7, 12, 0, 0, }, /* 392 */ + { 90, 10, 5, 0, 0, }, /* 393 */ + { 90, 12, 3, 0, 0, }, /* 394 */ + { 90, 10, 12, 0, 0, }, /* 395 */ + { 90, 13, 12, 0, 0, }, /* 396 */ + { 90, 21, 12, 0, 0, }, /* 397 */ + { 90, 6, 12, 0, 0, }, /* 398 */ + { 27, 11, 3, 0, 0, }, /* 399 */ + { 61, 12, 3, 0, 0, }, /* 400 */ + { 61, 10, 5, 0, 0, }, /* 401 */ + { 61, 7, 12, 0, 0, }, /* 402 */ + { 61, 13, 12, 0, 0, }, /* 403 */ + { 61, 21, 12, 0, 0, }, /* 404 */ + { 61, 26, 12, 0, 0, }, /* 405 */ + { 75, 12, 3, 0, 0, }, /* 406 */ + { 75, 10, 5, 0, 0, }, /* 407 */ + { 75, 7, 12, 0, 0, }, /* 408 */ + { 75, 13, 12, 0, 0, }, /* 409 */ + { 92, 7, 12, 0, 0, }, /* 410 */ + { 92, 12, 3, 0, 0, }, /* 411 */ + { 92, 10, 5, 0, 0, }, /* 412 */ + { 92, 21, 12, 0, 0, }, /* 413 */ + { 69, 7, 12, 0, 0, }, /* 414 */ + { 69, 10, 5, 0, 0, }, /* 415 */ + { 69, 12, 3, 0, 0, }, /* 416 */ + { 69, 21, 12, 0, 0, }, /* 417 */ + { 69, 13, 12, 0, 0, }, /* 418 */ + { 72, 13, 12, 0, 0, }, /* 419 */ + { 72, 7, 12, 0, 0, }, /* 420 */ + { 72, 6, 12, 0, 0, }, /* 421 */ + { 72, 21, 12, 0, 0, }, /* 422 */ + { 12, 5, 12, 63, -6222, }, /* 423 */ + { 12, 5, 12, 67, -6221, }, /* 424 */ + { 12, 5, 12, 71, -6212, }, /* 425 */ + { 12, 5, 12, 75, -6210, }, /* 426 */ + { 12, 5, 12, 79, -6210, }, /* 427 */ + { 12, 5, 12, 79, -6211, }, /* 428 */ + { 12, 5, 12, 84, -6204, }, /* 429 */ + { 12, 5, 12, 88, -6180, }, /* 430 */ + { 12, 5, 12, 108, 35267, }, /* 431 */ + { 75, 21, 12, 0, 0, }, /* 432 */ + { 9, 10, 5, 0, 0, }, /* 433 */ + { 9, 7, 12, 0, 0, }, /* 434 */ + { 12, 5, 12, 0, 0, }, /* 435 */ + { 12, 6, 12, 0, 0, }, /* 436 */ + { 33, 5, 12, 0, 35332, }, /* 437 */ + { 33, 5, 12, 0, 3814, }, /* 438 */ + { 33, 9, 12, 92, 1, }, /* 439 */ + { 33, 5, 12, 92, -1, }, /* 440 */ + { 33, 5, 12, 92, -58, }, /* 441 */ + { 33, 9, 12, 0, -7615, }, /* 442 */ + { 19, 5, 12, 0, 8, }, /* 443 */ + { 19, 9, 12, 0, -8, }, /* 444 */ + { 19, 5, 12, 0, 74, }, /* 445 */ + { 19, 5, 12, 0, 86, }, /* 446 */ + { 19, 5, 12, 0, 100, }, /* 447 */ + { 19, 5, 12, 0, 128, }, /* 448 */ + { 19, 5, 12, 0, 112, }, /* 449 */ + { 19, 5, 12, 0, 126, }, /* 450 */ + { 19, 8, 12, 0, -8, }, /* 451 */ + { 19, 5, 12, 0, 9, }, /* 452 */ + { 19, 9, 12, 0, -74, }, /* 453 */ + { 19, 8, 12, 0, -9, }, /* 454 */ + { 19, 5, 12, 21, -7173, }, /* 455 */ + { 19, 9, 12, 0, -86, }, /* 456 */ + { 19, 9, 12, 0, -100, }, /* 457 */ + { 19, 9, 12, 0, -112, }, /* 458 */ + { 19, 9, 12, 0, -128, }, /* 459 */ + { 19, 9, 12, 0, -126, }, /* 460 */ + { 27, 1, 3, 0, 0, }, /* 461 */ + { 27, 1, 16, 0, 0, }, /* 462 */ + { 9, 27, 2, 0, 0, }, /* 463 */ + { 9, 28, 2, 0, 0, }, /* 464 */ + { 9, 2, 2, 0, 0, }, /* 465 */ + { 9, 9, 12, 0, 0, }, /* 466 */ + { 9, 5, 12, 0, 0, }, /* 467 */ + { 19, 9, 12, 96, -7517, }, /* 468 */ + { 33, 9, 12, 100, -8383, }, /* 469 */ + { 33, 9, 12, 104, -8262, }, /* 470 */ + { 33, 9, 12, 0, 28, }, /* 471 */ + { 33, 5, 12, 0, -28, }, /* 472 */ + { 33, 14, 12, 0, 16, }, /* 473 */ + { 33, 14, 12, 0, -16, }, /* 474 */ + { 33, 14, 12, 0, 0, }, /* 475 */ + { 9, 26, 12, 0, 26, }, /* 476 */ + { 9, 26, 12, 0, -26, }, /* 477 */ + { 9, 26, 13, 0, 0, }, /* 478 */ + { 9, 26, 17, 0, 0, }, /* 479 */ + { 4, 26, 12, 0, 0, }, /* 480 */ + { 17, 9, 12, 0, 48, }, /* 481 */ + { 17, 5, 12, 0, -48, }, /* 482 */ + { 33, 9, 12, 0, -10743, }, /* 483 */ + { 33, 9, 12, 0, -3814, }, /* 484 */ + { 33, 9, 12, 0, -10727, }, /* 485 */ + { 33, 5, 12, 0, -10795, }, /* 486 */ + { 33, 5, 12, 0, -10792, }, /* 487 */ + { 33, 9, 12, 0, -10780, }, /* 488 */ + { 33, 9, 12, 0, -10749, }, /* 489 */ + { 33, 9, 12, 0, -10783, }, /* 490 */ + { 33, 9, 12, 0, -10782, }, /* 491 */ + { 33, 9, 12, 0, -10815, }, /* 492 */ + { 10, 5, 12, 0, 0, }, /* 493 */ + { 10, 26, 12, 0, 0, }, /* 494 */ + { 10, 12, 3, 0, 0, }, /* 495 */ + { 10, 21, 12, 0, 0, }, /* 496 */ + { 10, 15, 12, 0, 0, }, /* 497 */ + { 16, 5, 12, 0, -7264, }, /* 498 */ + { 58, 7, 12, 0, 0, }, /* 499 */ + { 58, 6, 12, 0, 0, }, /* 500 */ + { 58, 21, 12, 0, 0, }, /* 501 */ + { 58, 12, 3, 0, 0, }, /* 502 */ + { 22, 26, 12, 0, 0, }, /* 503 */ + { 22, 6, 12, 0, 0, }, /* 504 */ + { 22, 14, 12, 0, 0, }, /* 505 */ + { 23, 10, 3, 0, 0, }, /* 506 */ + { 26, 7, 12, 0, 0, }, /* 507 */ + { 26, 6, 12, 0, 0, }, /* 508 */ + { 29, 7, 12, 0, 0, }, /* 509 */ + { 29, 6, 12, 0, 0, }, /* 510 */ + { 3, 7, 12, 0, 0, }, /* 511 */ + { 23, 7, 12, 0, 0, }, /* 512 */ + { 23, 26, 12, 0, 0, }, /* 513 */ + { 29, 26, 12, 0, 0, }, /* 514 */ + { 22, 7, 12, 0, 0, }, /* 515 */ + { 60, 7, 12, 0, 0, }, /* 516 */ + { 60, 6, 12, 0, 0, }, /* 517 */ + { 60, 26, 12, 0, 0, }, /* 518 */ + { 85, 7, 12, 0, 0, }, /* 519 */ + { 85, 6, 12, 0, 0, }, /* 520 */ + { 85, 21, 12, 0, 0, }, /* 521 */ + { 76, 7, 12, 0, 0, }, /* 522 */ + { 76, 6, 12, 0, 0, }, /* 523 */ + { 76, 21, 12, 0, 0, }, /* 524 */ + { 76, 13, 12, 0, 0, }, /* 525 */ + { 12, 9, 12, 108, 1, }, /* 526 */ + { 12, 5, 12, 108, -35267, }, /* 527 */ + { 12, 7, 12, 0, 0, }, /* 528 */ + { 12, 21, 12, 0, 0, }, /* 529 */ + { 78, 7, 12, 0, 0, }, /* 530 */ + { 78, 14, 12, 0, 0, }, /* 531 */ + { 78, 12, 3, 0, 0, }, /* 532 */ + { 78, 21, 12, 0, 0, }, /* 533 */ + { 33, 9, 12, 0, -35332, }, /* 534 */ + { 33, 9, 12, 0, -42280, }, /* 535 */ + { 33, 9, 12, 0, -42308, }, /* 536 */ + { 33, 9, 12, 0, -42319, }, /* 537 */ + { 33, 9, 12, 0, -42315, }, /* 538 */ + { 33, 9, 12, 0, -42305, }, /* 539 */ + { 33, 9, 12, 0, -42258, }, /* 540 */ + { 33, 9, 12, 0, -42282, }, /* 541 */ + { 33, 9, 12, 0, -42261, }, /* 542 */ + { 33, 9, 12, 0, 928, }, /* 543 */ + { 48, 7, 12, 0, 0, }, /* 544 */ + { 48, 12, 3, 0, 0, }, /* 545 */ + { 48, 10, 5, 0, 0, }, /* 546 */ + { 48, 26, 12, 0, 0, }, /* 547 */ + { 64, 7, 12, 0, 0, }, /* 548 */ + { 64, 21, 12, 0, 0, }, /* 549 */ + { 74, 10, 5, 0, 0, }, /* 550 */ + { 74, 7, 12, 0, 0, }, /* 551 */ + { 74, 12, 3, 0, 0, }, /* 552 */ + { 74, 21, 12, 0, 0, }, /* 553 */ + { 74, 13, 12, 0, 0, }, /* 554 */ + { 68, 13, 12, 0, 0, }, /* 555 */ + { 68, 7, 12, 0, 0, }, /* 556 */ + { 68, 12, 3, 0, 0, }, /* 557 */ + { 68, 21, 12, 0, 0, }, /* 558 */ + { 73, 7, 12, 0, 0, }, /* 559 */ + { 73, 12, 3, 0, 0, }, /* 560 */ + { 73, 10, 5, 0, 0, }, /* 561 */ + { 73, 21, 12, 0, 0, }, /* 562 */ + { 83, 12, 3, 0, 0, }, /* 563 */ + { 83, 10, 5, 0, 0, }, /* 564 */ + { 83, 7, 12, 0, 0, }, /* 565 */ + { 83, 21, 12, 0, 0, }, /* 566 */ + { 83, 13, 12, 0, 0, }, /* 567 */ + { 38, 6, 12, 0, 0, }, /* 568 */ + { 67, 7, 12, 0, 0, }, /* 569 */ + { 67, 12, 3, 0, 0, }, /* 570 */ + { 67, 10, 5, 0, 0, }, /* 571 */ + { 67, 13, 12, 0, 0, }, /* 572 */ + { 67, 21, 12, 0, 0, }, /* 573 */ + { 91, 7, 12, 0, 0, }, /* 574 */ + { 91, 12, 3, 0, 0, }, /* 575 */ + { 91, 6, 12, 0, 0, }, /* 576 */ + { 91, 21, 12, 0, 0, }, /* 577 */ + { 86, 7, 12, 0, 0, }, /* 578 */ + { 86, 10, 5, 0, 0, }, /* 579 */ + { 86, 12, 3, 0, 0, }, /* 580 */ + { 86, 21, 12, 0, 0, }, /* 581 */ + { 86, 6, 12, 0, 0, }, /* 582 */ + { 33, 5, 12, 0, -928, }, /* 583 */ + { 8, 5, 12, 0, -38864, }, /* 584 */ + { 86, 13, 12, 0, 0, }, /* 585 */ + { 23, 7, 9, 0, 0, }, /* 586 */ + { 23, 7, 10, 0, 0, }, /* 587 */ + { 9, 4, 2, 0, 0, }, /* 588 */ + { 9, 3, 12, 0, 0, }, /* 589 */ + { 25, 25, 12, 0, 0, }, /* 590 */ + { 0, 24, 12, 0, 0, }, /* 591 */ + { 9, 6, 3, 0, 0, }, /* 592 */ + { 35, 7, 12, 0, 0, }, /* 593 */ + { 19, 14, 12, 0, 0, }, /* 594 */ + { 19, 15, 12, 0, 0, }, /* 595 */ + { 19, 26, 12, 0, 0, }, /* 596 */ + { 70, 7, 12, 0, 0, }, /* 597 */ + { 66, 7, 12, 0, 0, }, /* 598 */ + { 41, 7, 12, 0, 0, }, /* 599 */ + { 41, 15, 12, 0, 0, }, /* 600 */ + { 18, 7, 12, 0, 0, }, /* 601 */ + { 18, 14, 12, 0, 0, }, /* 602 */ + { 117, 7, 12, 0, 0, }, /* 603 */ + { 117, 12, 3, 0, 0, }, /* 604 */ + { 59, 7, 12, 0, 0, }, /* 605 */ + { 59, 21, 12, 0, 0, }, /* 606 */ + { 42, 7, 12, 0, 0, }, /* 607 */ + { 42, 21, 12, 0, 0, }, /* 608 */ + { 42, 14, 12, 0, 0, }, /* 609 */ + { 13, 9, 12, 0, 40, }, /* 610 */ + { 13, 5, 12, 0, -40, }, /* 611 */ + { 46, 7, 12, 0, 0, }, /* 612 */ + { 44, 7, 12, 0, 0, }, /* 613 */ + { 44, 13, 12, 0, 0, }, /* 614 */ + { 135, 9, 12, 0, 40, }, /* 615 */ + { 135, 5, 12, 0, -40, }, /* 616 */ + { 105, 7, 12, 0, 0, }, /* 617 */ + { 103, 7, 12, 0, 0, }, /* 618 */ + { 103, 21, 12, 0, 0, }, /* 619 */ + { 109, 7, 12, 0, 0, }, /* 620 */ + { 11, 7, 12, 0, 0, }, /* 621 */ + { 80, 7, 12, 0, 0, }, /* 622 */ + { 80, 21, 12, 0, 0, }, /* 623 */ + { 80, 15, 12, 0, 0, }, /* 624 */ + { 119, 7, 12, 0, 0, }, /* 625 */ + { 119, 26, 12, 0, 0, }, /* 626 */ + { 119, 15, 12, 0, 0, }, /* 627 */ + { 115, 7, 12, 0, 0, }, /* 628 */ + { 115, 15, 12, 0, 0, }, /* 629 */ + { 127, 7, 12, 0, 0, }, /* 630 */ + { 127, 15, 12, 0, 0, }, /* 631 */ + { 65, 7, 12, 0, 0, }, /* 632 */ + { 65, 15, 12, 0, 0, }, /* 633 */ + { 65, 21, 12, 0, 0, }, /* 634 */ + { 71, 7, 12, 0, 0, }, /* 635 */ + { 71, 21, 12, 0, 0, }, /* 636 */ + { 97, 7, 12, 0, 0, }, /* 637 */ + { 96, 7, 12, 0, 0, }, /* 638 */ + { 96, 15, 12, 0, 0, }, /* 639 */ + { 30, 7, 12, 0, 0, }, /* 640 */ + { 30, 12, 3, 0, 0, }, /* 641 */ + { 30, 15, 12, 0, 0, }, /* 642 */ + { 30, 21, 12, 0, 0, }, /* 643 */ + { 87, 7, 12, 0, 0, }, /* 644 */ + { 87, 15, 12, 0, 0, }, /* 645 */ + { 87, 21, 12, 0, 0, }, /* 646 */ + { 116, 7, 12, 0, 0, }, /* 647 */ + { 116, 15, 12, 0, 0, }, /* 648 */ + { 111, 7, 12, 0, 0, }, /* 649 */ + { 111, 26, 12, 0, 0, }, /* 650 */ + { 111, 12, 3, 0, 0, }, /* 651 */ + { 111, 15, 12, 0, 0, }, /* 652 */ + { 111, 21, 12, 0, 0, }, /* 653 */ + { 77, 7, 12, 0, 0, }, /* 654 */ + { 77, 21, 12, 0, 0, }, /* 655 */ + { 82, 7, 12, 0, 0, }, /* 656 */ + { 82, 15, 12, 0, 0, }, /* 657 */ + { 81, 7, 12, 0, 0, }, /* 658 */ + { 81, 15, 12, 0, 0, }, /* 659 */ + { 120, 7, 12, 0, 0, }, /* 660 */ + { 120, 21, 12, 0, 0, }, /* 661 */ + { 120, 15, 12, 0, 0, }, /* 662 */ + { 88, 7, 12, 0, 0, }, /* 663 */ + { 129, 9, 12, 0, 64, }, /* 664 */ + { 129, 5, 12, 0, -64, }, /* 665 */ + { 129, 15, 12, 0, 0, }, /* 666 */ + { 0, 15, 12, 0, 0, }, /* 667 */ + { 93, 10, 5, 0, 0, }, /* 668 */ + { 93, 12, 3, 0, 0, }, /* 669 */ + { 93, 7, 12, 0, 0, }, /* 670 */ + { 93, 21, 12, 0, 0, }, /* 671 */ + { 93, 15, 12, 0, 0, }, /* 672 */ + { 93, 13, 12, 0, 0, }, /* 673 */ + { 84, 12, 3, 0, 0, }, /* 674 */ + { 84, 10, 5, 0, 0, }, /* 675 */ + { 84, 7, 12, 0, 0, }, /* 676 */ + { 84, 21, 12, 0, 0, }, /* 677 */ + { 84, 1, 4, 0, 0, }, /* 678 */ + { 100, 7, 12, 0, 0, }, /* 679 */ + { 100, 13, 12, 0, 0, }, /* 680 */ + { 95, 12, 3, 0, 0, }, /* 681 */ + { 95, 7, 12, 0, 0, }, /* 682 */ + { 95, 10, 5, 0, 0, }, /* 683 */ + { 95, 13, 12, 0, 0, }, /* 684 */ + { 95, 21, 12, 0, 0, }, /* 685 */ + { 110, 7, 12, 0, 0, }, /* 686 */ + { 110, 12, 3, 0, 0, }, /* 687 */ + { 110, 21, 12, 0, 0, }, /* 688 */ + { 99, 12, 3, 0, 0, }, /* 689 */ + { 99, 10, 5, 0, 0, }, /* 690 */ + { 99, 7, 12, 0, 0, }, /* 691 */ + { 99, 7, 4, 0, 0, }, /* 692 */ + { 99, 21, 12, 0, 0, }, /* 693 */ + { 99, 13, 12, 0, 0, }, /* 694 */ + { 47, 15, 12, 0, 0, }, /* 695 */ + { 107, 7, 12, 0, 0, }, /* 696 */ + { 107, 10, 5, 0, 0, }, /* 697 */ + { 107, 12, 3, 0, 0, }, /* 698 */ + { 107, 21, 12, 0, 0, }, /* 699 */ + { 128, 7, 12, 0, 0, }, /* 700 */ + { 128, 21, 12, 0, 0, }, /* 701 */ + { 108, 7, 12, 0, 0, }, /* 702 */ + { 108, 12, 3, 0, 0, }, /* 703 */ + { 108, 10, 5, 0, 0, }, /* 704 */ + { 108, 13, 12, 0, 0, }, /* 705 */ + { 106, 12, 3, 0, 0, }, /* 706 */ + { 106, 10, 5, 0, 0, }, /* 707 */ + { 106, 7, 12, 0, 0, }, /* 708 */ + { 106, 10, 3, 0, 0, }, /* 709 */ + { 134, 7, 12, 0, 0, }, /* 710 */ + { 134, 10, 5, 0, 0, }, /* 711 */ + { 134, 12, 3, 0, 0, }, /* 712 */ + { 134, 21, 12, 0, 0, }, /* 713 */ + { 134, 13, 12, 0, 0, }, /* 714 */ + { 123, 7, 12, 0, 0, }, /* 715 */ + { 123, 10, 3, 0, 0, }, /* 716 */ + { 123, 10, 5, 0, 0, }, /* 717 */ + { 123, 12, 3, 0, 0, }, /* 718 */ + { 123, 21, 12, 0, 0, }, /* 719 */ + { 123, 13, 12, 0, 0, }, /* 720 */ + { 122, 7, 12, 0, 0, }, /* 721 */ + { 122, 10, 3, 0, 0, }, /* 722 */ + { 122, 10, 5, 0, 0, }, /* 723 */ + { 122, 12, 3, 0, 0, }, /* 724 */ + { 122, 21, 12, 0, 0, }, /* 725 */ + { 113, 7, 12, 0, 0, }, /* 726 */ + { 113, 10, 5, 0, 0, }, /* 727 */ + { 113, 12, 3, 0, 0, }, /* 728 */ + { 113, 21, 12, 0, 0, }, /* 729 */ + { 113, 13, 12, 0, 0, }, /* 730 */ + { 101, 7, 12, 0, 0, }, /* 731 */ + { 101, 12, 3, 0, 0, }, /* 732 */ + { 101, 10, 5, 0, 0, }, /* 733 */ + { 101, 13, 12, 0, 0, }, /* 734 */ + { 125, 7, 12, 0, 0, }, /* 735 */ + { 125, 12, 3, 0, 0, }, /* 736 */ + { 125, 10, 5, 0, 0, }, /* 737 */ + { 125, 13, 12, 0, 0, }, /* 738 */ + { 125, 15, 12, 0, 0, }, /* 739 */ + { 125, 21, 12, 0, 0, }, /* 740 */ + { 125, 26, 12, 0, 0, }, /* 741 */ + { 124, 9, 12, 0, 32, }, /* 742 */ + { 124, 5, 12, 0, -32, }, /* 743 */ + { 124, 13, 12, 0, 0, }, /* 744 */ + { 124, 15, 12, 0, 0, }, /* 745 */ + { 124, 7, 12, 0, 0, }, /* 746 */ + { 140, 7, 12, 0, 0, }, /* 747 */ + { 140, 12, 3, 0, 0, }, /* 748 */ + { 140, 10, 5, 0, 0, }, /* 749 */ + { 140, 7, 4, 0, 0, }, /* 750 */ + { 140, 21, 12, 0, 0, }, /* 751 */ + { 139, 7, 12, 0, 0, }, /* 752 */ + { 139, 12, 3, 0, 0, }, /* 753 */ + { 139, 10, 5, 0, 0, }, /* 754 */ + { 139, 7, 4, 0, 0, }, /* 755 */ + { 139, 21, 12, 0, 0, }, /* 756 */ + { 121, 7, 12, 0, 0, }, /* 757 */ + { 132, 7, 12, 0, 0, }, /* 758 */ + { 132, 10, 5, 0, 0, }, /* 759 */ + { 132, 12, 3, 0, 0, }, /* 760 */ + { 132, 21, 12, 0, 0, }, /* 761 */ + { 132, 13, 12, 0, 0, }, /* 762 */ + { 132, 15, 12, 0, 0, }, /* 763 */ + { 133, 21, 12, 0, 0, }, /* 764 */ + { 133, 7, 12, 0, 0, }, /* 765 */ + { 133, 12, 3, 0, 0, }, /* 766 */ + { 133, 10, 5, 0, 0, }, /* 767 */ + { 137, 7, 12, 0, 0, }, /* 768 */ + { 137, 12, 3, 0, 0, }, /* 769 */ + { 137, 7, 4, 0, 0, }, /* 770 */ + { 137, 13, 12, 0, 0, }, /* 771 */ + { 62, 7, 12, 0, 0, }, /* 772 */ + { 62, 14, 12, 0, 0, }, /* 773 */ + { 62, 21, 12, 0, 0, }, /* 774 */ + { 79, 7, 12, 0, 0, }, /* 775 */ + { 126, 7, 12, 0, 0, }, /* 776 */ + { 114, 7, 12, 0, 0, }, /* 777 */ + { 114, 13, 12, 0, 0, }, /* 778 */ + { 114, 21, 12, 0, 0, }, /* 779 */ + { 102, 7, 12, 0, 0, }, /* 780 */ + { 102, 12, 3, 0, 0, }, /* 781 */ + { 102, 21, 12, 0, 0, }, /* 782 */ + { 118, 7, 12, 0, 0, }, /* 783 */ + { 118, 12, 3, 0, 0, }, /* 784 */ + { 118, 21, 12, 0, 0, }, /* 785 */ + { 118, 26, 12, 0, 0, }, /* 786 */ + { 118, 6, 12, 0, 0, }, /* 787 */ + { 118, 13, 12, 0, 0, }, /* 788 */ + { 118, 15, 12, 0, 0, }, /* 789 */ + { 98, 7, 12, 0, 0, }, /* 790 */ + { 98, 10, 5, 0, 0, }, /* 791 */ + { 98, 12, 3, 0, 0, }, /* 792 */ + { 98, 6, 12, 0, 0, }, /* 793 */ + { 136, 6, 12, 0, 0, }, /* 794 */ + { 138, 6, 12, 0, 0, }, /* 795 */ + { 136, 7, 12, 0, 0, }, /* 796 */ + { 138, 7, 12, 0, 0, }, /* 797 */ + { 104, 7, 12, 0, 0, }, /* 798 */ + { 104, 26, 12, 0, 0, }, /* 799 */ + { 104, 12, 3, 0, 0, }, /* 800 */ + { 104, 21, 12, 0, 0, }, /* 801 */ + { 9, 10, 3, 0, 0, }, /* 802 */ + { 19, 12, 3, 0, 0, }, /* 803 */ + { 130, 26, 12, 0, 0, }, /* 804 */ + { 130, 12, 3, 0, 0, }, /* 805 */ + { 130, 21, 12, 0, 0, }, /* 806 */ + { 17, 12, 3, 0, 0, }, /* 807 */ + { 112, 7, 12, 0, 0, }, /* 808 */ + { 112, 15, 12, 0, 0, }, /* 809 */ + { 112, 12, 3, 0, 0, }, /* 810 */ + { 131, 9, 12, 0, 34, }, /* 811 */ + { 131, 5, 12, 0, -34, }, /* 812 */ + { 131, 12, 3, 0, 0, }, /* 813 */ + { 131, 13, 12, 0, 0, }, /* 814 */ + { 131, 21, 12, 0, 0, }, /* 815 */ + { 9, 26, 11, 0, 0, }, /* 816 */ + { 26, 26, 12, 0, 0, }, /* 817 */ + { 9, 24, 14, 0, 0, }, /* 818 */ + { 9, 26, 15, 0, 0, }, /* 819 */ + { 9, 1, 3, 0, 0, }, /* 820 */ }; const uint8_t PRIV(ucd_stage1)[] = { /* 8704 bytes */ @@ -834,549 +933,549 @@ const uint8_t PRIV(ucd_stage1)[] = { /* 8704 bytes */ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, /* U+0800 */ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 41, 41, 42, 43, 44, 45, /* U+1000 */ 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, /* U+1800 */ - 62, 63, 64, 65, 66, 66, 67, 68, 69, 70, 71, 72, 73, 71, 74, 75, /* U+2000 */ - 76, 76, 66, 77, 66, 66, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, /* U+2800 */ - 88, 89, 90, 91, 92, 93, 94, 71, 95, 95, 95, 95, 95, 95, 95, 95, /* U+3000 */ - 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, /* U+3800 */ - 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, /* U+4000 */ - 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 96, 95, 95, 95, 95, /* U+4800 */ - 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, /* U+5000 */ - 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, /* U+5800 */ - 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, /* U+6000 */ - 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, /* U+6800 */ - 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, /* U+7000 */ - 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, /* U+7800 */ - 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, /* U+8000 */ - 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, /* U+8800 */ - 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, /* U+9000 */ - 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 97, /* U+9800 */ - 98, 99, 99, 99, 99, 99, 99, 99, 99,100,101,101,102,103,104,105, /* U+A000 */ -106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,114, /* U+A800 */ -115,116,117,118,119,120,114,115,116,117,118,119,120,114,115,116, /* U+B000 */ -117,118,119,120,114,115,116,117,118,119,120,114,115,116,117,118, /* U+B800 */ -119,120,114,115,116,117,118,119,120,114,115,116,117,118,119,120, /* U+C000 */ -114,115,116,117,118,119,120,114,115,116,117,118,119,120,114,115, /* U+C800 */ -116,117,118,119,120,114,115,116,117,118,119,120,114,115,116,121, /* U+D000 */ -122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,122, /* U+D800 */ -123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+E000 */ -123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+E800 */ -123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+F000 */ -123,123, 95, 95,124,125,126,127,128,128,129,130,131,132,133,134, /* U+F800 */ -135,136,137,138,139,140,141,142,143,144,145,139,146,146,147,139, /* U+10000 */ -148,149,150,151,152,153,154,155,156,157,139,139,158,139,139,139, /* U+10800 */ -159,160,161,162,163,164,165,139,139,166,139,167,168,169,170,139, /* U+11000 */ -139,171,139,139,139,172,139,139,139,139,139,139,139,139,139,139, /* U+11800 */ -173,173,173,173,173,173,173,174,175,173,176,139,139,139,139,139, /* U+12000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+12800 */ -177,177,177,177,177,177,177,177,178,139,139,139,139,139,139,139, /* U+13000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+13800 */ -139,139,139,139,139,139,139,139,179,179,179,179,180,139,139,139, /* U+14000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+14800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+15000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+15800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+16000 */ -181,181,181,181,182,183,184,185,139,139,139,139,139,139,186,187, /* U+16800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+17000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+17800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+18000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+18800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+19000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+19800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+1A000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+1A800 */ -188,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+1B000 */ -139,139,139,139,139,139,139,139,189,190,139,139,139,139,139,139, /* U+1B800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+1C000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+1C800 */ - 71,191,192,193,194,139,195,139,196,197,198,199,200,201,202,203, /* U+1D000 */ -204,204,204,204,205,206,139,139,139,139,139,139,139,139,139,139, /* U+1D800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+1E000 */ -207,208,139,139,139,139,139,139,139,139,139,139,209,210,139,139, /* U+1E800 */ -211,212,213,214,215,139, 71,216, 71, 71,217,218, 71,219,220,221, /* U+1F000 */ -222,223,224,225,139,139,139,139,139,139,139,139,139,139,139,139, /* U+1F800 */ - 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, /* U+20000 */ - 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, /* U+20800 */ - 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, /* U+21000 */ - 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, /* U+21800 */ - 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, /* U+22000 */ - 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, /* U+22800 */ - 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, /* U+23000 */ - 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, /* U+23800 */ - 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, /* U+24000 */ - 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, /* U+24800 */ - 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, /* U+25000 */ - 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, /* U+25800 */ - 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, /* U+26000 */ - 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, /* U+26800 */ - 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, /* U+27000 */ - 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, /* U+27800 */ - 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, /* U+28000 */ - 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, /* U+28800 */ - 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, /* U+29000 */ - 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, /* U+29800 */ - 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95,226, 95, 95, /* U+2A000 */ - 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, /* U+2A800 */ - 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95,227, 95, /* U+2B000 */ -228, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, /* U+2B800 */ - 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, /* U+2C000 */ - 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95,229,139,139, /* U+2C800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+2D000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+2D800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+2E000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+2E800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+2F000 */ - 95, 95, 95, 95,230,139,139,139,139,139,139,139,139,139,139,139, /* U+2F800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+30000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+30800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+31000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+31800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+32000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+32800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+33000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+33800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+34000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+34800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+35000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+35800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+36000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+36800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+37000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+37800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+38000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+38800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+39000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+39800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+3A000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+3A800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+3B000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+3B800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+3C000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+3C800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+3D000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+3D800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+3E000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+3E800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+3F000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+3F800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+40000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+40800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+41000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+41800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+42000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+42800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+43000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+43800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+44000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+44800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+45000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+45800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+46000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+46800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+47000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+47800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+48000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+48800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+49000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+49800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+4A000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+4A800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+4B000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+4B800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+4C000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+4C800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+4D000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+4D800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+4E000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+4E800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+4F000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+4F800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+50000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+50800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+51000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+51800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+52000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+52800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+53000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+53800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+54000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+54800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+55000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+55800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+56000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+56800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+57000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+57800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+58000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+58800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+59000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+59800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+5A000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+5A800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+5B000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+5B800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+5C000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+5C800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+5D000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+5D800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+5E000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+5E800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+5F000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+5F800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+60000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+60800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+61000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+61800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+62000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+62800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+63000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+63800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+64000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+64800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+65000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+65800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+66000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+66800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+67000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+67800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+68000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+68800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+69000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+69800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+6A000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+6A800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+6B000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+6B800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+6C000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+6C800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+6D000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+6D800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+6E000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+6E800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+6F000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+6F800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+70000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+70800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+71000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+71800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+72000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+72800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+73000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+73800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+74000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+74800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+75000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+75800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+76000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+76800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+77000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+77800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+78000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+78800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+79000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+79800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+7A000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+7A800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+7B000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+7B800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+7C000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+7C800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+7D000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+7D800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+7E000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+7E800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+7F000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+7F800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+80000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+80800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+81000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+81800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+82000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+82800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+83000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+83800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+84000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+84800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+85000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+85800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+86000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+86800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+87000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+87800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+88000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+88800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+89000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+89800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+8A000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+8A800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+8B000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+8B800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+8C000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+8C800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+8D000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+8D800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+8E000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+8E800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+8F000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+8F800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+90000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+90800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+91000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+91800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+92000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+92800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+93000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+93800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+94000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+94800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+95000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+95800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+96000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+96800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+97000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+97800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+98000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+98800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+99000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+99800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+9A000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+9A800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+9B000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+9B800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+9C000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+9C800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+9D000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+9D800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+9E000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+9E800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+9F000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+9F800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+A0000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+A0800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+A1000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+A1800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+A2000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+A2800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+A3000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+A3800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+A4000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+A4800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+A5000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+A5800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+A6000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+A6800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+A7000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+A7800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+A8000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+A8800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+A9000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+A9800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+AA000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+AA800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+AB000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+AB800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+AC000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+AC800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+AD000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+AD800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+AE000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+AE800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+AF000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+AF800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+B0000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+B0800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+B1000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+B1800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+B2000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+B2800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+B3000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+B3800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+B4000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+B4800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+B5000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+B5800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+B6000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+B6800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+B7000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+B7800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+B8000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+B8800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+B9000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+B9800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+BA000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+BA800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+BB000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+BB800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+BC000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+BC800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+BD000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+BD800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+BE000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+BE800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+BF000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+BF800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+C0000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+C0800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+C1000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+C1800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+C2000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+C2800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+C3000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+C3800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+C4000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+C4800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+C5000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+C5800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+C6000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+C6800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+C7000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+C7800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+C8000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+C8800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+C9000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+C9800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+CA000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+CA800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+CB000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+CB800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+CC000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+CC800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+CD000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+CD800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+CE000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+CE800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+CF000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+CF800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+D0000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+D0800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+D1000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+D1800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+D2000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+D2800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+D3000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+D3800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+D4000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+D4800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+D5000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+D5800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+D6000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+D6800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+D7000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+D7800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+D8000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+D8800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+D9000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+D9800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+DA000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+DA800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+DB000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+DB800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+DC000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+DC800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+DD000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+DD800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+DE000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+DE800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+DF000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+DF800 */ -231,232,233,234,232,232,232,232,232,232,232,232,232,232,232,232, /* U+E0000 */ -232,232,232,232,232,232,232,232,232,232,232,232,232,232,232,232, /* U+E0800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+E1000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+E1800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+E2000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+E2800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+E3000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+E3800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+E4000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+E4800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+E5000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+E5800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+E6000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+E6800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+E7000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+E7800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+E8000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+E8800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+E9000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+E9800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+EA000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+EA800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+EB000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+EB800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+EC000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+EC800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+ED000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+ED800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+EE000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+EE800 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+EF000 */ -139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+EF800 */ -123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+F0000 */ -123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+F0800 */ -123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+F1000 */ -123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+F1800 */ -123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+F2000 */ -123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+F2800 */ -123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+F3000 */ -123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+F3800 */ -123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+F4000 */ -123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+F4800 */ -123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+F5000 */ -123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+F5800 */ -123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+F6000 */ -123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+F6800 */ -123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+F7000 */ -123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+F7800 */ -123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+F8000 */ -123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+F8800 */ -123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+F9000 */ -123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+F9800 */ -123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+FA000 */ -123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+FA800 */ -123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+FB000 */ -123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+FB800 */ -123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+FC000 */ -123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+FC800 */ -123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+FD000 */ -123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+FD800 */ -123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+FE000 */ -123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+FE800 */ -123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+FF000 */ -123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,235, /* U+FF800 */ -123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+100000 */ -123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+100800 */ -123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+101000 */ -123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+101800 */ -123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+102000 */ -123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+102800 */ -123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+103000 */ -123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+103800 */ -123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+104000 */ -123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+104800 */ -123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+105000 */ -123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+105800 */ -123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+106000 */ -123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+106800 */ -123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+107000 */ -123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+107800 */ -123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+108000 */ -123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+108800 */ -123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+109000 */ -123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+109800 */ -123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+10A000 */ -123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+10A800 */ -123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+10B000 */ -123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+10B800 */ -123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+10C000 */ -123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+10C800 */ -123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+10D000 */ -123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+10D800 */ -123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+10E000 */ -123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+10E800 */ -123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+10F000 */ -123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,235, /* U+10F800 */ + 62, 63, 64, 65, 66, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, /* U+2000 */ + 77, 77, 66, 78, 66, 66, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, /* U+2800 */ + 89, 90, 91, 92, 93, 94, 95, 71, 96, 96, 96, 96, 96, 96, 96, 96, /* U+3000 */ + 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, /* U+3800 */ + 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, /* U+4000 */ + 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 97, 96, 96, 96, 96, /* U+4800 */ + 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, /* U+5000 */ + 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, /* U+5800 */ + 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, /* U+6000 */ + 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, /* U+6800 */ + 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, /* U+7000 */ + 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, /* U+7800 */ + 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, /* U+8000 */ + 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, /* U+8800 */ + 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, /* U+9000 */ + 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 98, /* U+9800 */ + 99,100,100,100,100,100,100,100,100,101,102,102,103,104,105,106, /* U+A000 */ +107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,115, /* U+A800 */ +116,117,118,119,120,121,115,116,117,118,119,120,121,115,116,117, /* U+B000 */ +118,119,120,121,115,116,117,118,119,120,121,115,116,117,118,119, /* U+B800 */ +120,121,115,116,117,118,119,120,121,115,116,117,118,119,120,121, /* U+C000 */ +115,116,117,118,119,120,121,115,116,117,118,119,120,121,115,116, /* U+C800 */ +117,118,119,120,121,115,116,117,118,119,120,121,115,116,117,122, /* U+D000 */ +123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+D800 */ +124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, /* U+E000 */ +124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, /* U+E800 */ +124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, /* U+F000 */ +124,124, 96, 96,125,126,127,128,129,129,130,131,132,133,134,135, /* U+F800 */ +136,137,138,139,140,141,142,143,144,145,146,140,147,147,148,140, /* U+10000 */ +149,150,151,152,153,154,155,156,157,158,140,140,159,140,140,140, /* U+10800 */ +160,161,162,163,164,165,166,140,167,168,140,169,170,171,172,140, /* U+11000 */ +140,173,140,140,174,175,140,140,176,177,178,140,140,140,140,140, /* U+11800 */ +179,179,179,179,179,179,179,180,181,179,182,140,140,140,140,140, /* U+12000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+12800 */ +183,183,183,183,183,183,183,183,184,140,140,140,140,140,140,140, /* U+13000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+13800 */ +140,140,140,140,140,140,140,140,185,185,185,185,186,140,140,140, /* U+14000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+14800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+15000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+15800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+16000 */ +187,187,187,187,188,189,190,191,140,140,140,140,140,140,192,193, /* U+16800 */ +194,194,194,194,194,194,194,194,194,194,194,194,194,194,194,194, /* U+17000 */ +194,194,194,194,194,194,194,194,194,194,194,194,194,194,194,194, /* U+17800 */ +194,194,194,194,194,194,194,194,194,194,194,194,194,194,194,195, /* U+18000 */ +194,194,194,194,194,196,140,140,140,140,140,140,140,140,140,140, /* U+18800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+19000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+19800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+1A000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+1A800 */ +197,198,199,200,200,201,140,140,140,140,140,140,140,140,140,140, /* U+1B000 */ +140,140,140,140,140,140,140,140,202,203,140,140,140,140,140,140, /* U+1B800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+1C000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+1C800 */ + 71,204,205,206,207,140,208,140,209,210,211,212,213,214,215,216, /* U+1D000 */ +217,217,217,217,218,219,140,140,140,140,140,140,140,140,140,140, /* U+1D800 */ +220,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+1E000 */ +221,222,223,140,140,140,140,140,140,140,140,140,224,225,140,140, /* U+1E800 */ +226,227,228,229,230,140,231,232,233,234,235,236,237,238,239,240, /* U+1F000 */ +241,242,243,244,140,140,140,140,140,140,140,140,140,140,140,140, /* U+1F800 */ + 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, /* U+20000 */ + 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, /* U+20800 */ + 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, /* U+21000 */ + 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, /* U+21800 */ + 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, /* U+22000 */ + 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, /* U+22800 */ + 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, /* U+23000 */ + 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, /* U+23800 */ + 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, /* U+24000 */ + 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, /* U+24800 */ + 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, /* U+25000 */ + 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, /* U+25800 */ + 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, /* U+26000 */ + 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, /* U+26800 */ + 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, /* U+27000 */ + 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, /* U+27800 */ + 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, /* U+28000 */ + 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, /* U+28800 */ + 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, /* U+29000 */ + 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, /* U+29800 */ + 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,245, 96, 96, /* U+2A000 */ + 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, /* U+2A800 */ + 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,246, 96, /* U+2B000 */ +247, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, /* U+2B800 */ + 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, /* U+2C000 */ + 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,248, 96, 96, /* U+2C800 */ + 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, /* U+2D000 */ + 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, /* U+2D800 */ + 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, /* U+2E000 */ + 96, 96, 96, 96, 96, 96, 96,249,140,140,140,140,140,140,140,140, /* U+2E800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+2F000 */ + 96, 96, 96, 96,250,140,140,140,140,140,140,140,140,140,140,140, /* U+2F800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+30000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+30800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+31000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+31800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+32000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+32800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+33000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+33800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+34000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+34800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+35000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+35800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+36000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+36800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+37000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+37800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+38000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+38800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+39000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+39800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+3A000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+3A800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+3B000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+3B800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+3C000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+3C800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+3D000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+3D800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+3E000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+3E800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+3F000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+3F800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+40000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+40800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+41000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+41800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+42000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+42800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+43000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+43800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+44000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+44800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+45000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+45800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+46000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+46800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+47000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+47800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+48000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+48800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+49000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+49800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+4A000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+4A800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+4B000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+4B800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+4C000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+4C800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+4D000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+4D800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+4E000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+4E800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+4F000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+4F800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+50000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+50800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+51000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+51800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+52000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+52800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+53000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+53800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+54000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+54800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+55000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+55800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+56000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+56800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+57000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+57800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+58000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+58800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+59000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+59800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+5A000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+5A800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+5B000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+5B800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+5C000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+5C800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+5D000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+5D800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+5E000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+5E800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+5F000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+5F800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+60000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+60800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+61000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+61800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+62000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+62800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+63000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+63800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+64000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+64800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+65000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+65800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+66000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+66800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+67000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+67800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+68000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+68800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+69000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+69800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+6A000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+6A800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+6B000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+6B800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+6C000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+6C800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+6D000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+6D800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+6E000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+6E800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+6F000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+6F800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+70000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+70800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+71000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+71800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+72000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+72800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+73000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+73800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+74000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+74800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+75000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+75800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+76000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+76800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+77000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+77800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+78000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+78800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+79000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+79800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+7A000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+7A800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+7B000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+7B800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+7C000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+7C800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+7D000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+7D800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+7E000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+7E800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+7F000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+7F800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+80000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+80800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+81000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+81800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+82000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+82800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+83000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+83800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+84000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+84800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+85000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+85800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+86000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+86800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+87000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+87800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+88000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+88800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+89000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+89800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+8A000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+8A800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+8B000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+8B800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+8C000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+8C800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+8D000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+8D800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+8E000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+8E800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+8F000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+8F800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+90000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+90800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+91000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+91800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+92000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+92800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+93000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+93800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+94000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+94800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+95000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+95800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+96000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+96800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+97000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+97800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+98000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+98800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+99000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+99800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+9A000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+9A800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+9B000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+9B800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+9C000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+9C800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+9D000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+9D800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+9E000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+9E800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+9F000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+9F800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+A0000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+A0800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+A1000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+A1800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+A2000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+A2800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+A3000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+A3800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+A4000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+A4800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+A5000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+A5800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+A6000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+A6800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+A7000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+A7800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+A8000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+A8800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+A9000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+A9800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+AA000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+AA800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+AB000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+AB800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+AC000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+AC800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+AD000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+AD800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+AE000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+AE800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+AF000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+AF800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+B0000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+B0800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+B1000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+B1800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+B2000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+B2800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+B3000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+B3800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+B4000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+B4800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+B5000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+B5800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+B6000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+B6800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+B7000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+B7800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+B8000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+B8800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+B9000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+B9800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+BA000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+BA800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+BB000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+BB800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+BC000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+BC800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+BD000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+BD800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+BE000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+BE800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+BF000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+BF800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+C0000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+C0800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+C1000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+C1800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+C2000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+C2800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+C3000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+C3800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+C4000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+C4800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+C5000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+C5800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+C6000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+C6800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+C7000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+C7800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+C8000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+C8800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+C9000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+C9800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+CA000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+CA800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+CB000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+CB800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+CC000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+CC800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+CD000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+CD800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+CE000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+CE800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+CF000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+CF800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+D0000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+D0800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+D1000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+D1800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+D2000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+D2800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+D3000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+D3800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+D4000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+D4800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+D5000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+D5800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+D6000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+D6800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+D7000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+D7800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+D8000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+D8800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+D9000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+D9800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+DA000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+DA800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+DB000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+DB800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+DC000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+DC800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+DD000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+DD800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+DE000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+DE800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+DF000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+DF800 */ +251,252,253,254,252,252,252,252,252,252,252,252,252,252,252,252, /* U+E0000 */ +252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252, /* U+E0800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+E1000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+E1800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+E2000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+E2800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+E3000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+E3800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+E4000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+E4800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+E5000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+E5800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+E6000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+E6800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+E7000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+E7800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+E8000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+E8800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+E9000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+E9800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+EA000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+EA800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+EB000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+EB800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+EC000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+EC800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+ED000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+ED800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+EE000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+EE800 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+EF000 */ +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, /* U+EF800 */ +124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, /* U+F0000 */ +124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, /* U+F0800 */ +124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, /* U+F1000 */ +124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, /* U+F1800 */ +124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, /* U+F2000 */ +124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, /* U+F2800 */ +124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, /* U+F3000 */ +124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, /* U+F3800 */ +124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, /* U+F4000 */ +124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, /* U+F4800 */ +124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, /* U+F5000 */ +124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, /* U+F5800 */ +124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, /* U+F6000 */ +124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, /* U+F6800 */ +124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, /* U+F7000 */ +124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, /* U+F7800 */ +124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, /* U+F8000 */ +124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, /* U+F8800 */ +124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, /* U+F9000 */ +124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, /* U+F9800 */ +124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, /* U+FA000 */ +124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, /* U+FA800 */ +124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, /* U+FB000 */ +124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, /* U+FB800 */ +124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, /* U+FC000 */ +124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, /* U+FC800 */ +124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, /* U+FD000 */ +124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, /* U+FD800 */ +124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, /* U+FE000 */ +124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, /* U+FE800 */ +124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, /* U+FF000 */ +124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,255, /* U+FF800 */ +124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, /* U+100000 */ +124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, /* U+100800 */ +124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, /* U+101000 */ +124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, /* U+101800 */ +124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, /* U+102000 */ +124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, /* U+102800 */ +124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, /* U+103000 */ +124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, /* U+103800 */ +124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, /* U+104000 */ +124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, /* U+104800 */ +124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, /* U+105000 */ +124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, /* U+105800 */ +124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, /* U+106000 */ +124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, /* U+106800 */ +124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, /* U+107000 */ +124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, /* U+107800 */ +124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, /* U+108000 */ +124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, /* U+108800 */ +124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, /* U+109000 */ +124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, /* U+109800 */ +124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, /* U+10A000 */ +124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, /* U+10A800 */ +124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, /* U+10B000 */ +124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, /* U+10B800 */ +124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, /* U+10C000 */ +124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, /* U+10C800 */ +124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, /* U+10D000 */ +124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, /* U+10D800 */ +124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, /* U+10E000 */ +124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, /* U+10E800 */ +124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, /* U+10F000 */ +124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,255, /* U+10F800 */ }; -const uint16_t PRIV(ucd_stage2)[] = { /* 60416 bytes, block = 128 */ +const uint16_t PRIV(ucd_stage2)[] = { /* 65536 bytes, block = 128 */ /* block 0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -1424,7 +1523,7 @@ const uint16_t PRIV(ucd_stage2)[] = { /* 60416 bytes, block = 128 */ 30, 31, 30, 31, 33, 33, 33, 33, 33, 33, 71, 30, 31, 72, 73, 74, 74, 30, 31, 75, 76, 77, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 78, 79, 80, 81, 82, 33, 83, 83, 33, 84, 33, 85, 86, 33, 33, 33, - 83, 87, 33, 88, 33, 89, 90, 33, 91, 92, 33, 93, 94, 33, 33, 92, + 83, 87, 33, 88, 33, 89, 90, 33, 91, 92, 90, 93, 94, 33, 33, 92, 33, 95, 96, 33, 33, 97, 33, 33, 33, 33, 33, 33, 33, 98, 33, 33, /* block 5 */ @@ -1459,493 +1558,493 @@ const uint16_t PRIV(ucd_stage2)[] = { /* 60416 bytes, block = 128 */ /* block 8 */ 171,171,171,171,171,171,171,171,171,171,171,171,171,171,171,171, -172,172,172,172,172,172,172,172,172,172,172,172,172,172,172,172, -172,172,172,172,172,172,172,172,172,172,172,172,172,172,172,172, -173,173,173,173,173,173,173,173,173,173,173,173,173,173,173,173, -173,173,173,173,173,173,173,173,173,173,173,173,173,173,173,173, -174,174,174,174,174,174,174,174,174,174,174,174,174,174,174,174, -175,176,175,176,175,176,175,176,175,176,175,176,175,176,175,176, -175,176,175,176,175,176,175,176,175,176,175,176,175,176,175,176, +172,172,173,172,174,172,172,172,172,172,172,172,172,172,175,172, +172,176,177,172,172,172,172,172,172,172,178,172,172,172,172,172, +179,179,180,179,181,179,179,179,179,179,179,179,179,179,182,179, +179,183,184,179,179,179,179,179,179,179,185,179,179,179,179,179, +186,186,186,186,186,186,186,186,186,186,186,186,186,186,186,186, +187,188,189,190,187,188,187,188,187,188,187,188,187,188,187,188, +187,188,187,188,187,188,187,188,187,188,187,188,187,188,187,188, /* block 9 */ -175,176,177,178,178,110,110,178,179,179,175,176,175,176,175,176, -175,176,175,176,175,176,175,176,175,176,175,176,175,176,175,176, -175,176,175,176,175,176,175,176,175,176,175,176,175,176,175,176, -175,176,175,176,175,176,175,176,175,176,175,176,175,176,175,176, -180,175,176,175,176,175,176,175,176,175,176,175,176,175,176,181, -175,176,175,176,175,176,175,176,175,176,175,176,175,176,175,176, -175,176,175,176,175,176,175,176,175,176,175,176,175,176,175,176, -175,176,175,176,175,176,175,176,175,176,175,176,175,176,175,176, +187,188,191,192,192,110,110,192,193,193,187,188,187,188,187,188, +187,188,187,188,187,188,187,188,187,188,187,188,187,188,187,188, +187,188,187,188,187,188,187,188,187,188,187,188,187,188,187,188, +187,188,187,188,187,188,187,188,187,188,187,188,187,188,187,188, +194,187,188,187,188,187,188,187,188,187,188,187,188,187,188,195, +187,188,187,188,187,188,187,188,187,188,187,188,187,188,187,188, +187,188,187,188,187,188,187,188,187,188,187,188,187,188,187,188, +187,188,187,188,187,188,187,188,187,188,187,188,187,188,187,188, /* block 10 */ -175,176,175,176,175,176,175,176,175,176,175,176,175,176,175,176, -175,176,175,176,175,176,175,176,175,176,175,176,175,176,175,176, -175,176,175,176,175,176,175,176,175,176,175,176,175,176,175,176, -115,182,182,182,182,182,182,182,182,182,182,182,182,182,182,182, -182,182,182,182,182,182,182,182,182,182,182,182,182,182,182,182, -182,182,182,182,182,182,182,115,115,183,184,184,184,184,184,184, -115,185,185,185,185,185,185,185,185,185,185,185,185,185,185,185, -185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,185, +187,188,187,188,187,188,187,188,187,188,187,188,187,188,187,188, +187,188,187,188,187,188,187,188,187,188,187,188,187,188,187,188, +187,188,187,188,187,188,187,188,187,188,187,188,187,188,187,188, +115,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, +196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196, +196,196,196,196,196,196,196,115,115,197,198,198,198,198,198,198, +115,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199, +199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199, /* block 11 */ -185,185,185,185,185,185,185,186,115, 4,187,115,115,188,188,189, -115,190,190,190,190,190,190,190,190,190,190,190,190,190,190,190, -190,190,190,190,190,190,190,190,190,190,190,190,190,190,190,190, -190,190,190,190,190,190,190,190,190,190,190,190,190,190,191,190, -192,190,190,192,190,190,192,190,115,115,115,115,115,115,115,115, -193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193, -193,193,193,193,193,193,193,193,193,193,193,115,115,115,115,115, -193,193,193,192,192,115,115,115,115,115,115,115,115,115,115,115, +199,199,199,199,199,199,199,200,115, 4,201,115,115,202,202,203, +115,204,204,204,204,204,204,204,204,204,204,204,204,204,204,204, +204,204,204,204,204,204,204,204,204,204,204,204,204,204,204,204, +204,204,204,204,204,204,204,204,204,204,204,204,204,204,205,204, +206,204,204,206,204,204,206,204,115,115,115,115,115,115,115,115, +207,207,207,207,207,207,207,207,207,207,207,207,207,207,207,207, +207,207,207,207,207,207,207,207,207,207,207,115,115,115,115,115, +207,207,207,206,206,115,115,115,115,115,115,115,115,115,115,115, /* block 12 */ -194,194,194,194,194, 22,195,195,195,196,196,197, 4,196,198,198, -199,199,199,199,199,199,199,199,199,199,199, 4, 22,115,196, 4, -200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200, -200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200, -108,200,200,200,200,200,200,200,200,200,200,110,110,110,110,110, -110,110,110,110,110,110,199,199,199,199,199,199,199,199,199,199, -201,201,201,201,201,201,201,201,201,201,196,196,196,196,200,200, -110,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200, +208,208,208,208,208,209,210,210,210,211,211,212, 4,211,213,213, +214,214,214,214,214,214,214,214,214,214,214, 4,215,115,211, 4, +216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216, +216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216, +108,216,216,216,216,216,216,216,216,216,216,110,110,110,110,110, +110,110,110,110,110,110,214,214,214,214,214,214,214,214,214,214, +217,217,217,217,217,217,217,217,217,217,211,211,211,211,216,216, +110,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216, /* block 13 */ -200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200, -200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200, -200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200, -200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200, -200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200, -200,200,200,200,196,200,199,199,199,199,199,199,199, 22,198,199, -199,199,199,199,199,202,202,199,199,198,199,199,199,199,200,200, -201,201,201,201,201,201,201,201,201,201,200,200,200,198,198,200, +216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216, +216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216, +216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216, +216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216, +216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216, +216,216,216,216,211,216,214,214,214,214,214,214,214,209,213,214, +214,214,214,214,214,218,218,214,214,213,214,214,214,214,216,216, +217,217,217,217,217,217,217,217,217,217,216,216,216,213,213,216, /* block 14 */ -203,203,203,203,203,203,203,203,203,203,203,203,203,203,115,204, -205,206,205,205,205,205,205,205,205,205,205,205,205,205,205,205, -205,205,205,205,205,205,205,205,205,205,205,205,205,205,205,205, -206,206,206,206,206,206,206,206,206,206,206,206,206,206,206,206, -206,206,206,206,206,206,206,206,206,206,206,115,115,205,205,205, -200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200, -200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200, -200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200, +219,219,219,219,219,219,219,219,219,219,219,219,219,219,115,220, +221,222,221,221,221,221,221,221,221,221,221,221,221,221,221,221, +221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221, +222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222, +222,222,222,222,222,222,222,222,222,222,222,115,115,221,221,221, +216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216, +216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216, +216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216, /* block 15 */ -207,207,207,207,207,207,207,207,207,207,207,207,207,207,207,207, -207,207,207,207,207,207,207,207,207,207,207,207,207,207,207,207, -207,207,207,207,207,207,208,208,208,208,208,208,208,208,208,208, -208,207,115,115,115,115,115,115,115,115,115,115,115,115,115,115, -209,209,209,209,209,209,209,209,209,209,210,210,210,210,210,210, -210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210, -210,210,210,210,210,210,210,210,210,210,210,211,211,211,211,211, -211,211,211,211,212,212,213,214,214,214,212,115,115,115,115,115, +223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223, +223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223, +223,223,223,223,223,223,224,224,224,224,224,224,224,224,224,224, +224,223,115,115,115,115,115,115,115,115,115,115,115,115,115,115, +225,225,225,225,225,225,225,225,225,225,226,226,226,226,226,226, +226,226,226,226,226,226,226,226,226,226,226,226,226,226,226,226, +226,226,226,226,226,226,226,226,226,226,226,227,227,227,227,227, +227,227,227,227,228,228,229,230,230,230,228,115,115,115,115,115, /* block 16 */ -215,215,215,215,215,215,215,215,215,215,215,215,215,215,215,215, -215,215,215,215,215,215,216,216,216,216,217,216,216,216,216,216, -216,216,216,216,217,216,216,216,217,216,216,216,216,216,115,115, -218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,115, -219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219, -219,219,219,219,219,219,219,219,219,220,220,220,115,115,221,115, -115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, +231,231,231,231,231,231,231,231,231,231,231,231,231,231,231,231, +231,231,231,231,231,231,232,232,232,232,233,232,232,232,232,232, +232,232,232,232,233,232,232,232,233,232,232,232,232,232,115,115, +234,234,234,234,234,234,234,234,234,234,234,234,234,234,234,115, +235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235, +235,235,235,235,235,235,235,235,235,236,236,236,115,115,237,115, +221,221,221,221,221,221,221,221,221,221,221,115,115,115,115,115, 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, /* block 17 */ 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, -200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200, -200,200,200,200,200,115,115,115,115,115,115,115,115,115,115,115, +216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216, +216,216,216,216,216,115,216,216,216,216,216,216,216,216,115,115, 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, -115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, -115,115,115,199,199,199,199,199,199,199,199,199,199,199,199,199, -199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199, +115,115,115,115,214,214,214,214,214,214,214,214,214,214,214,214, +214,214,209,214,214,214,214,214,214,214,214,214,214,214,214,214, +214,214,214,214,214,214,214,214,214,214,214,214,214,214,214,214, /* block 18 */ -222,222,222,223,224,224,224,224,224,224,224,224,224,224,224,224, -224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224, -224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224, -224,224,224,224,224,224,224,224,224,224,222,223,222,224,223,223, -223,222,222,222,222,222,222,222,222,223,223,223,223,222,223,223, -224,110,110,222,222,222,222,222,224,224,224,224,224,224,224,224, -224,224,222,222, 4, 4,225,225,225,225,225,225,225,225,225,225, -226,227,224,224,224,224,224,224,224,224,224,224,224,224,224,224, +238,238,238,239,240,240,240,240,240,240,240,240,240,240,240,240, +240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240, +240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240, +240,240,240,240,240,240,240,240,240,240,238,239,238,240,239,239, +239,238,238,238,238,238,238,238,238,239,239,239,239,238,239,239, +240,110,110,238,238,238,238,238,240,240,240,240,240,240,240,240, +240,240,238,238, 4, 4,241,241,241,241,241,241,241,241,241,241, +242,243,240,240,240,240,240,240,240,240,240,240,240,240,240,240, /* block 19 */ -228,229,230,230,115,228,228,228,228,228,228,228,228,115,115,228, -228,115,115,228,228,228,228,228,228,228,228,228,228,228,228,228, -228,228,228,228,228,228,228,228,228,115,228,228,228,228,228,228, -228,115,228,115,115,115,228,228,228,228,115,115,229,228,231,230, -230,229,229,229,229,115,115,230,230,115,115,230,230,229,228,115, -115,115,115,115,115,115,115,231,115,115,115,115,228,228,115,228, -228,228,229,229,115,115,232,232,232,232,232,232,232,232,232,232, -228,228,233,233,234,234,234,234,234,234,235,233,115,115,115,115, +244,245,246,246,115,244,244,244,244,244,244,244,244,115,115,244, +244,115,115,244,244,244,244,244,244,244,244,244,244,244,244,244, +244,244,244,244,244,244,244,244,244,115,244,244,244,244,244,244, +244,115,244,115,115,115,244,244,244,244,115,115,245,244,247,246, +246,245,245,245,245,115,115,246,246,115,115,246,246,245,244,115, +115,115,115,115,115,115,115,247,115,115,115,115,244,244,115,244, +244,244,245,245,115,115,248,248,248,248,248,248,248,248,248,248, +244,244,249,249,250,250,250,250,250,250,251,249,244,252,115,115, /* block 20 */ -115,236,236,237,115,238,238,238,238,238,238,115,115,115,115,238, -238,115,115,238,238,238,238,238,238,238,238,238,238,238,238,238, -238,238,238,238,238,238,238,238,238,115,238,238,238,238,238,238, -238,115,238,238,115,238,238,115,238,238,115,115,236,115,237,237, -237,236,236,115,115,115,115,236,236,115,115,236,236,236,115,115, -115,236,115,115,115,115,115,115,115,238,238,238,238,115,238,115, -115,115,115,115,115,115,239,239,239,239,239,239,239,239,239,239, -236,236,238,238,238,236,115,115,115,115,115,115,115,115,115,115, +115,253,253,254,115,255,255,255,255,255,255,115,115,115,115,255, +255,115,115,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,115,255,255,255,255,255,255, +255,115,255,255,115,255,255,115,255,255,115,115,253,115,254,254, +254,253,253,115,115,115,115,253,253,115,115,253,253,253,115,115, +115,253,115,115,115,115,115,115,115,255,255,255,255,115,255,115, +115,115,115,115,115,115,256,256,256,256,256,256,256,256,256,256, +253,253,255,255,255,253,115,115,115,115,115,115,115,115,115,115, /* block 21 */ -115,240,240,241,115,242,242,242,242,242,242,242,242,242,115,242, -242,242,115,242,242,242,242,242,242,242,242,242,242,242,242,242, -242,242,242,242,242,242,242,242,242,115,242,242,242,242,242,242, -242,115,242,242,115,242,242,242,242,242,115,115,240,242,241,241, -241,240,240,240,240,240,115,240,240,241,115,241,241,240,115,115, -242,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, -242,242,240,240,115,115,243,243,243,243,243,243,243,243,243,243, -244,245,115,115,115,115,115,115,115,242,115,115,115,115,115,115, +115,257,257,258,115,259,259,259,259,259,259,259,259,259,115,259, +259,259,115,259,259,259,259,259,259,259,259,259,259,259,259,259, +259,259,259,259,259,259,259,259,259,115,259,259,259,259,259,259, +259,115,259,259,115,259,259,259,259,259,115,115,257,259,258,258, +258,257,257,257,257,257,115,257,257,258,115,258,258,257,115,115, +259,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, +259,259,257,257,115,115,260,260,260,260,260,260,260,260,260,260, +261,262,115,115,115,115,115,115,115,259,257,257,257,257,257,257, /* block 22 */ -115,246,247,247,115,248,248,248,248,248,248,248,248,115,115,248, -248,115,115,248,248,248,248,248,248,248,248,248,248,248,248,248, -248,248,248,248,248,248,248,248,248,115,248,248,248,248,248,248, -248,115,248,248,115,248,248,248,248,248,115,115,246,248,249,246, -247,246,246,246,246,115,115,247,247,115,115,247,247,246,115,115, -115,115,115,115,115,115,246,249,115,115,115,115,248,248,115,248, -248,248,246,246,115,115,250,250,250,250,250,250,250,250,250,250, -251,248,252,252,252,252,252,252,115,115,115,115,115,115,115,115, +115,263,264,264,115,265,265,265,265,265,265,265,265,115,115,265, +265,115,115,265,265,265,265,265,265,265,265,265,265,265,265,265, +265,265,265,265,265,265,265,265,265,115,265,265,265,265,265,265, +265,115,265,265,115,265,265,265,265,265,115,115,263,265,266,263, +264,263,263,263,263,115,115,264,264,115,115,264,264,263,115,115, +115,115,115,115,115,115,263,266,115,115,115,115,265,265,115,265, +265,265,263,263,115,115,267,267,267,267,267,267,267,267,267,267, +268,265,269,269,269,269,269,269,115,115,115,115,115,115,115,115, /* block 23 */ -115,115,253,254,115,254,254,254,254,254,254,115,115,115,254,254, -254,115,254,254,254,254,115,115,115,254,254,115,254,115,254,254, -115,115,115,254,254,115,115,115,254,254,254,115,115,115,254,254, -254,254,254,254,254,254,254,254,254,254,115,115,115,115,255,256, -253,256,256,115,115,115,256,256,256,115,256,256,256,253,115,115, -254,115,115,115,115,115,115,255,115,115,115,115,115,115,115,115, -115,115,115,115,115,115,257,257,257,257,257,257,257,257,257,257, -258,258,258,259,259,259,259,259,259,260,259,115,115,115,115,115, +115,115,270,271,115,271,271,271,271,271,271,115,115,115,271,271, +271,115,271,271,271,271,115,115,115,271,271,115,271,115,271,271, +115,115,115,271,271,115,115,115,271,271,271,115,115,115,271,271, +271,271,271,271,271,271,271,271,271,271,115,115,115,115,272,273, +270,273,273,115,115,115,273,273,273,115,273,273,273,270,115,115, +271,115,115,115,115,115,115,272,115,115,115,115,115,115,115,115, +115,115,115,115,115,115,274,274,274,274,274,274,274,274,274,274, +275,275,275,276,276,276,276,276,276,277,276,115,115,115,115,115, /* block 24 */ -261,262,262,262,115,263,263,263,263,263,263,263,263,115,263,263, -263,115,263,263,263,263,263,263,263,263,263,263,263,263,263,263, -263,263,263,263,263,263,263,263,263,115,263,263,263,263,263,263, -263,263,263,263,263,263,263,263,263,263,115,115,115,263,261,261, -261,262,262,262,262,115,261,261,261,115,261,261,261,261,115,115, -115,115,115,115,115,261,261,115,263,263,263,115,115,115,115,115, -263,263,261,261,115,115,264,264,264,264,264,264,264,264,264,264, -115,115,115,115,115,115,115,115,265,265,265,265,265,265,265,266, +278,279,279,279,115,280,280,280,280,280,280,280,280,115,280,280, +280,115,280,280,280,280,280,280,280,280,280,280,280,280,280,280, +280,280,280,280,280,280,280,280,280,115,280,280,280,280,280,280, +280,280,280,280,280,280,280,280,280,280,115,115,115,280,278,278, +278,279,279,279,279,115,278,278,278,115,278,278,278,278,115,115, +115,115,115,115,115,278,278,115,280,280,280,115,115,115,115,115, +280,280,278,278,115,115,281,281,281,281,281,281,281,281,281,281, +115,115,115,115,115,115,115,115,282,282,282,282,282,282,282,283, /* block 25 */ -115,267,268,268,115,269,269,269,269,269,269,269,269,115,269,269, -269,115,269,269,269,269,269,269,269,269,269,269,269,269,269,269, -269,269,269,269,269,269,269,269,269,115,269,269,269,269,269,269, -269,269,269,269,115,269,269,269,269,269,115,115,267,269,268,267, -268,268,270,268,268,115,267,268,268,115,268,268,267,267,115,115, -115,115,115,115,115,270,270,115,115,115,115,115,115,115,269,115, -269,269,267,267,115,115,271,271,271,271,271,271,271,271,271,271, -115,269,269,115,115,115,115,115,115,115,115,115,115,115,115,115, +284,285,286,286,115,284,284,284,284,284,284,284,284,115,284,284, +284,115,284,284,284,284,284,284,284,284,284,284,284,284,284,284, +284,284,284,284,284,284,284,284,284,115,284,284,284,284,284,284, +284,284,284,284,115,284,284,284,284,284,115,115,285,284,286,285, +286,286,287,286,286,115,285,286,286,115,286,286,285,285,115,115, +115,115,115,115,115,287,287,115,115,115,115,115,115,115,284,115, +284,284,285,285,115,115,288,288,288,288,288,288,288,288,288,288, +115,284,284,115,115,115,115,115,115,115,115,115,115,115,115,115, /* block 26 */ -115,272,273,273,115,274,274,274,274,274,274,274,274,115,274,274, -274,115,274,274,274,274,274,274,274,274,274,274,274,274,274,274, -274,274,274,274,274,274,274,274,274,274,274,274,274,274,274,274, -274,274,274,274,274,274,274,274,274,274,274,115,115,274,275,273, -273,272,272,272,272,115,273,273,273,115,273,273,273,272,274,115, -115,115,115,115,115,115,115,275,115,115,115,115,115,115,115,274, -274,274,272,272,115,115,276,276,276,276,276,276,276,276,276,276, -277,277,277,277,277,277,115,115,115,278,274,274,274,274,274,274, +289,289,290,290,115,291,291,291,291,291,291,291,291,115,291,291, +291,115,291,291,291,291,291,291,291,291,291,291,291,291,291,291, +291,291,291,291,291,291,291,291,291,291,291,291,291,291,291,291, +291,291,291,291,291,291,291,291,291,291,291,289,289,291,292,290, +290,289,289,289,289,115,290,290,290,115,290,290,290,289,293,294, +115,115,115,115,291,291,291,292,295,295,295,295,295,295,295,291, +291,291,289,289,115,115,296,296,296,296,296,296,296,296,296,296, +295,295,295,295,295,295,295,295,295,294,291,291,291,291,291,291, /* block 27 */ -115,115,279,279,115,280,280,280,280,280,280,280,280,280,280,280, -280,280,280,280,280,280,280,115,115,115,280,280,280,280,280,280, -280,280,280,280,280,280,280,280,280,280,280,280,280,280,280,280, -280,280,115,280,280,280,280,280,280,280,280,280,115,280,115,115, -280,280,280,280,280,280,280,115,115,115,281,115,115,115,115,282, -279,279,281,281,281,115,281,115,279,279,279,279,279,279,279,282, -115,115,115,115,115,115,283,283,283,283,283,283,283,283,283,283, -115,115,279,279,284,115,115,115,115,115,115,115,115,115,115,115, +115,115,297,297,115,298,298,298,298,298,298,298,298,298,298,298, +298,298,298,298,298,298,298,115,115,115,298,298,298,298,298,298, +298,298,298,298,298,298,298,298,298,298,298,298,298,298,298,298, +298,298,115,298,298,298,298,298,298,298,298,298,115,298,115,115, +298,298,298,298,298,298,298,115,115,115,299,115,115,115,115,300, +297,297,299,299,299,115,299,115,297,297,297,297,297,297,297,300, +115,115,115,115,115,115,301,301,301,301,301,301,301,301,301,301, +115,115,297,297,302,115,115,115,115,115,115,115,115,115,115,115, /* block 28 */ -115,285,285,285,285,285,285,285,285,285,285,285,285,285,285,285, -285,285,285,285,285,285,285,285,285,285,285,285,285,285,285,285, -285,285,285,285,285,285,285,285,285,285,285,285,285,285,285,285, -285,286,285,287,286,286,286,286,286,286,286,115,115,115,115, 5, -285,285,285,285,285,285,288,286,286,286,286,286,286,286,286,289, -290,290,290,290,290,290,290,290,290,290,289,289,115,115,115,115, +115,303,303,303,303,303,303,303,303,303,303,303,303,303,303,303, +303,303,303,303,303,303,303,303,303,303,303,303,303,303,303,303, +303,303,303,303,303,303,303,303,303,303,303,303,303,303,303,303, +303,304,303,305,304,304,304,304,304,304,304,115,115,115,115, 5, +303,303,303,303,303,303,306,304,304,304,304,304,304,304,304,307, +308,308,308,308,308,308,308,308,308,308,307,307,115,115,115,115, 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, /* block 29 */ -115,291,291,115,291,115,115,291,291,115,291,115,115,291,115,115, -115,115,115,115,291,291,291,291,115,291,291,291,291,291,291,291, -115,291,291,291,115,291,115,291,115,115,291,291,115,291,291,291, -291,292,291,293,292,292,292,292,292,292,115,292,292,291,115,115, -291,291,291,291,291,115,294,115,292,292,292,292,292,292,115,115, -295,295,295,295,295,295,295,295,295,295,115,115,291,291,291,291, +115,309,309,115,309,115,115,309,309,115,309,115,115,309,115,115, +115,115,115,115,309,309,309,309,115,309,309,309,309,309,309,309, +115,309,309,309,115,309,115,309,115,115,309,309,115,309,309,309, +309,310,309,311,310,310,310,310,310,310,115,310,310,309,115,115, +309,309,309,309,309,115,312,115,310,310,310,310,310,310,115,115, +313,313,313,313,313,313,313,313,313,313,115,115,309,309,309,309, 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, /* block 30 */ -296,297,297,297,298,298,298,298,298,298,298,298,298,298,298,298, -298,298,298,297,298,297,297,297,299,299,297,297,297,297,297,297, -300,300,300,300,300,300,300,300,300,300,301,301,301,301,301,301, -301,301,301,301,297,299,297,299,297,299,302,303,302,303,304,304, -296,296,296,296,296,296,296,296,115,296,296,296,296,296,296,296, -296,296,296,296,296,296,296,296,296,296,296,296,296,296,296,296, -296,296,296,296,296,296,296,296,296,296,296,296,296,115,115,115, -115,299,299,299,299,299,299,299,299,299,299,299,299,299,299,304, +314,315,315,315,316,316,316,316,316,316,316,316,316,316,316,316, +316,316,316,315,316,315,315,315,317,317,315,315,315,315,315,315, +318,318,318,318,318,318,318,318,318,318,319,319,319,319,319,319, +319,319,319,319,315,317,315,317,315,317,320,321,320,321,322,322, +314,314,314,314,314,314,314,314,115,314,314,314,314,314,314,314, +314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,314, +314,314,314,314,314,314,314,314,314,314,314,314,314,115,115,115, +115,317,317,317,317,317,317,317,317,317,317,317,317,317,317,322, /* block 31 */ -299,299,299,299,299,298,299,299,296,296,296,296,296,299,299,299, -299,299,299,299,299,299,299,299,115,299,299,299,299,299,299,299, -299,299,299,299,299,299,299,299,299,299,299,299,299,299,299,299, -299,299,299,299,299,299,299,299,299,299,299,299,299,115,297,297, -297,297,297,297,297,297,299,297,297,297,297,297,297,115,297,297, -298,298,298,298,298, 19, 19, 19, 19,298,298,115,115,115,115,115, +317,317,317,317,317,316,317,317,314,314,314,314,314,317,317,317, +317,317,317,317,317,317,317,317,115,317,317,317,317,317,317,317, +317,317,317,317,317,317,317,317,317,317,317,317,317,317,317,317, +317,317,317,317,317,317,317,317,317,317,317,317,317,115,315,315, +315,315,315,315,315,315,317,315,315,315,315,315,315,115,315,315, +316,316,316,316,316, 19, 19, 19, 19,316,316,115,115,115,115,115, 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, /* block 32 */ -305,305,305,305,305,305,305,305,305,305,305,305,305,305,305,305, -305,305,305,305,305,305,305,305,305,305,305,305,305,305,305,305, -305,305,305,305,305,305,305,305,305,305,305,306,306,307,307,307, -307,308,307,307,307,307,307,307,306,307,307,308,308,307,307,305, -309,309,309,309,309,309,309,309,309,309,310,310,310,310,310,310, -305,305,305,305,305,305,308,308,307,307,305,305,305,305,307,307, -307,305,306,306,306,305,305,306,306,306,306,306,306,306,305,305, -305,307,307,307,307,305,305,305,305,305,305,305,305,305,305,305, +323,323,323,323,323,323,323,323,323,323,323,323,323,323,323,323, +323,323,323,323,323,323,323,323,323,323,323,323,323,323,323,323, +323,323,323,323,323,323,323,323,323,323,323,324,324,325,325,325, +325,326,325,325,325,325,325,325,324,325,325,326,326,325,325,323, +327,327,327,327,327,327,327,327,327,327,328,328,328,328,328,328, +323,323,323,323,323,323,326,326,325,325,323,323,323,323,325,325, +325,323,324,324,324,323,323,324,324,324,324,324,324,324,323,323, +323,325,325,325,325,323,323,323,323,323,323,323,323,323,323,323, /* block 33 */ -305,305,307,306,308,307,307,306,306,306,306,306,306,307,305,306, -309,309,309,309,309,309,309,309,309,309,306,306,306,307,311,311, -312,312,312,312,312,312,312,312,312,312,312,312,312,312,312,312, -312,312,312,312,312,312,312,312,312,312,312,312,312,312,312,312, -312,312,312,312,312,312,115,312,115,115,115,115,115,312,115,115, -313,313,313,313,313,313,313,313,313,313,313,313,313,313,313,313, -313,313,313,313,313,313,313,313,313,313,313,313,313,313,313,313, -313,313,313,313,313,313,313,313,313,313,313, 4,314,313,313,313, +323,323,325,324,326,325,325,324,324,324,324,324,324,325,323,324, +327,327,327,327,327,327,327,327,327,327,324,324,324,325,329,329, +330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330, +330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330, +330,330,330,330,330,330,115,330,115,115,115,115,115,330,115,115, +331,331,331,331,331,331,331,331,331,331,331,331,331,331,331,331, +331,331,331,331,331,331,331,331,331,331,331,331,331,331,331,331, +331,331,331,331,331,331,331,331,331,331,331, 4,332,331,331,331, /* block 34 */ -315,315,315,315,315,315,315,315,315,315,315,315,315,315,315,315, -315,315,315,315,315,315,315,315,315,315,315,315,315,315,315,315, -315,315,315,315,315,315,315,315,315,315,315,315,315,315,315,315, -315,315,315,315,315,315,315,315,315,315,315,315,315,315,315,315, -315,315,315,315,315,315,315,315,315,315,315,315,315,315,315,315, -315,315,315,315,315,315,315,315,315,315,315,315,315,315,315,315, -316,316,316,316,316,316,316,316,316,316,316,316,316,316,316,316, -316,316,316,316,316,316,316,316,316,316,316,316,316,316,316,316, +333,333,333,333,333,333,333,333,333,333,333,333,333,333,333,333, +333,333,333,333,333,333,333,333,333,333,333,333,333,333,333,333, +333,333,333,333,333,333,333,333,333,333,333,333,333,333,333,333, +333,333,333,333,333,333,333,333,333,333,333,333,333,333,333,333, +333,333,333,333,333,333,333,333,333,333,333,333,333,333,333,333, +333,333,333,333,333,333,333,333,333,333,333,333,333,333,333,333, +334,334,334,334,334,334,334,334,334,334,334,334,334,334,334,334, +334,334,334,334,334,334,334,334,334,334,334,334,334,334,334,334, /* block 35 */ -316,316,316,316,316,316,316,316,316,316,316,316,316,316,316,316, -316,316,316,316,316,316,316,316,316,316,316,316,316,316,316,316, -316,316,316,316,316,316,316,316,317,317,317,317,317,317,317,317, -317,317,317,317,317,317,317,317,317,317,317,317,317,317,317,317, -317,317,317,317,317,317,317,317,317,317,317,317,317,317,317,317, -317,317,317,317,317,317,317,317,317,317,317,317,317,317,317,317, -317,317,317,317,317,317,317,317,317,317,317,317,317,317,317,317, -317,317,317,317,317,317,317,317,317,317,317,317,317,317,317,317, +334,334,334,334,334,334,334,334,334,334,334,334,334,334,334,334, +334,334,334,334,334,334,334,334,334,334,334,334,334,334,334,334, +334,334,334,334,334,334,334,334,335,335,335,335,335,335,335,335, +335,335,335,335,335,335,335,335,335,335,335,335,335,335,335,335, +335,335,335,335,335,335,335,335,335,335,335,335,335,335,335,335, +335,335,335,335,335,335,335,335,335,335,335,335,335,335,335,335, +335,335,335,335,335,335,335,335,335,335,335,335,335,335,335,335, +335,335,335,335,335,335,335,335,335,335,335,335,335,335,335,335, /* block 36 */ -318,318,318,318,318,318,318,318,318,318,318,318,318,318,318,318, -318,318,318,318,318,318,318,318,318,318,318,318,318,318,318,318, -318,318,318,318,318,318,318,318,318,318,318,318,318,318,318,318, -318,318,318,318,318,318,318,318,318,318,318,318,318,318,318,318, -318,318,318,318,318,318,318,318,318,115,318,318,318,318,115,115, -318,318,318,318,318,318,318,115,318,115,318,318,318,318,115,115, -318,318,318,318,318,318,318,318,318,318,318,318,318,318,318,318, -318,318,318,318,318,318,318,318,318,318,318,318,318,318,318,318, +336,336,336,336,336,336,336,336,336,336,336,336,336,336,336,336, +336,336,336,336,336,336,336,336,336,336,336,336,336,336,336,336, +336,336,336,336,336,336,336,336,336,336,336,336,336,336,336,336, +336,336,336,336,336,336,336,336,336,336,336,336,336,336,336,336, +336,336,336,336,336,336,336,336,336,115,336,336,336,336,115,115, +336,336,336,336,336,336,336,115,336,115,336,336,336,336,115,115, +336,336,336,336,336,336,336,336,336,336,336,336,336,336,336,336, +336,336,336,336,336,336,336,336,336,336,336,336,336,336,336,336, /* block 37 */ -318,318,318,318,318,318,318,318,318,115,318,318,318,318,115,115, -318,318,318,318,318,318,318,318,318,318,318,318,318,318,318,318, -318,318,318,318,318,318,318,318,318,318,318,318,318,318,318,318, -318,115,318,318,318,318,115,115,318,318,318,318,318,318,318,115, -318,115,318,318,318,318,115,115,318,318,318,318,318,318,318,318, -318,318,318,318,318,318,318,115,318,318,318,318,318,318,318,318, -318,318,318,318,318,318,318,318,318,318,318,318,318,318,318,318, -318,318,318,318,318,318,318,318,318,318,318,318,318,318,318,318, +336,336,336,336,336,336,336,336,336,115,336,336,336,336,115,115, +336,336,336,336,336,336,336,336,336,336,336,336,336,336,336,336, +336,336,336,336,336,336,336,336,336,336,336,336,336,336,336,336, +336,115,336,336,336,336,115,115,336,336,336,336,336,336,336,115, +336,115,336,336,336,336,115,115,336,336,336,336,336,336,336,336, +336,336,336,336,336,336,336,115,336,336,336,336,336,336,336,336, +336,336,336,336,336,336,336,336,336,336,336,336,336,336,336,336, +336,336,336,336,336,336,336,336,336,336,336,336,336,336,336,336, /* block 38 */ -318,318,318,318,318,318,318,318,318,318,318,318,318,318,318,318, -318,115,318,318,318,318,115,115,318,318,318,318,318,318,318,318, -318,318,318,318,318,318,318,318,318,318,318,318,318,318,318,318, -318,318,318,318,318,318,318,318,318,318,318,318,318,318,318,318, -318,318,318,318,318,318,318,318,318,318,318,318,318,318,318,318, -318,318,318,318,318,318,318,318,318,318,318,115,115,319,319,319, -320,320,320,320,320,320,320,320,320,321,321,321,321,321,321,321, -321,321,321,321,321,321,321,321,321,321,321,321,321,115,115,115, +336,336,336,336,336,336,336,336,336,336,336,336,336,336,336,336, +336,115,336,336,336,336,115,115,336,336,336,336,336,336,336,336, +336,336,336,336,336,336,336,336,336,336,336,336,336,336,336,336, +336,336,336,336,336,336,336,336,336,336,336,336,336,336,336,336, +336,336,336,336,336,336,336,336,336,336,336,336,336,336,336,336, +336,336,336,336,336,336,336,336,336,336,336,115,115,337,337,337, +338,338,338,338,338,338,338,338,338,339,339,339,339,339,339,339, +339,339,339,339,339,339,339,339,339,339,339,339,339,115,115,115, /* block 39 */ -318,318,318,318,318,318,318,318,318,318,318,318,318,318,318,318, -322,322,322,322,322,322,322,322,322,322,115,115,115,115,115,115, -323,323,323,323,323,323,323,323,323,323,323,323,323,323,323,323, -323,323,323,323,323,323,323,323,323,323,323,323,323,323,323,323, -323,323,323,323,323,323,323,323,323,323,323,323,323,323,323,323, -323,323,323,323,323,323,323,323,323,323,323,323,323,323,323,323, -323,323,323,323,323,323,323,323,323,323,323,323,323,323,323,323, -324,324,324,324,324,324,115,115,325,325,325,325,325,325,115,115, +336,336,336,336,336,336,336,336,336,336,336,336,336,336,336,336, +340,340,340,340,340,340,340,340,340,340,115,115,115,115,115,115, +341,341,341,341,341,341,341,341,341,341,341,341,341,341,341,341, +341,341,341,341,341,341,341,341,341,341,341,341,341,341,341,341, +341,341,341,341,341,341,341,341,341,341,341,341,341,341,341,341, +341,341,341,341,341,341,341,341,341,341,341,341,341,341,341,341, +341,341,341,341,341,341,341,341,341,341,341,341,341,341,341,341, +342,342,342,342,342,342,115,115,343,343,343,343,343,343,115,115, /* block 40 */ -326,327,327,327,327,327,327,327,327,327,327,327,327,327,327,327, -327,327,327,327,327,327,327,327,327,327,327,327,327,327,327,327, -327,327,327,327,327,327,327,327,327,327,327,327,327,327,327,327, -327,327,327,327,327,327,327,327,327,327,327,327,327,327,327,327, -327,327,327,327,327,327,327,327,327,327,327,327,327,327,327,327, -327,327,327,327,327,327,327,327,327,327,327,327,327,327,327,327, -327,327,327,327,327,327,327,327,327,327,327,327,327,327,327,327, -327,327,327,327,327,327,327,327,327,327,327,327,327,327,327,327, +344,345,345,345,345,345,345,345,345,345,345,345,345,345,345,345, +345,345,345,345,345,345,345,345,345,345,345,345,345,345,345,345, +345,345,345,345,345,345,345,345,345,345,345,345,345,345,345,345, +345,345,345,345,345,345,345,345,345,345,345,345,345,345,345,345, +345,345,345,345,345,345,345,345,345,345,345,345,345,345,345,345, +345,345,345,345,345,345,345,345,345,345,345,345,345,345,345,345, +345,345,345,345,345,345,345,345,345,345,345,345,345,345,345,345, +345,345,345,345,345,345,345,345,345,345,345,345,345,345,345,345, /* block 41 */ -327,327,327,327,327,327,327,327,327,327,327,327,327,327,327,327, -327,327,327,327,327,327,327,327,327,327,327,327,327,327,327,327, -327,327,327,327,327,327,327,327,327,327,327,327,327,327,327,327, -327,327,327,327,327,327,327,327,327,327,327,327,327,327,327,327, -327,327,327,327,327,327,327,327,327,327,327,327,327,327,327,327, -327,327,327,327,327,327,327,327,327,327,327,327,327,327,327,327, -327,327,327,327,327,327,327,327,327,327,327,327,327,327,327,327, -327,327,327,327,327,327,327,327,327,327,327,327,327,327,327,327, +345,345,345,345,345,345,345,345,345,345,345,345,345,345,345,345, +345,345,345,345,345,345,345,345,345,345,345,345,345,345,345,345, +345,345,345,345,345,345,345,345,345,345,345,345,345,345,345,345, +345,345,345,345,345,345,345,345,345,345,345,345,345,345,345,345, +345,345,345,345,345,345,345,345,345,345,345,345,345,345,345,345, +345,345,345,345,345,345,345,345,345,345,345,345,345,345,345,345, +345,345,345,345,345,345,345,345,345,345,345,345,345,345,345,345, +345,345,345,345,345,345,345,345,345,345,345,345,345,345,345,345, /* block 42 */ -327,327,327,327,327,327,327,327,327,327,327,327,327,327,327,327, -327,327,327,327,327,327,327,327,327,327,327,327,327,327,327,327, -327,327,327,327,327,327,327,327,327,327,327,327,327,327,327,327, -327,327,327,327,327,327,327,327,327,327,327,327,327,327,327,327, -327,327,327,327,327,327,327,327,327,327,327,327,327,327,327,327, -327,327,327,327,327,327,327,327,327,327,327,327,327,327,327,327, -327,327,327,327,327,327,327,327,327,327,327,327,327,328,328,327, -327,327,327,327,327,327,327,327,327,327,327,327,327,327,327,327, +345,345,345,345,345,345,345,345,345,345,345,345,345,345,345,345, +345,345,345,345,345,345,345,345,345,345,345,345,345,345,345,345, +345,345,345,345,345,345,345,345,345,345,345,345,345,345,345,345, +345,345,345,345,345,345,345,345,345,345,345,345,345,345,345,345, +345,345,345,345,345,345,345,345,345,345,345,345,345,345,345,345, +345,345,345,345,345,345,345,345,345,345,345,345,345,345,345,345, +345,345,345,345,345,345,345,345,345,345,345,345,345,346,346,345, +345,345,345,345,345,345,345,345,345,345,345,345,345,345,345,345, /* block 43 */ -329,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330, -330,330,330,330,330,330,330,330,330,330,330,331,332,115,115,115, -333,333,333,333,333,333,333,333,333,333,333,333,333,333,333,333, -333,333,333,333,333,333,333,333,333,333,333,333,333,333,333,333, -333,333,333,333,333,333,333,333,333,333,333,333,333,333,333,333, -333,333,333,333,333,333,333,333,333,333,333,333,333,333,333,333, -333,333,333,333,333,333,333,333,333,333,333, 4, 4, 4,334,334, -334,333,333,333,333,333,333,333,333,115,115,115,115,115,115,115, +347,348,348,348,348,348,348,348,348,348,348,348,348,348,348,348, +348,348,348,348,348,348,348,348,348,348,348,349,350,115,115,115, +351,351,351,351,351,351,351,351,351,351,351,351,351,351,351,351, +351,351,351,351,351,351,351,351,351,351,351,351,351,351,351,351, +351,351,351,351,351,351,351,351,351,351,351,351,351,351,351,351, +351,351,351,351,351,351,351,351,351,351,351,351,351,351,351,351, +351,351,351,351,351,351,351,351,351,351,351, 4, 4, 4,352,352, +352,351,351,351,351,351,351,351,351,115,115,115,115,115,115,115, /* block 44 */ -335,335,335,335,335,335,335,335,335,335,335,335,335,115,335,335, -335,335,336,336,336,115,115,115,115,115,115,115,115,115,115,115, -337,337,337,337,337,337,337,337,337,337,337,337,337,337,337,337, -337,337,338,338,338, 4, 4,115,115,115,115,115,115,115,115,115, -339,339,339,339,339,339,339,339,339,339,339,339,339,339,339,339, -339,339,340,340,115,115,115,115,115,115,115,115,115,115,115,115, -341,341,341,341,341,341,341,341,341,341,341,341,341,115,341,341, -341,115,342,342,115,115,115,115,115,115,115,115,115,115,115,115, +353,353,353,353,353,353,353,353,353,353,353,353,353,115,353,353, +353,353,354,354,354,115,115,115,115,115,115,115,115,115,115,115, +355,355,355,355,355,355,355,355,355,355,355,355,355,355,355,355, +355,355,356,356,356, 4, 4,115,115,115,115,115,115,115,115,115, +357,357,357,357,357,357,357,357,357,357,357,357,357,357,357,357, +357,357,358,358,115,115,115,115,115,115,115,115,115,115,115,115, +359,359,359,359,359,359,359,359,359,359,359,359,359,115,359,359, +359,115,360,360,115,115,115,115,115,115,115,115,115,115,115,115, /* block 45 */ -343,343,343,343,343,343,343,343,343,343,343,343,343,343,343,343, -343,343,343,343,343,343,343,343,343,343,343,343,343,343,343,343, -343,343,343,343,343,343,343,343,343,343,343,343,343,343,343,343, -343,343,343,343,344,344,345,344,344,344,344,344,344,344,345,345, -345,345,345,345,345,345,344,345,345,344,344,344,344,344,344,344, -344,344,344,344,346,346,346,347,346,346,346,348,343,344,115,115, -349,349,349,349,349,349,349,349,349,349,115,115,115,115,115,115, -350,350,350,350,350,350,350,350,350,350,115,115,115,115,115,115, +361,361,361,361,361,361,361,361,361,361,361,361,361,361,361,361, +361,361,361,361,361,361,361,361,361,361,361,361,361,361,361,361, +361,361,361,361,361,361,361,361,361,361,361,361,361,361,361,361, +361,361,361,361,362,362,363,362,362,362,362,362,362,362,363,363, +363,363,363,363,363,363,362,363,363,362,362,362,362,362,362,362, +362,362,362,362,364,364,364,365,364,364,364,366,361,362,115,115, +367,367,367,367,367,367,367,367,367,367,115,115,115,115,115,115, +368,368,368,368,368,368,368,368,368,368,115,115,115,115,115,115, /* block 46 */ -351,351, 4, 4,351, 4,352,351,351,351,351,353,353,353,354,115, -355,355,355,355,355,355,355,355,355,355,115,115,115,115,115,115, -356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356, -356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356, -356,356,356,357,356,356,356,356,356,356,356,356,356,356,356,356, -356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356, -356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356, -356,356,356,356,356,356,356,356,115,115,115,115,115,115,115,115, +369,369, 4, 4,369, 4,370,369,369,369,369,371,371,371,372,115, +373,373,373,373,373,373,373,373,373,373,115,115,115,115,115,115, +374,374,374,374,374,374,374,374,374,374,374,374,374,374,374,374, +374,374,374,374,374,374,374,374,374,374,374,374,374,374,374,374, +374,374,374,375,374,374,374,374,374,374,374,374,374,374,374,374, +374,374,374,374,374,374,374,374,374,374,374,374,374,374,374,374, +374,374,374,374,374,374,374,374,374,374,374,374,374,374,374,374, +374,374,374,374,374,374,374,374,115,115,115,115,115,115,115,115, /* block 47 */ -356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356, -356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356, -356,356,356,356,356,356,356,356,356,353,356,115,115,115,115,115, -327,327,327,327,327,327,327,327,327,327,327,327,327,327,327,327, -327,327,327,327,327,327,327,327,327,327,327,327,327,327,327,327, -327,327,327,327,327,327,327,327,327,327,327,327,327,327,327,327, -327,327,327,327,327,327,327,327,327,327,327,327,327,327,327,327, -327,327,327,327,327,327,115,115,115,115,115,115,115,115,115,115, +374,374,374,374,374,371,371,374,374,374,374,374,374,374,374,374, +374,374,374,374,374,374,374,374,374,374,374,374,374,374,374,374, +374,374,374,374,374,374,374,374,374,371,374,115,115,115,115,115, +345,345,345,345,345,345,345,345,345,345,345,345,345,345,345,345, +345,345,345,345,345,345,345,345,345,345,345,345,345,345,345,345, +345,345,345,345,345,345,345,345,345,345,345,345,345,345,345,345, +345,345,345,345,345,345,345,345,345,345,345,345,345,345,345,345, +345,345,345,345,345,345,115,115,115,115,115,115,115,115,115,115, /* block 48 */ -358,358,358,358,358,358,358,358,358,358,358,358,358,358,358,358, -358,358,358,358,358,358,358,358,358,358,358,358,358,358,358,115, -359,359,359,360,360,360,360,359,359,360,360,360,115,115,115,115, -360,360,359,360,360,360,360,360,360,359,359,359,115,115,115,115, -361,115,115,115,362,362,363,363,363,363,363,363,363,363,363,363, -364,364,364,364,364,364,364,364,364,364,364,364,364,364,364,364, -364,364,364,364,364,364,364,364,364,364,364,364,364,364,115,115, -364,364,364,364,364,115,115,115,115,115,115,115,115,115,115,115, +376,376,376,376,376,376,376,376,376,376,376,376,376,376,376,376, +376,376,376,376,376,376,376,376,376,376,376,376,376,376,376,115, +377,377,377,378,378,378,378,377,377,378,378,378,115,115,115,115, +378,378,377,378,378,378,378,378,378,377,377,377,115,115,115,115, +379,115,115,115,380,380,381,381,381,381,381,381,381,381,381,381, +382,382,382,382,382,382,382,382,382,382,382,382,382,382,382,382, +382,382,382,382,382,382,382,382,382,382,382,382,382,382,115,115, +382,382,382,382,382,115,115,115,115,115,115,115,115,115,115,115, /* block 49 */ -365,365,365,365,365,365,365,365,365,365,365,365,365,365,365,365, -365,365,365,365,365,365,365,365,365,365,365,365,365,365,365,365, -365,365,365,365,365,365,365,365,365,365,365,365,115,115,115,115, -365,365,365,365,365,365,365,365,365,365,365,365,365,365,365,365, -365,365,365,365,365,365,365,365,365,365,115,115,115,115,115,115, -366,366,366,366,366,366,366,366,366,366,367,115,115,115,368,368, -369,369,369,369,369,369,369,369,369,369,369,369,369,369,369,369, -369,369,369,369,369,369,369,369,369,369,369,369,369,369,369,369, +383,383,383,383,383,383,383,383,383,383,383,383,383,383,383,383, +383,383,383,383,383,383,383,383,383,383,383,383,383,383,383,383, +383,383,383,383,383,383,383,383,383,383,383,383,115,115,115,115, +383,383,383,383,383,383,383,383,383,383,383,383,383,383,383,383, +383,383,383,383,383,383,383,383,383,383,115,115,115,115,115,115, +384,384,384,384,384,384,384,384,384,384,385,115,115,115,386,386, +387,387,387,387,387,387,387,387,387,387,387,387,387,387,387,387, +387,387,387,387,387,387,387,387,387,387,387,387,387,387,387,387, /* block 50 */ -370,370,370,370,370,370,370,370,370,370,370,370,370,370,370,370, -370,370,370,370,370,370,370,371,371,372,372,371,115,115,373,373, -374,374,374,374,374,374,374,374,374,374,374,374,374,374,374,374, -374,374,374,374,374,374,374,374,374,374,374,374,374,374,374,374, -374,374,374,374,374,374,374,374,374,374,374,374,374,374,374,374, -374,374,374,374,374,375,376,375,376,376,376,376,376,376,376,115, -376,377,376,377,377,376,376,376,376,376,376,376,376,375,375,375, -375,375,375,376,376,376,376,376,376,376,376,376,376,115,115,376, +388,388,388,388,388,388,388,388,388,388,388,388,388,388,388,388, +388,388,388,388,388,388,388,389,389,390,390,389,115,115,391,391, +392,392,392,392,392,392,392,392,392,392,392,392,392,392,392,392, +392,392,392,392,392,392,392,392,392,392,392,392,392,392,392,392, +392,392,392,392,392,392,392,392,392,392,392,392,392,392,392,392, +392,392,392,392,392,393,394,393,394,394,394,394,394,394,394,115, +394,395,394,395,395,394,394,394,394,394,394,394,394,393,393,393, +393,393,393,394,394,394,394,394,394,394,394,394,394,115,115,394, /* block 51 */ -378,378,378,378,378,378,378,378,378,378,115,115,115,115,115,115, -378,378,378,378,378,378,378,378,378,378,115,115,115,115,115,115, -379,379,379,379,379,379,379,380,379,379,379,379,379,379,115,115, -110,110,110,110,110,110,110,110,110,110,110,110,110,110,381,115, +396,396,396,396,396,396,396,396,396,396,115,115,115,115,115,115, +396,396,396,396,396,396,396,396,396,396,115,115,115,115,115,115, +397,397,397,397,397,397,397,398,397,397,397,397,397,397,115,115, +110,110,110,110,110,110,110,110,110,110,110,110,110,110,399,115, 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, /* block 52 */ -382,382,382,382,383,384,384,384,384,384,384,384,384,384,384,384, -384,384,384,384,384,384,384,384,384,384,384,384,384,384,384,384, -384,384,384,384,384,384,384,384,384,384,384,384,384,384,384,384, -384,384,384,384,382,383,382,382,382,382,382,383,382,383,383,383, -383,383,382,383,383,384,384,384,384,384,384,384,115,115,115,115, -385,385,385,385,385,385,385,385,385,385,386,386,386,386,386,386, -386,387,387,387,387,387,387,387,387,387,387,382,382,382,382,382, -382,382,382,382,387,387,387,387,387,387,387,387,387,115,115,115, +400,400,400,400,401,402,402,402,402,402,402,402,402,402,402,402, +402,402,402,402,402,402,402,402,402,402,402,402,402,402,402,402, +402,402,402,402,402,402,402,402,402,402,402,402,402,402,402,402, +402,402,402,402,400,401,400,400,400,400,400,401,400,401,401,401, +401,401,400,401,401,402,402,402,402,402,402,402,115,115,115,115, +403,403,403,403,403,403,403,403,403,403,404,404,404,404,404,404, +404,405,405,405,405,405,405,405,405,405,405,400,400,400,400,400, +400,400,400,400,405,405,405,405,405,405,405,405,405,115,115,115, /* block 53 */ -388,388,389,390,390,390,390,390,390,390,390,390,390,390,390,390, -390,390,390,390,390,390,390,390,390,390,390,390,390,390,390,390, -390,389,388,388,388,388,389,389,388,388,389,388,388,388,390,390, -391,391,391,391,391,391,391,391,391,391,390,390,390,390,390,390, -392,392,392,392,392,392,392,392,392,392,392,392,392,392,392,392, -392,392,392,392,392,392,392,392,392,392,392,392,392,392,392,392, -392,392,392,392,392,392,393,394,393,393,394,394,394,393,394,393, -393,393,394,394,115,115,115,115,115,115,115,115,395,395,395,395, +406,406,407,408,408,408,408,408,408,408,408,408,408,408,408,408, +408,408,408,408,408,408,408,408,408,408,408,408,408,408,408,408, +408,407,406,406,406,406,407,407,406,406,407,406,406,406,408,408, +409,409,409,409,409,409,409,409,409,409,408,408,408,408,408,408, +410,410,410,410,410,410,410,410,410,410,410,410,410,410,410,410, +410,410,410,410,410,410,410,410,410,410,410,410,410,410,410,410, +410,410,410,410,410,410,411,412,411,411,412,412,412,411,412,411, +411,411,412,412,115,115,115,115,115,115,115,115,413,413,413,413, /* block 54 */ -396,396,396,396,396,396,396,396,396,396,396,396,396,396,396,396, -396,396,396,396,396,396,396,396,396,396,396,396,396,396,396,396, -396,396,396,396,397,397,397,397,397,397,397,397,398,398,398,398, -398,398,398,398,397,397,398,398,115,115,115,399,399,399,399,399, -400,400,400,400,400,400,400,400,400,400,115,115,115,396,396,396, -401,401,401,401,401,401,401,401,401,401,402,402,402,402,402,402, -402,402,402,402,402,402,402,402,402,402,402,402,402,402,402,402, -402,402,402,402,402,402,402,402,403,403,403,403,403,403,404,404, +414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,414, +414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,414, +414,414,414,414,415,415,415,415,415,415,415,415,416,416,416,416, +416,416,416,416,415,415,416,416,115,115,115,417,417,417,417,417, +418,418,418,418,418,418,418,418,418,418,115,115,115,414,414,414, +419,419,419,419,419,419,419,419,419,419,420,420,420,420,420,420, +420,420,420,420,420,420,420,420,420,420,420,420,420,420,420,420, +420,420,420,420,420,420,420,420,421,421,421,421,421,421,422,422, /* block 55 */ +423,424,425,426,427,428,429,430,431,115,115,115,115,115,115,115, 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, -115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, -405,405,405,405,405,405,405,405,115,115,115,115,115,115,115,115, +432,432,432,432,432,432,432,432,115,115,115,115,115,115,115,115, 110,110,110, 4,110,110,110,110,110,110,110,110,110,110,110,110, -110,406,110,110,110,110,110,110,110,407,407,407,407,110,407,407, -407,407,406,406,110,407,407,115,110,110,115,115,115,115,115,115, +110,433,110,110,110,110,110,110,110,434,434,434,434,110,434,434, +434,434,433,433,110,434,434,433,110,110,115,115,115,115,115,115, /* block 56 */ 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, - 33, 33, 33, 33, 33, 33,123,123,123,123,123,408,107,107,107,107, + 33, 33, 33, 33, 33, 33,123,123,123,123,123,435,107,107,107,107, 107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,107, 107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,107, 107,107,107,107,107,107,107,107,107,107,107,107,107,116,116,116, 116,116,107,107,107,107,116,116,116,116,116, 33, 33, 33, 33, 33, - 33, 33, 33, 33, 33, 33, 33, 33,409,410, 33, 33, 33,411, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33,436,437, 33, 33, 33,438, 33, 33, /* block 57 */ 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, @@ -1955,7 +2054,7 @@ const uint16_t PRIV(ucd_stage2)[] = { /* 60416 bytes, block = 128 */ 110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110, 110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110, 110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110, -110,110,110,110,110,110,115,115,115,115,115,115,110,110,110,110, +110,110,110,110,110,110,110,110,110,110,115,110,110,110,110,110, /* block 58 */ 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, @@ -1964,12 +2063,12 @@ const uint16_t PRIV(ucd_stage2)[] = { /* 60416 bytes, block = 128 */ 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, -412,413, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, +439,440, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, /* block 59 */ 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, - 30, 31, 30, 31, 30, 31, 33, 33, 33, 33, 33,414, 33, 33,415, 33, + 30, 31, 30, 31, 30, 31, 33, 33, 33, 33, 33,441, 33, 33,442, 33, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, @@ -1978,57 +2077,57 @@ const uint16_t PRIV(ucd_stage2)[] = { /* 60416 bytes, block = 128 */ 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, /* block 60 */ -416,416,416,416,416,416,416,416,417,417,417,417,417,417,417,417, -416,416,416,416,416,416,115,115,417,417,417,417,417,417,115,115, -416,416,416,416,416,416,416,416,417,417,417,417,417,417,417,417, -416,416,416,416,416,416,416,416,417,417,417,417,417,417,417,417, -416,416,416,416,416,416,115,115,417,417,417,417,417,417,115,115, -123,416,123,416,123,416,123,416,115,417,115,417,115,417,115,417, -416,416,416,416,416,416,416,416,417,417,417,417,417,417,417,417, -418,418,419,419,419,419,420,420,421,421,422,422,423,423,115,115, +443,443,443,443,443,443,443,443,444,444,444,444,444,444,444,444, +443,443,443,443,443,443,115,115,444,444,444,444,444,444,115,115, +443,443,443,443,443,443,443,443,444,444,444,444,444,444,444,444, +443,443,443,443,443,443,443,443,444,444,444,444,444,444,444,444, +443,443,443,443,443,443,115,115,444,444,444,444,444,444,115,115, +123,443,123,443,123,443,123,443,115,444,115,444,115,444,115,444, +443,443,443,443,443,443,443,443,444,444,444,444,444,444,444,444, +445,445,446,446,446,446,447,447,448,448,449,449,450,450,115,115, /* block 61 */ -416,416,416,416,416,416,416,416,424,424,424,424,424,424,424,424, -416,416,416,416,416,416,416,416,424,424,424,424,424,424,424,424, -416,416,416,416,416,416,416,416,424,424,424,424,424,424,424,424, -416,416,123,425,123,115,123,123,417,417,426,426,427,114,428,114, -114,114,123,425,123,115,123,123,429,429,429,429,427,114,114,114, -416,416,123,123,115,115,123,123,417,417,430,430,115,114,114,114, -416,416,123,123,123,164,123,123,417,417,431,431,169,114,114,114, -115,115,123,425,123,115,123,123,432,432,433,433,427,114,114,115, +443,443,443,443,443,443,443,443,451,451,451,451,451,451,451,451, +443,443,443,443,443,443,443,443,451,451,451,451,451,451,451,451, +443,443,443,443,443,443,443,443,451,451,451,451,451,451,451,451, +443,443,123,452,123,115,123,123,444,444,453,453,454,114,455,114, +114,114,123,452,123,115,123,123,456,456,456,456,454,114,114,114, +443,443,123,123,115,115,123,123,444,444,457,457,115,114,114,114, +443,443,123,123,123,164,123,123,444,444,458,458,169,114,114,114, +115,115,123,452,123,115,123,123,459,459,460,460,454,114,114,115, /* block 62 */ - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 22,434,434, 22, 22, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 22,461,462, 22, 22, 9, 9, 9, 9, 9, 9, 4, 4, 21, 25, 6, 21, 21, 25, 6, 21, - 4, 4, 4, 4, 4, 4, 4, 4,435,436, 22, 22, 22, 22, 22, 3, + 4, 4, 4, 4, 4, 4, 4, 4,463,464, 22, 22, 22, 22, 22, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 21, 25, 4, 4, 4, 4, 15, 15, 4, 4, 4, 8, 6, 7, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 8, 4, 15, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 3, - 22, 22, 22, 22, 22,437, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22,465, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23,107,115,115, 23, 23, 23, 23, 23, 23, 8, 8, 8, 6, 7,107, /* block 63 */ 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 8, 8, 8, 6, 7,115, 107,107,107,107,107,107,107,107,107,107,107,107,107,115,115,115, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,115, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, -110,110,110,110,110,110,110,110,110,110,110,110,110,381,381,381, -381,110,381,381,381,110,110,110,110,110,110,110,110,110,110,110, +110,110,110,110,110,110,110,110,110,110,110,110,110,399,399,399, +399,110,399,399,399,110,110,110,110,110,110,110,110,110,110,110, 110,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, /* block 64 */ - 19, 19,438, 19, 19, 19, 19,438, 19, 19,439,438,438,438,439,439, -438,438,438,439, 19,438, 19, 19, 8,438,438,438,438,438, 19, 19, - 19, 19, 19, 19,438, 19,440, 19,438, 19,441,442,438,438, 19,439, -438,438,443,438,439,407,407,407,407,439, 19, 19,439,439,438,438, - 8, 8, 8, 8, 8,438,439,439,439,439, 19, 8, 19, 19,444, 19, + 19, 19,466, 19, 19, 19, 19,466, 19, 19,467,466,466,466,467,467, +466,466,466,467, 19,466, 19, 19, 8,466,466,466,466,466, 19, 19, + 19, 19, 19, 19,466, 19,468, 19,466, 19,469,470,466,466, 19,467, +466,466,471,466,467,434,434,434,434,467, 19, 19,467,467,466,466, + 8, 8, 8, 8, 8,466,467,467,467,467, 19, 8, 19, 19,472, 19, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, -445,445,445,445,445,445,445,445,445,445,445,445,445,445,445,445, -446,446,446,446,446,446,446,446,446,446,446,446,446,446,446,446, +473,473,473,473,473,473,473,473,473,473,473,473,473,473,473,473, +474,474,474,474,474,474,474,474,474,474,474,474,474,474,474,474, /* block 65 */ -447,447,447, 30, 31,447,447,447,447, 23, 19, 19,115,115,115,115, +475,475,475, 30, 31,475,475,475,475, 23, 19, 19,115,115,115,115, 8, 8, 8, 8, 8, 19, 19, 19, 19, 19, 8, 8, 19, 19, 19, 19, 8, 19, 19, 8, 19, 19, 8, 19, 19, 19, 19, 19, 19, 19, 8, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, @@ -2065,7 +2164,7 @@ const uint16_t PRIV(ucd_stage2)[] = { /* 60416 bytes, block = 128 */ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 8, 8, 8, 8, 8, 8, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,115,115,115,115,115, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, /* block 69 */ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, @@ -2081,10 +2180,10 @@ const uint16_t PRIV(ucd_stage2)[] = { /* 60416 bytes, block = 128 */ 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19,448,448,448,448,448,448,448,448,448,448, -448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448, -449,449,449,449,449,449,449,449,449,449,449,449,449,449,449,449, -449,449,449,449,449,449,449,449,449,449, 23, 23, 23, 23, 23, 23, + 19, 19, 19, 19, 19, 19,476,476,476,476,476,476,476,476,476,476, +476,476,476,476,476,476,476,476,476,476,476,476,476,476,476,476, +477,477,477,477,477,477,477,477,477,477,477,477,477,477,477,477, +477,477,477,477,477,477,477,477,477,477, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, /* block 71 */ @@ -2109,25 +2208,35 @@ const uint16_t PRIV(ucd_stage2)[] = { /* 60416 bytes, block = 128 */ /* block 73 */ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,478, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, +479, 19,479, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 8, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, /* block 74 */ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19,479,479, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, 6, 7, 6, 7, 6, 7, 6, 7, - 6, 7, 6, 7, 6, 7, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 19, 19, 19, 19, 19, 19, 19, 19, 19,478, 19, 19, 19, 19, 19, 19, /* block 75 */ + 19, 19, 19, 19, 19, 19, 19, 19,479, 19,478,478,478,478, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19,479, 19, 19, 19, 6, 7, 6, 7, 6, 7, 6, 7, + 6, 7, 6, 7, 6, 7, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + +/* block 76 */ 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, @@ -2137,17 +2246,17 @@ const uint16_t PRIV(ucd_stage2)[] = { /* 60416 bytes, block = 128 */ 8, 8, 8, 8, 8, 8, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, -/* block 76 */ -450,450,450,450,450,450,450,450,450,450,450,450,450,450,450,450, -450,450,450,450,450,450,450,450,450,450,450,450,450,450,450,450, -450,450,450,450,450,450,450,450,450,450,450,450,450,450,450,450, -450,450,450,450,450,450,450,450,450,450,450,450,450,450,450,450, -450,450,450,450,450,450,450,450,450,450,450,450,450,450,450,450, -450,450,450,450,450,450,450,450,450,450,450,450,450,450,450,450, -450,450,450,450,450,450,450,450,450,450,450,450,450,450,450,450, -450,450,450,450,450,450,450,450,450,450,450,450,450,450,450,450, - /* block 77 */ +480,480,480,480,480,480,480,480,480,480,480,480,480,480,480,480, +480,480,480,480,480,480,480,480,480,480,480,480,480,480,480,480, +480,480,480,480,480,480,480,480,480,480,480,480,480,480,480,480, +480,480,480,480,480,480,480,480,480,480,480,480,480,480,480,480, +480,480,480,480,480,480,480,480,480,480,480,480,480,480,480,480, +480,480,480,480,480,480,480,480,480,480,480,480,480,480,480,480, +480,480,480,480,480,480,480,480,480,480,480,480,480,480,480,480, +480,480,480,480,480,480,480,480,480,480,480,480,480,480,480,480, + +/* block 78 */ 8, 8, 8, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, @@ -2157,7 +2266,7 @@ const uint16_t PRIV(ucd_stage2)[] = { /* 60416 bytes, block = 128 */ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 6, 7, 8, 8, -/* block 78 */ +/* block 79 */ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, @@ -2167,257 +2276,257 @@ const uint16_t PRIV(ucd_stage2)[] = { /* 60416 bytes, block = 128 */ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,115,115, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, -/* block 79 */ +/* block 80 */ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,115,115, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,115,115,115, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,115, 19, 19, 19, 19, 19, 19, - 19, 19,115,115,115,115,115,115,115,115,115,115,115,115,115,115, + 19, 19, 19,115,115,115,115,115,115,115,115,115,115,115,115,115, 115,115,115,115,115,115,115,115,115,115,115,115, 19, 19, 19, 19, 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, -/* block 80 */ -451,451,451,451,451,451,451,451,451,451,451,451,451,451,451,451, -451,451,451,451,451,451,451,451,451,451,451,451,451,451,451,451, -451,451,451,451,451,451,451,451,451,451,451,451,451,451,451,115, -452,452,452,452,452,452,452,452,452,452,452,452,452,452,452,452, -452,452,452,452,452,452,452,452,452,452,452,452,452,452,452,452, -452,452,452,452,452,452,452,452,452,452,452,452,452,452,452,115, - 30, 31,453,454,455,456,457, 30, 31, 30, 31, 30, 31,458,459,460, -461, 33, 30, 31, 33, 30, 31, 33, 33, 33, 33, 33,107,107,462,462, - /* block 81 */ +481,481,481,481,481,481,481,481,481,481,481,481,481,481,481,481, +481,481,481,481,481,481,481,481,481,481,481,481,481,481,481,481, +481,481,481,481,481,481,481,481,481,481,481,481,481,481,481,115, +482,482,482,482,482,482,482,482,482,482,482,482,482,482,482,482, +482,482,482,482,482,482,482,482,482,482,482,482,482,482,482,482, +482,482,482,482,482,482,482,482,482,482,482,482,482,482,482,115, + 30, 31,483,484,485,486,487, 30, 31, 30, 31, 30, 31,488,489,490, +491, 33, 30, 31, 33, 30, 31, 33, 33, 33, 33, 33,107,107,492,492, + +/* block 82 */ 160,161,160,161,160,161,160,161,160,161,160,161,160,161,160,161, 160,161,160,161,160,161,160,161,160,161,160,161,160,161,160,161, 160,161,160,161,160,161,160,161,160,161,160,161,160,161,160,161, 160,161,160,161,160,161,160,161,160,161,160,161,160,161,160,161, 160,161,160,161,160,161,160,161,160,161,160,161,160,161,160,161, 160,161,160,161,160,161,160,161,160,161,160,161,160,161,160,161, -160,161,160,161,463,464,464,464,464,464,464,160,161,160,161,465, -465,465,160,161,115,115,115,115,115,466,466,466,466,467,466,466, - -/* block 82 */ -468,468,468,468,468,468,468,468,468,468,468,468,468,468,468,468, -468,468,468,468,468,468,468,468,468,468,468,468,468,468,468,468, -468,468,468,468,468,468,115,468,115,115,115,115,115,468,115,115, -469,469,469,469,469,469,469,469,469,469,469,469,469,469,469,469, -469,469,469,469,469,469,469,469,469,469,469,469,469,469,469,469, -469,469,469,469,469,469,469,469,469,469,469,469,469,469,469,469, -469,469,469,469,469,469,469,469,115,115,115,115,115,115,115,470, -471,115,115,115,115,115,115,115,115,115,115,115,115,115,115,472, +160,161,160,161,493,494,494,494,494,494,494,160,161,160,161,495, +495,495,160,161,115,115,115,115,115,496,496,496,496,497,496,496, /* block 83 */ -318,318,318,318,318,318,318,318,318,318,318,318,318,318,318,318, -318,318,318,318,318,318,318,115,115,115,115,115,115,115,115,115, -318,318,318,318,318,318,318,115,318,318,318,318,318,318,318,115, -318,318,318,318,318,318,318,115,318,318,318,318,318,318,318,115, -318,318,318,318,318,318,318,115,318,318,318,318,318,318,318,115, -318,318,318,318,318,318,318,115,318,318,318,318,318,318,318,115, -178,178,178,178,178,178,178,178,178,178,178,178,178,178,178,178, -178,178,178,178,178,178,178,178,178,178,178,178,178,178,178,178, +498,498,498,498,498,498,498,498,498,498,498,498,498,498,498,498, +498,498,498,498,498,498,498,498,498,498,498,498,498,498,498,498, +498,498,498,498,498,498,115,498,115,115,115,115,115,498,115,115, +499,499,499,499,499,499,499,499,499,499,499,499,499,499,499,499, +499,499,499,499,499,499,499,499,499,499,499,499,499,499,499,499, +499,499,499,499,499,499,499,499,499,499,499,499,499,499,499,499, +499,499,499,499,499,499,499,499,115,115,115,115,115,115,115,500, +501,115,115,115,115,115,115,115,115,115,115,115,115,115,115,502, /* block 84 */ +336,336,336,336,336,336,336,336,336,336,336,336,336,336,336,336, +336,336,336,336,336,336,336,115,115,115,115,115,115,115,115,115, +336,336,336,336,336,336,336,115,336,336,336,336,336,336,336,115, +336,336,336,336,336,336,336,115,336,336,336,336,336,336,336,115, +336,336,336,336,336,336,336,115,336,336,336,336,336,336,336,115, +336,336,336,336,336,336,336,115,336,336,336,336,336,336,336,115, +192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192, +192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192, + +/* block 85 */ 4, 4, 21, 25, 21, 25, 4, 4, 4, 21, 25, 4, 21, 25, 4, 4, 4, 4, 4, 4, 4, 4, 4, 9, 4, 4, 9, 4, 21, 25, 4, 4, 21, 25, 6, 7, 6, 7, 6, 7, 6, 7, 4, 4, 4, 4, 4,108, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 9, 9, 4, 4, 4, 4, - 9, 4, 6,115,115,115,115,115,115,115,115,115,115,115,115,115, + 9, 4, 6, 4, 4, 4, 4, 4, 4, 4,115,115,115,115,115,115, 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, -/* block 85 */ -473,473,473,473,473,473,473,473,473,473,473,473,473,473,473,473, -473,473,473,473,473,473,473,473,473,473,115,473,473,473,473,473, -473,473,473,473,473,473,473,473,473,473,473,473,473,473,473,473, -473,473,473,473,473,473,473,473,473,473,473,473,473,473,473,473, -473,473,473,473,473,473,473,473,473,473,473,473,473,473,473,473, -473,473,473,473,473,473,473,473,473,473,473,473,473,473,473,473, -473,473,473,473,473,473,473,473,473,473,473,473,473,473,473,473, -473,473,473,473,115,115,115,115,115,115,115,115,115,115,115,115, - /* block 86 */ -473,473,473,473,473,473,473,473,473,473,473,473,473,473,473,473, -473,473,473,473,473,473,473,473,473,473,473,473,473,473,473,473, -473,473,473,473,473,473,473,473,473,473,473,473,473,473,473,473, -473,473,473,473,473,473,473,473,473,473,473,473,473,473,473,473, -473,473,473,473,473,473,473,473,473,473,473,473,473,473,473,473, -473,473,473,473,473,473,473,473,473,473,473,473,473,473,473,473, -473,473,473,473,473,473,473,473,473,473,473,473,473,473,473,473, -473,473,473,473,473,473,473,473,473,473,473,473,473,473,473,473, +503,503,503,503,503,503,503,503,503,503,503,503,503,503,503,503, +503,503,503,503,503,503,503,503,503,503,115,503,503,503,503,503, +503,503,503,503,503,503,503,503,503,503,503,503,503,503,503,503, +503,503,503,503,503,503,503,503,503,503,503,503,503,503,503,503, +503,503,503,503,503,503,503,503,503,503,503,503,503,503,503,503, +503,503,503,503,503,503,503,503,503,503,503,503,503,503,503,503, +503,503,503,503,503,503,503,503,503,503,503,503,503,503,503,503, +503,503,503,503,115,115,115,115,115,115,115,115,115,115,115,115, /* block 87 */ -473,473,473,473,473,473,473,473,473,473,473,473,473,473,473,473, -473,473,473,473,473,473,473,473,473,473,473,473,473,473,473,473, -473,473,473,473,473,473,473,473,473,473,473,473,473,473,473,473, -473,473,473,473,473,473,473,473,473,473,473,473,473,473,473,473, -473,473,473,473,473,473,473,473,473,473,473,473,473,473,473,473, -473,473,473,473,473,473,115,115,115,115,115,115,115,115,115,115, -115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, - 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,115,115,115,115, +503,503,503,503,503,503,503,503,503,503,503,503,503,503,503,503, +503,503,503,503,503,503,503,503,503,503,503,503,503,503,503,503, +503,503,503,503,503,503,503,503,503,503,503,503,503,503,503,503, +503,503,503,503,503,503,503,503,503,503,503,503,503,503,503,503, +503,503,503,503,503,503,503,503,503,503,503,503,503,503,503,503, +503,503,503,503,503,503,503,503,503,503,503,503,503,503,503,503, +503,503,503,503,503,503,503,503,503,503,503,503,503,503,503,503, +503,503,503,503,503,503,503,503,503,503,503,503,503,503,503,503, /* block 88 */ - 3, 4, 4, 4, 19,474,407,475, 6, 7, 6, 7, 6, 7, 6, 7, - 6, 7, 19, 19, 6, 7, 6, 7, 6, 7, 6, 7, 9, 6, 7, 7, - 19,475,475,475,475,475,475,475,475,475,110,110,110,110,476,476, - 9,108,108,108,108,108, 19, 19,475,475,475,474,407, 4, 19, 19, -115,477,477,477,477,477,477,477,477,477,477,477,477,477,477,477, -477,477,477,477,477,477,477,477,477,477,477,477,477,477,477,477, -477,477,477,477,477,477,477,477,477,477,477,477,477,477,477,477, -477,477,477,477,477,477,477,477,477,477,477,477,477,477,477,477, +503,503,503,503,503,503,503,503,503,503,503,503,503,503,503,503, +503,503,503,503,503,503,503,503,503,503,503,503,503,503,503,503, +503,503,503,503,503,503,503,503,503,503,503,503,503,503,503,503, +503,503,503,503,503,503,503,503,503,503,503,503,503,503,503,503, +503,503,503,503,503,503,503,503,503,503,503,503,503,503,503,503, +503,503,503,503,503,503,115,115,115,115,115,115,115,115,115,115, +115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,115,115,115,115, /* block 89 */ -477,477,477,477,477,477,477,477,477,477,477,477,477,477,477,477, -477,477,477,477,477,477,477,115,115,110,110, 14, 14,478,478,477, - 9,479,479,479,479,479,479,479,479,479,479,479,479,479,479,479, -479,479,479,479,479,479,479,479,479,479,479,479,479,479,479,479, -479,479,479,479,479,479,479,479,479,479,479,479,479,479,479,479, -479,479,479,479,479,479,479,479,479,479,479,479,479,479,479,479, -479,479,479,479,479,479,479,479,479,479,479,479,479,479,479,479, -479,479,479,479,479,479,479,479,479,479,479, 4,108,480,480,479, + 3, 4, 4, 4, 19,504,434,505, 6, 7, 6, 7, 6, 7, 6, 7, + 6, 7, 19, 19, 6, 7, 6, 7, 6, 7, 6, 7, 9, 6, 7, 7, + 19,505,505,505,505,505,505,505,505,505,110,110,110,110,506,506, + 9,108,108,108,108,108, 19, 19,505,505,505,504,434, 4, 19, 19, +115,507,507,507,507,507,507,507,507,507,507,507,507,507,507,507, +507,507,507,507,507,507,507,507,507,507,507,507,507,507,507,507, +507,507,507,507,507,507,507,507,507,507,507,507,507,507,507,507, +507,507,507,507,507,507,507,507,507,507,507,507,507,507,507,507, /* block 90 */ -115,115,115,115,115,481,481,481,481,481,481,481,481,481,481,481, -481,481,481,481,481,481,481,481,481,481,481,481,481,481,481,481, -481,481,481,481,481,481,481,481,481,481,481,481,481,481,115,115, -115,482,482,482,482,482,482,482,482,482,482,482,482,482,482,482, -482,482,482,482,482,482,482,482,482,482,482,482,482,482,482,482, -482,482,482,482,482,482,482,482,482,482,482,482,482,482,482,482, -482,482,482,482,482,482,482,482,482,482,482,482,482,482,482,482, -482,482,482,482,482,482,482,482,482,482,482,482,482,482,482,482, +507,507,507,507,507,507,507,507,507,507,507,507,507,507,507,507, +507,507,507,507,507,507,507,115,115,110,110, 14, 14,508,508,507, + 9,509,509,509,509,509,509,509,509,509,509,509,509,509,509,509, +509,509,509,509,509,509,509,509,509,509,509,509,509,509,509,509, +509,509,509,509,509,509,509,509,509,509,509,509,509,509,509,509, +509,509,509,509,509,509,509,509,509,509,509,509,509,509,509,509, +509,509,509,509,509,509,509,509,509,509,509,509,509,509,509,509, +509,509,509,509,509,509,509,509,509,509,509, 4,108,510,510,509, /* block 91 */ -482,482,482,482,482,482,482,482,482,482,482,482,482,482,482,115, +115,115,115,115,115,511,511,511,511,511,511,511,511,511,511,511, +511,511,511,511,511,511,511,511,511,511,511,511,511,511,511,511, +511,511,511,511,511,511,511,511,511,511,511,511,511,511,511,115, +115,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512, +512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512, +512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512, +512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512, +512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512, + +/* block 92 */ +512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,115, 19, 19, 23, 23, 23, 23, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, -481,481,481,481,481,481,481,481,481,481,481,481,481,481,481,481, -481,481,481,481,481,481,481,481,481,481,481,115,115,115,115,115, +511,511,511,511,511,511,511,511,511,511,511,511,511,511,511,511, +511,511,511,511,511,511,511,511,511,511,511,115,115,115,115,115, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,115,115,115,115,115,115,115,115,115,115,115,115, -479,479,479,479,479,479,479,479,479,479,479,479,479,479,479,479, +509,509,509,509,509,509,509,509,509,509,509,509,509,509,509,509, -/* block 92 */ -483,483,483,483,483,483,483,483,483,483,483,483,483,483,483,483, -483,483,483,483,483,483,483,483,483,483,483,483,483,483,483,115, +/* block 93 */ +513,513,513,513,513,513,513,513,513,513,513,513,513,513,513,513, +513,513,513,513,513,513,513,513,513,513,513,513,513,513,513,115, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 23, 23, 23, 23, 23, 23, 23, 23, 19, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, -483,483,483,483,483,483,483,483,483,483,483,483,483,483,483,483, -483,483,483,483,483,483,483,483,483,483,483,483,483,483,483, 19, +513,513,513,513,513,513,513,513,513,513,513,513,513,513,513,513, +513,513,513,513,513,513,513,513,513,513,513,513,513,513,513, 19, -/* block 93 */ +/* block 94 */ 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, -484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,484, -484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,484, -484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,115, +514,514,514,514,514,514,514,514,514,514,514,514,514,514,514,514, +514,514,514,514,514,514,514,514,514,514,514,514,514,514,514,514, +514,514,514,514,514,514,514,514,514,514,514,514,514,514,514,115, -/* block 94 */ -484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,484, -484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,484, -484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,484, -484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,484, -484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,484, -484,484,484,484,484,484,484,484, 19, 19, 19, 19, 19, 19, 19, 19, +/* block 95 */ +514,514,514,514,514,514,514,514,514,514,514,514,514,514,514,514, +514,514,514,514,514,514,514,514,514,514,514,514,514,514,514,514, +514,514,514,514,514,514,514,514,514,514,514,514,514,514,514,514, +514,514,514,514,514,514,514,514,514,514,514,514,514,514,514,514, +514,514,514,514,514,514,514,514,514,514,514,514,514,514,514,514, +514,514,514,514,514,514,514,514, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, -/* block 95 */ -485,485,485,485,485,485,485,485,485,485,485,485,485,485,485,485, -485,485,485,485,485,485,485,485,485,485,485,485,485,485,485,485, -485,485,485,485,485,485,485,485,485,485,485,485,485,485,485,485, -485,485,485,485,485,485,485,485,485,485,485,485,485,485,485,485, -485,485,485,485,485,485,485,485,485,485,485,485,485,485,485,485, -485,485,485,485,485,485,485,485,485,485,485,485,485,485,485,485, -485,485,485,485,485,485,485,485,485,485,485,485,485,485,485,485, -485,485,485,485,485,485,485,485,485,485,485,485,485,485,485,485, - /* block 96 */ -485,485,485,485,485,485,485,485,485,485,485,485,485,485,485,485, -485,485,485,485,485,485,485,485,485,485,485,485,485,485,485,485, -485,485,485,485,485,485,485,485,485,485,485,485,485,485,485,485, -485,485,485,485,485,485,115,115,115,115,115,115,115,115,115,115, +515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515, +515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515, +515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515, +515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515, +515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515, +515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515, +515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515, +515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515, + +/* block 97 */ +515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515, +515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515, +515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515, +515,515,515,515,515,515,115,115,115,115,115,115,115,115,115,115, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, -/* block 97 */ -485,485,485,485,485,485,485,485,485,485,485,485,485,485,485,485, -485,485,485,485,485,485,485,485,485,485,485,485,485,485,485,485, -485,485,485,485,485,485,485,485,485,485,485,485,485,485,485,485, -485,485,485,485,485,485,485,485,485,485,485,485,485,485,485,485, -485,485,485,485,485,485,485,485,485,485,485,485,485,485,485,485, -485,485,485,485,485,485,115,115,115,115,115,115,115,115,115,115, -115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, -115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, - /* block 98 */ -486,486,486,486,486,486,486,486,486,486,486,486,486,486,486,486, -486,486,486,486,486,487,486,486,486,486,486,486,486,486,486,486, -486,486,486,486,486,486,486,486,486,486,486,486,486,486,486,486, -486,486,486,486,486,486,486,486,486,486,486,486,486,486,486,486, -486,486,486,486,486,486,486,486,486,486,486,486,486,486,486,486, -486,486,486,486,486,486,486,486,486,486,486,486,486,486,486,486, -486,486,486,486,486,486,486,486,486,486,486,486,486,486,486,486, -486,486,486,486,486,486,486,486,486,486,486,486,486,486,486,486, +515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515, +515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515, +515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515, +515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515, +515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515, +515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515, +515,515,515,515,515,515,515,515,515,515,515,115,115,115,115,115, +115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, /* block 99 */ -486,486,486,486,486,486,486,486,486,486,486,486,486,486,486,486, -486,486,486,486,486,486,486,486,486,486,486,486,486,486,486,486, -486,486,486,486,486,486,486,486,486,486,486,486,486,486,486,486, -486,486,486,486,486,486,486,486,486,486,486,486,486,486,486,486, -486,486,486,486,486,486,486,486,486,486,486,486,486,486,486,486, -486,486,486,486,486,486,486,486,486,486,486,486,486,486,486,486, -486,486,486,486,486,486,486,486,486,486,486,486,486,486,486,486, -486,486,486,486,486,486,486,486,486,486,486,486,486,486,486,486, +516,516,516,516,516,516,516,516,516,516,516,516,516,516,516,516, +516,516,516,516,516,517,516,516,516,516,516,516,516,516,516,516, +516,516,516,516,516,516,516,516,516,516,516,516,516,516,516,516, +516,516,516,516,516,516,516,516,516,516,516,516,516,516,516,516, +516,516,516,516,516,516,516,516,516,516,516,516,516,516,516,516, +516,516,516,516,516,516,516,516,516,516,516,516,516,516,516,516, +516,516,516,516,516,516,516,516,516,516,516,516,516,516,516,516, +516,516,516,516,516,516,516,516,516,516,516,516,516,516,516,516, /* block 100 */ -486,486,486,486,486,486,486,486,486,486,486,486,486,115,115,115, -488,488,488,488,488,488,488,488,488,488,488,488,488,488,488,488, -488,488,488,488,488,488,488,488,488,488,488,488,488,488,488,488, -488,488,488,488,488,488,488,488,488,488,488,488,488,488,488,488, -488,488,488,488,488,488,488,115,115,115,115,115,115,115,115,115, -489,489,489,489,489,489,489,489,489,489,489,489,489,489,489,489, -489,489,489,489,489,489,489,489,489,489,489,489,489,489,489,489, -489,489,489,489,489,489,489,489,490,490,490,490,490,490,491,491, +516,516,516,516,516,516,516,516,516,516,516,516,516,516,516,516, +516,516,516,516,516,516,516,516,516,516,516,516,516,516,516,516, +516,516,516,516,516,516,516,516,516,516,516,516,516,516,516,516, +516,516,516,516,516,516,516,516,516,516,516,516,516,516,516,516, +516,516,516,516,516,516,516,516,516,516,516,516,516,516,516,516, +516,516,516,516,516,516,516,516,516,516,516,516,516,516,516,516, +516,516,516,516,516,516,516,516,516,516,516,516,516,516,516,516, +516,516,516,516,516,516,516,516,516,516,516,516,516,516,516,516, /* block 101 */ -492,492,492,492,492,492,492,492,492,492,492,492,492,492,492,492, -492,492,492,492,492,492,492,492,492,492,492,492,492,492,492,492, -492,492,492,492,492,492,492,492,492,492,492,492,492,492,492,492, -492,492,492,492,492,492,492,492,492,492,492,492,492,492,492,492, -492,492,492,492,492,492,492,492,492,492,492,492,492,492,492,492, -492,492,492,492,492,492,492,492,492,492,492,492,492,492,492,492, -492,492,492,492,492,492,492,492,492,492,492,492,492,492,492,492, -492,492,492,492,492,492,492,492,492,492,492,492,492,492,492,492, +516,516,516,516,516,516,516,516,516,516,516,516,516,115,115,115, +518,518,518,518,518,518,518,518,518,518,518,518,518,518,518,518, +518,518,518,518,518,518,518,518,518,518,518,518,518,518,518,518, +518,518,518,518,518,518,518,518,518,518,518,518,518,518,518,518, +518,518,518,518,518,518,518,115,115,115,115,115,115,115,115,115, +519,519,519,519,519,519,519,519,519,519,519,519,519,519,519,519, +519,519,519,519,519,519,519,519,519,519,519,519,519,519,519,519, +519,519,519,519,519,519,519,519,520,520,520,520,520,520,521,521, /* block 102 */ -492,492,492,492,492,492,492,492,492,492,492,492,493,494,494,494, -492,492,492,492,492,492,492,492,492,492,492,492,492,492,492,492, -495,495,495,495,495,495,495,495,495,495,492,492,115,115,115,115, -115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, -175,176,175,176,175,176,175,176,175,176,175,176,175,176,175,176, -175,176,175,176,175,176,175,176,175,176,175,176,175,176,175,176, -175,176,175,176,175,176,175,176,175,176,175,176,175,176,496,178, -179,179,179,497,178,178,178,178,178,178,178,178,178,178,497,409, +522,522,522,522,522,522,522,522,522,522,522,522,522,522,522,522, +522,522,522,522,522,522,522,522,522,522,522,522,522,522,522,522, +522,522,522,522,522,522,522,522,522,522,522,522,522,522,522,522, +522,522,522,522,522,522,522,522,522,522,522,522,522,522,522,522, +522,522,522,522,522,522,522,522,522,522,522,522,522,522,522,522, +522,522,522,522,522,522,522,522,522,522,522,522,522,522,522,522, +522,522,522,522,522,522,522,522,522,522,522,522,522,522,522,522, +522,522,522,522,522,522,522,522,522,522,522,522,522,522,522,522, /* block 103 */ -175,176,175,176,175,176,175,176,175,176,175,176,175,176,175,176, -175,176,175,176,175,176,175,176,175,176,175,176,409,409,178,178, -498,498,498,498,498,498,498,498,498,498,498,498,498,498,498,498, -498,498,498,498,498,498,498,498,498,498,498,498,498,498,498,498, -498,498,498,498,498,498,498,498,498,498,498,498,498,498,498,498, -498,498,498,498,498,498,498,498,498,498,498,498,498,498,498,498, -498,498,498,498,498,498,499,499,499,499,499,499,499,499,499,499, -500,500,501,501,501,501,501,501,115,115,115,115,115,115,115,115, +522,522,522,522,522,522,522,522,522,522,522,522,523,524,524,524, +522,522,522,522,522,522,522,522,522,522,522,522,522,522,522,522, +525,525,525,525,525,525,525,525,525,525,522,522,115,115,115,115, +115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, +187,188,187,188,187,188,187,188,187,188,526,527,187,188,187,188, +187,188,187,188,187,188,187,188,187,188,187,188,187,188,187,188, +187,188,187,188,187,188,187,188,187,188,187,188,187,188,528,192, +193,193,193,529,192,192,192,192,192,192,192,192,192,192,529,436, /* block 104 */ +187,188,187,188,187,188,187,188,187,188,187,188,187,188,187,188, +187,188,187,188,187,188,187,188,187,188,187,188,436,436,192,192, +530,530,530,530,530,530,530,530,530,530,530,530,530,530,530,530, +530,530,530,530,530,530,530,530,530,530,530,530,530,530,530,530, +530,530,530,530,530,530,530,530,530,530,530,530,530,530,530,530, +530,530,530,530,530,530,530,530,530,530,530,530,530,530,530,530, +530,530,530,530,530,530,531,531,531,531,531,531,531,531,531,531, +532,532,533,533,533,533,533,533,115,115,115,115,115,115,115,115, + +/* block 105 */ 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,108,108,108,108,108,108,108,108,108, 14, 14, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, @@ -2425,349 +2534,349 @@ const uint16_t PRIV(ucd_stage2)[] = { /* 60416 bytes, block = 128 */ 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, -107, 33, 33, 33, 33, 33, 33, 33, 33, 30, 31, 30, 31,502, 30, 31, +107, 33, 33, 33, 33, 33, 33, 33, 33, 30, 31, 30, 31,534, 30, 31, -/* block 105 */ - 30, 31, 30, 31, 30, 31, 30, 31,108, 14, 14, 30, 31,503, 33, 20, +/* block 106 */ + 30, 31, 30, 31, 30, 31, 30, 31,108, 14, 14, 30, 31,535, 33, 20, 30, 31, 30, 31, 33, 33, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, - 30, 31, 30, 31, 30, 31, 30, 31, 30, 31,504,505,506,507,115,115, -508,509,510,511, 30, 31, 30, 31,115,115,115,115,115,115,115,115, + 30, 31, 30, 31, 30, 31, 30, 31, 30, 31,536,537,538,539,536,115, +540,541,542,543, 30, 31, 30, 31,115,115,115,115,115,115,115,115, 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, 115,115,115,115,115,115,115, 20,107,107, 33, 20, 20, 20, 20, 20, -/* block 106 */ -512,512,513,512,512,512,513,512,512,512,512,513,512,512,512,512, -512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512, -512,512,512,514,514,513,513,514,515,515,515,515,115,115,115,115, - 23, 23, 23, 23, 23, 23, 19, 19, 5, 19,115,115,115,115,115,115, -516,516,516,516,516,516,516,516,516,516,516,516,516,516,516,516, -516,516,516,516,516,516,516,516,516,516,516,516,516,516,516,516, -516,516,516,516,516,516,516,516,516,516,516,516,516,516,516,516, -516,516,516,516,517,517,517,517,115,115,115,115,115,115,115,115, - /* block 107 */ -518,518,519,519,519,519,519,519,519,519,519,519,519,519,519,519, -519,519,519,519,519,519,519,519,519,519,519,519,519,519,519,519, -519,519,519,519,519,519,519,519,519,519,519,519,519,519,519,519, -519,519,519,519,518,518,518,518,518,518,518,518,518,518,518,518, -518,518,518,518,520,115,115,115,115,115,115,115,115,115,521,521, -522,522,522,522,522,522,522,522,522,522,115,115,115,115,115,115, -222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222, -222,222,224,224,224,224,224,224,226,226,226,224,226,224,115,115, +544,544,545,544,544,544,545,544,544,544,544,545,544,544,544,544, +544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544, +544,544,544,546,546,545,545,546,547,547,547,547,115,115,115,115, + 23, 23, 23, 23, 23, 23, 19, 19, 5, 19,115,115,115,115,115,115, +548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548, +548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548, +548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548, +548,548,548,548,549,549,549,549,115,115,115,115,115,115,115,115, /* block 108 */ -523,523,523,523,523,523,523,523,523,523,524,524,524,524,524,524, -524,524,524,524,524,524,524,524,524,524,524,524,524,524,524,524, -524,524,524,524,524,524,525,525,525,525,525,525,525,525, 4,526, -527,527,527,527,527,527,527,527,527,527,527,527,527,527,527,527, -527,527,527,527,527,527,527,528,528,528,528,528,528,528,528,528, -528,528,529,529,115,115,115,115,115,115,115,115,115,115,115,530, -315,315,315,315,315,315,315,315,315,315,315,315,315,315,315,315, -315,315,315,315,315,315,315,315,315,315,315,315,315,115,115,115, +550,550,551,551,551,551,551,551,551,551,551,551,551,551,551,551, +551,551,551,551,551,551,551,551,551,551,551,551,551,551,551,551, +551,551,551,551,551,551,551,551,551,551,551,551,551,551,551,551, +551,551,551,551,550,550,550,550,550,550,550,550,550,550,550,550, +550,550,550,550,552,552,115,115,115,115,115,115,115,115,553,553, +554,554,554,554,554,554,554,554,554,554,115,115,115,115,115,115, +238,238,238,238,238,238,238,238,238,238,238,238,238,238,238,238, +238,238,240,240,240,240,240,240,242,242,242,240,242,240,115,115, /* block 109 */ -531,531,531,532,533,533,533,533,533,533,533,533,533,533,533,533, -533,533,533,533,533,533,533,533,533,533,533,533,533,533,533,533, -533,533,533,533,533,533,533,533,533,533,533,533,533,533,533,533, -533,533,533,531,532,532,531,531,531,531,532,532,531,532,532,532, -532,534,534,534,534,534,534,534,534,534,534,534,534,534,115,108, -535,535,535,535,535,535,535,535,535,535,115,115,115,115,534,534, -305,305,305,305,305,307,536,305,305,305,305,305,305,305,305,305, -309,309,309,309,309,309,309,309,309,309,305,305,305,305,305,115, +555,555,555,555,555,555,555,555,555,555,556,556,556,556,556,556, +556,556,556,556,556,556,556,556,556,556,556,556,556,556,556,556, +556,556,556,556,556,556,557,557,557,557,557,557,557,557, 4,558, +559,559,559,559,559,559,559,559,559,559,559,559,559,559,559,559, +559,559,559,559,559,559,559,560,560,560,560,560,560,560,560,560, +560,560,561,561,115,115,115,115,115,115,115,115,115,115,115,562, +333,333,333,333,333,333,333,333,333,333,333,333,333,333,333,333, +333,333,333,333,333,333,333,333,333,333,333,333,333,115,115,115, /* block 110 */ -537,537,537,537,537,537,537,537,537,537,537,537,537,537,537,537, -537,537,537,537,537,537,537,537,537,537,537,537,537,537,537,537, -537,537,537,537,537,537,537,537,537,538,538,538,538,538,538,539, -539,538,538,539,539,538,538,115,115,115,115,115,115,115,115,115, -537,537,537,538,537,537,537,537,537,537,537,537,538,539,115,115, -540,540,540,540,540,540,540,540,540,540,115,115,541,541,541,541, -305,305,305,305,305,305,305,305,305,305,305,305,305,305,305,305, -536,305,305,305,305,305,305,311,311,311,305,306,307,306,305,305, +563,563,563,564,565,565,565,565,565,565,565,565,565,565,565,565, +565,565,565,565,565,565,565,565,565,565,565,565,565,565,565,565, +565,565,565,565,565,565,565,565,565,565,565,565,565,565,565,565, +565,565,565,563,564,564,563,563,563,563,564,564,563,564,564,564, +564,566,566,566,566,566,566,566,566,566,566,566,566,566,115,108, +567,567,567,567,567,567,567,567,567,567,115,115,115,115,566,566, +323,323,323,323,323,325,568,323,323,323,323,323,323,323,323,323, +327,327,327,327,327,327,327,327,327,327,323,323,323,323,323,115, /* block 111 */ -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, -542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542, -543,542,543,543,543,542,542,543,543,542,542,542,542,542,543,543, -542,543,542,115,115,115,115,115,115,115,115,115,115,115,115,115, -115,115,115,115,115,115,115,115,115,115,115,542,542,544,545,545, -546,546,546,546,546,546,546,546,546,546,546,547,548,548,547,547, -549,549,546,550,550,547,548,115,115,115,115,115,115,115,115,115, +569,569,569,569,569,569,569,569,569,569,569,569,569,569,569,569, +569,569,569,569,569,569,569,569,569,569,569,569,569,569,569,569, +569,569,569,569,569,569,569,569,569,570,570,570,570,570,570,571, +571,570,570,571,571,570,570,115,115,115,115,115,115,115,115,115, +569,569,569,570,569,569,569,569,569,569,569,569,570,571,115,115, +572,572,572,572,572,572,572,572,572,572,115,115,573,573,573,573, +323,323,323,323,323,323,323,323,323,323,323,323,323,323,323,323, +568,323,323,323,323,323,323,329,329,329,323,324,325,324,323,323, /* block 112 */ -115,318,318,318,318,318,318,115,115,318,318,318,318,318,318,115, -115,318,318,318,318,318,318,115,115,115,115,115,115,115,115,115, -318,318,318,318,318,318,318,115,318,318,318,318,318,318,318,115, +574,574,574,574,574,574,574,574,574,574,574,574,574,574,574,574, +574,574,574,574,574,574,574,574,574,574,574,574,574,574,574,574, +574,574,574,574,574,574,574,574,574,574,574,574,574,574,574,574, +575,574,575,575,575,574,574,575,575,574,574,574,574,574,575,575, +574,575,574,115,115,115,115,115,115,115,115,115,115,115,115,115, +115,115,115,115,115,115,115,115,115,115,115,574,574,576,577,577, +578,578,578,578,578,578,578,578,578,578,578,579,580,580,579,579, +581,581,578,582,582,579,580,115,115,115,115,115,115,115,115,115, + +/* block 113 */ +115,336,336,336,336,336,336,115,115,336,336,336,336,336,336,115, +115,336,336,336,336,336,336,115,115,115,115,115,115,115,115,115, +336,336,336,336,336,336,336,115,336,336,336,336,336,336,336,115, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, - 33, 33, 33,551, 33, 33, 33, 33, 33, 33, 33, 14,107,107,107,107, + 33, 33, 33,583, 33, 33, 33, 33, 33, 33, 33, 14,107,107,107,107, 33, 33, 33, 33, 33,123,115,115,115,115,115,115,115,115,115,115, -552,552,552,552,552,552,552,552,552,552,552,552,552,552,552,552, - -/* block 113 */ -552,552,552,552,552,552,552,552,552,552,552,552,552,552,552,552, -552,552,552,552,552,552,552,552,552,552,552,552,552,552,552,552, -552,552,552,552,552,552,552,552,552,552,552,552,552,552,552,552, -552,552,552,552,552,552,552,552,552,552,552,552,552,552,552,552, -546,546,546,546,546,546,546,546,546,546,546,546,546,546,546,546, -546,546,546,546,546,546,546,546,546,546,546,546,546,546,546,546, -546,546,546,547,547,548,547,547,548,547,547,549,547,548,115,115, -553,553,553,553,553,553,553,553,553,553,115,115,115,115,115,115, +584,584,584,584,584,584,584,584,584,584,584,584,584,584,584,584, /* block 114 */ -554,555,555,555,555,555,555,555,555,555,555,555,555,555,555,555, -555,555,555,555,555,555,555,555,555,555,555,555,554,555,555,555, -555,555,555,555,555,555,555,555,555,555,555,555,555,555,555,555, -555,555,555,555,555,555,555,555,554,555,555,555,555,555,555,555, -555,555,555,555,555,555,555,555,555,555,555,555,555,555,555,555, -555,555,555,555,554,555,555,555,555,555,555,555,555,555,555,555, -555,555,555,555,555,555,555,555,555,555,555,555,555,555,555,555, -554,555,555,555,555,555,555,555,555,555,555,555,555,555,555,555, +584,584,584,584,584,584,584,584,584,584,584,584,584,584,584,584, +584,584,584,584,584,584,584,584,584,584,584,584,584,584,584,584, +584,584,584,584,584,584,584,584,584,584,584,584,584,584,584,584, +584,584,584,584,584,584,584,584,584,584,584,584,584,584,584,584, +578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,578, +578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,578, +578,578,578,579,579,580,579,579,580,579,579,581,579,580,115,115, +585,585,585,585,585,585,585,585,585,585,115,115,115,115,115,115, /* block 115 */ -555,555,555,555,555,555,555,555,555,555,555,555,554,555,555,555, -555,555,555,555,555,555,555,555,555,555,555,555,555,555,555,555, -555,555,555,555,555,555,555,555,554,555,555,555,555,555,555,555, -555,555,555,555,555,555,555,555,555,555,555,555,555,555,555,555, -555,555,555,555,554,555,555,555,555,555,555,555,555,555,555,555, -555,555,555,555,555,555,555,555,555,555,555,555,555,555,555,555, -554,555,555,555,555,555,555,555,555,555,555,555,555,555,555,555, -555,555,555,555,555,555,555,555,555,555,555,555,554,555,555,555, +586,587,587,587,587,587,587,587,587,587,587,587,587,587,587,587, +587,587,587,587,587,587,587,587,587,587,587,587,586,587,587,587, +587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,587, +587,587,587,587,587,587,587,587,586,587,587,587,587,587,587,587, +587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,587, +587,587,587,587,586,587,587,587,587,587,587,587,587,587,587,587, +587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,587, +586,587,587,587,587,587,587,587,587,587,587,587,587,587,587,587, /* block 116 */ -555,555,555,555,555,555,555,555,555,555,555,555,555,555,555,555, -555,555,555,555,555,555,555,555,554,555,555,555,555,555,555,555, -555,555,555,555,555,555,555,555,555,555,555,555,555,555,555,555, -555,555,555,555,554,555,555,555,555,555,555,555,555,555,555,555, -555,555,555,555,555,555,555,555,555,555,555,555,555,555,555,555, -554,555,555,555,555,555,555,555,555,555,555,555,555,555,555,555, -555,555,555,555,555,555,555,555,555,555,555,555,554,555,555,555, -555,555,555,555,555,555,555,555,555,555,555,555,555,555,555,555, +587,587,587,587,587,587,587,587,587,587,587,587,586,587,587,587, +587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,587, +587,587,587,587,587,587,587,587,586,587,587,587,587,587,587,587, +587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,587, +587,587,587,587,586,587,587,587,587,587,587,587,587,587,587,587, +587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,587, +586,587,587,587,587,587,587,587,587,587,587,587,587,587,587,587, +587,587,587,587,587,587,587,587,587,587,587,587,586,587,587,587, /* block 117 */ -555,555,555,555,555,555,555,555,554,555,555,555,555,555,555,555, -555,555,555,555,555,555,555,555,555,555,555,555,555,555,555,555, -555,555,555,555,554,555,555,555,555,555,555,555,555,555,555,555, -555,555,555,555,555,555,555,555,555,555,555,555,555,555,555,555, -554,555,555,555,555,555,555,555,555,555,555,555,555,555,555,555, -555,555,555,555,555,555,555,555,555,555,555,555,554,555,555,555, -555,555,555,555,555,555,555,555,555,555,555,555,555,555,555,555, -555,555,555,555,555,555,555,555,554,555,555,555,555,555,555,555, +587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,587, +587,587,587,587,587,587,587,587,586,587,587,587,587,587,587,587, +587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,587, +587,587,587,587,586,587,587,587,587,587,587,587,587,587,587,587, +587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,587, +586,587,587,587,587,587,587,587,587,587,587,587,587,587,587,587, +587,587,587,587,587,587,587,587,587,587,587,587,586,587,587,587, +587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,587, /* block 118 */ -555,555,555,555,555,555,555,555,555,555,555,555,555,555,555,555, -555,555,555,555,554,555,555,555,555,555,555,555,555,555,555,555, -555,555,555,555,555,555,555,555,555,555,555,555,555,555,555,555, -554,555,555,555,555,555,555,555,555,555,555,555,555,555,555,555, -555,555,555,555,555,555,555,555,555,555,555,555,554,555,555,555, -555,555,555,555,555,555,555,555,555,555,555,555,555,555,555,555, -555,555,555,555,555,555,555,555,554,555,555,555,555,555,555,555, -555,555,555,555,555,555,555,555,555,555,555,555,555,555,555,555, +587,587,587,587,587,587,587,587,586,587,587,587,587,587,587,587, +587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,587, +587,587,587,587,586,587,587,587,587,587,587,587,587,587,587,587, +587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,587, +586,587,587,587,587,587,587,587,587,587,587,587,587,587,587,587, +587,587,587,587,587,587,587,587,587,587,587,587,586,587,587,587, +587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,587, +587,587,587,587,587,587,587,587,586,587,587,587,587,587,587,587, /* block 119 */ -555,555,555,555,554,555,555,555,555,555,555,555,555,555,555,555, -555,555,555,555,555,555,555,555,555,555,555,555,555,555,555,555, -554,555,555,555,555,555,555,555,555,555,555,555,555,555,555,555, -555,555,555,555,555,555,555,555,555,555,555,555,554,555,555,555, -555,555,555,555,555,555,555,555,555,555,555,555,555,555,555,555, -555,555,555,555,555,555,555,555,554,555,555,555,555,555,555,555, -555,555,555,555,555,555,555,555,555,555,555,555,555,555,555,555, -555,555,555,555,554,555,555,555,555,555,555,555,555,555,555,555, +587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,587, +587,587,587,587,586,587,587,587,587,587,587,587,587,587,587,587, +587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,587, +586,587,587,587,587,587,587,587,587,587,587,587,587,587,587,587, +587,587,587,587,587,587,587,587,587,587,587,587,586,587,587,587, +587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,587, +587,587,587,587,587,587,587,587,586,587,587,587,587,587,587,587, +587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,587, /* block 120 */ -555,555,555,555,555,555,555,555,555,555,555,555,555,555,555,555, -554,555,555,555,555,555,555,555,555,555,555,555,555,555,555,555, -555,555,555,555,555,555,555,555,555,555,555,555,554,555,555,555, -555,555,555,555,555,555,555,555,555,555,555,555,555,555,555,555, -555,555,555,555,555,555,555,555,554,555,555,555,555,555,555,555, -555,555,555,555,555,555,555,555,555,555,555,555,555,555,555,555, -555,555,555,555,554,555,555,555,555,555,555,555,555,555,555,555, -555,555,555,555,555,555,555,555,555,555,555,555,555,555,555,555, +587,587,587,587,586,587,587,587,587,587,587,587,587,587,587,587, +587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,587, +586,587,587,587,587,587,587,587,587,587,587,587,587,587,587,587, +587,587,587,587,587,587,587,587,587,587,587,587,586,587,587,587, +587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,587, +587,587,587,587,587,587,587,587,586,587,587,587,587,587,587,587, +587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,587, +587,587,587,587,586,587,587,587,587,587,587,587,587,587,587,587, /* block 121 */ -555,555,555,555,555,555,555,555,554,555,555,555,555,555,555,555, -555,555,555,555,555,555,555,555,555,555,555,555,555,555,555,555, -555,555,555,555,115,115,115,115,115,115,115,115,115,115,115,115, -316,316,316,316,316,316,316,316,316,316,316,316,316,316,316,316, -316,316,316,316,316,316,316,115,115,115,115,317,317,317,317,317, -317,317,317,317,317,317,317,317,317,317,317,317,317,317,317,317, -317,317,317,317,317,317,317,317,317,317,317,317,317,317,317,317, -317,317,317,317,317,317,317,317,317,317,317,317,115,115,115,115, +587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,587, +586,587,587,587,587,587,587,587,587,587,587,587,587,587,587,587, +587,587,587,587,587,587,587,587,587,587,587,587,586,587,587,587, +587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,587, +587,587,587,587,587,587,587,587,586,587,587,587,587,587,587,587, +587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,587, +587,587,587,587,586,587,587,587,587,587,587,587,587,587,587,587, +587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,587, /* block 122 */ -556,556,556,556,556,556,556,556,556,556,556,556,556,556,556,556, -556,556,556,556,556,556,556,556,556,556,556,556,556,556,556,556, -556,556,556,556,556,556,556,556,556,556,556,556,556,556,556,556, -556,556,556,556,556,556,556,556,556,556,556,556,556,556,556,556, -556,556,556,556,556,556,556,556,556,556,556,556,556,556,556,556, -556,556,556,556,556,556,556,556,556,556,556,556,556,556,556,556, -556,556,556,556,556,556,556,556,556,556,556,556,556,556,556,556, -556,556,556,556,556,556,556,556,556,556,556,556,556,556,556,556, +587,587,587,587,587,587,587,587,586,587,587,587,587,587,587,587, +587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,587, +587,587,587,587,115,115,115,115,115,115,115,115,115,115,115,115, +334,334,334,334,334,334,334,334,334,334,334,334,334,334,334,334, +334,334,334,334,334,334,334,115,115,115,115,335,335,335,335,335, +335,335,335,335,335,335,335,335,335,335,335,335,335,335,335,335, +335,335,335,335,335,335,335,335,335,335,335,335,335,335,335,335, +335,335,335,335,335,335,335,335,335,335,335,335,115,115,115,115, /* block 123 */ -557,557,557,557,557,557,557,557,557,557,557,557,557,557,557,557, -557,557,557,557,557,557,557,557,557,557,557,557,557,557,557,557, -557,557,557,557,557,557,557,557,557,557,557,557,557,557,557,557, -557,557,557,557,557,557,557,557,557,557,557,557,557,557,557,557, -557,557,557,557,557,557,557,557,557,557,557,557,557,557,557,557, -557,557,557,557,557,557,557,557,557,557,557,557,557,557,557,557, -557,557,557,557,557,557,557,557,557,557,557,557,557,557,557,557, -557,557,557,557,557,557,557,557,557,557,557,557,557,557,557,557, +588,588,588,588,588,588,588,588,588,588,588,588,588,588,588,588, +588,588,588,588,588,588,588,588,588,588,588,588,588,588,588,588, +588,588,588,588,588,588,588,588,588,588,588,588,588,588,588,588, +588,588,588,588,588,588,588,588,588,588,588,588,588,588,588,588, +588,588,588,588,588,588,588,588,588,588,588,588,588,588,588,588, +588,588,588,588,588,588,588,588,588,588,588,588,588,588,588,588, +588,588,588,588,588,588,588,588,588,588,588,588,588,588,588,588, +588,588,588,588,588,588,588,588,588,588,588,588,588,588,588,588, /* block 124 */ -485,485,485,485,485,485,485,485,485,485,485,485,485,485,485,485, -485,485,485,485,485,485,485,485,485,485,485,485,485,485,485,485, -485,485,485,485,485,485,485,485,485,485,485,485,485,485,485,485, -485,485,485,485,485,485,485,485,485,485,485,485,485,485,485,485, -485,485,485,485,485,485,485,485,485,485,485,485,485,485,485,485, -485,485,485,485,485,485,485,485,485,485,485,485,485,485,485,485, -485,485,485,485,485,485,485,485,485,485,485,485,485,485,115,115, -485,485,485,485,485,485,485,485,485,485,485,485,485,485,485,485, +589,589,589,589,589,589,589,589,589,589,589,589,589,589,589,589, +589,589,589,589,589,589,589,589,589,589,589,589,589,589,589,589, +589,589,589,589,589,589,589,589,589,589,589,589,589,589,589,589, +589,589,589,589,589,589,589,589,589,589,589,589,589,589,589,589, +589,589,589,589,589,589,589,589,589,589,589,589,589,589,589,589, +589,589,589,589,589,589,589,589,589,589,589,589,589,589,589,589, +589,589,589,589,589,589,589,589,589,589,589,589,589,589,589,589, +589,589,589,589,589,589,589,589,589,589,589,589,589,589,589,589, /* block 125 */ -485,485,485,485,485,485,485,485,485,485,485,485,485,485,485,485, -485,485,485,485,485,485,485,485,485,485,485,485,485,485,485,485, -485,485,485,485,485,485,485,485,485,485,485,485,485,485,485,485, -485,485,485,485,485,485,485,485,485,485,485,485,485,485,485,485, -485,485,485,485,485,485,485,485,485,485,485,485,485,485,485,485, -485,485,485,485,485,485,485,485,485,485,115,115,115,115,115,115, -115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, -115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, +515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515, +515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515, +515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515, +515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515, +515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515, +515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515, +515,515,515,515,515,515,515,515,515,515,515,515,515,515,115,115, +515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515, /* block 126 */ - 33, 33, 33, 33, 33, 33, 33,115,115,115,115,115,115,115,115,115, -115,115,115,186,186,186,186,186,115,115,115,115,115,193,190,193, -193,193,193,193,193,193,193,193,193,558,193,193,193,193,193,193, -193,193,193,193,193,193,193,115,193,193,193,193,193,115,193,115, -193,193,115,193,193,115,193,193,193,193,193,193,193,193,193,193, -200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200, -200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200, -200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200, +515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515, +515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515, +515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515, +515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515, +515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515, +515,515,515,515,515,515,515,515,515,515,115,115,115,115,115,115, +115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, +115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, /* block 127 */ -200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200, -200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200, -200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200, -200,200,559,559,559,559,559,559,559,559,559,559,559,559,559,559, -559,559,115,115,115,115,115,115,115,115,115,115,115,115,115,115, -115,115,115,200,200,200,200,200,200,200,200,200,200,200,200,200, -200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200, -200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200, + 33, 33, 33, 33, 33, 33, 33,115,115,115,115,115,115,115,115,115, +115,115,115,200,200,200,200,200,115,115,115,115,115,207,204,207, +207,207,207,207,207,207,207,207,207,590,207,207,207,207,207,207, +207,207,207,207,207,207,207,115,207,207,207,207,207,115,207,115, +207,207,115,207,207,115,207,207,207,207,207,207,207,207,207,207, +216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216, +216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216, +216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216, /* block 128 */ -200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200, -200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200, -200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200, -200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200, -200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200, -200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200, -200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200, -200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200, +216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216, +216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216, +216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216, +216,216,591,591,591,591,591,591,591,591,591,591,591,591,591,591, +591,591,115,115,115,115,115,115,115,115,115,115,115,115,115,115, +115,115,115,216,216,216,216,216,216,216,216,216,216,216,216,216, +216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216, +216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216, /* block 129 */ -200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200, -200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200, -200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200, -200,200,200,200,200,200,200,200,200,200,200,200,200,200, 7, 6, -115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, -200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200, -200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200, -200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200, +216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216, +216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216, +216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216, +216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216, +216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216, +216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216, +216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216, +216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216, /* block 130 */ -200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200, -115,115,200,200,200,200,200,200,200,200,200,200,200,200,200,200, -200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200, -200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200, -200,200,200,200,200,200,200,200,115,115,115,115,115,115,115,115, -115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, +216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216, +216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216, +216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216, +216,216,216,216,216,216,216,216,216,216,216,216,216,216, 7, 6, 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, -200,200,200,200,200,200,200,200,200,200,200,200,197,198,115,115, +216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216, +216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216, +216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216, /* block 131 */ +216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216, +115,115,216,216,216,216,216,216,216,216,216,216,216,216,216,216, +216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216, +216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216, +216,216,216,216,216,216,216,216,115,115,115,115,115,115,115,115, +115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, +115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, +216,216,216,216,216,216,216,216,216,216,216,216,212,213,115,115, + +/* block 132 */ 110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110, 4, 4, 4, 4, 4, 4, 4, 6, 7, 4,115,115,115,115,115,115, -110,110,110,110,110,110,110,110,110,110,110,110,110,110,178,178, +110,110,110,110,110,110,110,110,110,110,110,110,110,110,192,192, 4, 9, 9, 15, 15, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 4, 4, 6, 7, 4, 4, 4, 4, 15, 15, 15, 4, 4, 4,115, 4, 4, 4, 4, 9, 6, 7, 6, 7, 6, 7, 4, 4, 4, 8, 9, 8, 8, 8,115, 4, 5, 4, 4,115,115,115,115, -200,200,200,200,200,115,200,200,200,200,200,200,200,200,200,200, - -/* block 132 */ -200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200, -200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200, -200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200, -200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200, -200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200, -200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200, -200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200, -200,200,200,200,200,200,200,200,200,200,200,200,200,115,115, 22, +216,216,216,216,216,115,216,216,216,216,216,216,216,216,216,216, /* block 133 */ +216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216, +216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216, +216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216, +216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216, +216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216, +216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216, +216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216, +216,216,216,216,216,216,216,216,216,216,216,216,216,115,115, 22, + +/* block 134 */ 115, 4, 4, 4, 5, 4, 4, 4, 6, 7, 4, 8, 4, 9, 4, 4, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 4, 4, 8, 8, 8, 4, 4, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 6, 4, 7, 14, 15, 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 6, 8, 7, 8, 6, - 7, 4, 6, 7, 4, 4,479,479,479,479,479,479,479,479,479,479, -108,479,479,479,479,479,479,479,479,479,479,479,479,479,479,479, + 7, 4, 6, 7, 4, 4,509,509,509,509,509,509,509,509,509,509, +108,509,509,509,509,509,509,509,509,509,509,509,509,509,509,509, -/* block 134 */ -479,479,479,479,479,479,479,479,479,479,479,479,479,479,479,479, -479,479,479,479,479,479,479,479,479,479,479,479,479,479,560,560, -482,482,482,482,482,482,482,482,482,482,482,482,482,482,482,482, -482,482,482,482,482,482,482,482,482,482,482,482,482,482,482,115, -115,115,482,482,482,482,482,482,115,115,482,482,482,482,482,482, -115,115,482,482,482,482,482,482,115,115,482,482,482,115,115,115, +/* block 135 */ +509,509,509,509,509,509,509,509,509,509,509,509,509,509,509,509, +509,509,509,509,509,509,509,509,509,509,509,509,509,509,592,592, +512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512, +512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,115, +115,115,512,512,512,512,512,512,115,115,512,512,512,512,512,512, +115,115,512,512,512,512,512,512,115,115,512,512,512,115,115,115, 5, 5, 8, 14, 19, 5, 5,115, 19, 8, 8, 8, 8, 19, 19,115, -437,437,437,437,437,437,437,437,437, 22, 22, 22, 19, 19,115,115, +465,465,465,465,465,465,465,465,465, 22, 22, 22, 19, 19,115,115, -/* block 135 */ -561,561,561,561,561,561,561,561,561,561,561,561,115,561,561,561, -561,561,561,561,561,561,561,561,561,561,561,561,561,561,561,561, -561,561,561,561,561,561,561,115,561,561,561,561,561,561,561,561, -561,561,561,561,561,561,561,561,561,561,561,115,561,561,115,561, -561,561,561,561,561,561,561,561,561,561,561,561,561,561,115,115, -561,561,561,561,561,561,561,561,561,561,561,561,561,561,115,115, +/* block 136 */ +593,593,593,593,593,593,593,593,593,593,593,593,115,593,593,593, +593,593,593,593,593,593,593,593,593,593,593,593,593,593,593,593, +593,593,593,593,593,593,593,115,593,593,593,593,593,593,593,593, +593,593,593,593,593,593,593,593,593,593,593,115,593,593,115,593, +593,593,593,593,593,593,593,593,593,593,593,593,593,593,115,115, +593,593,593,593,593,593,593,593,593,593,593,593,593,593,115,115, 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, -/* block 136 */ -561,561,561,561,561,561,561,561,561,561,561,561,561,561,561,561, -561,561,561,561,561,561,561,561,561,561,561,561,561,561,561,561, -561,561,561,561,561,561,561,561,561,561,561,561,561,561,561,561, -561,561,561,561,561,561,561,561,561,561,561,561,561,561,561,561, -561,561,561,561,561,561,561,561,561,561,561,561,561,561,561,561, -561,561,561,561,561,561,561,561,561,561,561,561,561,561,561,561, -561,561,561,561,561,561,561,561,561,561,561,561,561,561,561,561, -561,561,561,561,561,561,561,561,561,561,561,115,115,115,115,115, - /* block 137 */ +593,593,593,593,593,593,593,593,593,593,593,593,593,593,593,593, +593,593,593,593,593,593,593,593,593,593,593,593,593,593,593,593, +593,593,593,593,593,593,593,593,593,593,593,593,593,593,593,593, +593,593,593,593,593,593,593,593,593,593,593,593,593,593,593,593, +593,593,593,593,593,593,593,593,593,593,593,593,593,593,593,593, +593,593,593,593,593,593,593,593,593,593,593,593,593,593,593,593, +593,593,593,593,593,593,593,593,593,593,593,593,593,593,593,593, +593,593,593,593,593,593,593,593,593,593,593,115,115,115,115,115, + +/* block 138 */ 4, 4, 4,115,115,115,115, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,115,115,115, 19, 19, 19, 19, 19, 19, 19, 19, 19, -562,562,562,562,562,562,562,562,562,562,562,562,562,562,562,562, -562,562,562,562,562,562,562,562,562,562,562,562,562,562,562,562, -562,562,562,562,562,562,562,562,562,562,562,562,562,562,562,562, -562,562,562,562,562,563,563,563,563,564,564,564,564,564,564,564, +594,594,594,594,594,594,594,594,594,594,594,594,594,594,594,594, +594,594,594,594,594,594,594,594,594,594,594,594,594,594,594,594, +594,594,594,594,594,594,594,594,594,594,594,594,594,594,594,594, +594,594,594,594,594,595,595,595,595,596,596,596,596,596,596,596, -/* block 138 */ -564,564,564,564,564,564,564,564,564,564,563,563,564,115,115,115, +/* block 139 */ +596,596,596,596,596,596,596,596,596,596,595,595,596,596,596,115, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,115,115,115,115, -564,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, +596,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,110,115,115, -/* block 139 */ +/* block 140 */ 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, @@ -2777,479 +2886,509 @@ const uint16_t PRIV(ucd_stage2)[] = { /* 60416 bytes, block = 128 */ 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, -/* block 140 */ -565,565,565,565,565,565,565,565,565,565,565,565,565,565,565,565, -565,565,565,565,565,565,565,565,565,565,565,565,565,115,115,115, -566,566,566,566,566,566,566,566,566,566,566,566,566,566,566,566, -566,566,566,566,566,566,566,566,566,566,566,566,566,566,566,566, -566,566,566,566,566,566,566,566,566,566,566,566,566,566,566,566, -566,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, +/* block 141 */ +597,597,597,597,597,597,597,597,597,597,597,597,597,597,597,597, +597,597,597,597,597,597,597,597,597,597,597,597,597,115,115,115, +598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,598, +598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,598, +598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,598, +598,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, 110, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,115,115,115,115, -/* block 141 */ -567,567,567,567,567,567,567,567,567,567,567,567,567,567,567,567, -567,567,567,567,567,567,567,567,567,567,567,567,567,567,567,567, -568,568,568,568,115,115,115,115,115,115,115,115,115,115,115,115, -569,569,569,569,569,569,569,569,569,569,569,569,569,569,569,569, -569,570,569,569,569,569,569,569,569,569,570,115,115,115,115,115, -571,571,571,571,571,571,571,571,571,571,571,571,571,571,571,571, -571,571,571,571,571,571,571,571,571,571,571,571,571,571,571,571, -571,571,571,571,571,571,572,572,572,572,572,115,115,115,115,115, - /* block 142 */ -573,573,573,573,573,573,573,573,573,573,573,573,573,573,573,573, -573,573,573,573,573,573,573,573,573,573,573,573,573,573,115,574, -575,575,575,575,575,575,575,575,575,575,575,575,575,575,575,575, -575,575,575,575,575,575,575,575,575,575,575,575,575,575,575,575, -575,575,575,575,115,115,115,115,575,575,575,575,575,575,575,575, -576,577,577,577,577,577,115,115,115,115,115,115,115,115,115,115, -115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, -115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, +599,599,599,599,599,599,599,599,599,599,599,599,599,599,599,599, +599,599,599,599,599,599,599,599,599,599,599,599,599,599,599,599, +600,600,600,600,115,115,115,115,115,115,115,115,115,599,599,599, +601,601,601,601,601,601,601,601,601,601,601,601,601,601,601,601, +601,602,601,601,601,601,601,601,601,601,602,115,115,115,115,115, +603,603,603,603,603,603,603,603,603,603,603,603,603,603,603,603, +603,603,603,603,603,603,603,603,603,603,603,603,603,603,603,603, +603,603,603,603,603,603,604,604,604,604,604,115,115,115,115,115, /* block 143 */ -578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,578, -578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,578, -578,578,578,578,578,578,578,578,579,579,579,579,579,579,579,579, -579,579,579,579,579,579,579,579,579,579,579,579,579,579,579,579, -579,579,579,579,579,579,579,579,579,579,579,579,579,579,579,579, -580,580,580,580,580,580,580,580,580,580,580,580,580,580,580,580, -580,580,580,580,580,580,580,580,580,580,580,580,580,580,580,580, -580,580,580,580,580,580,580,580,580,580,580,580,580,580,580,580, - -/* block 144 */ -581,581,581,581,581,581,581,581,581,581,581,581,581,581,581,581, -581,581,581,581,581,581,581,581,581,581,581,581,581,581,115,115, -582,582,582,582,582,582,582,582,582,582,115,115,115,115,115,115, -115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, -115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, -115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, +605,605,605,605,605,605,605,605,605,605,605,605,605,605,605,605, +605,605,605,605,605,605,605,605,605,605,605,605,605,605,115,606, +607,607,607,607,607,607,607,607,607,607,607,607,607,607,607,607, +607,607,607,607,607,607,607,607,607,607,607,607,607,607,607,607, +607,607,607,607,115,115,115,115,607,607,607,607,607,607,607,607, +608,609,609,609,609,609,115,115,115,115,115,115,115,115,115,115, 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, +/* block 144 */ +610,610,610,610,610,610,610,610,610,610,610,610,610,610,610,610, +610,610,610,610,610,610,610,610,610,610,610,610,610,610,610,610, +610,610,610,610,610,610,610,610,611,611,611,611,611,611,611,611, +611,611,611,611,611,611,611,611,611,611,611,611,611,611,611,611, +611,611,611,611,611,611,611,611,611,611,611,611,611,611,611,611, +612,612,612,612,612,612,612,612,612,612,612,612,612,612,612,612, +612,612,612,612,612,612,612,612,612,612,612,612,612,612,612,612, +612,612,612,612,612,612,612,612,612,612,612,612,612,612,612,612, + /* block 145 */ -583,583,583,583,583,583,583,583,583,583,583,583,583,583,583,583, -583,583,583,583,583,583,583,583,583,583,583,583,583,583,583,583, -583,583,583,583,583,583,583,583,115,115,115,115,115,115,115,115, -584,584,584,584,584,584,584,584,584,584,584,584,584,584,584,584, -584,584,584,584,584,584,584,584,584,584,584,584,584,584,584,584, -584,584,584,584,584,584,584,584,584,584,584,584,584,584,584,584, -584,584,584,584,115,115,115,115,115,115,115,115,115,115,115,585, -115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, +613,613,613,613,613,613,613,613,613,613,613,613,613,613,613,613, +613,613,613,613,613,613,613,613,613,613,613,613,613,613,115,115, +614,614,614,614,614,614,614,614,614,614,115,115,115,115,115,115, +615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,615, +615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,615, +615,615,615,615,115,115,115,115,616,616,616,616,616,616,616,616, +616,616,616,616,616,616,616,616,616,616,616,616,616,616,616,616, +616,616,616,616,616,616,616,616,616,616,616,616,115,115,115,115, /* block 146 */ -586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586, -586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586, -586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586, -586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586, -586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586, -586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586, -586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586, -586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586, +617,617,617,617,617,617,617,617,617,617,617,617,617,617,617,617, +617,617,617,617,617,617,617,617,617,617,617,617,617,617,617,617, +617,617,617,617,617,617,617,617,115,115,115,115,115,115,115,115, +618,618,618,618,618,618,618,618,618,618,618,618,618,618,618,618, +618,618,618,618,618,618,618,618,618,618,618,618,618,618,618,618, +618,618,618,618,618,618,618,618,618,618,618,618,618,618,618,618, +618,618,618,618,115,115,115,115,115,115,115,115,115,115,115,619, +115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, /* block 147 */ -586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586, -586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586, -586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586, -586,586,586,586,586,586,586,115,115,115,115,115,115,115,115,115, -586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586, -586,586,586,586,586,586,115,115,115,115,115,115,115,115,115,115, -586,586,586,586,586,586,586,586,115,115,115,115,115,115,115,115, -115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, +620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620, +620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620, +620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620, +620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620, +620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620, +620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620, +620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620, +620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620, /* block 148 */ -587,587,587,587,587,587,115,115,587,115,587,587,587,587,587,587, -587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,587, -587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,587, -587,587,587,587,587,587,115,587,587,115,115,115,587,115,115,587, -588,588,588,588,588,588,588,588,588,588,588,588,588,588,588,588, -588,588,588,588,588,588,115,589,590,590,590,590,590,590,590,590, -591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,591, -591,591,591,591,591,591,591,592,592,593,593,593,593,593,593,593, +620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620, +620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620, +620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620, +620,620,620,620,620,620,620,115,115,115,115,115,115,115,115,115, +620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620, +620,620,620,620,620,620,115,115,115,115,115,115,115,115,115,115, +620,620,620,620,620,620,620,620,115,115,115,115,115,115,115,115, +115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, /* block 149 */ -594,594,594,594,594,594,594,594,594,594,594,594,594,594,594,594, -594,594,594,594,594,594,594,594,594,594,594,594,594,594,594,115, -115,115,115,115,115,115,115,595,595,595,595,595,595,595,595,595, +621,621,621,621,621,621,115,115,621,115,621,621,621,621,621,621, +621,621,621,621,621,621,621,621,621,621,621,621,621,621,621,621, +621,621,621,621,621,621,621,621,621,621,621,621,621,621,621,621, +621,621,621,621,621,621,115,621,621,115,115,115,621,115,115,621, +622,622,622,622,622,622,622,622,622,622,622,622,622,622,622,622, +622,622,622,622,622,622,115,623,624,624,624,624,624,624,624,624, +625,625,625,625,625,625,625,625,625,625,625,625,625,625,625,625, +625,625,625,625,625,625,625,626,626,627,627,627,627,627,627,627, + +/* block 150 */ +628,628,628,628,628,628,628,628,628,628,628,628,628,628,628,628, +628,628,628,628,628,628,628,628,628,628,628,628,628,628,628,115, +115,115,115,115,115,115,115,629,629,629,629,629,629,629,629,629, 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, -596,596,596,596,596,596,596,596,596,596,596,596,596,596,596,596, -596,596,596,115,596,596,115,115,115,115,115,597,597,597,597,597, +630,630,630,630,630,630,630,630,630,630,630,630,630,630,630,630, +630,630,630,115,630,630,115,115,115,115,115,631,631,631,631,631, -/* block 150 */ -598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,598, -598,598,598,598,598,598,599,599,599,599,599,599,115,115,115,600, -601,601,601,601,601,601,601,601,601,601,601,601,601,601,601,601, -601,601,601,601,601,601,601,601,601,601,115,115,115,115,115,602, +/* block 151 */ +632,632,632,632,632,632,632,632,632,632,632,632,632,632,632,632, +632,632,632,632,632,632,633,633,633,633,633,633,115,115,115,634, +635,635,635,635,635,635,635,635,635,635,635,635,635,635,635,635, +635,635,635,635,635,635,635,635,635,635,115,115,115,115,115,636, 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, -/* block 151 */ -603,603,603,603,603,603,603,603,603,603,603,603,603,603,603,603, -603,603,603,603,603,603,603,603,603,603,603,603,603,603,603,603, -604,604,604,604,604,604,604,604,604,604,604,604,604,604,604,604, -604,604,604,604,604,604,604,604,115,115,115,115,605,605,604,604, -605,605,605,605,605,605,605,605,605,605,605,605,605,605,605,605, -115,115,605,605,605,605,605,605,605,605,605,605,605,605,605,605, -605,605,605,605,605,605,605,605,605,605,605,605,605,605,605,605, -605,605,605,605,605,605,605,605,605,605,605,605,605,605,605,605, - /* block 152 */ -606,607,607,607,115,607,607,115,115,115,115,115,607,607,607,607, -606,606,606,606,115,606,606,606,115,606,606,606,606,606,606,606, -606,606,606,606,606,606,606,606,606,606,606,606,606,606,606,606, -606,606,606,606,115,115,115,115,607,607,607,115,115,115,115,607, -608,608,608,608,608,608,608,608,115,115,115,115,115,115,115,115, -609,609,609,609,609,609,609,609,609,115,115,115,115,115,115,115, -610,610,610,610,610,610,610,610,610,610,610,610,610,610,610,610, -610,610,610,610,610,610,610,610,610,610,610,610,610,611,611,612, +637,637,637,637,637,637,637,637,637,637,637,637,637,637,637,637, +637,637,637,637,637,637,637,637,637,637,637,637,637,637,637,637, +638,638,638,638,638,638,638,638,638,638,638,638,638,638,638,638, +638,638,638,638,638,638,638,638,115,115,115,115,639,639,638,638, +639,639,639,639,639,639,639,639,639,639,639,639,639,639,639,639, +115,115,639,639,639,639,639,639,639,639,639,639,639,639,639,639, +639,639,639,639,639,639,639,639,639,639,639,639,639,639,639,639, +639,639,639,639,639,639,639,639,639,639,639,639,639,639,639,639, /* block 153 */ -613,613,613,613,613,613,613,613,613,613,613,613,613,613,613,613, -613,613,613,613,613,613,613,613,613,613,613,613,613,614,614,614, -115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, -115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, -615,615,615,615,615,615,615,615,616,615,615,615,615,615,615,615, -615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,615, -615,615,615,615,615,617,617,115,115,115,115,618,618,618,618,618, -619,619,619,619,619,619,619,115,115,115,115,115,115,115,115,115, +640,641,641,641,115,641,641,115,115,115,115,115,641,641,641,641, +640,640,640,640,115,640,640,640,115,640,640,640,640,640,640,640, +640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640, +640,640,640,640,115,115,115,115,641,641,641,115,115,115,115,641, +642,642,642,642,642,642,642,642,115,115,115,115,115,115,115,115, +643,643,643,643,643,643,643,643,643,115,115,115,115,115,115,115, +644,644,644,644,644,644,644,644,644,644,644,644,644,644,644,644, +644,644,644,644,644,644,644,644,644,644,644,644,644,645,645,646, /* block 154 */ -620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620, -620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620, -620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620, -620,620,620,620,620,620,115,115,115,621,621,621,621,621,621,621, -622,622,622,622,622,622,622,622,622,622,622,622,622,622,622,622, -622,622,622,622,622,622,115,115,623,623,623,623,623,623,623,623, -624,624,624,624,624,624,624,624,624,624,624,624,624,624,624,624, -624,624,624,115,115,115,115,115,625,625,625,625,625,625,625,625, +647,647,647,647,647,647,647,647,647,647,647,647,647,647,647,647, +647,647,647,647,647,647,647,647,647,647,647,647,647,648,648,648, +115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, +115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, +649,649,649,649,649,649,649,649,650,649,649,649,649,649,649,649, +649,649,649,649,649,649,649,649,649,649,649,649,649,649,649,649, +649,649,649,649,649,651,651,115,115,115,115,652,652,652,652,652, +653,653,653,653,653,653,653,115,115,115,115,115,115,115,115,115, /* block 155 */ -626,626,626,626,626,626,626,626,626,626,626,626,626,626,626,626, -626,626,115,115,115,115,115,115,115,627,627,627,627,115,115,115, -115,115,115,115,115,115,115,115,115,628,628,628,628,628,628,628, +654,654,654,654,654,654,654,654,654,654,654,654,654,654,654,654, +654,654,654,654,654,654,654,654,654,654,654,654,654,654,654,654, +654,654,654,654,654,654,654,654,654,654,654,654,654,654,654,654, +654,654,654,654,654,654,115,115,115,655,655,655,655,655,655,655, +656,656,656,656,656,656,656,656,656,656,656,656,656,656,656,656, +656,656,656,656,656,656,115,115,657,657,657,657,657,657,657,657, +658,658,658,658,658,658,658,658,658,658,658,658,658,658,658,658, +658,658,658,115,115,115,115,115,659,659,659,659,659,659,659,659, + +/* block 156 */ +660,660,660,660,660,660,660,660,660,660,660,660,660,660,660,660, +660,660,115,115,115,115,115,115,115,661,661,661,661,115,115,115, +115,115,115,115,115,115,115,115,115,662,662,662,662,662,662,662, 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, -/* block 156 */ -629,629,629,629,629,629,629,629,629,629,629,629,629,629,629,629, -629,629,629,629,629,629,629,629,629,629,629,629,629,629,629,629, -629,629,629,629,629,629,629,629,629,629,629,629,629,629,629,629, -629,629,629,629,629,629,629,629,629,629,629,629,629,629,629,629, -629,629,629,629,629,629,629,629,629,115,115,115,115,115,115,115, +/* block 157 */ +663,663,663,663,663,663,663,663,663,663,663,663,663,663,663,663, +663,663,663,663,663,663,663,663,663,663,663,663,663,663,663,663, +663,663,663,663,663,663,663,663,663,663,663,663,663,663,663,663, +663,663,663,663,663,663,663,663,663,663,663,663,663,663,663,663, +663,663,663,663,663,663,663,663,663,115,115,115,115,115,115,115, 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, -/* block 157 */ -630,630,630,630,630,630,630,630,630,630,630,630,630,630,630,630, -630,630,630,630,630,630,630,630,630,630,630,630,630,630,630,630, -630,630,630,630,630,630,630,630,630,630,630,630,630,630,630,630, -630,630,630,115,115,115,115,115,115,115,115,115,115,115,115,115, -631,631,631,631,631,631,631,631,631,631,631,631,631,631,631,631, -631,631,631,631,631,631,631,631,631,631,631,631,631,631,631,631, -631,631,631,631,631,631,631,631,631,631,631,631,631,631,631,631, -631,631,631,115,115,115,115,115,115,115,632,632,632,632,632,632, - /* block 158 */ +664,664,664,664,664,664,664,664,664,664,664,664,664,664,664,664, +664,664,664,664,664,664,664,664,664,664,664,664,664,664,664,664, +664,664,664,664,664,664,664,664,664,664,664,664,664,664,664,664, +664,664,664,115,115,115,115,115,115,115,115,115,115,115,115,115, +665,665,665,665,665,665,665,665,665,665,665,665,665,665,665,665, +665,665,665,665,665,665,665,665,665,665,665,665,665,665,665,665, +665,665,665,665,665,665,665,665,665,665,665,665,665,665,665,665, +665,665,665,115,115,115,115,115,115,115,666,666,666,666,666,666, + +/* block 159 */ 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, -633,633,633,633,633,633,633,633,633,633,633,633,633,633,633,633, -633,633,633,633,633,633,633,633,633,633,633,633,633,633,633,115, - -/* block 159 */ -634,635,634,636,636,636,636,636,636,636,636,636,636,636,636,636, -636,636,636,636,636,636,636,636,636,636,636,636,636,636,636,636, -636,636,636,636,636,636,636,636,636,636,636,636,636,636,636,636, -636,636,636,636,636,636,636,636,635,635,635,635,635,635,635,635, -635,635,635,635,635,635,635,637,637,637,637,637,637,637,115,115, -115,115,638,638,638,638,638,638,638,638,638,638,638,638,638,638, -638,638,638,638,638,638,639,639,639,639,639,639,639,639,639,639, -115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,635, +667,667,667,667,667,667,667,667,667,667,667,667,667,667,667,667, +667,667,667,667,667,667,667,667,667,667,667,667,667,667,667,115, /* block 160 */ -640,640,641,642,642,642,642,642,642,642,642,642,642,642,642,642, -642,642,642,642,642,642,642,642,642,642,642,642,642,642,642,642, -642,642,642,642,642,642,642,642,642,642,642,642,642,642,642,642, -641,641,641,640,640,640,640,641,641,640,640,643,643,644,643,643, -643,643,115,115,115,115,115,115,115,115,115,115,115,115,115,115, -645,645,645,645,645,645,645,645,645,645,645,645,645,645,645,645, -645,645,645,645,645,645,645,645,645,115,115,115,115,115,115,115, -646,646,646,646,646,646,646,646,646,646,115,115,115,115,115,115, +668,669,668,670,670,670,670,670,670,670,670,670,670,670,670,670, +670,670,670,670,670,670,670,670,670,670,670,670,670,670,670,670, +670,670,670,670,670,670,670,670,670,670,670,670,670,670,670,670, +670,670,670,670,670,670,670,670,669,669,669,669,669,669,669,669, +669,669,669,669,669,669,669,671,671,671,671,671,671,671,115,115, +115,115,672,672,672,672,672,672,672,672,672,672,672,672,672,672, +672,672,672,672,672,672,673,673,673,673,673,673,673,673,673,673, +115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,669, /* block 161 */ -647,647,647,648,648,648,648,648,648,648,648,648,648,648,648,648, -648,648,648,648,648,648,648,648,648,648,648,648,648,648,648,648, -648,648,648,648,648,648,648,647,647,647,647,647,649,647,647,647, -647,647,647,647,647,115,650,650,650,650,650,650,650,650,650,650, -651,651,651,651,115,115,115,115,115,115,115,115,115,115,115,115, -652,652,652,652,652,652,652,652,652,652,652,652,652,652,652,652, -652,652,652,652,652,652,652,652,652,652,652,652,652,652,652,652, -652,652,652,653,654,654,652,115,115,115,115,115,115,115,115,115, +674,674,675,676,676,676,676,676,676,676,676,676,676,676,676,676, +676,676,676,676,676,676,676,676,676,676,676,676,676,676,676,676, +676,676,676,676,676,676,676,676,676,676,676,676,676,676,676,676, +675,675,675,674,674,674,674,675,675,674,674,677,677,678,677,677, +677,677,115,115,115,115,115,115,115,115,115,115,115,115,115,115, +679,679,679,679,679,679,679,679,679,679,679,679,679,679,679,679, +679,679,679,679,679,679,679,679,679,115,115,115,115,115,115,115, +680,680,680,680,680,680,680,680,680,680,115,115,115,115,115,115, /* block 162 */ -655,655,656,657,657,657,657,657,657,657,657,657,657,657,657,657, -657,657,657,657,657,657,657,657,657,657,657,657,657,657,657,657, -657,657,657,657,657,657,657,657,657,657,657,657,657,657,657,657, -657,657,657,656,656,656,655,655,655,655,655,655,655,655,655,656, -656,657,657,657,657,658,658,658,658,658,655,655,655,658,115,115, -659,659,659,659,659,659,659,659,659,659,657,658,657,658,658,658, -115,660,660,660,660,660,660,660,660,660,660,660,660,660,660,660, -660,660,660,660,660,115,115,115,115,115,115,115,115,115,115,115, +681,681,681,682,682,682,682,682,682,682,682,682,682,682,682,682, +682,682,682,682,682,682,682,682,682,682,682,682,682,682,682,682, +682,682,682,682,682,682,682,681,681,681,681,681,683,681,681,681, +681,681,681,681,681,115,684,684,684,684,684,684,684,684,684,684, +685,685,685,685,115,115,115,115,115,115,115,115,115,115,115,115, +686,686,686,686,686,686,686,686,686,686,686,686,686,686,686,686, +686,686,686,686,686,686,686,686,686,686,686,686,686,686,686,686, +686,686,686,687,688,688,686,115,115,115,115,115,115,115,115,115, /* block 163 */ -661,661,661,661,661,661,661,661,661,661,661,661,661,661,661,661, -661,661,115,661,661,661,661,661,661,661,661,661,661,661,661,661, -661,661,661,661,661,661,661,661,661,661,661,661,662,662,662,663, -663,663,662,662,663,662,663,663,664,664,664,664,664,664,115,115, +689,689,690,691,691,691,691,691,691,691,691,691,691,691,691,691, +691,691,691,691,691,691,691,691,691,691,691,691,691,691,691,691, +691,691,691,691,691,691,691,691,691,691,691,691,691,691,691,691, +691,691,691,690,690,690,689,689,689,689,689,689,689,689,689,690, +690,691,692,692,691,693,693,693,693,693,689,689,689,693,115,115, +694,694,694,694,694,694,694,694,694,694,691,693,691,693,693,693, +115,695,695,695,695,695,695,695,695,695,695,695,695,695,695,695, +695,695,695,695,695,115,115,115,115,115,115,115,115,115,115,115, + +/* block 164 */ +696,696,696,696,696,696,696,696,696,696,696,696,696,696,696,696, +696,696,115,696,696,696,696,696,696,696,696,696,696,696,696,696, +696,696,696,696,696,696,696,696,696,696,696,696,697,697,697,698, +698,698,697,697,698,697,698,698,699,699,699,699,699,699,698,115, 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, -/* block 164 */ -665,665,665,665,665,665,665,115,665,115,665,665,665,665,115,665, -665,665,665,665,665,665,665,665,665,665,665,665,665,665,115,665, -665,665,665,665,665,665,665,665,665,666,115,115,115,115,115,115, -667,667,667,667,667,667,667,667,667,667,667,667,667,667,667,667, -667,667,667,667,667,667,667,667,667,667,667,667,667,667,667,667, -667,667,667,667,667,667,667,667,667,667,667,667,667,667,667,668, -669,669,669,668,668,668,668,668,668,668,668,115,115,115,115,115, -670,670,670,670,670,670,670,670,670,670,115,115,115,115,115,115, - /* block 165 */ -671,671,672,672,115,673,673,673,673,673,673,673,673,115,115,673, -673,115,115,673,673,673,673,673,673,673,673,673,673,673,673,673, -673,673,673,673,673,673,673,673,673,115,673,673,673,673,673,673, -673,115,673,673,115,673,673,673,673,673,115,115,671,673,674,672, -671,672,672,672,672,115,115,672,672,115,115,672,672,672,115,115, -673,115,115,115,115,115,115,674,115,115,115,115,115,673,673,673, -673,673,672,672,115,115,671,671,671,671,671,671,671,115,115,115, -671,671,671,671,671,115,115,115,115,115,115,115,115,115,115,115, +700,700,700,700,700,700,700,115,700,115,700,700,700,700,115,700, +700,700,700,700,700,700,700,700,700,700,700,700,700,700,115,700, +700,700,700,700,700,700,700,700,700,701,115,115,115,115,115,115, +702,702,702,702,702,702,702,702,702,702,702,702,702,702,702,702, +702,702,702,702,702,702,702,702,702,702,702,702,702,702,702,702, +702,702,702,702,702,702,702,702,702,702,702,702,702,702,702,703, +704,704,704,703,703,703,703,703,703,703,703,115,115,115,115,115, +705,705,705,705,705,705,705,705,705,705,115,115,115,115,115,115, /* block 166 */ -675,675,675,675,675,675,675,675,675,675,675,675,675,675,675,675, -675,675,675,675,675,675,675,675,675,675,675,675,675,675,675,675, -675,675,675,675,675,675,675,675,675,675,675,675,675,675,675,675, -676,677,677,678,678,678,678,678,678,677,678,677,677,676,677,678, -678,677,678,678,675,675,679,675,115,115,115,115,115,115,115,115, -680,680,680,680,680,680,680,680,680,680,115,115,115,115,115,115, -115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, -115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, +706,706,707,707,115,708,708,708,708,708,708,708,708,115,115,708, +708,115,115,708,708,708,708,708,708,708,708,708,708,708,708,708, +708,708,708,708,708,708,708,708,708,115,708,708,708,708,708,708, +708,115,708,708,115,708,708,708,708,708,115,115,706,708,709,707, +706,707,707,707,707,115,115,707,707,115,115,707,707,707,115,115, +708,115,115,115,115,115,115,709,115,115,115,115,115,708,708,708, +708,708,707,707,115,115,706,706,706,706,706,706,706,115,115,115, +706,706,706,706,706,115,115,115,115,115,115,115,115,115,115,115, /* block 167 */ -681,681,681,681,681,681,681,681,681,681,681,681,681,681,681,681, -681,681,681,681,681,681,681,681,681,681,681,681,681,681,681,681, -681,681,681,681,681,681,681,681,681,681,681,681,681,681,681,682, -683,683,684,684,684,684,115,115,683,683,683,683,684,684,683,684, -684,685,685,685,685,685,685,685,685,685,685,685,685,685,685,685, -685,685,685,685,685,685,685,685,681,681,681,681,684,684,115,115, +710,710,710,710,710,710,710,710,710,710,710,710,710,710,710,710, +710,710,710,710,710,710,710,710,710,710,710,710,710,710,710,710, +710,710,710,710,710,710,710,710,710,710,710,710,710,710,710,710, +710,710,710,710,710,711,711,711,712,712,712,712,712,712,712,712, +711,711,712,712,712,711,712,710,710,710,710,713,713,713,713,713, +714,714,714,714,714,714,714,714,714,714,115,713,115,713,115,115, 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, /* block 168 */ -686,686,686,686,686,686,686,686,686,686,686,686,686,686,686,686, -686,686,686,686,686,686,686,686,686,686,686,686,686,686,686,686, -686,686,686,686,686,686,686,686,686,686,686,686,686,686,686,686, -687,687,687,688,688,688,688,688,688,688,688,687,687,688,687,688, -688,689,689,689,686,115,115,115,115,115,115,115,115,115,115,115, -690,690,690,690,690,690,690,690,690,690,115,115,115,115,115,115, +715,715,715,715,715,715,715,715,715,715,715,715,715,715,715,715, +715,715,715,715,715,715,715,715,715,715,715,715,715,715,715,715, +715,715,715,715,715,715,715,715,715,715,715,715,715,715,715,715, +716,717,717,718,718,718,718,718,718,717,718,717,717,716,717,718, +718,717,718,718,715,715,719,715,115,115,115,115,115,115,115,115, +720,720,720,720,720,720,720,720,720,720,115,115,115,115,115,115, 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, /* block 169 */ -691,691,691,691,691,691,691,691,691,691,691,691,691,691,691,691, -691,691,691,691,691,691,691,691,691,691,691,691,691,691,691,691, -691,691,691,691,691,691,691,691,691,691,691,692,693,692,693,693, -692,692,692,692,692,692,693,692,115,115,115,115,115,115,115,115, -694,694,694,694,694,694,694,694,694,694,115,115,115,115,115,115, -115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, +721,721,721,721,721,721,721,721,721,721,721,721,721,721,721,721, +721,721,721,721,721,721,721,721,721,721,721,721,721,721,721,721, +721,721,721,721,721,721,721,721,721,721,721,721,721,721,721,722, +723,723,724,724,724,724,115,115,723,723,723,723,724,724,723,724, +724,725,725,725,725,725,725,725,725,725,725,725,725,725,725,725, +725,725,725,725,725,725,725,725,721,721,721,721,724,724,115,115, 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, /* block 170 */ -695,695,695,695,695,695,695,695,695,695,695,695,695,695,695,695, -695,695,695,695,695,695,695,695,695,695,115,115,115,696,696,696, -697,697,696,696,696,696,697,696,696,696,696,696,115,115,115,115, -698,698,698,698,698,698,698,698,698,698,699,699,700,700,700,701, -115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, -115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, -115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, +726,726,726,726,726,726,726,726,726,726,726,726,726,726,726,726, +726,726,726,726,726,726,726,726,726,726,726,726,726,726,726,726, +726,726,726,726,726,726,726,726,726,726,726,726,726,726,726,726, +727,727,727,728,728,728,728,728,728,728,728,727,727,728,727,728, +728,729,729,729,726,115,115,115,115,115,115,115,115,115,115,115, +730,730,730,730,730,730,730,730,730,730,115,115,115,115,115,115, +369,369,369,369,369,369,369,369,369,369,369,369,369,115,115,115, 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, /* block 171 */ +731,731,731,731,731,731,731,731,731,731,731,731,731,731,731,731, +731,731,731,731,731,731,731,731,731,731,731,731,731,731,731,731, +731,731,731,731,731,731,731,731,731,731,731,732,733,732,733,733, +732,732,732,732,732,732,733,732,115,115,115,115,115,115,115,115, +734,734,734,734,734,734,734,734,734,734,115,115,115,115,115,115, +115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, -702,702,702,702,702,702,702,702,702,702,702,702,702,702,702,702, -702,702,702,702,702,702,702,702,702,702,702,702,702,702,702,702, -703,703,703,703,703,703,703,703,703,703,703,703,703,703,703,703, -703,703,703,703,703,703,703,703,703,703,703,703,703,703,703,703, -704,704,704,704,704,704,704,704,704,704,705,705,705,705,705,705, -705,705,705,115,115,115,115,115,115,115,115,115,115,115,115,706, /* block 172 */ +735,735,735,735,735,735,735,735,735,735,735,735,735,735,735,735, +735,735,735,735,735,735,735,735,735,735,115,115,115,736,736,736, +737,737,736,736,736,736,737,736,736,736,736,736,115,115,115,115, +738,738,738,738,738,738,738,738,738,738,739,739,740,740,740,741, 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, -707,707,707,707,707,707,707,707,707,707,707,707,707,707,707,707, -707,707,707,707,707,707,707,707,707,707,707,707,707,707,707,707, -707,707,707,707,707,707,707,707,707,707,707,707,707,707,707,707, -707,707,707,707,707,707,707,707,707,115,115,115,115,115,115,115, /* block 173 */ -708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,708, -708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,708, -708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,708, -708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,708, -708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,708, -708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,708, -708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,708, -708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,708, - -/* block 174 */ -708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,708, -708,708,708,708,708,708,708,708,708,708,115,115,115,115,115,115, -115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, -115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, -115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, -115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, +742,742,742,742,742,742,742,742,742,742,742,742,742,742,742,742, +742,742,742,742,742,742,742,742,742,742,742,742,742,742,742,742, +743,743,743,743,743,743,743,743,743,743,743,743,743,743,743,743, +743,743,743,743,743,743,743,743,743,743,743,743,743,743,743,743, +744,744,744,744,744,744,744,744,744,744,745,745,745,745,745,745, +745,745,745,115,115,115,115,115,115,115,115,115,115,115,115,746, + +/* block 174 */ +747,748,748,748,748,748,748,749,749,748,748,747,747,747,747,747, +747,747,747,747,747,747,747,747,747,747,747,747,747,747,747,747, +747,747,747,747,747,747,747,747,747,747,747,747,747,747,747,747, +747,747,747,748,748,748,748,748,748,749,750,748,748,748,748,751, +751,751,751,751,751,751,751,748,115,115,115,115,115,115,115,115, +752,753,753,753,753,753,753,754,754,753,753,753,752,752,752,752, +752,752,752,752,752,752,752,752,752,752,752,752,752,752,752,752, +752,752,752,752,752,752,752,752,752,752,752,752,752,752,752,752, /* block 175 */ -709,709,709,709,709,709,709,709,709,709,709,709,709,709,709,709, -709,709,709,709,709,709,709,709,709,709,709,709,709,709,709,709, -709,709,709,709,709,709,709,709,709,709,709,709,709,709,709,709, -709,709,709,709,709,709,709,709,709,709,709,709,709,709,709,709, -709,709,709,709,709,709,709,709,709,709,709,709,709,709,709,709, -709,709,709,709,709,709,709,709,709,709,709,709,709,709,709,709, -709,709,709,709,709,709,709,709,709,709,709,709,709,709,709,115, -710,710,710,710,710,115,115,115,115,115,115,115,115,115,115,115, +752,752,752,752,115,115,755,755,755,755,753,753,753,753,753,753, +753,753,753,753,753,753,753,754,753,753,756,756,756,115,756,756, +756,756,756,115,115,115,115,115,115,115,115,115,115,115,115,115, +115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, +757,757,757,757,757,757,757,757,757,757,757,757,757,757,757,757, +757,757,757,757,757,757,757,757,757,757,757,757,757,757,757,757, +757,757,757,757,757,757,757,757,757,757,757,757,757,757,757,757, +757,757,757,757,757,757,757,757,757,115,115,115,115,115,115,115, /* block 176 */ -708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,708, -708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,708, -708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,708, -708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,708, -708,708,708,708,115,115,115,115,115,115,115,115,115,115,115,115, -115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, -115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, -115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, +758,758,758,758,758,758,758,758,758,115,758,758,758,758,758,758, +758,758,758,758,758,758,758,758,758,758,758,758,758,758,758,758, +758,758,758,758,758,758,758,758,758,758,758,758,758,758,758,759, +760,760,760,760,760,760,760,115,760,760,760,760,760,760,759,760, +758,761,761,761,761,761,115,115,115,115,115,115,115,115,115,115, +762,762,762,762,762,762,762,762,762,762,763,763,763,763,763,763, +763,763,763,763,763,763,763,763,763,763,763,763,763,115,115,115, +764,764,765,765,765,765,765,765,765,765,765,765,765,765,765,765, /* block 177 */ -711,711,711,711,711,711,711,711,711,711,711,711,711,711,711,711, -711,711,711,711,711,711,711,711,711,711,711,711,711,711,711,711, -711,711,711,711,711,711,711,711,711,711,711,711,711,711,711,711, -711,711,711,711,711,711,711,711,711,711,711,711,711,711,711,711, -711,711,711,711,711,711,711,711,711,711,711,711,711,711,711,711, -711,711,711,711,711,711,711,711,711,711,711,711,711,711,711,711, -711,711,711,711,711,711,711,711,711,711,711,711,711,711,711,711, -711,711,711,711,711,711,711,711,711,711,711,711,711,711,711,711, - -/* block 178 */ -711,711,711,711,711,711,711,711,711,711,711,711,711,711,711,711, -711,711,711,711,711,711,711,711,711,711,711,711,711,711,711,711, -711,711,711,711,711,711,711,711,711,711,711,711,711,711,711,115, +765,765,765,765,765,765,765,765,765,765,765,765,765,765,765,765, +115,115,766,766,766,766,766,766,766,766,766,766,766,766,766,766, +766,766,766,766,766,766,766,766,115,767,766,766,766,766,766,766, +766,767,766,766,767,766,766,115,115,115,115,115,115,115,115,115, +115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, + +/* block 178 */ +768,768,768,768,768,768,768,115,768,768,115,768,768,768,768,768, +768,768,768,768,768,768,768,768,768,768,768,768,768,768,768,768, +768,768,768,768,768,768,768,768,768,768,768,768,768,768,768,768, +768,769,769,769,769,769,769,115,115,115,769,115,769,769,115,769, +769,769,769,769,769,769,770,769,115,115,115,115,115,115,115,115, +771,771,771,771,771,771,771,771,771,771,115,115,115,115,115,115, 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, /* block 179 */ -712,712,712,712,712,712,712,712,712,712,712,712,712,712,712,712, -712,712,712,712,712,712,712,712,712,712,712,712,712,712,712,712, -712,712,712,712,712,712,712,712,712,712,712,712,712,712,712,712, -712,712,712,712,712,712,712,712,712,712,712,712,712,712,712,712, -712,712,712,712,712,712,712,712,712,712,712,712,712,712,712,712, -712,712,712,712,712,712,712,712,712,712,712,712,712,712,712,712, -712,712,712,712,712,712,712,712,712,712,712,712,712,712,712,712, -712,712,712,712,712,712,712,712,712,712,712,712,712,712,712,712, +772,772,772,772,772,772,772,772,772,772,772,772,772,772,772,772, +772,772,772,772,772,772,772,772,772,772,772,772,772,772,772,772, +772,772,772,772,772,772,772,772,772,772,772,772,772,772,772,772, +772,772,772,772,772,772,772,772,772,772,772,772,772,772,772,772, +772,772,772,772,772,772,772,772,772,772,772,772,772,772,772,772, +772,772,772,772,772,772,772,772,772,772,772,772,772,772,772,772, +772,772,772,772,772,772,772,772,772,772,772,772,772,772,772,772, +772,772,772,772,772,772,772,772,772,772,772,772,772,772,772,772, /* block 180 */ -712,712,712,712,712,712,712,712,712,712,712,712,712,712,712,712, -712,712,712,712,712,712,712,712,712,712,712,712,712,712,712,712, -712,712,712,712,712,712,712,712,712,712,712,712,712,712,712,712, -712,712,712,712,712,712,712,712,712,712,712,712,712,712,712,712, -712,712,712,712,712,712,712,115,115,115,115,115,115,115,115,115, +772,772,772,772,772,772,772,772,772,772,772,772,772,772,772,772, +772,772,772,772,772,772,772,772,772,772,115,115,115,115,115,115, +115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, +115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, +115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, /* block 181 */ -498,498,498,498,498,498,498,498,498,498,498,498,498,498,498,498, -498,498,498,498,498,498,498,498,498,498,498,498,498,498,498,498, -498,498,498,498,498,498,498,498,498,498,498,498,498,498,498,498, -498,498,498,498,498,498,498,498,498,498,498,498,498,498,498,498, -498,498,498,498,498,498,498,498,498,498,498,498,498,498,498,498, -498,498,498,498,498,498,498,498,498,498,498,498,498,498,498,498, -498,498,498,498,498,498,498,498,498,498,498,498,498,498,498,498, -498,498,498,498,498,498,498,498,498,498,498,498,498,498,498,498, +773,773,773,773,773,773,773,773,773,773,773,773,773,773,773,773, +773,773,773,773,773,773,773,773,773,773,773,773,773,773,773,773, +773,773,773,773,773,773,773,773,773,773,773,773,773,773,773,773, +773,773,773,773,773,773,773,773,773,773,773,773,773,773,773,773, +773,773,773,773,773,773,773,773,773,773,773,773,773,773,773,773, +773,773,773,773,773,773,773,773,773,773,773,773,773,773,773,773, +773,773,773,773,773,773,773,773,773,773,773,773,773,773,773,115, +774,774,774,774,774,115,115,115,115,115,115,115,115,115,115,115, /* block 182 */ -498,498,498,498,498,498,498,498,498,498,498,498,498,498,498,498, -498,498,498,498,498,498,498,498,498,498,498,498,498,498,498,498, -498,498,498,498,498,498,498,498,498,498,498,498,498,498,498,498, -498,498,498,498,498,498,498,498,498,115,115,115,115,115,115,115, -713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713, -713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,115, -714,714,714,714,714,714,714,714,714,714,115,115,115,115,715,715, +772,772,772,772,772,772,772,772,772,772,772,772,772,772,772,772, +772,772,772,772,772,772,772,772,772,772,772,772,772,772,772,772, +772,772,772,772,772,772,772,772,772,772,772,772,772,772,772,772, +772,772,772,772,772,772,772,772,772,772,772,772,772,772,772,772, +772,772,772,772,115,115,115,115,115,115,115,115,115,115,115,115, +115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, +115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, /* block 183 */ +775,775,775,775,775,775,775,775,775,775,775,775,775,775,775,775, +775,775,775,775,775,775,775,775,775,775,775,775,775,775,775,775, +775,775,775,775,775,775,775,775,775,775,775,775,775,775,775,775, +775,775,775,775,775,775,775,775,775,775,775,775,775,775,775,775, +775,775,775,775,775,775,775,775,775,775,775,775,775,775,775,775, +775,775,775,775,775,775,775,775,775,775,775,775,775,775,775,775, +775,775,775,775,775,775,775,775,775,775,775,775,775,775,775,775, +775,775,775,775,775,775,775,775,775,775,775,775,775,775,775,775, + +/* block 184 */ +775,775,775,775,775,775,775,775,775,775,775,775,775,775,775,775, +775,775,775,775,775,775,775,775,775,775,775,775,775,775,775,775, +775,775,775,775,775,775,775,775,775,775,775,775,775,775,775,115, 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, -716,716,716,716,716,716,716,716,716,716,716,716,716,716,716,716, -716,716,716,716,716,716,716,716,716,716,716,716,716,716,115,115, -717,717,717,717,717,718,115,115,115,115,115,115,115,115,115,115, - -/* block 184 */ -719,719,719,719,719,719,719,719,719,719,719,719,719,719,719,719, -719,719,719,719,719,719,719,719,719,719,719,719,719,719,719,719, -719,719,719,719,719,719,719,719,719,719,719,719,719,719,719,719, -720,720,720,720,720,720,720,721,721,721,721,721,722,722,722,722, -723,723,723,723,721,722,115,115,115,115,115,115,115,115,115,115, -724,724,724,724,724,724,724,724,724,724,115,725,725,725,725,725, -725,725,115,719,719,719,719,719,719,719,719,719,719,719,719,719, -719,719,719,719,719,719,719,719,115,115,115,115,115,719,719,719, /* block 185 */ -719,719,719,719,719,719,719,719,719,719,719,719,719,719,719,719, +776,776,776,776,776,776,776,776,776,776,776,776,776,776,776,776, +776,776,776,776,776,776,776,776,776,776,776,776,776,776,776,776, +776,776,776,776,776,776,776,776,776,776,776,776,776,776,776,776, +776,776,776,776,776,776,776,776,776,776,776,776,776,776,776,776, +776,776,776,776,776,776,776,776,776,776,776,776,776,776,776,776, +776,776,776,776,776,776,776,776,776,776,776,776,776,776,776,776, +776,776,776,776,776,776,776,776,776,776,776,776,776,776,776,776, +776,776,776,776,776,776,776,776,776,776,776,776,776,776,776,776, + +/* block 186 */ +776,776,776,776,776,776,776,776,776,776,776,776,776,776,776,776, +776,776,776,776,776,776,776,776,776,776,776,776,776,776,776,776, +776,776,776,776,776,776,776,776,776,776,776,776,776,776,776,776, +776,776,776,776,776,776,776,776,776,776,776,776,776,776,776,776, +776,776,776,776,776,776,776,115,115,115,115,115,115,115,115,115, +115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, + +/* block 187 */ +530,530,530,530,530,530,530,530,530,530,530,530,530,530,530,530, +530,530,530,530,530,530,530,530,530,530,530,530,530,530,530,530, +530,530,530,530,530,530,530,530,530,530,530,530,530,530,530,530, +530,530,530,530,530,530,530,530,530,530,530,530,530,530,530,530, +530,530,530,530,530,530,530,530,530,530,530,530,530,530,530,530, +530,530,530,530,530,530,530,530,530,530,530,530,530,530,530,530, +530,530,530,530,530,530,530,530,530,530,530,530,530,530,530,530, +530,530,530,530,530,530,530,530,530,530,530,530,530,530,530,530, + +/* block 188 */ +530,530,530,530,530,530,530,530,530,530,530,530,530,530,530,530, +530,530,530,530,530,530,530,530,530,530,530,530,530,530,530,530, +530,530,530,530,530,530,530,530,530,530,530,530,530,530,530,530, +530,530,530,530,530,530,530,530,530,115,115,115,115,115,115,115, +777,777,777,777,777,777,777,777,777,777,777,777,777,777,777,777, +777,777,777,777,777,777,777,777,777,777,777,777,777,777,777,115, +778,778,778,778,778,778,778,778,778,778,115,115,115,115,779,779, +115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, + +/* block 189 */ 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, +780,780,780,780,780,780,780,780,780,780,780,780,780,780,780,780, +780,780,780,780,780,780,780,780,780,780,780,780,780,780,115,115, +781,781,781,781,781,782,115,115,115,115,115,115,115,115,115,115, -/* block 186 */ -726,726,726,726,726,726,726,726,726,726,726,726,726,726,726,726, -726,726,726,726,726,726,726,726,726,726,726,726,726,726,726,726, -726,726,726,726,726,726,726,726,726,726,726,726,726,726,726,726, -726,726,726,726,726,726,726,726,726,726,726,726,726,726,726,726, -726,726,726,726,726,115,115,115,115,115,115,115,115,115,115,115, -726,727,727,727,727,727,727,727,727,727,727,727,727,727,727,727, -727,727,727,727,727,727,727,727,727,727,727,727,727,727,727,727, -727,727,727,727,727,727,727,727,727,727,727,727,727,727,727,115, +/* block 190 */ +783,783,783,783,783,783,783,783,783,783,783,783,783,783,783,783, +783,783,783,783,783,783,783,783,783,783,783,783,783,783,783,783, +783,783,783,783,783,783,783,783,783,783,783,783,783,783,783,783, +784,784,784,784,784,784,784,785,785,785,785,785,786,786,786,786, +787,787,787,787,785,786,115,115,115,115,115,115,115,115,115,115, +788,788,788,788,788,788,788,788,788,788,115,789,789,789,789,789, +789,789,115,783,783,783,783,783,783,783,783,783,783,783,783,783, +783,783,783,783,783,783,783,783,115,115,115,115,115,783,783,783, -/* block 187 */ -115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,728, -728,728,728,729,729,729,729,729,729,729,729,729,729,729,729,729, +/* block 191 */ +783,783,783,783,783,783,783,783,783,783,783,783,783,783,783,783, +115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, @@ -3257,29 +3396,119 @@ const uint16_t PRIV(ucd_stage2)[] = { /* 60416 bytes, block = 128 */ 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, -/* block 188 */ -479,477,115,115,115,115,115,115,115,115,115,115,115,115,115,115, +/* block 192 */ +790,790,790,790,790,790,790,790,790,790,790,790,790,790,790,790, +790,790,790,790,790,790,790,790,790,790,790,790,790,790,790,790, +790,790,790,790,790,790,790,790,790,790,790,790,790,790,790,790, +790,790,790,790,790,790,790,790,790,790,790,790,790,790,790,790, +790,790,790,790,790,115,115,115,115,115,115,115,115,115,115,115, +790,791,791,791,791,791,791,791,791,791,791,791,791,791,791,791, +791,791,791,791,791,791,791,791,791,791,791,791,791,791,791,791, +791,791,791,791,791,791,791,791,791,791,791,791,791,791,791,115, + +/* block 193 */ +115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,792, +792,792,792,793,793,793,793,793,793,793,793,793,793,793,793,793, +115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, +115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, +794,795,115,115,115,115,115,115,115,115,115,115,115,115,115,115, +115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, + +/* block 194 */ +796,796,796,796,796,796,796,796,796,796,796,796,796,796,796,796, +796,796,796,796,796,796,796,796,796,796,796,796,796,796,796,796, +796,796,796,796,796,796,796,796,796,796,796,796,796,796,796,796, +796,796,796,796,796,796,796,796,796,796,796,796,796,796,796,796, +796,796,796,796,796,796,796,796,796,796,796,796,796,796,796,796, +796,796,796,796,796,796,796,796,796,796,796,796,796,796,796,796, +796,796,796,796,796,796,796,796,796,796,796,796,796,796,796,796, +796,796,796,796,796,796,796,796,796,796,796,796,796,796,796,796, + +/* block 195 */ +796,796,796,796,796,796,796,796,796,796,796,796,796,796,796,796, +796,796,796,796,796,796,796,796,796,796,796,796,796,796,796,796, +796,796,796,796,796,796,796,796,796,796,796,796,796,796,796,796, +796,796,796,796,796,796,796,796,796,796,796,796,796,796,796,796, +796,796,796,796,796,796,796,796,796,796,796,796,796,796,796,796, +796,796,796,796,796,796,796,796,796,796,796,796,796,796,796,796, +796,796,796,796,796,796,796,796,796,796,796,796,796,115,115,115, +115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, + +/* block 196 */ +796,796,796,796,796,796,796,796,796,796,796,796,796,796,796,796, +796,796,796,796,796,796,796,796,796,796,796,796,796,796,796,796, +796,796,796,796,796,796,796,796,796,796,796,796,796,796,796,796, +796,796,796,796,796,796,796,796,796,796,796,796,796,796,796,796, +796,796,796,796,796,796,796,796,796,796,796,796,796,796,796,796, +796,796,796,796,796,796,796,796,796,796,796,796,796,796,796,796, +796,796,796,796,796,796,796,796,796,796,796,796,796,796,796,796, +796,796,796,115,115,115,115,115,115,115,115,115,115,115,115,115, + +/* block 197 */ +509,507,507,507,507,507,507,507,507,507,507,507,507,507,507,507, +507,507,507,507,507,507,507,507,507,507,507,507,507,507,507,507, +507,507,507,507,507,507,507,507,507,507,507,507,507,507,507,507, +507,507,507,507,507,507,507,507,507,507,507,507,507,507,507,507, +507,507,507,507,507,507,507,507,507,507,507,507,507,507,507,507, +507,507,507,507,507,507,507,507,507,507,507,507,507,507,507,507, +507,507,507,507,507,507,507,507,507,507,507,507,507,507,507,507, +507,507,507,507,507,507,507,507,507,507,507,507,507,507,507,507, + +/* block 198 */ +507,507,507,507,507,507,507,507,507,507,507,507,507,507,507,507, +507,507,507,507,507,507,507,507,507,507,507,507,507,507,507,507, +507,507,507,507,507,507,507,507,507,507,507,507,507,507,507,507, +507,507,507,507,507,507,507,507,507,507,507,507,507,507,507,507, +507,507,507,507,507,507,507,507,507,507,507,507,507,507,507,507, +507,507,507,507,507,507,507,507,507,507,507,507,507,507,507,507, +507,507,507,507,507,507,507,507,507,507,507,507,507,507,507,507, +507,507,507,507,507,507,507,507,507,507,507,507,507,507,507,507, + +/* block 199 */ +507,507,507,507,507,507,507,507,507,507,507,507,507,507,507,507, +507,507,507,507,507,507,507,507,507,507,507,507,507,507,507,115, 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, +797,797,797,797,797,797,797,797,797,797,797,797,797,797,797,797, -/* block 189 */ -730,730,730,730,730,730,730,730,730,730,730,730,730,730,730,730, -730,730,730,730,730,730,730,730,730,730,730,730,730,730,730,730, -730,730,730,730,730,730,730,730,730,730,730,730,730,730,730,730, -730,730,730,730,730,730,730,730,730,730,730,730,730,730,730,730, -730,730,730,730,730,730,730,730,730,730,730,730,730,730,730,730, -730,730,730,730,730,730,730,730,730,730,730,730,730,730,730,730, -730,730,730,730,730,730,730,730,730,730,730,115,115,115,115,115, -730,730,730,730,730,730,730,730,730,730,730,730,730,115,115,115, +/* block 200 */ +797,797,797,797,797,797,797,797,797,797,797,797,797,797,797,797, +797,797,797,797,797,797,797,797,797,797,797,797,797,797,797,797, +797,797,797,797,797,797,797,797,797,797,797,797,797,797,797,797, +797,797,797,797,797,797,797,797,797,797,797,797,797,797,797,797, +797,797,797,797,797,797,797,797,797,797,797,797,797,797,797,797, +797,797,797,797,797,797,797,797,797,797,797,797,797,797,797,797, +797,797,797,797,797,797,797,797,797,797,797,797,797,797,797,797, +797,797,797,797,797,797,797,797,797,797,797,797,797,797,797,797, -/* block 190 */ -730,730,730,730,730,730,730,730,730,115,115,115,115,115,115,115, -730,730,730,730,730,730,730,730,730,730,115,115,731,732,732,733, +/* block 201 */ +797,797,797,797,797,797,797,797,797,797,797,797,797,797,797,797, +797,797,797,797,797,797,797,797,797,797,797,797,797,797,797,797, +797,797,797,797,797,797,797,797,797,797,797,797,797,797,797,797, +797,797,797,797,797,797,797,797,797,797,797,797,797,797,797,797, +797,797,797,797,797,797,797,797,797,797,797,797,797,797,797,797, +797,797,797,797,797,797,797,797,797,797,797,797,797,797,797,797, +797,797,797,797,797,797,797,797,797,797,797,797,797,797,797,797, +797,797,797,797,797,797,797,797,797,797,797,797,115,115,115,115, + +/* block 202 */ +798,798,798,798,798,798,798,798,798,798,798,798,798,798,798,798, +798,798,798,798,798,798,798,798,798,798,798,798,798,798,798,798, +798,798,798,798,798,798,798,798,798,798,798,798,798,798,798,798, +798,798,798,798,798,798,798,798,798,798,798,798,798,798,798,798, +798,798,798,798,798,798,798,798,798,798,798,798,798,798,798,798, +798,798,798,798,798,798,798,798,798,798,798,798,798,798,798,798, +798,798,798,798,798,798,798,798,798,798,798,115,115,115,115,115, +798,798,798,798,798,798,798,798,798,798,798,798,798,115,115,115, + +/* block 203 */ +798,798,798,798,798,798,798,798,798,115,115,115,115,115,115,115, +798,798,798,798,798,798,798,798,798,798,115,115,799,800,800,801, 22, 22, 22, 22,115,115,115,115,115,115,115,115,115,115,115,115, 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, @@ -3287,7 +3516,7 @@ const uint16_t PRIV(ucd_stage2)[] = { /* 60416 bytes, block = 128 */ 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, -/* block 191 */ +/* block 204 */ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, @@ -3297,17 +3526,17 @@ const uint16_t PRIV(ucd_stage2)[] = { /* 60416 bytes, block = 128 */ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,115,115,115,115,115,115,115,115,115,115, -/* block 192 */ +/* block 205 */ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,115,115, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19,734,406,110,110,110, 19, 19, 19,406,734,734, -734,734,734, 22, 22, 22, 22, 22, 22, 22, 22,110,110,110,110,110, + 19, 19, 19, 19, 19,802,433,110,110,110, 19, 19, 19,433,802,802, +802,802,802, 22, 22, 22, 22, 22, 22, 22, 22,110,110,110,110,110, -/* block 193 */ +/* block 206 */ 110,110,110, 19, 19,110,110,110,110,110,110,110, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,110,110,110,110, 19, 19, @@ -3317,17 +3546,17 @@ const uint16_t PRIV(ucd_stage2)[] = { /* 60416 bytes, block = 128 */ 19, 19, 19, 19, 19, 19, 19, 19, 19,115,115,115,115,115,115,115, 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, -/* block 194 */ -564,564,564,564,564,564,564,564,564,564,564,564,564,564,564,564, -564,564,564,564,564,564,564,564,564,564,564,564,564,564,564,564, -564,564,564,564,564,564,564,564,564,564,564,564,564,564,564,564, -564,564,564,564,564,564,564,564,564,564,564,564,564,564,564,564, -564,564,735,735,735,564,115,115,115,115,115,115,115,115,115,115, +/* block 207 */ +596,596,596,596,596,596,596,596,596,596,596,596,596,596,596,596, +596,596,596,596,596,596,596,596,596,596,596,596,596,596,596,596, +596,596,596,596,596,596,596,596,596,596,596,596,596,596,596,596, +596,596,596,596,596,596,596,596,596,596,596,596,596,596,596,596, +596,596,803,803,803,596,115,115,115,115,115,115,115,115,115,115, 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, -/* block 195 */ +/* block 208 */ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, @@ -3337,157 +3566,177 @@ const uint16_t PRIV(ucd_stage2)[] = { /* 60416 bytes, block = 128 */ 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,115,115,115,115,115,115,115,115,115,115,115,115,115,115, -/* block 196 */ -438,438,438,438,438,438,438,438,438,438,438,438,438,438,438,438, -438,438,438,438,438,438,438,438,438,438,439,439,439,439,439,439, -439,439,439,439,439,439,439,439,439,439,439,439,439,439,439,439, -439,439,439,439,438,438,438,438,438,438,438,438,438,438,438,438, -438,438,438,438,438,438,438,438,438,438,438,438,438,438,439,439, -439,439,439,439,439,115,439,439,439,439,439,439,439,439,439,439, -439,439,439,439,439,439,439,439,438,438,438,438,438,438,438,438, -438,438,438,438,438,438,438,438,438,438,438,438,438,438,438,438, +/* block 209 */ +466,466,466,466,466,466,466,466,466,466,466,466,466,466,466,466, +466,466,466,466,466,466,466,466,466,466,467,467,467,467,467,467, +467,467,467,467,467,467,467,467,467,467,467,467,467,467,467,467, +467,467,467,467,466,466,466,466,466,466,466,466,466,466,466,466, +466,466,466,466,466,466,466,466,466,466,466,466,466,466,467,467, +467,467,467,467,467,115,467,467,467,467,467,467,467,467,467,467, +467,467,467,467,467,467,467,467,466,466,466,466,466,466,466,466, +466,466,466,466,466,466,466,466,466,466,466,466,466,466,466,466, -/* block 197 */ -438,438,439,439,439,439,439,439,439,439,439,439,439,439,439,439, -439,439,439,439,439,439,439,439,439,439,439,439,438,115,438,438, -115,115,438,115,115,438,438,115,115,438,438,438,438,115,438,438, -438,438,438,438,438,438,439,439,439,439,115,439,115,439,439,439, -439,439,439,439,115,439,439,439,439,439,439,439,439,439,439,439, -438,438,438,438,438,438,438,438,438,438,438,438,438,438,438,438, -438,438,438,438,438,438,438,438,438,438,439,439,439,439,439,439, -439,439,439,439,439,439,439,439,439,439,439,439,439,439,439,439, +/* block 210 */ +466,466,467,467,467,467,467,467,467,467,467,467,467,467,467,467, +467,467,467,467,467,467,467,467,467,467,467,467,466,115,466,466, +115,115,466,115,115,466,466,115,115,466,466,466,466,115,466,466, +466,466,466,466,466,466,467,467,467,467,115,467,115,467,467,467, +467,467,467,467,115,467,467,467,467,467,467,467,467,467,467,467, +466,466,466,466,466,466,466,466,466,466,466,466,466,466,466,466, +466,466,466,466,466,466,466,466,466,466,467,467,467,467,467,467, +467,467,467,467,467,467,467,467,467,467,467,467,467,467,467,467, -/* block 198 */ -439,439,439,439,438,438,115,438,438,438,438,115,115,438,438,438, -438,438,438,438,438,115,438,438,438,438,438,438,438,115,439,439, -439,439,439,439,439,439,439,439,439,439,439,439,439,439,439,439, -439,439,439,439,439,439,439,439,438,438,115,438,438,438,438,115, -438,438,438,438,438,115,438,115,115,115,438,438,438,438,438,438, -438,115,439,439,439,439,439,439,439,439,439,439,439,439,439,439, -439,439,439,439,439,439,439,439,439,439,439,439,438,438,438,438, -438,438,438,438,438,438,438,438,438,438,438,438,438,438,438,438, +/* block 211 */ +467,467,467,467,466,466,115,466,466,466,466,115,115,466,466,466, +466,466,466,466,466,115,466,466,466,466,466,466,466,115,467,467, +467,467,467,467,467,467,467,467,467,467,467,467,467,467,467,467, +467,467,467,467,467,467,467,467,466,466,115,466,466,466,466,115, +466,466,466,466,466,115,466,115,115,115,466,466,466,466,466,466, +466,115,467,467,467,467,467,467,467,467,467,467,467,467,467,467, +467,467,467,467,467,467,467,467,467,467,467,467,466,466,466,466, +466,466,466,466,466,466,466,466,466,466,466,466,466,466,466,466, -/* block 199 */ -438,438,438,438,438,438,439,439,439,439,439,439,439,439,439,439, -439,439,439,439,439,439,439,439,439,439,439,439,439,439,439,439, -438,438,438,438,438,438,438,438,438,438,438,438,438,438,438,438, -438,438,438,438,438,438,438,438,438,438,439,439,439,439,439,439, -439,439,439,439,439,439,439,439,439,439,439,439,439,439,439,439, -439,439,439,439,438,438,438,438,438,438,438,438,438,438,438,438, -438,438,438,438,438,438,438,438,438,438,438,438,438,438,439,439, -439,439,439,439,439,439,439,439,439,439,439,439,439,439,439,439, +/* block 212 */ +466,466,466,466,466,466,467,467,467,467,467,467,467,467,467,467, +467,467,467,467,467,467,467,467,467,467,467,467,467,467,467,467, +466,466,466,466,466,466,466,466,466,466,466,466,466,466,466,466, +466,466,466,466,466,466,466,466,466,466,467,467,467,467,467,467, +467,467,467,467,467,467,467,467,467,467,467,467,467,467,467,467, +467,467,467,467,466,466,466,466,466,466,466,466,466,466,466,466, +466,466,466,466,466,466,466,466,466,466,466,466,466,466,467,467, +467,467,467,467,467,467,467,467,467,467,467,467,467,467,467,467, -/* block 200 */ -439,439,439,439,439,439,439,439,438,438,438,438,438,438,438,438, -438,438,438,438,438,438,438,438,438,438,438,438,438,438,438,438, -438,438,439,439,439,439,439,439,439,439,439,439,439,439,439,439, -439,439,439,439,439,439,439,439,439,439,439,439,438,438,438,438, -438,438,438,438,438,438,438,438,438,438,438,438,438,438,438,438, -438,438,438,438,438,438,439,439,439,439,439,439,439,439,439,439, -439,439,439,439,439,439,439,439,439,439,439,439,439,439,439,439, -438,438,438,438,438,438,438,438,438,438,438,438,438,438,438,438, +/* block 213 */ +467,467,467,467,467,467,467,467,466,466,466,466,466,466,466,466, +466,466,466,466,466,466,466,466,466,466,466,466,466,466,466,466, +466,466,467,467,467,467,467,467,467,467,467,467,467,467,467,467, +467,467,467,467,467,467,467,467,467,467,467,467,466,466,466,466, +466,466,466,466,466,466,466,466,466,466,466,466,466,466,466,466, +466,466,466,466,466,466,467,467,467,467,467,467,467,467,467,467, +467,467,467,467,467,467,467,467,467,467,467,467,467,467,467,467, +466,466,466,466,466,466,466,466,466,466,466,466,466,466,466,466, -/* block 201 */ -438,438,438,438,438,438,438,438,438,438,439,439,439,439,439,439, -439,439,439,439,439,439,439,439,439,439,439,439,439,439,439,439, -439,439,439,439,439,439,115,115,438,438,438,438,438,438,438,438, -438,438,438,438,438,438,438,438,438,438,438,438,438,438,438,438, -438, 8,439,439,439,439,439,439,439,439,439,439,439,439,439,439, -439,439,439,439,439,439,439,439,439,439,439, 8,439,439,439,439, -439,439,438,438,438,438,438,438,438,438,438,438,438,438,438,438, -438,438,438,438,438,438,438,438,438,438,438, 8,439,439,439,439, +/* block 214 */ +466,466,466,466,466,466,466,466,466,466,467,467,467,467,467,467, +467,467,467,467,467,467,467,467,467,467,467,467,467,467,467,467, +467,467,467,467,467,467,115,115,466,466,466,466,466,466,466,466, +466,466,466,466,466,466,466,466,466,466,466,466,466,466,466,466, +466, 8,467,467,467,467,467,467,467,467,467,467,467,467,467,467, +467,467,467,467,467,467,467,467,467,467,467, 8,467,467,467,467, +467,467,466,466,466,466,466,466,466,466,466,466,466,466,466,466, +466,466,466,466,466,466,466,466,466,466,466, 8,467,467,467,467, -/* block 202 */ -439,439,439,439,439,439,439,439,439,439,439,439,439,439,439,439, -439,439,439,439,439, 8,439,439,439,439,439,439,438,438,438,438, -438,438,438,438,438,438,438,438,438,438,438,438,438,438,438,438, -438,438,438,438,438, 8,439,439,439,439,439,439,439,439,439,439, -439,439,439,439,439,439,439,439,439,439,439,439,439,439,439, 8, -439,439,439,439,439,439,438,438,438,438,438,438,438,438,438,438, -438,438,438,438,438,438,438,438,438,438,438,438,438,438,438, 8, -439,439,439,439,439,439,439,439,439,439,439,439,439,439,439,439, +/* block 215 */ +467,467,467,467,467,467,467,467,467,467,467,467,467,467,467,467, +467,467,467,467,467, 8,467,467,467,467,467,467,466,466,466,466, +466,466,466,466,466,466,466,466,466,466,466,466,466,466,466,466, +466,466,466,466,466, 8,467,467,467,467,467,467,467,467,467,467, +467,467,467,467,467,467,467,467,467,467,467,467,467,467,467, 8, +467,467,467,467,467,467,466,466,466,466,466,466,466,466,466,466, +466,466,466,466,466,466,466,466,466,466,466,466,466,466,466, 8, +467,467,467,467,467,467,467,467,467,467,467,467,467,467,467,467, -/* block 203 */ -439,439,439,439,439,439,439,439,439, 8,439,439,439,439,439,439, -438,438,438,438,438,438,438,438,438,438,438,438,438,438,438,438, -438,438,438,438,438,438,438,438,438, 8,439,439,439,439,439,439, -439,439,439,439,439,439,439,439,439,439,439,439,439,439,439,439, -439,439,439, 8,439,439,439,439,439,439,438,439,115,115, 10, 10, +/* block 216 */ +467,467,467,467,467,467,467,467,467, 8,467,467,467,467,467,467, +466,466,466,466,466,466,466,466,466,466,466,466,466,466,466,466, +466,466,466,466,466,466,466,466,466, 8,467,467,467,467,467,467, +467,467,467,467,467,467,467,467,467,467,467,467,467,467,467,467, +467,467,467, 8,467,467,467,467,467,467,466,467,115,115, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, -/* block 204 */ -736,736,736,736,736,736,736,736,736,736,736,736,736,736,736,736, -736,736,736,736,736,736,736,736,736,736,736,736,736,736,736,736, -736,736,736,736,736,736,736,736,736,736,736,736,736,736,736,736, -736,736,736,736,736,736,736,736,736,736,736,736,736,736,736,736, -736,736,736,736,736,736,736,736,736,736,736,736,736,736,736,736, -736,736,736,736,736,736,736,736,736,736,736,736,736,736,736,736, -736,736,736,736,736,736,736,736,736,736,736,736,736,736,736,736, -736,736,736,736,736,736,736,736,736,736,736,736,736,736,736,736, +/* block 217 */ +804,804,804,804,804,804,804,804,804,804,804,804,804,804,804,804, +804,804,804,804,804,804,804,804,804,804,804,804,804,804,804,804, +804,804,804,804,804,804,804,804,804,804,804,804,804,804,804,804, +804,804,804,804,804,804,804,804,804,804,804,804,804,804,804,804, +804,804,804,804,804,804,804,804,804,804,804,804,804,804,804,804, +804,804,804,804,804,804,804,804,804,804,804,804,804,804,804,804, +804,804,804,804,804,804,804,804,804,804,804,804,804,804,804,804, +804,804,804,804,804,804,804,804,804,804,804,804,804,804,804,804, -/* block 205 */ -737,737,737,737,737,737,737,737,737,737,737,737,737,737,737,737, -737,737,737,737,737,737,737,737,737,737,737,737,737,737,737,737, -737,737,737,737,737,737,737,737,737,737,737,737,737,737,737,737, -737,737,737,737,737,737,737,736,736,736,736,737,737,737,737,737, -737,737,737,737,737,737,737,737,737,737,737,737,737,737,737,737, -737,737,737,737,737,737,737,737,737,737,737,737,737,737,737,737, -737,737,737,737,737,737,737,737,737,737,737,737,737,736,736,736, -736,736,736,736,736,737,736,736,736,736,736,736,736,736,736,736, +/* block 218 */ +805,805,805,805,805,805,805,805,805,805,805,805,805,805,805,805, +805,805,805,805,805,805,805,805,805,805,805,805,805,805,805,805, +805,805,805,805,805,805,805,805,805,805,805,805,805,805,805,805, +805,805,805,805,805,805,805,804,804,804,804,805,805,805,805,805, +805,805,805,805,805,805,805,805,805,805,805,805,805,805,805,805, +805,805,805,805,805,805,805,805,805,805,805,805,805,805,805,805, +805,805,805,805,805,805,805,805,805,805,805,805,805,804,804,804, +804,804,804,804,804,805,804,804,804,804,804,804,804,804,804,804, -/* block 206 */ -736,736,736,736,737,736,736,738,738,738,738,738,115,115,115,115, -115,115,115,115,115,115,115,115,115,115,115,737,737,737,737,737, -115,737,737,737,737,737,737,737,737,737,737,737,737,737,737,737, +/* block 219 */ +804,804,804,804,805,804,804,806,806,806,806,806,115,115,115,115, +115,115,115,115,115,115,115,115,115,115,115,805,805,805,805,805, +115,805,805,805,805,805,805,805,805,805,805,805,805,805,805,805, 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, -/* block 207 */ -739,739,739,739,739,739,739,739,739,739,739,739,739,739,739,739, -739,739,739,739,739,739,739,739,739,739,739,739,739,739,739,739, -739,739,739,739,739,739,739,739,739,739,739,739,739,739,739,739, -739,739,739,739,739,739,739,739,739,739,739,739,739,739,739,739, -739,739,739,739,739,739,739,739,739,739,739,739,739,739,739,739, -739,739,739,739,739,739,739,739,739,739,739,739,739,739,739,739, -739,739,739,739,739,739,739,739,739,739,739,739,739,739,739,739, -739,739,739,739,739,739,739,739,739,739,739,739,739,739,739,739, +/* block 220 */ +807,807,807,807,807,807,807,115,807,807,807,807,807,807,807,807, +807,807,807,807,807,807,807,807,807,115,115,807,807,807,807,807, +807,807,115,807,807,115,807,807,807,807,807,115,115,115,115,115, +115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, +115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, +115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, +115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, +115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, -/* block 208 */ -739,739,739,739,739,739,739,739,739,739,739,739,739,739,739,739, -739,739,739,739,739,739,739,739,739,739,739,739,739,739,739,739, -739,739,739,739,739,739,739,739,739,739,739,739,739,739,739,739, -739,739,739,739,739,739,739,739,739,739,739,739,739,739,739,739, -739,739,739,739,739,115,115,740,740,740,740,740,740,740,740,740, -741,741,741,741,741,741,741,115,115,115,115,115,115,115,115,115, +/* block 221 */ +808,808,808,808,808,808,808,808,808,808,808,808,808,808,808,808, +808,808,808,808,808,808,808,808,808,808,808,808,808,808,808,808, +808,808,808,808,808,808,808,808,808,808,808,808,808,808,808,808, +808,808,808,808,808,808,808,808,808,808,808,808,808,808,808,808, +808,808,808,808,808,808,808,808,808,808,808,808,808,808,808,808, +808,808,808,808,808,808,808,808,808,808,808,808,808,808,808,808, +808,808,808,808,808,808,808,808,808,808,808,808,808,808,808,808, +808,808,808,808,808,808,808,808,808,808,808,808,808,808,808,808, + +/* block 222 */ +808,808,808,808,808,808,808,808,808,808,808,808,808,808,808,808, +808,808,808,808,808,808,808,808,808,808,808,808,808,808,808,808, +808,808,808,808,808,808,808,808,808,808,808,808,808,808,808,808, +808,808,808,808,808,808,808,808,808,808,808,808,808,808,808,808, +808,808,808,808,808,115,115,809,809,809,809,809,809,809,809,809, +810,810,810,810,810,810,810,115,115,115,115,115,115,115,115,115, 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, -/* block 209 */ -200,200,200,200,115,200,200,200,200,200,200,200,200,200,200,200, -200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200, -115,200,200,115,200,115,115,200,115,200,200,200,200,200,200,200, -200,200,200,115,200,200,200,200,115,200,115,200,115,115,115,115, -115,115,200,115,115,115,115,200,115,200,115,200,115,200,200,200, -115,200,200,115,200,115,115,200,115,200,115,200,115,200,115,200, -115,200,200,115,200,115,115,200,200,200,200,115,200,200,200,200, -200,200,200,115,200,200,200,200,115,200,200,200,200,115,200,115, +/* block 223 */ +811,811,811,811,811,811,811,811,811,811,811,811,811,811,811,811, +811,811,811,811,811,811,811,811,811,811,811,811,811,811,811,811, +811,811,812,812,812,812,812,812,812,812,812,812,812,812,812,812, +812,812,812,812,812,812,812,812,812,812,812,812,812,812,812,812, +812,812,812,812,813,813,813,813,813,813,813,115,115,115,115,115, +814,814,814,814,814,814,814,814,814,814,115,115,115,115,815,815, +115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, +115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, -/* block 210 */ -200,200,200,200,200,200,200,200,200,200,115,200,200,200,200,200, -200,200,200,200,200,200,200,200,200,200,200,200,115,115,115,115, -115,200,200,200,115,200,200,200,200,200,115,200,200,200,200,200, -200,200,200,200,200,200,200,200,200,200,200,200,115,115,115,115, +/* block 224 */ +216,216,216,216,115,216,216,216,216,216,216,216,216,216,216,216, +216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216, +115,216,216,115,216,115,115,216,115,216,216,216,216,216,216,216, +216,216,216,115,216,216,216,216,115,216,115,216,115,115,115,115, +115,115,216,115,115,115,115,216,115,216,115,216,115,216,216,216, +115,216,216,115,216,115,115,216,115,216,115,216,115,216,115,216, +115,216,216,115,216,115,115,216,216,216,216,115,216,216,216,216, +216,216,216,115,216,216,216,216,115,216,216,216,216,115,216,115, + +/* block 225 */ +216,216,216,216,216,216,216,216,216,216,115,216,216,216,216,216, +216,216,216,216,216,216,216,216,216,216,216,216,115,115,115,115, +115,216,216,216,115,216,216,216,216,216,115,216,216,216,216,216, +216,216,216,216,216,216,216,216,216,216,216,216,115,115,115,115, 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, -195,195,115,115,115,115,115,115,115,115,115,115,115,115,115,115, +210,210,115,115,115,115,115,115,115,115,115,115,115,115,115,115, -/* block 211 */ +/* block 226 */ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,115,115,115,115, @@ -3497,7 +3746,7 @@ const uint16_t PRIV(ucd_stage2)[] = { /* 60416 bytes, block = 128 */ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, -/* block 212 */ +/* block 227 */ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,115,115,115,115,115,115,115,115,115,115,115,115, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,115, @@ -3507,7 +3756,7 @@ const uint16_t PRIV(ucd_stage2)[] = { /* 60416 bytes, block = 128 */ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,115,115,115,115,115,115,115,115,115,115, -/* block 213 */ +/* block 228 */ 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,115,115,115, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,115, @@ -3517,67 +3766,107 @@ const uint16_t PRIV(ucd_stage2)[] = { /* 60416 bytes, block = 128 */ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,115,115,115,115, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, -/* block 214 */ +/* block 229 */ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,115,115,115,115,115, -115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,115,115,115, 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, -115,115,115,115,115,115,742,742,742,742,742,742,742,742,742,742, -742,742,742,742,742,742,742,742,742,742,742,742,742,742,742,742, +115,115,115,115,115,115,816,816,816,816,816,816,816,816,816,816, +816,816,816,816,816,816,816,816,816,816,816,816,816,816,816,816, -/* block 215 */ -743, 19, 19,115,115,115,115,115,115,115,115,115,115,115,115,115, +/* block 230 */ +817, 19, 19,115,115,115,115,115,115,115,115,115,115,115,115,115, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,115,115,115,115,115, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,115,115,115,115, 19, 19, 19, 19, 19, 19, 19, 19, 19,115,115,115,115,115,115,115, 19, 19,115,115,115,115,115,115,115,115,115,115,115,115,115,115, -115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, + 19, 19, 19, 19, 19, 19,115,115,115,115,115,115,115,115,115,115, 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, -/* block 216 */ +/* block 231 */ + 19, 19, 19, 19, 19, 19, 19, 19,479, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,479, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19,479, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + +/* block 232 */ + 19, 19, 19, 19, 19,478, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19,479, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19,479, 19, 19, 19,479, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19,478,478,478, 19, 19,478, 19, 19,478,478,478, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 14, 14, 14, 14, 14, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,479, 19,479, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,818,818,818,818,818, -/* block 217 */ +/* block 233 */ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19,478,478, 19, 19,478,478,478,478,478,478,478,478,478,478, +478, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19,819,819,819,819, 19, 19, 19, 19,478, 19, +478,478,478,478,478,478,478,478,478, 19, 19, 19,478, 19, 19, 19, + +/* block 234 */ + 19,478,478,478, 19,478,478,478, 19, 19, 19,479, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,478, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,479,479, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,115, 19, 19, 19, 19, 19, -/* block 218 */ +/* block 235 */ + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19,479, 19, 19, 19, 19,479, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, - 19, 19, 19, 19,115, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19,478,478, 19, 19, 19, 19,478, 19, 19, 19, 19, 19, + +/* block 236 */ + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, +478, 19, 19, 19, 19,478,478, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19,479, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, -/* block 219 */ +/* block 237 */ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19,478,478,478, 19, 19, 19,478,478,478,478,478, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, - 19,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + +/* block 238 */ +479, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19,479, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19,478, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19,478,478,478, 19, 19, 19, 19, 19, 19, 19, 19, 19, +478, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,478, 19, 19, 19, + 19, 19, 19, 19, 19,115,115,115,115,115,115,115,115,115,115,115, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,115,115,115, - 19, 19, 19, 19,115,115,115,115,115,115,115,115,115,115,115,115, + 19, 19, 19, 19, 19, 19, 19, 19, 19,115,115,115,115,115,115,115, -/* block 220 */ +/* block 239 */ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, @@ -3587,7 +3876,7 @@ const uint16_t PRIV(ucd_stage2)[] = { /* 60416 bytes, block = 128 */ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,115,115,115,115,115,115,115,115,115,115,115,115, -/* block 221 */ +/* block 240 */ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, @@ -3597,7 +3886,7 @@ const uint16_t PRIV(ucd_stage2)[] = { /* 60416 bytes, block = 128 */ 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, -/* block 222 */ +/* block 241 */ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,115,115,115,115, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, @@ -3607,7 +3896,7 @@ const uint16_t PRIV(ucd_stage2)[] = { /* 60416 bytes, block = 128 */ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, -/* block 223 */ +/* block 242 */ 19, 19, 19, 19, 19, 19, 19, 19,115,115,115,115,115,115,115,115, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,115,115, @@ -3617,97 +3906,107 @@ const uint16_t PRIV(ucd_stage2)[] = { /* 60416 bytes, block = 128 */ 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, -/* block 224 */ -115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, - 19, 19, 19, 19, 19, 19, 19, 19, 19,115,115,115,115,115,115,115, -115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, -115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, -115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, -115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, -115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, +/* block 243 */ + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,115,115,115,115, + 19, 19, 19, 19, 19, 19, 19, 19,478,478,478,478,478, 19,478,478, + 19, 19, 19, 19, 19, 19,478, 19, 19, 19, 19, 19, 19, 19, 19, 19, +478,478,478,478,478,478,478,478,478,478, 19, 19, 19,478,478,115, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,115,115,115, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,115,115,115,115, 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, -/* block 225 */ - 19, 19, 19, 19, 19,115,115,115,115,115,115,115,115,115,115,115, -115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, +/* block 244 */ + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19,115,115,115,115,115,115,115,115, 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, 19,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, + 19,478,478,478,478,478,478,478,478,478,478,478,478,478, 19, 19, + 19, 19, 19, 19, 19, 19, 19,115,115,115,115,115,115,115,115,115, 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, -115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, -115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, - -/* block 226 */ -485,485,485,485,485,485,485,485,485,485,485,485,485,485,485,485, -485,485,485,485,485,485,485,485,485,485,485,485,485,485,485,485, -485,485,485,485,485,485,485,485,485,485,485,485,485,485,485,485, -485,485,485,485,485,485,485,485,485,485,485,485,485,485,485,485, -485,485,485,485,485,485,485,485,485,485,485,485,485,485,485,485, -485,485,485,485,485,485,485,115,115,115,115,115,115,115,115,115, -115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, -115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, - -/* block 227 */ -485,485,485,485,485,485,485,485,485,485,485,485,485,485,485,485, -485,485,485,485,485,485,485,485,485,485,485,485,485,485,485,485, -485,485,485,485,485,485,485,485,485,485,485,485,485,485,485,485, -485,485,485,485,485,115,115,115,115,115,115,115,115,115,115,115, -485,485,485,485,485,485,485,485,485,485,485,485,485,485,485,485, -485,485,485,485,485,485,485,485,485,485,485,485,485,485,485,485, -485,485,485,485,485,485,485,485,485,485,485,485,485,485,485,485, -485,485,485,485,485,485,485,485,485,485,485,485,485,485,485,485, - -/* block 228 */ -485,485,485,485,485,485,485,485,485,485,485,485,485,485,485,485, -485,485,485,485,485,485,485,485,485,485,485,485,485,485,115,115, -485,485,485,485,485,485,485,485,485,485,485,485,485,485,485,485, -485,485,485,485,485,485,485,485,485,485,485,485,485,485,485,485, -485,485,485,485,485,485,485,485,485,485,485,485,485,485,485,485, -485,485,485,485,485,485,485,485,485,485,485,485,485,485,485,485, -485,485,485,485,485,485,485,485,485,485,485,485,485,485,485,485, -485,485,485,485,485,485,485,485,485,485,485,485,485,485,485,485, - -/* block 229 */ -485,485,485,485,485,485,485,485,485,485,485,485,485,485,485,485, -485,485,485,485,485,485,485,485,485,485,485,485,485,485,485,485, -485,485,115,115,115,115,115,115,115,115,115,115,115,115,115,115, -115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, -115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, -115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, -115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, -115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, - -/* block 230 */ -485,485,485,485,485,485,485,485,485,485,485,485,485,485,485,485, -485,485,485,485,485,485,485,485,485,485,485,485,485,485,115,115, -115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, -115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, -115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, -115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, -115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, -115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, - -/* block 231 */ -437, 22,437,437,437,437,437,437,437,437,437,437,437,437,437,437, -437,437,437,437,437,437,437,437,437,437,437,437,437,437,437,437, - 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, - 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, - 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, - 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, - 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, - 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, - -/* block 232 */ -437,437,437,437,437,437,437,437,437,437,437,437,437,437,437,437, -437,437,437,437,437,437,437,437,437,437,437,437,437,437,437,437, -437,437,437,437,437,437,437,437,437,437,437,437,437,437,437,437, -437,437,437,437,437,437,437,437,437,437,437,437,437,437,437,437, -437,437,437,437,437,437,437,437,437,437,437,437,437,437,437,437, -437,437,437,437,437,437,437,437,437,437,437,437,437,437,437,437, -437,437,437,437,437,437,437,437,437,437,437,437,437,437,437,437, -437,437,437,437,437,437,437,437,437,437,437,437,437,437,437,437, -/* block 233 */ +/* block 245 */ +515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515, +515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515, +515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515, +515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515, +515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515, +515,515,515,515,515,515,515,115,115,115,115,115,115,115,115,115, +115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, +115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, + +/* block 246 */ +515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515, +515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515, +515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515, +515,515,515,515,515,115,115,115,115,115,115,115,115,115,115,115, +515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515, +515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515, +515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515, +515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515, + +/* block 247 */ +515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515, +515,515,515,515,515,515,515,515,515,515,515,515,515,515,115,115, +515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515, +515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515, +515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515, +515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515, +515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515, +515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515, + +/* block 248 */ +515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515, +515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515, +515,515,115,115,115,115,115,115,115,115,115,115,115,115,115,115, +515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515, +515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515, +515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515, +515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515, +515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515, + +/* block 249 */ +515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515, +515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515, +515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515, +515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515, +515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515, +515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515, +515,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, +115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, + +/* block 250 */ +515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515, +515,515,515,515,515,515,515,515,515,515,515,515,515,515,115,115, +115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, +115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, +115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, +115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, +115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, +115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115, + +/* block 251 */ +465, 22,465,465,465,465,465,465,465,465,465,465,465,465,465,465, +465,465,465,465,465,465,465,465,465,465,465,465,465,465,465,465, +820,820,820,820,820,820,820,820,820,820,820,820,820,820,820,820, +820,820,820,820,820,820,820,820,820,820,820,820,820,820,820,820, +820,820,820,820,820,820,820,820,820,820,820,820,820,820,820,820, +820,820,820,820,820,820,820,820,820,820,820,820,820,820,820,820, +820,820,820,820,820,820,820,820,820,820,820,820,820,820,820,820, +820,820,820,820,820,820,820,820,820,820,820,820,820,820,820,820, + +/* block 252 */ +465,465,465,465,465,465,465,465,465,465,465,465,465,465,465,465, +465,465,465,465,465,465,465,465,465,465,465,465,465,465,465,465, +465,465,465,465,465,465,465,465,465,465,465,465,465,465,465,465, +465,465,465,465,465,465,465,465,465,465,465,465,465,465,465,465, +465,465,465,465,465,465,465,465,465,465,465,465,465,465,465,465, +465,465,465,465,465,465,465,465,465,465,465,465,465,465,465,465, +465,465,465,465,465,465,465,465,465,465,465,465,465,465,465,465, +465,465,465,465,465,465,465,465,465,465,465,465,465,465,465,465, + +/* block 253 */ 110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110, 110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110, 110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110, @@ -3717,7 +4016,7 @@ const uint16_t PRIV(ucd_stage2)[] = { /* 60416 bytes, block = 128 */ 110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110, 110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110, -/* block 234 */ +/* block 254 */ 110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110, 110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110, 110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110, @@ -3725,17 +4024,17 @@ const uint16_t PRIV(ucd_stage2)[] = { /* 60416 bytes, block = 128 */ 110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110, 110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110, 110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110, -437,437,437,437,437,437,437,437,437,437,437,437,437,437,437,437, - -/* block 235 */ -557,557,557,557,557,557,557,557,557,557,557,557,557,557,557,557, -557,557,557,557,557,557,557,557,557,557,557,557,557,557,557,557, -557,557,557,557,557,557,557,557,557,557,557,557,557,557,557,557, -557,557,557,557,557,557,557,557,557,557,557,557,557,557,557,557, -557,557,557,557,557,557,557,557,557,557,557,557,557,557,557,557, -557,557,557,557,557,557,557,557,557,557,557,557,557,557,557,557, -557,557,557,557,557,557,557,557,557,557,557,557,557,557,557,557, -557,557,557,557,557,557,557,557,557,557,557,557,557,557,115,115, +465,465,465,465,465,465,465,465,465,465,465,465,465,465,465,465, + +/* block 255 */ +589,589,589,589,589,589,589,589,589,589,589,589,589,589,589,589, +589,589,589,589,589,589,589,589,589,589,589,589,589,589,589,589, +589,589,589,589,589,589,589,589,589,589,589,589,589,589,589,589, +589,589,589,589,589,589,589,589,589,589,589,589,589,589,589,589, +589,589,589,589,589,589,589,589,589,589,589,589,589,589,589,589, +589,589,589,589,589,589,589,589,589,589,589,589,589,589,589,589, +589,589,589,589,589,589,589,589,589,589,589,589,589,589,589,589, +589,589,589,589,589,589,589,589,589,589,589,589,589,589,115,115, }; diff --git a/thirdparty/pcre2/src/pcre2_ucp.h b/thirdparty/pcre2/src/pcre2_ucp.h index 02e5012c29..defba4c10e 100644 --- a/thirdparty/pcre2/src/pcre2_ucp.h +++ b/thirdparty/pcre2/src/pcre2_ucp.h @@ -100,9 +100,7 @@ enum { ucp_Zs /* Space separator */ }; -/* These are grapheme break properties. Note that the code for processing them -assumes that the values are less than 16. If more values are added that take -the number to 16 or more, the code will have to be rewritten. */ +/* These are grapheme break properties. */ enum { ucp_gbCR, /* 0 */ @@ -117,7 +115,12 @@ enum { ucp_gbLV, /* 9 Hangul syllable type LV */ ucp_gbLVT, /* 10 Hangul syllable type LVT */ ucp_gbRegionalIndicator, /* 11 */ - ucp_gbOther /* 12 */ + ucp_gbOther, /* 12 */ + ucp_gbE_Base, /* 13 */ + ucp_gbE_Modifier, /* 14 */ + ucp_gbE_Base_GAZ, /* 15 */ + ucp_gbZWJ, /* 16 */ + ucp_gbGlue_After_Zwj /* 17 */ }; /* These are the script identifications. */ @@ -184,13 +187,13 @@ enum { ucp_Tifinagh, ucp_Ugaritic, ucp_Yi, - /* New for Unicode 5.0: */ + /* New for Unicode 5.0 */ ucp_Balinese, ucp_Cuneiform, ucp_Nko, ucp_Phags_Pa, ucp_Phoenician, - /* New for Unicode 5.1: */ + /* New for Unicode 5.1 */ ucp_Carian, ucp_Cham, ucp_Kayah_Li, @@ -202,7 +205,7 @@ enum { ucp_Saurashtra, ucp_Sundanese, ucp_Vai, - /* New for Unicode 5.2: */ + /* New for Unicode 5.2 */ ucp_Avestan, ucp_Bamum, ucp_Egyptian_Hieroglyphs, @@ -218,11 +221,11 @@ enum { ucp_Samaritan, ucp_Tai_Tham, ucp_Tai_Viet, - /* New for Unicode 6.0.0: */ + /* New for Unicode 6.0.0 */ ucp_Batak, ucp_Brahmi, ucp_Mandaic, - /* New for Unicode 6.1.0: */ + /* New for Unicode 6.1.0 */ ucp_Chakma, ucp_Meroitic_Cursive, ucp_Meroitic_Hieroglyphs, @@ -230,7 +233,7 @@ enum { ucp_Sharada, ucp_Sora_Sompeng, ucp_Takri, - /* New for Unicode 7.0.0: */ + /* New for Unicode 7.0.0 */ ucp_Bassa_Vah, ucp_Caucasian_Albanian, ucp_Duployan, @@ -254,13 +257,24 @@ enum { ucp_Siddham, ucp_Tirhuta, ucp_Warang_Citi, - /* New for Unicode 8.0.0: */ + /* New for Unicode 8.0.0 */ ucp_Ahom, ucp_Anatolian_Hieroglyphs, ucp_Hatran, ucp_Multani, ucp_Old_Hungarian, - ucp_SignWriting + ucp_SignWriting, + /* New for Unicode 10.0.0 (no update since 8.0.0) */ + ucp_Adlam, + ucp_Bhaiksuki, + ucp_Marchen, + ucp_Newa, + ucp_Osage, + ucp_Tangut, + ucp_Masaram_Gondi, + ucp_Nushu, + ucp_Soyombo, + ucp_Zanabazar_Square }; #endif /* PCRE2_UCP_H_IDEMPOTENT_GUARD */ diff --git a/thirdparty/pcre2/src/pcre2_valid_utf.c b/thirdparty/pcre2/src/pcre2_valid_utf.c index 3e18f1200b..96e8bff993 100644 --- a/thirdparty/pcre2/src/pcre2_valid_utf.c +++ b/thirdparty/pcre2/src/pcre2_valid_utf.c @@ -7,7 +7,7 @@ and semantics are as close as possible to those of the Perl 5 language. Written by Philip Hazel Original API code Copyright (c) 1997-2012 University of Cambridge - New API code Copyright (c) 2016 University of Cambridge + New API code Copyright (c) 2016-2017 University of Cambridge ----------------------------------------------------------------------------- Redistribution and use in source and binary forms, with or without @@ -142,20 +142,20 @@ for (p = string; length > 0; p++) if (c < 0xc0) /* Isolated 10xx xxxx byte */ { - *erroroffset = (int)(p - string); + *erroroffset = (PCRE2_SIZE)(p - string); return PCRE2_ERROR_UTF8_ERR20; } if (c >= 0xfe) /* Invalid 0xfe or 0xff bytes */ { - *erroroffset = (int)(p - string); + *erroroffset = (PCRE2_SIZE)(p - string); return PCRE2_ERROR_UTF8_ERR21; } ab = PRIV(utf8_table4)[c & 0x3f]; /* Number of additional bytes (1-5) */ if (length < ab) /* Missing bytes */ { - *erroroffset = (int)(p - string); + *erroroffset = (PCRE2_SIZE)(p - string); switch(ab - length) { case 1: return PCRE2_ERROR_UTF8_ERR1; diff --git a/thirdparty/pcre2/src/sljit/sljitConfig.h b/thirdparty/pcre2/src/sljit/sljitConfig.h index 2e70224da8..d54b5e6f54 100644 --- a/thirdparty/pcre2/src/sljit/sljitConfig.h +++ b/thirdparty/pcre2/src/sljit/sljitConfig.h @@ -1,7 +1,7 @@ /* * Stack-less Just-In-Time compiler * - * Copyright 2009-2012 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved. + * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are * permitted provided that the following conditions are met: @@ -108,8 +108,10 @@ /* Force cdecl calling convention even if a better calling convention (e.g. fastcall) is supported by the C compiler. - If this option is enabled, C functions without - SLJIT_CALL can also be called from JIT code. */ + If this option is disabled (this is the default), functions + called from JIT should be defined with SLJIT_FUNC attribute. + Standard C functions can still be called by using the + SLJIT_CALL_CDECL jump type. */ #ifndef SLJIT_USE_CDECL_CALLING_CONVENTION /* Disabled by default */ #define SLJIT_USE_CDECL_CALLING_CONVENTION 0 diff --git a/thirdparty/pcre2/src/sljit/sljitConfigInternal.h b/thirdparty/pcre2/src/sljit/sljitConfigInternal.h index 5d461017e4..e13282c842 100644 --- a/thirdparty/pcre2/src/sljit/sljitConfigInternal.h +++ b/thirdparty/pcre2/src/sljit/sljitConfigInternal.h @@ -1,7 +1,7 @@ /* * Stack-less Just-In-Time compiler * - * Copyright 2009-2012 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved. + * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are * permitted provided that the following conditions are met: @@ -60,11 +60,13 @@ a single precision floating point array by index SLJIT_F64_SHIFT : the shift required to apply when accessing a double precision floating point array by index + SLJIT_PREF_SHIFT_REG : x86 systems prefers ecx for shifting by register + the scratch register index of ecx is stored in this variable SLJIT_LOCALS_OFFSET : local space starting offset (SLJIT_SP + SLJIT_LOCALS_OFFSET) SLJIT_RETURN_ADDRESS_OFFSET : a return instruction always adds this offset to the return address Other macros: - SLJIT_CALL : C calling convention define for both calling JIT form C and C callbacks for JIT + SLJIT_FUNC : calling convention attribute for both calling JIT form C and C calling back from JIT SLJIT_W(number) : defining 64 bit constants on 64 bit architectures (compiler independent helper) */ @@ -296,6 +298,13 @@ #define SLJIT_CACHE_FLUSH(from, to) \ sys_icache_invalidate((char*)(from), (char*)(to) - (char*)(from)) +#elif (defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC) + +/* The __clear_cache() implementation of GCC is a dummy function on PowerPC. */ +#define SLJIT_CACHE_FLUSH(from, to) \ + ppc_cache_flush((from), (to)) +#define SLJIT_CACHE_FLUSH_OWN_IMPL 1 + #elif (defined(__GNUC__) && (__GNUC__ >= 5 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3))) #define SLJIT_CACHE_FLUSH(from, to) \ @@ -308,13 +317,6 @@ #define SLJIT_CACHE_FLUSH(from, to) \ cacheflush((long)(from), (long)(to), 0) -#elif (defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC) - -/* The __clear_cache() implementation of GCC is a dummy function on PowerPC. */ -#define SLJIT_CACHE_FLUSH(from, to) \ - ppc_cache_flush((from), (to)) -#define SLJIT_CACHE_FLUSH_OWN_IMPL 1 - #elif (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32) /* The __clear_cache() implementation of GCC is a dummy function on Sparc. */ @@ -393,7 +395,9 @@ typedef double sljit_f64; #ifndef SLJIT_W /* Defining long constants. */ -#if (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE) +#if (defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED) +#define SLJIT_W(w) (w##l) +#elif (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE) #define SLJIT_W(w) (w##ll) #else #define SLJIT_W(w) (w) @@ -469,44 +473,44 @@ typedef double sljit_f64; /* Calling convention of functions generated by SLJIT or called from the generated code. */ /*****************************************************************************************/ -#ifndef SLJIT_CALL +#ifndef SLJIT_FUNC #if (defined SLJIT_USE_CDECL_CALLING_CONVENTION && SLJIT_USE_CDECL_CALLING_CONVENTION) /* Force cdecl. */ -#define SLJIT_CALL +#define SLJIT_FUNC #elif (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) #if defined(__GNUC__) && !defined(__APPLE__) -#define SLJIT_CALL __attribute__ ((fastcall)) +#define SLJIT_FUNC __attribute__ ((fastcall)) #define SLJIT_X86_32_FASTCALL 1 #elif defined(_MSC_VER) -#define SLJIT_CALL __fastcall +#define SLJIT_FUNC __fastcall #define SLJIT_X86_32_FASTCALL 1 #elif defined(__BORLANDC__) -#define SLJIT_CALL __msfastcall +#define SLJIT_FUNC __msfastcall #define SLJIT_X86_32_FASTCALL 1 #else /* Unknown compiler. */ /* The cdecl attribute is the default. */ -#define SLJIT_CALL +#define SLJIT_FUNC #endif #else /* Non x86-32 architectures. */ -#define SLJIT_CALL +#define SLJIT_FUNC #endif /* SLJIT_CONFIG_X86_32 */ -#endif /* !SLJIT_CALL */ +#endif /* !SLJIT_FUNC */ #ifndef SLJIT_INDIRECT_CALL #if ((defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) && (defined SLJIT_BIG_ENDIAN && SLJIT_BIG_ENDIAN)) \ @@ -553,48 +557,44 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_sw sljit_exec_offset(void* ptr); #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) -#define SLJIT_NUMBER_OF_REGISTERS 10 -#define SLJIT_NUMBER_OF_SAVED_REGISTERS 7 -#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL) -#define SLJIT_LOCALS_OFFSET_BASE ((2 + 4) * sizeof(sljit_sw)) -#else -/* Maximum 3 arguments are passed on the stack, +1 for double alignment. */ -#define SLJIT_LOCALS_OFFSET_BASE ((3 + 1 + 4) * sizeof(sljit_sw)) -#endif /* SLJIT_X86_32_FASTCALL */ +#define SLJIT_NUMBER_OF_REGISTERS 12 +#define SLJIT_NUMBER_OF_SAVED_REGISTERS 9 +#define SLJIT_LOCALS_OFFSET_BASE (compiler->locals_offset) +#define SLJIT_PREF_SHIFT_REG SLJIT_R2 #elif (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) +#define SLJIT_NUMBER_OF_REGISTERS 13 #ifndef _WIN64 -#define SLJIT_NUMBER_OF_REGISTERS 12 #define SLJIT_NUMBER_OF_SAVED_REGISTERS 6 -#define SLJIT_LOCALS_OFFSET_BASE (sizeof(sljit_sw)) -#else -#define SLJIT_NUMBER_OF_REGISTERS 12 +#define SLJIT_LOCALS_OFFSET_BASE 0 +#else /* _WIN64 */ #define SLJIT_NUMBER_OF_SAVED_REGISTERS 8 -#define SLJIT_LOCALS_OFFSET_BASE ((4 + 2) * sizeof(sljit_sw)) -#endif /* _WIN64 */ +#define SLJIT_LOCALS_OFFSET_BASE (compiler->locals_offset) +#endif /* !_WIN64 */ +#define SLJIT_PREF_SHIFT_REG SLJIT_R3 #elif (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) || (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7) -#define SLJIT_NUMBER_OF_REGISTERS 11 +#define SLJIT_NUMBER_OF_REGISTERS 12 #define SLJIT_NUMBER_OF_SAVED_REGISTERS 8 #define SLJIT_LOCALS_OFFSET_BASE 0 #elif (defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2) -#define SLJIT_NUMBER_OF_REGISTERS 11 -#define SLJIT_NUMBER_OF_SAVED_REGISTERS 7 +#define SLJIT_NUMBER_OF_REGISTERS 12 +#define SLJIT_NUMBER_OF_SAVED_REGISTERS 8 #define SLJIT_LOCALS_OFFSET_BASE 0 #elif (defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64) -#define SLJIT_NUMBER_OF_REGISTERS 25 +#define SLJIT_NUMBER_OF_REGISTERS 26 #define SLJIT_NUMBER_OF_SAVED_REGISTERS 10 #define SLJIT_LOCALS_OFFSET_BASE (2 * sizeof(sljit_sw)) #elif (defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC) -#define SLJIT_NUMBER_OF_REGISTERS 22 +#define SLJIT_NUMBER_OF_REGISTERS 23 #define SLJIT_NUMBER_OF_SAVED_REGISTERS 17 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) || (defined _AIX) #define SLJIT_LOCALS_OFFSET_BASE ((6 + 8) * sizeof(sljit_sw)) @@ -607,7 +607,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_sw sljit_exec_offset(void* ptr); #elif (defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS) -#define SLJIT_NUMBER_OF_REGISTERS 17 +#define SLJIT_NUMBER_OF_REGISTERS 21 #define SLJIT_NUMBER_OF_SAVED_REGISTERS 8 #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) #define SLJIT_LOCALS_OFFSET_BASE (4 * sizeof(sljit_sw)) @@ -620,8 +620,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_sw sljit_exec_offset(void* ptr); #define SLJIT_NUMBER_OF_REGISTERS 18 #define SLJIT_NUMBER_OF_SAVED_REGISTERS 14 #if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32) -/* Add +1 for double alignment. */ -#define SLJIT_LOCALS_OFFSET_BASE ((23 + 1) * sizeof(sljit_sw)) +/* saved registers (16), return struct pointer (1), space for 6 argument words (1), + 4th double arg (2), double alignment (1). */ +#define SLJIT_LOCALS_OFFSET_BASE ((16 + 1 + 6 + 2 + 1) * sizeof(sljit_sw)) #endif #elif (defined SLJIT_CONFIG_TILEGX && SLJIT_CONFIG_TILEGX) @@ -663,7 +664,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_sw sljit_exec_offset(void* ptr); #if (defined SLJIT_DEBUG && SLJIT_DEBUG) -#if !defined(SLJIT_ASSERT) || !defined(SLJIT_ASSERT_STOP) +#if !defined(SLJIT_ASSERT) || !defined(SLJIT_UNREACHABLE) /* SLJIT_HALT_PROCESS must halt the process. */ #ifndef SLJIT_HALT_PROCESS @@ -675,7 +676,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_sw sljit_exec_offset(void* ptr); #include <stdio.h> -#endif /* !SLJIT_ASSERT || !SLJIT_ASSERT_STOP */ +#endif /* !SLJIT_ASSERT || !SLJIT_UNREACHABLE */ /* Feel free to redefine these two macros. */ #ifndef SLJIT_ASSERT @@ -690,34 +691,33 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_sw sljit_exec_offset(void* ptr); #endif /* !SLJIT_ASSERT */ -#ifndef SLJIT_ASSERT_STOP +#ifndef SLJIT_UNREACHABLE -#define SLJIT_ASSERT_STOP() \ +#define SLJIT_UNREACHABLE() \ do { \ printf("Should never been reached " __FILE__ ":%d\n", __LINE__); \ SLJIT_HALT_PROCESS(); \ } while (0) -#endif /* !SLJIT_ASSERT_STOP */ +#endif /* !SLJIT_UNREACHABLE */ #else /* (defined SLJIT_DEBUG && SLJIT_DEBUG) */ /* Forcing empty, but valid statements. */ #undef SLJIT_ASSERT -#undef SLJIT_ASSERT_STOP +#undef SLJIT_UNREACHABLE #define SLJIT_ASSERT(x) \ do { } while (0) -#define SLJIT_ASSERT_STOP() \ +#define SLJIT_UNREACHABLE() \ do { } while (0) #endif /* (defined SLJIT_DEBUG && SLJIT_DEBUG) */ #ifndef SLJIT_COMPILE_ASSERT -/* Should be improved eventually. */ #define SLJIT_COMPILE_ASSERT(x, description) \ - SLJIT_ASSERT(x) + switch(0) { case 0: case ((x) ? 1 : 0): break; } #endif /* !SLJIT_COMPILE_ASSERT */ diff --git a/thirdparty/pcre2/src/sljit/sljitExecAllocator.c b/thirdparty/pcre2/src/sljit/sljitExecAllocator.c index 9f88f990b0..f5009788f6 100644 --- a/thirdparty/pcre2/src/sljit/sljitExecAllocator.c +++ b/thirdparty/pcre2/src/sljit/sljitExecAllocator.c @@ -1,7 +1,7 @@ /* * Stack-less Just-In-Time compiler * - * Copyright 2009-2012 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved. + * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are * permitted provided that the following conditions are met: diff --git a/thirdparty/pcre2/src/sljit/sljitLir.c b/thirdparty/pcre2/src/sljit/sljitLir.c index 0b39ec90a9..5e435f0154 100644 --- a/thirdparty/pcre2/src/sljit/sljitLir.c +++ b/thirdparty/pcre2/src/sljit/sljitLir.c @@ -1,7 +1,7 @@ /* * Stack-less Just-In-Time compiler * - * Copyright 2009-2012 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved. + * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are * permitted provided that the following conditions are met: @@ -84,17 +84,26 @@ #if !(defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED) +#define VARIABLE_FLAG_SHIFT (10) +#define VARIABLE_FLAG_MASK (0x3f << VARIABLE_FLAG_SHIFT) +#define GET_FLAG_TYPE(op) ((op) >> VARIABLE_FLAG_SHIFT) + #define GET_OPCODE(op) \ - ((op) & ~(SLJIT_I32_OP | SLJIT_SET_E | SLJIT_SET_U | SLJIT_SET_S | SLJIT_SET_O | SLJIT_SET_C | SLJIT_KEEP_FLAGS)) + ((op) & ~(SLJIT_I32_OP | SLJIT_SET_Z | VARIABLE_FLAG_MASK)) -#define GET_FLAGS(op) \ - ((op) & (SLJIT_SET_E | SLJIT_SET_U | SLJIT_SET_S | SLJIT_SET_O | SLJIT_SET_C)) +#define HAS_FLAGS(op) \ + ((op) & (SLJIT_SET_Z | VARIABLE_FLAG_MASK)) #define GET_ALL_FLAGS(op) \ - ((op) & (SLJIT_I32_OP | SLJIT_SET_E | SLJIT_SET_U | SLJIT_SET_S | SLJIT_SET_O | SLJIT_SET_C | SLJIT_KEEP_FLAGS)) + ((op) & (SLJIT_I32_OP | SLJIT_SET_Z | VARIABLE_FLAG_MASK)) +#if (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE) +#define TYPE_CAST_NEEDED(op) \ + ((op) >= SLJIT_MOV_U8 && (op) <= SLJIT_MOV_S32) +#else #define TYPE_CAST_NEEDED(op) \ - (((op) >= SLJIT_MOV_U8 && (op) <= SLJIT_MOV_S16) || ((op) >= SLJIT_MOVU_U8 && (op) <= SLJIT_MOVU_S16)) + ((op) >= SLJIT_MOV_U8 && (op) <= SLJIT_MOV_S16) +#endif #define BUF_SIZE 4096 @@ -114,16 +123,19 @@ /* When reg can be unused. */ #define SLOW_IS_REG(reg) ((reg) > 0 && (reg) <= REG_MASK) +/* Mask for argument types. */ +#define SLJIT_DEF_MASK ((1 << SLJIT_DEF_SHIFT) - 1) + /* Jump flags. */ #define JUMP_LABEL 0x1 #define JUMP_ADDR 0x2 /* SLJIT_REWRITABLE_JUMP is 0x1000. */ #if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86) -# define PATCH_MB 0x4 -# define PATCH_MW 0x8 +# define PATCH_MB 0x4 +# define PATCH_MW 0x8 #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) -# define PATCH_MD 0x10 +# define PATCH_MD 0x10 #endif #endif @@ -338,7 +350,7 @@ /* Public functions */ /* --------------------------------------------------------------------- */ -#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) || (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86) +#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86) #define SLJIT_NEEDS_COMPILER_INIT 1 static sljit_s32 compiler_initialized = 0; /* A thread safe initialization. */ @@ -365,6 +377,8 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_compiler* sljit_create_compiler(void *allo int_op_and_single_op_must_be_the_same); SLJIT_COMPILE_ASSERT(SLJIT_REWRITABLE_JUMP != SLJIT_F32_OP, rewritable_jump_and_single_op_must_not_be_the_same); + SLJIT_COMPILE_ASSERT(!(SLJIT_EQUAL & 0x1) && !(SLJIT_LESS & 0x1) && !(SLJIT_EQUAL_F64 & 0x1) && !(SLJIT_JUMP & 0x1), + conditional_flags_must_be_even_numbers); /* Only the non-zero members must be set. */ compiler->error = SLJIT_SUCCESS; @@ -499,6 +513,18 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_target(struct sljit_jump *jump, sljit_uw } } +SLJIT_API_FUNC_ATTRIBUTE void sljit_set_current_flags(struct sljit_compiler *compiler, sljit_s32 current_flags) +{ + SLJIT_UNUSED_ARG(compiler); + SLJIT_UNUSED_ARG(current_flags); + +#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) + if ((current_flags & ~(VARIABLE_FLAG_MASK | SLJIT_I32_OP | SLJIT_SET_Z)) == 0) { + compiler->last_flags = GET_FLAG_TYPE(current_flags) | (current_flags & (SLJIT_I32_OP | SLJIT_SET_Z)); + } +#endif +} + /* --------------------------------------------------------------------- */ /* Private functions */ /* --------------------------------------------------------------------- */ @@ -573,6 +599,19 @@ static SLJIT_INLINE void reverse_buf(struct sljit_compiler *compiler) compiler->buf = prev; } +static SLJIT_INLINE sljit_s32 get_arg_count(sljit_s32 arg_types) +{ + sljit_s32 arg_count = 0; + + arg_types >>= SLJIT_DEF_SHIFT; + while (arg_types) { + arg_count++; + arg_types >>= SLJIT_DEF_SHIFT; + } + + return arg_count; +} + static SLJIT_INLINE void set_emit_enter(struct sljit_compiler *compiler, sljit_s32 options, sljit_s32 args, sljit_s32 scratches, sljit_s32 saveds, sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size) @@ -644,150 +683,109 @@ static SLJIT_INLINE void set_const(struct sljit_const *const_, struct sljit_comp (((exp) & SLJIT_MEM) && (((exp) & REG_MASK) == reg || OFFS_REG(exp) == reg)) #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) -#define FUNCTION_CHECK_OP() \ - CHECK_ARGUMENT(!GET_FLAGS(op) || !(op & SLJIT_KEEP_FLAGS)); \ - switch (GET_OPCODE(op)) { \ - case SLJIT_NOT: \ - case SLJIT_CLZ: \ - case SLJIT_AND: \ - case SLJIT_OR: \ - case SLJIT_XOR: \ - case SLJIT_SHL: \ - case SLJIT_LSHR: \ - case SLJIT_ASHR: \ - CHECK_ARGUMENT(!(op & (SLJIT_SET_U | SLJIT_SET_S | SLJIT_SET_O | SLJIT_SET_C))); \ - break; \ - case SLJIT_NEG: \ - CHECK_ARGUMENT(!(op & (SLJIT_SET_U | SLJIT_SET_S | SLJIT_SET_C))); \ - break; \ - case SLJIT_MUL: \ - CHECK_ARGUMENT(!(op & (SLJIT_SET_E | SLJIT_SET_U | SLJIT_SET_S | SLJIT_SET_C))); \ - break; \ - case SLJIT_ADD: \ - CHECK_ARGUMENT(!(op & (SLJIT_SET_U | SLJIT_SET_S))); \ - break; \ - case SLJIT_SUB: \ - break; \ - case SLJIT_ADDC: \ - case SLJIT_SUBC: \ - CHECK_ARGUMENT(!(op & (SLJIT_SET_E | SLJIT_SET_U | SLJIT_SET_S | SLJIT_SET_O))); \ - break; \ - case SLJIT_BREAKPOINT: \ - case SLJIT_NOP: \ - case SLJIT_LMUL_UW: \ - case SLJIT_LMUL_SW: \ - case SLJIT_MOV: \ - case SLJIT_MOV_U32: \ - case SLJIT_MOV_P: \ - case SLJIT_MOVU: \ - case SLJIT_MOVU_U32: \ - case SLJIT_MOVU_P: \ - /* Nothing allowed */ \ - CHECK_ARGUMENT(!(op & (SLJIT_I32_OP | SLJIT_SET_E | SLJIT_SET_U | SLJIT_SET_S | SLJIT_SET_O | SLJIT_SET_C | SLJIT_KEEP_FLAGS))); \ - break; \ - default: \ - /* Only SLJIT_I32_OP or SLJIT_F32_OP is allowed. */ \ - CHECK_ARGUMENT(!(op & (SLJIT_SET_E | SLJIT_SET_U | SLJIT_SET_S | SLJIT_SET_O | SLJIT_SET_C | SLJIT_KEEP_FLAGS))); \ - break; \ - } - -#define FUNCTION_CHECK_FOP() \ - CHECK_ARGUMENT(!GET_FLAGS(op) || !(op & SLJIT_KEEP_FLAGS)); \ - switch (GET_OPCODE(op)) { \ - case SLJIT_CMP_F64: \ - CHECK_ARGUMENT(!(op & (SLJIT_SET_U | SLJIT_SET_O | SLJIT_SET_C | SLJIT_KEEP_FLAGS))); \ - CHECK_ARGUMENT((op & (SLJIT_SET_E | SLJIT_SET_S))); \ - break; \ - default: \ - /* Only SLJIT_I32_OP or SLJIT_F32_OP is allowed. */ \ - CHECK_ARGUMENT(!(op & (SLJIT_SET_E | SLJIT_SET_U | SLJIT_SET_S | SLJIT_SET_O | SLJIT_SET_C | SLJIT_KEEP_FLAGS))); \ - break; \ - } #define FUNCTION_CHECK_IS_REG(r) \ - (((r) >= SLJIT_R0 && (r) < (SLJIT_R0 + compiler->scratches)) || \ - ((r) > (SLJIT_S0 - compiler->saveds) && (r) <= SLJIT_S0)) + (((r) >= SLJIT_R0 && (r) < (SLJIT_R0 + compiler->scratches)) \ + || ((r) > (SLJIT_S0 - compiler->saveds) && (r) <= SLJIT_S0)) -#define FUNCTION_CHECK_IS_REG_OR_UNUSED(r) \ - ((r) == SLJIT_UNUSED || \ - ((r) >= SLJIT_R0 && (r) < (SLJIT_R0 + compiler->scratches)) || \ - ((r) > (SLJIT_S0 - compiler->saveds) && (r) <= SLJIT_S0)) +#define FUNCTION_CHECK_IS_FREG(fr) \ + (((fr) >= SLJIT_FR0 && (fr) < (SLJIT_FR0 + compiler->fscratches)) \ + || ((fr) > (SLJIT_FS0 - compiler->fsaveds) && (fr) <= SLJIT_FS0)) #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) -#define CHECK_NOT_VIRTUAL_REGISTER(p) \ - CHECK_ARGUMENT((p) < SLJIT_R3 || (p) > SLJIT_R6); +#define CHECK_IF_VIRTUAL_REGISTER(p) ((p) <= SLJIT_S3 && (p) >= SLJIT_S8) #else -#define CHECK_NOT_VIRTUAL_REGISTER(p) +#define CHECK_IF_VIRTUAL_REGISTER(p) 0 #endif -#define FUNCTION_CHECK_SRC(p, i) \ - CHECK_ARGUMENT(compiler->scratches != -1 && compiler->saveds != -1); \ - if (FUNCTION_CHECK_IS_REG(p)) \ - CHECK_ARGUMENT((i) == 0); \ - else if ((p) == SLJIT_IMM) \ - ; \ - else if ((p) == (SLJIT_MEM1(SLJIT_SP))) \ - CHECK_ARGUMENT((i) >= 0 && (i) < compiler->logical_local_size); \ - else { \ - CHECK_ARGUMENT((p) & SLJIT_MEM); \ - CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG_OR_UNUSED((p) & REG_MASK)); \ - CHECK_NOT_VIRTUAL_REGISTER((p) & REG_MASK); \ - if ((p) & OFFS_REG_MASK) { \ - CHECK_ARGUMENT(((p) & REG_MASK) != SLJIT_UNUSED); \ - CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(OFFS_REG(p))); \ - CHECK_NOT_VIRTUAL_REGISTER(OFFS_REG(p)); \ - CHECK_ARGUMENT(!((i) & ~0x3)); \ - } \ - CHECK_ARGUMENT(!((p) & ~(SLJIT_MEM | SLJIT_IMM | REG_MASK | OFFS_REG_MASK))); \ - } +static sljit_s32 function_check_src_mem(struct sljit_compiler *compiler, sljit_s32 p, sljit_sw i) +{ + if (compiler->scratches == -1 || compiler->saveds == -1) + return 0; -#define FUNCTION_CHECK_DST(p, i) \ - CHECK_ARGUMENT(compiler->scratches != -1 && compiler->saveds != -1); \ - if (FUNCTION_CHECK_IS_REG_OR_UNUSED(p)) \ - CHECK_ARGUMENT((i) == 0); \ - else if ((p) == (SLJIT_MEM1(SLJIT_SP))) \ - CHECK_ARGUMENT((i) >= 0 && (i) < compiler->logical_local_size); \ - else { \ - CHECK_ARGUMENT((p) & SLJIT_MEM); \ - CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG_OR_UNUSED((p) & REG_MASK)); \ - CHECK_NOT_VIRTUAL_REGISTER((p) & REG_MASK); \ - if ((p) & OFFS_REG_MASK) { \ - CHECK_ARGUMENT(((p) & REG_MASK) != SLJIT_UNUSED); \ - CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(OFFS_REG(p))); \ - CHECK_NOT_VIRTUAL_REGISTER(OFFS_REG(p)); \ - CHECK_ARGUMENT(!((i) & ~0x3)); \ - } \ - CHECK_ARGUMENT(!((p) & ~(SLJIT_MEM | SLJIT_IMM | REG_MASK | OFFS_REG_MASK))); \ - } + if (!(p & SLJIT_MEM)) + return 0; -#define FUNCTION_FCHECK(p, i) \ - CHECK_ARGUMENT(compiler->fscratches != -1 && compiler->fsaveds != -1); \ - if (((p) >= SLJIT_FR0 && (p) < (SLJIT_FR0 + compiler->fscratches)) || \ - ((p) > (SLJIT_FS0 - compiler->fsaveds) && (p) <= SLJIT_FS0)) \ - CHECK_ARGUMENT(i == 0); \ - else if ((p) == (SLJIT_MEM1(SLJIT_SP))) \ - CHECK_ARGUMENT((i) >= 0 && (i) < compiler->logical_local_size); \ - else { \ - CHECK_ARGUMENT((p) & SLJIT_MEM); \ - CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG_OR_UNUSED((p) & REG_MASK)); \ - CHECK_NOT_VIRTUAL_REGISTER((p) & REG_MASK); \ - if ((p) & OFFS_REG_MASK) { \ - CHECK_ARGUMENT(((p) & REG_MASK) != SLJIT_UNUSED); \ - CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(OFFS_REG(p))); \ - CHECK_NOT_VIRTUAL_REGISTER(OFFS_REG(p)); \ - CHECK_ARGUMENT(((p) & OFFS_REG_MASK) != TO_OFFS_REG(SLJIT_SP) && !(i & ~0x3)); \ - } \ - CHECK_ARGUMENT(!((p) & ~(SLJIT_MEM | SLJIT_IMM | REG_MASK | OFFS_REG_MASK))); \ - } + if (!((p & REG_MASK) == SLJIT_UNUSED || FUNCTION_CHECK_IS_REG(p & REG_MASK))) + return 0; + + if (CHECK_IF_VIRTUAL_REGISTER(p & REG_MASK)) + return 0; + + if (p & OFFS_REG_MASK) { + if ((p & REG_MASK) == SLJIT_UNUSED) + return 0; + + if (!(FUNCTION_CHECK_IS_REG(OFFS_REG(p)))) + return 0; -#define FUNCTION_CHECK_OP1() \ - if (GET_OPCODE(op) >= SLJIT_MOVU && GET_OPCODE(op) <= SLJIT_MOVU_P) { \ - CHECK_ARGUMENT(!(src & SLJIT_MEM) || (src & REG_MASK) != SLJIT_SP); \ - CHECK_ARGUMENT(!(dst & SLJIT_MEM) || (dst & REG_MASK) != SLJIT_SP); \ - if ((src & SLJIT_MEM) && (src & REG_MASK)) \ - CHECK_ARGUMENT((dst & REG_MASK) != (src & REG_MASK) && OFFS_REG(dst) != (src & REG_MASK)); \ + if (CHECK_IF_VIRTUAL_REGISTER(OFFS_REG(p))) + return 0; + + if ((i & ~0x3) != 0) + return 0; } + return (p & ~(SLJIT_MEM | REG_MASK | OFFS_REG_MASK)) == 0; +} + +#define FUNCTION_CHECK_SRC_MEM(p, i) \ + CHECK_ARGUMENT(function_check_src_mem(compiler, p, i)); + +static sljit_s32 function_check_src(struct sljit_compiler *compiler, sljit_s32 p, sljit_sw i) +{ + if (compiler->scratches == -1 || compiler->saveds == -1) + return 0; + + if (FUNCTION_CHECK_IS_REG(p)) + return (i == 0); + + if (p == SLJIT_IMM) + return 1; + + if (p == SLJIT_MEM1(SLJIT_SP)) + return (i >= 0 && i < compiler->logical_local_size); + + return function_check_src_mem(compiler, p, i); +} + +#define FUNCTION_CHECK_SRC(p, i) \ + CHECK_ARGUMENT(function_check_src(compiler, p, i)); + +static sljit_s32 function_check_dst(struct sljit_compiler *compiler, sljit_s32 p, sljit_sw i, sljit_s32 unused) +{ + if (compiler->scratches == -1 || compiler->saveds == -1) + return 0; + + if (FUNCTION_CHECK_IS_REG(p) || ((unused) && (p) == SLJIT_UNUSED)) + return (i == 0); + + if (p == SLJIT_MEM1(SLJIT_SP)) + return (i >= 0 && i < compiler->logical_local_size); + + return function_check_src_mem(compiler, p, i); +} + +#define FUNCTION_CHECK_DST(p, i, unused) \ + CHECK_ARGUMENT(function_check_dst(compiler, p, i, unused)); + +static sljit_s32 function_fcheck(struct sljit_compiler *compiler, sljit_s32 p, sljit_sw i) +{ + if (compiler->scratches == -1 || compiler->saveds == -1) + return 0; + + if (FUNCTION_CHECK_IS_FREG(p)) + return (i == 0); + + if (p == SLJIT_MEM1(SLJIT_SP)) + return (i >= 0 && i < compiler->logical_local_size); + + return function_check_src_mem(compiler, p, i); +} + +#define FUNCTION_FCHECK(p, i) \ + CHECK_ARGUMENT(function_fcheck(compiler, p, i)); + #endif /* SLJIT_ARGUMENT_CHECKS */ #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) @@ -807,62 +805,72 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_compiler_verbose(struct sljit_compiler *comp # define SLJIT_PRINT_D "" #endif -#define sljit_verbose_reg(compiler, r) \ - do { \ - if ((r) < (SLJIT_R0 + compiler->scratches)) \ - fprintf(compiler->verbose, "r%d", (r) - SLJIT_R0); \ - else \ - fprintf(compiler->verbose, "s%d", SLJIT_NUMBER_OF_REGISTERS - (r)); \ - } while (0) +static void sljit_verbose_reg(struct sljit_compiler *compiler, sljit_s32 r) +{ + if (r < (SLJIT_R0 + compiler->scratches)) + fprintf(compiler->verbose, "r%d", r - SLJIT_R0); + else if (r != SLJIT_SP) + fprintf(compiler->verbose, "s%d", SLJIT_NUMBER_OF_REGISTERS - r); + else + fprintf(compiler->verbose, "sp"); +} -#define sljit_verbose_param(compiler, p, i) \ - if ((p) & SLJIT_IMM) \ - fprintf(compiler->verbose, "#%" SLJIT_PRINT_D "d", (i)); \ - else if ((p) & SLJIT_MEM) { \ - if ((p) & REG_MASK) { \ - fputc('[', compiler->verbose); \ - sljit_verbose_reg(compiler, (p) & REG_MASK); \ - if ((p) & OFFS_REG_MASK) { \ - fprintf(compiler->verbose, " + "); \ - sljit_verbose_reg(compiler, OFFS_REG(p)); \ - if (i) \ - fprintf(compiler->verbose, " * %d", 1 << (i)); \ - } \ - else if (i) \ - fprintf(compiler->verbose, " + %" SLJIT_PRINT_D "d", (i)); \ - fputc(']', compiler->verbose); \ - } \ - else \ - fprintf(compiler->verbose, "[#%" SLJIT_PRINT_D "d]", (i)); \ - } else if (p) \ - sljit_verbose_reg(compiler, p); \ - else \ +static void sljit_verbose_freg(struct sljit_compiler *compiler, sljit_s32 r) +{ + if (r < (SLJIT_FR0 + compiler->fscratches)) + fprintf(compiler->verbose, "fr%d", r - SLJIT_FR0); + else + fprintf(compiler->verbose, "fs%d", SLJIT_NUMBER_OF_FLOAT_REGISTERS - r); +} + +static void sljit_verbose_param(struct sljit_compiler *compiler, sljit_s32 p, sljit_sw i) +{ + if ((p) & SLJIT_IMM) + fprintf(compiler->verbose, "#%" SLJIT_PRINT_D "d", (i)); + else if ((p) & SLJIT_MEM) { + if ((p) & REG_MASK) { + fputc('[', compiler->verbose); + sljit_verbose_reg(compiler, (p) & REG_MASK); + if ((p) & OFFS_REG_MASK) { + fprintf(compiler->verbose, " + "); + sljit_verbose_reg(compiler, OFFS_REG(p)); + if (i) + fprintf(compiler->verbose, " * %d", 1 << (i)); + } + else if (i) + fprintf(compiler->verbose, " + %" SLJIT_PRINT_D "d", (i)); + fputc(']', compiler->verbose); + } + else + fprintf(compiler->verbose, "[#%" SLJIT_PRINT_D "d]", (i)); + } else if (p) + sljit_verbose_reg(compiler, p); + else fprintf(compiler->verbose, "unused"); +} -#define sljit_verbose_fparam(compiler, p, i) \ - if ((p) & SLJIT_MEM) { \ - if ((p) & REG_MASK) { \ - fputc('[', compiler->verbose); \ - sljit_verbose_reg(compiler, (p) & REG_MASK); \ - if ((p) & OFFS_REG_MASK) { \ - fprintf(compiler->verbose, " + "); \ - sljit_verbose_reg(compiler, OFFS_REG(p)); \ - if (i) \ - fprintf(compiler->verbose, "%d", 1 << (i)); \ - } \ - else if (i) \ - fprintf(compiler->verbose, "%" SLJIT_PRINT_D "d", (i)); \ - fputc(']', compiler->verbose); \ - } \ - else \ - fprintf(compiler->verbose, "[#%" SLJIT_PRINT_D "d]", (i)); \ - } \ - else { \ - if ((p) < (SLJIT_FR0 + compiler->fscratches)) \ - fprintf(compiler->verbose, "fr%d", (p) - SLJIT_FR0); \ - else \ - fprintf(compiler->verbose, "fs%d", SLJIT_NUMBER_OF_FLOAT_REGISTERS - (p)); \ +static void sljit_verbose_fparam(struct sljit_compiler *compiler, sljit_s32 p, sljit_sw i) +{ + if ((p) & SLJIT_MEM) { + if ((p) & REG_MASK) { + fputc('[', compiler->verbose); + sljit_verbose_reg(compiler, (p) & REG_MASK); + if ((p) & OFFS_REG_MASK) { + fprintf(compiler->verbose, " + "); + sljit_verbose_reg(compiler, OFFS_REG(p)); + if (i) + fprintf(compiler->verbose, "%d", 1 << (i)); + } + else if (i) + fprintf(compiler->verbose, " + %" SLJIT_PRINT_D "d", (i)); + fputc(']', compiler->verbose); + } + else + fprintf(compiler->verbose, "[#%" SLJIT_PRINT_D "d]", (i)); } + else + sljit_verbose_freg(compiler, p); +} static const char* op0_names[] = { (char*)"breakpoint", (char*)"nop", (char*)"lmul.uw", (char*)"lmul.sw", @@ -905,12 +913,17 @@ static char* jump_names[] = { (char*)"sig_greater", (char*)"sig_less_equal", (char*)"overflow", (char*)"not_overflow", (char*)"mul_overflow", (char*)"mul_not_overflow", + (char*)"carry", (char*)"", (char*)"equal", (char*)"not_equal", (char*)"less", (char*)"greater_equal", (char*)"greater", (char*)"less_equal", (char*)"unordered", (char*)"ordered", (char*)"jump", (char*)"fast_call", - (char*)"call0", (char*)"call1", (char*)"call2", (char*)"call3" + (char*)"call", (char*)"call.cdecl" +}; + +static char* call_arg_names[] = { + (char*)"void", (char*)"sw", (char*)"uw", (char*)"s32", (char*)"u32", (char*)"f32", (char*)"f64" }; #endif /* SLJIT_VERBOSE */ @@ -943,56 +956,104 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_generate_code(struct sljit_com } static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_enter(struct sljit_compiler *compiler, - sljit_s32 options, sljit_s32 args, sljit_s32 scratches, sljit_s32 saveds, + sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds, sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size) { +#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) + sljit_s32 types, arg_count, curr_type; +#endif + SLJIT_UNUSED_ARG(compiler); #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) - CHECK_ARGUMENT(!(options & ~SLJIT_DOUBLE_ALIGNMENT)); - CHECK_ARGUMENT(args >= 0 && args <= 3); + CHECK_ARGUMENT(!(options & ~SLJIT_F64_ALIGNMENT)); CHECK_ARGUMENT(scratches >= 0 && scratches <= SLJIT_NUMBER_OF_REGISTERS); CHECK_ARGUMENT(saveds >= 0 && saveds <= SLJIT_NUMBER_OF_REGISTERS); CHECK_ARGUMENT(scratches + saveds <= SLJIT_NUMBER_OF_REGISTERS); - CHECK_ARGUMENT(args <= saveds); CHECK_ARGUMENT(fscratches >= 0 && fscratches <= SLJIT_NUMBER_OF_FLOAT_REGISTERS); CHECK_ARGUMENT(fsaveds >= 0 && fsaveds <= SLJIT_NUMBER_OF_FLOAT_REGISTERS); CHECK_ARGUMENT(fscratches + fsaveds <= SLJIT_NUMBER_OF_FLOAT_REGISTERS); CHECK_ARGUMENT(local_size >= 0 && local_size <= SLJIT_MAX_LOCAL_SIZE); + CHECK_ARGUMENT((arg_types & SLJIT_DEF_MASK) == 0); + + types = (arg_types >> SLJIT_DEF_SHIFT); + arg_count = 0; + while (types != 0 && arg_count < 3) { + curr_type = (types & SLJIT_DEF_MASK); + CHECK_ARGUMENT(curr_type == SLJIT_ARG_TYPE_SW || curr_type == SLJIT_ARG_TYPE_UW); + arg_count++; + types >>= SLJIT_DEF_SHIFT; + } + CHECK_ARGUMENT(arg_count <= saveds && types == 0); + + compiler->last_flags = 0; #endif #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) - if (SLJIT_UNLIKELY(!!compiler->verbose)) - fprintf(compiler->verbose, " enter options:none args:%d scratches:%d saveds:%d fscratches:%d fsaveds:%d local_size:%d\n", - args, scratches, saveds, fscratches, fsaveds, local_size); + if (SLJIT_UNLIKELY(!!compiler->verbose)) { + fprintf(compiler->verbose, " enter options:%s args[", (options & SLJIT_F64_ALIGNMENT) ? "f64_align" : ""); + + arg_types >>= SLJIT_DEF_SHIFT; + while (arg_types) { + fprintf(compiler->verbose, "%s", call_arg_names[arg_types & SLJIT_DEF_MASK]); + arg_types >>= SLJIT_DEF_SHIFT; + if (arg_types) + fprintf(compiler->verbose, ","); + } + + fprintf(compiler->verbose, "] scratches:%d saveds:%d fscratches:%d fsaveds:%d local_size:%d\n", + scratches, saveds, fscratches, fsaveds, local_size); + } #endif CHECK_RETURN_OK; } static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_set_context(struct sljit_compiler *compiler, - sljit_s32 options, sljit_s32 args, sljit_s32 scratches, sljit_s32 saveds, + sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds, sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size) { - if (SLJIT_UNLIKELY(compiler->skip_checks)) { - compiler->skip_checks = 0; - CHECK_RETURN_OK; - } +#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) + sljit_s32 types, arg_count, curr_type; +#endif + + SLJIT_UNUSED_ARG(compiler); #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) - CHECK_ARGUMENT(!(options & ~SLJIT_DOUBLE_ALIGNMENT)); - CHECK_ARGUMENT(args >= 0 && args <= 3); + CHECK_ARGUMENT(!(options & ~SLJIT_F64_ALIGNMENT)); CHECK_ARGUMENT(scratches >= 0 && scratches <= SLJIT_NUMBER_OF_REGISTERS); CHECK_ARGUMENT(saveds >= 0 && saveds <= SLJIT_NUMBER_OF_REGISTERS); CHECK_ARGUMENT(scratches + saveds <= SLJIT_NUMBER_OF_REGISTERS); - CHECK_ARGUMENT(args <= saveds); CHECK_ARGUMENT(fscratches >= 0 && fscratches <= SLJIT_NUMBER_OF_FLOAT_REGISTERS); CHECK_ARGUMENT(fsaveds >= 0 && fsaveds <= SLJIT_NUMBER_OF_FLOAT_REGISTERS); CHECK_ARGUMENT(fscratches + fsaveds <= SLJIT_NUMBER_OF_FLOAT_REGISTERS); CHECK_ARGUMENT(local_size >= 0 && local_size <= SLJIT_MAX_LOCAL_SIZE); + + types = (arg_types >> SLJIT_DEF_SHIFT); + arg_count = 0; + while (types != 0 && arg_count < 3) { + curr_type = (types & SLJIT_DEF_MASK); + CHECK_ARGUMENT(curr_type == SLJIT_ARG_TYPE_SW || curr_type == SLJIT_ARG_TYPE_UW); + arg_count++; + types >>= SLJIT_DEF_SHIFT; + } + CHECK_ARGUMENT(arg_count <= saveds && types == 0); + + compiler->last_flags = 0; #endif #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) - if (SLJIT_UNLIKELY(!!compiler->verbose)) - fprintf(compiler->verbose, " set_context options:none args:%d scratches:%d saveds:%d fscratches:%d fsaveds:%d local_size:%d\n", - args, scratches, saveds, fscratches, fsaveds, local_size); + if (SLJIT_UNLIKELY(!!compiler->verbose)) { + fprintf(compiler->verbose, " set_context options:%s args[", (options & SLJIT_F64_ALIGNMENT) ? "f64_align" : ""); + + arg_types >>= SLJIT_DEF_SHIFT; + while (arg_types) { + fprintf(compiler->verbose, "%s", call_arg_names[arg_types & SLJIT_DEF_MASK]); + arg_types >>= SLJIT_DEF_SHIFT; + if (arg_types) + fprintf(compiler->verbose, ","); + } + + fprintf(compiler->verbose, "] scratches:%d saveds:%d fscratches:%d fsaveds:%d local_size:%d\n", + scratches, saveds, fscratches, fsaveds, local_size); + } #endif CHECK_RETURN_OK; } @@ -1007,6 +1068,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_return(struct sljit_compi } else CHECK_ARGUMENT(src == 0 && srcw == 0); + compiler->last_flags = 0; #endif #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) if (SLJIT_UNLIKELY(!!compiler->verbose)) { @@ -1025,7 +1087,8 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_return(struct sljit_compi static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fast_enter(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw) { #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) - FUNCTION_CHECK_DST(dst, dstw); + FUNCTION_CHECK_DST(dst, dstw, 0); + compiler->last_flags = 0; #endif #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) if (SLJIT_UNLIKELY(!!compiler->verbose)) { @@ -1041,6 +1104,8 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fast_return(struct sljit_ { #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) FUNCTION_CHECK_SRC(src, srcw); + CHECK_ARGUMENT(src != SLJIT_IMM); + compiler->last_flags = 0; #endif #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) if (SLJIT_UNLIKELY(!!compiler->verbose)) { @@ -1058,6 +1123,8 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op0(struct sljit_compiler CHECK_ARGUMENT((op >= SLJIT_BREAKPOINT && op <= SLJIT_LMUL_SW) || ((op & ~SLJIT_I32_OP) >= SLJIT_DIVMOD_UW && (op & ~SLJIT_I32_OP) <= SLJIT_DIV_SW)); CHECK_ARGUMENT(op < SLJIT_LMUL_UW || compiler->scratches >= 2); + if (op >= SLJIT_LMUL_UW) + compiler->last_flags = 0; #endif #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) if (SLJIT_UNLIKELY(!!compiler->verbose)) @@ -1083,23 +1150,48 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op1(struct sljit_compiler #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) CHECK_ARGUMENT(GET_OPCODE(op) >= SLJIT_MOV && GET_OPCODE(op) <= SLJIT_CLZ); - FUNCTION_CHECK_OP(); + + switch (GET_OPCODE(op)) { + case SLJIT_NOT: + /* Only SLJIT_I32_OP and SLJIT_SET_Z are allowed. */ + CHECK_ARGUMENT(!(op & VARIABLE_FLAG_MASK)); + break; + case SLJIT_NEG: + CHECK_ARGUMENT(!(op & VARIABLE_FLAG_MASK) + || GET_FLAG_TYPE(op) == SLJIT_OVERFLOW); + break; + case SLJIT_MOV: + case SLJIT_MOV_U32: + case SLJIT_MOV_P: + /* Nothing allowed */ + CHECK_ARGUMENT(!(op & (SLJIT_I32_OP | SLJIT_SET_Z | VARIABLE_FLAG_MASK))); + break; + default: + /* Only SLJIT_I32_OP is allowed. */ + CHECK_ARGUMENT(!(op & (SLJIT_SET_Z | VARIABLE_FLAG_MASK))); + break; + } + + FUNCTION_CHECK_DST(dst, dstw, 1); FUNCTION_CHECK_SRC(src, srcw); - FUNCTION_CHECK_DST(dst, dstw); - FUNCTION_CHECK_OP1(); + + if (GET_OPCODE(op) >= SLJIT_NOT) { + CHECK_ARGUMENT(src != SLJIT_IMM); + compiler->last_flags = GET_FLAG_TYPE(op) | (op & (SLJIT_I32_OP | SLJIT_SET_Z)); + } #endif #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) if (SLJIT_UNLIKELY(!!compiler->verbose)) { - if (GET_OPCODE(op) <= SLJIT_MOVU_P) + if (GET_OPCODE(op) <= SLJIT_MOV_P) { - fprintf(compiler->verbose, " mov%s%s%s ", (GET_OPCODE(op) >= SLJIT_MOVU) ? "u" : "", - !(op & SLJIT_I32_OP) ? "" : "32", (op != SLJIT_MOV32 && op != SLJIT_MOVU32) ? op1_names[GET_OPCODE(op) - SLJIT_OP1_BASE] : ""); + fprintf(compiler->verbose, " mov%s%s ", !(op & SLJIT_I32_OP) ? "" : "32", + (op != SLJIT_MOV32) ? op1_names[GET_OPCODE(op) - SLJIT_OP1_BASE] : ""); } else { - fprintf(compiler->verbose, " %s%s%s%s%s%s%s%s ", op1_names[GET_OPCODE(op) - SLJIT_OP1_BASE], !(op & SLJIT_I32_OP) ? "" : "32", - !(op & SLJIT_SET_E) ? "" : ".e", !(op & SLJIT_SET_U) ? "" : ".u", !(op & SLJIT_SET_S) ? "" : ".s", - !(op & SLJIT_SET_O) ? "" : ".o", !(op & SLJIT_SET_C) ? "" : ".c", !(op & SLJIT_KEEP_FLAGS) ? "" : ".k"); + fprintf(compiler->verbose, " %s%s%s%s%s ", op1_names[GET_OPCODE(op) - SLJIT_OP1_BASE], !(op & SLJIT_I32_OP) ? "" : "32", + !(op & SLJIT_SET_Z) ? "" : ".z", !(op & VARIABLE_FLAG_MASK) ? "" : ".", + !(op & VARIABLE_FLAG_MASK) ? "" : jump_names[GET_FLAG_TYPE(op)]); } sljit_verbose_param(compiler, dst, dstw); @@ -1123,16 +1215,53 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op2(struct sljit_compiler #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) CHECK_ARGUMENT(GET_OPCODE(op) >= SLJIT_ADD && GET_OPCODE(op) <= SLJIT_ASHR); - FUNCTION_CHECK_OP(); + + switch (GET_OPCODE(op)) { + case SLJIT_AND: + case SLJIT_OR: + case SLJIT_XOR: + case SLJIT_SHL: + case SLJIT_LSHR: + case SLJIT_ASHR: + CHECK_ARGUMENT(!(op & VARIABLE_FLAG_MASK)); + break; + case SLJIT_MUL: + CHECK_ARGUMENT(!(op & SLJIT_SET_Z)); + CHECK_ARGUMENT(!(op & VARIABLE_FLAG_MASK) + || GET_FLAG_TYPE(op) == SLJIT_MUL_OVERFLOW); + break; + case SLJIT_ADD: + CHECK_ARGUMENT(!(op & VARIABLE_FLAG_MASK) + || GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY) + || GET_FLAG_TYPE(op) == SLJIT_OVERFLOW); + break; + case SLJIT_SUB: + CHECK_ARGUMENT(!(op & VARIABLE_FLAG_MASK) + || (GET_FLAG_TYPE(op) >= SLJIT_LESS && GET_FLAG_TYPE(op) <= SLJIT_OVERFLOW) + || GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY)); + break; + case SLJIT_ADDC: + case SLJIT_SUBC: + CHECK_ARGUMENT(!(op & VARIABLE_FLAG_MASK) + || GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY)); + CHECK_ARGUMENT((compiler->last_flags & 0xff) == GET_FLAG_TYPE(SLJIT_SET_CARRY)); + CHECK_ARGUMENT((op & SLJIT_I32_OP) == (compiler->last_flags & SLJIT_I32_OP)); + break; + default: + SLJIT_UNREACHABLE(); + break; + } + + FUNCTION_CHECK_DST(dst, dstw, 1); FUNCTION_CHECK_SRC(src1, src1w); FUNCTION_CHECK_SRC(src2, src2w); - FUNCTION_CHECK_DST(dst, dstw); + compiler->last_flags = GET_FLAG_TYPE(op) | (op & (SLJIT_I32_OP | SLJIT_SET_Z)); #endif #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) if (SLJIT_UNLIKELY(!!compiler->verbose)) { - fprintf(compiler->verbose, " %s%s%s%s%s%s%s%s ", op2_names[GET_OPCODE(op) - SLJIT_OP2_BASE], !(op & SLJIT_I32_OP) ? "" : "32", - !(op & SLJIT_SET_E) ? "" : ".e", !(op & SLJIT_SET_U) ? "" : ".u", !(op & SLJIT_SET_S) ? "" : ".s", - !(op & SLJIT_SET_O) ? "" : ".o", !(op & SLJIT_SET_C) ? "" : ".c", !(op & SLJIT_KEEP_FLAGS) ? "" : ".k"); + fprintf(compiler->verbose, " %s%s%s%s%s ", op2_names[GET_OPCODE(op) - SLJIT_OP2_BASE], !(op & SLJIT_I32_OP) ? "" : "32", + !(op & SLJIT_SET_Z) ? "" : ".z", !(op & VARIABLE_FLAG_MASK) ? "" : ".", + !(op & VARIABLE_FLAG_MASK) ? "" : jump_names[GET_FLAG_TYPE(op)]); sljit_verbose_param(compiler, dst, dstw); fprintf(compiler->verbose, ", "); sljit_verbose_param(compiler, src1, src1w); @@ -1173,6 +1302,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op_custom(struct sljit_co #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) CHECK_ARGUMENT(instruction); + #if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86) CHECK_ARGUMENT(size > 0 && size < 16); #elif (defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2) @@ -1182,6 +1312,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op_custom(struct sljit_co CHECK_ARGUMENT(size == 4 && (((sljit_sw)instruction) & 0x3) == 0); #endif + compiler->last_flags = 0; #endif #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) if (SLJIT_UNLIKELY(!!compiler->verbose)) { @@ -1204,9 +1335,9 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fop1(struct sljit_compile } #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) - CHECK_ARGUMENT(sljit_is_fpu_available()); + CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_FPU)); CHECK_ARGUMENT(GET_OPCODE(op) >= SLJIT_MOV_F64 && GET_OPCODE(op) <= SLJIT_ABS_F64); - FUNCTION_CHECK_FOP(); + CHECK_ARGUMENT(!(op & (SLJIT_SET_Z | VARIABLE_FLAG_MASK))); FUNCTION_FCHECK(src, srcw); FUNCTION_FCHECK(dst, dstw); #endif @@ -1232,22 +1363,31 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fop1_cmp(struct sljit_com sljit_s32 src1, sljit_sw src1w, sljit_s32 src2, sljit_sw src2w) { +#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) + compiler->last_flags = GET_FLAG_TYPE(op) | (op & (SLJIT_I32_OP | SLJIT_SET_Z)); +#endif + if (SLJIT_UNLIKELY(compiler->skip_checks)) { compiler->skip_checks = 0; CHECK_RETURN_OK; } #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) - CHECK_ARGUMENT(sljit_is_fpu_available()); + CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_FPU)); CHECK_ARGUMENT(GET_OPCODE(op) == SLJIT_CMP_F64); - FUNCTION_CHECK_FOP(); + CHECK_ARGUMENT(!(op & SLJIT_SET_Z)); + CHECK_ARGUMENT((op & VARIABLE_FLAG_MASK) + || (GET_FLAG_TYPE(op) >= SLJIT_EQUAL_F64 && GET_FLAG_TYPE(op) <= SLJIT_ORDERED_F64)); FUNCTION_FCHECK(src1, src1w); FUNCTION_FCHECK(src2, src2w); #endif #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) if (SLJIT_UNLIKELY(!!compiler->verbose)) { - fprintf(compiler->verbose, " %s%s%s%s ", fop1_names[SLJIT_CMP_F64 - SLJIT_FOP1_BASE], (op & SLJIT_F32_OP) ? ".f32" : ".f64", - (op & SLJIT_SET_E) ? ".e" : "", (op & SLJIT_SET_S) ? ".s" : ""); + fprintf(compiler->verbose, " %s%s", fop1_names[SLJIT_CMP_F64 - SLJIT_FOP1_BASE], (op & SLJIT_F32_OP) ? ".f32" : ".f64"); + if (op & VARIABLE_FLAG_MASK) { + fprintf(compiler->verbose, ".%s_f", jump_names[GET_FLAG_TYPE(op)]); + } + fprintf(compiler->verbose, " "); sljit_verbose_fparam(compiler, src1, src1w); fprintf(compiler->verbose, ", "); sljit_verbose_fparam(compiler, src2, src2w); @@ -1267,11 +1407,11 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fop1_conv_sw_from_f64(str } #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) - CHECK_ARGUMENT(sljit_is_fpu_available()); + CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_FPU)); CHECK_ARGUMENT(GET_OPCODE(op) >= SLJIT_CONV_SW_FROM_F64 && GET_OPCODE(op) <= SLJIT_CONV_S32_FROM_F64); - FUNCTION_CHECK_FOP(); + CHECK_ARGUMENT(!(op & (SLJIT_SET_Z | VARIABLE_FLAG_MASK))); FUNCTION_FCHECK(src, srcw); - FUNCTION_CHECK_DST(dst, dstw); + FUNCTION_CHECK_DST(dst, dstw, 0); #endif #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) if (SLJIT_UNLIKELY(!!compiler->verbose)) { @@ -1297,9 +1437,9 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fop1_conv_f64_from_sw(str } #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) - CHECK_ARGUMENT(sljit_is_fpu_available()); + CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_FPU)); CHECK_ARGUMENT(GET_OPCODE(op) >= SLJIT_CONV_F64_FROM_SW && GET_OPCODE(op) <= SLJIT_CONV_F64_FROM_S32); - FUNCTION_CHECK_FOP(); + CHECK_ARGUMENT(!(op & (SLJIT_SET_Z | VARIABLE_FLAG_MASK))); FUNCTION_CHECK_SRC(src, srcw); FUNCTION_FCHECK(dst, dstw); #endif @@ -1323,9 +1463,9 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fop2(struct sljit_compile sljit_s32 src2, sljit_sw src2w) { #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) - CHECK_ARGUMENT(sljit_is_fpu_available()); + CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_FPU)); CHECK_ARGUMENT(GET_OPCODE(op) >= SLJIT_ADD_F64 && GET_OPCODE(op) <= SLJIT_DIV_F64); - FUNCTION_CHECK_FOP(); + CHECK_ARGUMENT(!(op & (SLJIT_SET_Z | VARIABLE_FLAG_MASK))); FUNCTION_FCHECK(src1, src1w); FUNCTION_FCHECK(src2, src2w); FUNCTION_FCHECK(dst, dstw); @@ -1348,6 +1488,15 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_label(struct sljit_compil { SLJIT_UNUSED_ARG(compiler); + if (SLJIT_UNLIKELY(compiler->skip_checks)) { + compiler->skip_checks = 0; + CHECK_RETURN_OK; + } + +#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) + compiler->last_flags = 0; +#endif + #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) if (SLJIT_UNLIKELY(!!compiler->verbose)) fprintf(compiler->verbose, "label:\n"); @@ -1364,9 +1513,19 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_jump(struct sljit_compile #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) CHECK_ARGUMENT(!(type & ~(0xff | SLJIT_REWRITABLE_JUMP | SLJIT_I32_OP))); - CHECK_ARGUMENT((type & 0xff) >= SLJIT_EQUAL && (type & 0xff) <= SLJIT_CALL3); + CHECK_ARGUMENT((type & 0xff) != GET_FLAG_TYPE(SLJIT_SET_CARRY) && (type & 0xff) != (GET_FLAG_TYPE(SLJIT_SET_CARRY) + 1)); + CHECK_ARGUMENT((type & 0xff) >= SLJIT_EQUAL && (type & 0xff) <= SLJIT_FAST_CALL); CHECK_ARGUMENT((type & 0xff) < SLJIT_JUMP || !(type & SLJIT_I32_OP)); - CHECK_ARGUMENT((type & 0xff) <= SLJIT_CALL0 || ((type & 0xff) - SLJIT_CALL0) <= compiler->scratches); + + if ((type & 0xff) < SLJIT_JUMP) { + if ((type & 0xff) <= SLJIT_NOT_ZERO) + CHECK_ARGUMENT(compiler->last_flags & SLJIT_SET_Z); + else + CHECK_ARGUMENT((type & 0xff) == (compiler->last_flags & 0xff) + || ((type & 0xff) == SLJIT_NOT_OVERFLOW && (compiler->last_flags & 0xff) == SLJIT_OVERFLOW) + || ((type & 0xff) == SLJIT_MUL_NOT_OVERFLOW && (compiler->last_flags & 0xff) == SLJIT_MUL_OVERFLOW)); + CHECK_ARGUMENT((type & SLJIT_I32_OP) == (compiler->last_flags & SLJIT_I32_OP)); + } #endif #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) if (SLJIT_UNLIKELY(!!compiler->verbose)) @@ -1376,6 +1535,63 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_jump(struct sljit_compile CHECK_RETURN_OK; } +static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_call(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 arg_types) +{ +#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) + sljit_s32 i, types, curr_type, scratches, fscratches; + + CHECK_ARGUMENT(!(type & ~(0xff | SLJIT_REWRITABLE_JUMP))); + CHECK_ARGUMENT((type & 0xff) == SLJIT_CALL || (type & 0xff) == SLJIT_CALL_CDECL); + + types = arg_types; + scratches = 0; + fscratches = 0; + for (i = 0; i < 5; i++) { + curr_type = (types & SLJIT_DEF_MASK); + CHECK_ARGUMENT(curr_type <= SLJIT_ARG_TYPE_F64); + if (i > 0) { + if (curr_type == 0) { + break; + } + if (curr_type >= SLJIT_ARG_TYPE_F32) + fscratches++; + else + scratches++; + } else { + if (curr_type >= SLJIT_ARG_TYPE_F32) { + CHECK_ARGUMENT(compiler->fscratches > 0); + } else if (curr_type >= SLJIT_ARG_TYPE_SW) { + CHECK_ARGUMENT(compiler->scratches > 0); + } + } + types >>= SLJIT_DEF_SHIFT; + } + CHECK_ARGUMENT(compiler->scratches >= scratches); + CHECK_ARGUMENT(compiler->fscratches >= fscratches); + CHECK_ARGUMENT(types == 0); +#endif +#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) + if (SLJIT_UNLIKELY(!!compiler->verbose)) { + fprintf(compiler->verbose, " %s%s ret[%s", jump_names[type & 0xff], + !(type & SLJIT_REWRITABLE_JUMP) ? "" : ".r", call_arg_names[arg_types & SLJIT_DEF_MASK]); + + arg_types >>= SLJIT_DEF_SHIFT; + if (arg_types) { + fprintf(compiler->verbose, "], args["); + do { + fprintf(compiler->verbose, "%s", call_arg_names[arg_types & SLJIT_DEF_MASK]); + arg_types >>= SLJIT_DEF_SHIFT; + if (arg_types) + fprintf(compiler->verbose, ","); + } while (arg_types); + } + fprintf(compiler->verbose, "]\n"); + } +#endif + CHECK_RETURN_OK; +} + static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_cmp(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 src1, sljit_sw src1w, sljit_s32 src2, sljit_sw src2w) @@ -1385,6 +1601,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_cmp(struct sljit_compiler CHECK_ARGUMENT((type & 0xff) >= SLJIT_EQUAL && (type & 0xff) <= SLJIT_SIG_LESS_EQUAL); FUNCTION_CHECK_SRC(src1, src1w); FUNCTION_CHECK_SRC(src2, src2w); + compiler->last_flags = 0; #endif #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) if (SLJIT_UNLIKELY(!!compiler->verbose)) { @@ -1404,11 +1621,12 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fcmp(struct sljit_compile sljit_s32 src2, sljit_sw src2w) { #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) - CHECK_ARGUMENT(sljit_is_fpu_available()); + CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_FPU)); CHECK_ARGUMENT(!(type & ~(0xff | SLJIT_REWRITABLE_JUMP | SLJIT_F32_OP))); CHECK_ARGUMENT((type & 0xff) >= SLJIT_EQUAL_F64 && (type & 0xff) <= SLJIT_ORDERED_F64); FUNCTION_FCHECK(src1, src1w); FUNCTION_FCHECK(src2, src2w); + compiler->last_flags = 0; #endif #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) if (SLJIT_UNLIKELY(!!compiler->verbose)) { @@ -1423,7 +1641,8 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fcmp(struct sljit_compile CHECK_RETURN_OK; } -static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_ijump(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 src, sljit_sw srcw) +static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_ijump(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 src, sljit_sw srcw) { if (SLJIT_UNLIKELY(compiler->skip_checks)) { compiler->skip_checks = 0; @@ -1431,8 +1650,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_ijump(struct sljit_compil } #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) - CHECK_ARGUMENT(type >= SLJIT_JUMP && type <= SLJIT_CALL3); - CHECK_ARGUMENT(type <= SLJIT_CALL0 || (type - SLJIT_CALL0) <= compiler->scratches); + CHECK_ARGUMENT(type >= SLJIT_JUMP && type <= SLJIT_FAST_CALL); FUNCTION_CHECK_SRC(src, srcw); #endif #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) @@ -1445,48 +1663,212 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_ijump(struct sljit_compil CHECK_RETURN_OK; } +static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_icall(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 arg_types, + sljit_s32 src, sljit_sw srcw) +{ +#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) + sljit_s32 i, types, curr_type, scratches, fscratches; + + CHECK_ARGUMENT(type == SLJIT_CALL || type == SLJIT_CALL_CDECL); + FUNCTION_CHECK_SRC(src, srcw); + + types = arg_types; + scratches = 0; + fscratches = 0; + for (i = 0; i < 5; i++) { + curr_type = (types & SLJIT_DEF_MASK); + CHECK_ARGUMENT(curr_type <= SLJIT_ARG_TYPE_F64); + if (i > 0) { + if (curr_type == 0) { + break; + } + if (curr_type >= SLJIT_ARG_TYPE_F32) + fscratches++; + else + scratches++; + } else { + if (curr_type >= SLJIT_ARG_TYPE_F32) { + CHECK_ARGUMENT(compiler->fscratches > 0); + } else if (curr_type >= SLJIT_ARG_TYPE_SW) { + CHECK_ARGUMENT(compiler->scratches > 0); + } + } + types >>= SLJIT_DEF_SHIFT; + } + CHECK_ARGUMENT(compiler->scratches >= scratches); + CHECK_ARGUMENT(compiler->fscratches >= fscratches); + CHECK_ARGUMENT(types == 0); +#endif +#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) + if (SLJIT_UNLIKELY(!!compiler->verbose)) { + fprintf(compiler->verbose, " i%s%s ret[%s", jump_names[type & 0xff], + !(type & SLJIT_REWRITABLE_JUMP) ? "" : ".r", call_arg_names[arg_types & SLJIT_DEF_MASK]); + + arg_types >>= SLJIT_DEF_SHIFT; + if (arg_types) { + fprintf(compiler->verbose, "], args["); + do { + fprintf(compiler->verbose, "%s", call_arg_names[arg_types & SLJIT_DEF_MASK]); + arg_types >>= SLJIT_DEF_SHIFT; + if (arg_types) + fprintf(compiler->verbose, ","); + } while (arg_types); + } + fprintf(compiler->verbose, "], "); + sljit_verbose_param(compiler, src, srcw); + fprintf(compiler->verbose, "\n"); + } +#endif + CHECK_RETURN_OK; +} + static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op_flags(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw dstw, - sljit_s32 src, sljit_sw srcw, sljit_s32 type) { #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) CHECK_ARGUMENT(!(type & ~(0xff | SLJIT_I32_OP))); CHECK_ARGUMENT((type & 0xff) >= SLJIT_EQUAL && (type & 0xff) <= SLJIT_ORDERED_F64); - CHECK_ARGUMENT(op == SLJIT_MOV || GET_OPCODE(op) == SLJIT_MOV_U32 || GET_OPCODE(op) == SLJIT_MOV_S32 + CHECK_ARGUMENT((type & 0xff) != GET_FLAG_TYPE(SLJIT_SET_CARRY) && (type & 0xff) != (GET_FLAG_TYPE(SLJIT_SET_CARRY) + 1)); + CHECK_ARGUMENT(op == SLJIT_MOV || op == SLJIT_MOV32 || (GET_OPCODE(op) >= SLJIT_AND && GET_OPCODE(op) <= SLJIT_XOR)); - CHECK_ARGUMENT((op & (SLJIT_SET_U | SLJIT_SET_S | SLJIT_SET_O | SLJIT_SET_C)) == 0); - CHECK_ARGUMENT((op & (SLJIT_SET_E | SLJIT_KEEP_FLAGS)) != (SLJIT_SET_E | SLJIT_KEEP_FLAGS)); - if (GET_OPCODE(op) < SLJIT_ADD) { - CHECK_ARGUMENT(src == SLJIT_UNUSED && srcw == 0); - } else { - CHECK_ARGUMENT(src == dst && srcw == dstw); - } - FUNCTION_CHECK_DST(dst, dstw); + CHECK_ARGUMENT(!(op & VARIABLE_FLAG_MASK)); + + if ((type & 0xff) <= SLJIT_NOT_ZERO) + CHECK_ARGUMENT(compiler->last_flags & SLJIT_SET_Z); + else + CHECK_ARGUMENT((type & 0xff) == (compiler->last_flags & 0xff) + || ((type & 0xff) == SLJIT_NOT_OVERFLOW && (compiler->last_flags & 0xff) == SLJIT_OVERFLOW) + || ((type & 0xff) == SLJIT_MUL_NOT_OVERFLOW && (compiler->last_flags & 0xff) == SLJIT_MUL_OVERFLOW)); + + FUNCTION_CHECK_DST(dst, dstw, 0); + + if (GET_OPCODE(op) >= SLJIT_ADD) + compiler->last_flags = GET_FLAG_TYPE(op) | (op & (SLJIT_I32_OP | SLJIT_SET_Z)); #endif #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) if (SLJIT_UNLIKELY(!!compiler->verbose)) { - fprintf(compiler->verbose, " flags %s%s%s%s, ", - !(op & SLJIT_SET_E) ? "" : ".e", !(op & SLJIT_KEEP_FLAGS) ? "" : ".k", + fprintf(compiler->verbose, " flags%s %s%s, ", + !(op & SLJIT_SET_Z) ? "" : ".z", GET_OPCODE(op) < SLJIT_OP2_BASE ? "mov" : op2_names[GET_OPCODE(op) - SLJIT_OP2_BASE], GET_OPCODE(op) < SLJIT_OP2_BASE ? op1_names[GET_OPCODE(op) - SLJIT_OP1_BASE] : ((op & SLJIT_I32_OP) ? "32" : "")); sljit_verbose_param(compiler, dst, dstw); - if (src != SLJIT_UNUSED) { - fprintf(compiler->verbose, ", "); - sljit_verbose_param(compiler, src, srcw); - } fprintf(compiler->verbose, ", %s%s\n", jump_names[type & 0xff], JUMP_POSTFIX(type)); } #endif CHECK_RETURN_OK; } +static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_cmov(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 dst_reg, + sljit_s32 src, sljit_sw srcw) +{ +#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) + CHECK_ARGUMENT(!(type & ~(0xff | SLJIT_I32_OP))); + CHECK_ARGUMENT((type & 0xff) >= SLJIT_EQUAL && (type & 0xff) <= SLJIT_ORDERED_F64); + + CHECK_ARGUMENT(compiler->scratches != -1 && compiler->saveds != -1); + CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(dst_reg & ~SLJIT_I32_OP)); + if (src != SLJIT_IMM) { + CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(src)); + CHECK_ARGUMENT(srcw == 0); + } + + if ((type & 0xff) <= SLJIT_NOT_ZERO) + CHECK_ARGUMENT(compiler->last_flags & SLJIT_SET_Z); + else + CHECK_ARGUMENT((type & 0xff) == (compiler->last_flags & 0xff) + || ((type & 0xff) == SLJIT_NOT_OVERFLOW && (compiler->last_flags & 0xff) == SLJIT_OVERFLOW) + || ((type & 0xff) == SLJIT_MUL_NOT_OVERFLOW && (compiler->last_flags & 0xff) == SLJIT_MUL_OVERFLOW)); +#endif +#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) + if (SLJIT_UNLIKELY(!!compiler->verbose)) { + fprintf(compiler->verbose, " cmov%s %s%s, ", + !(dst_reg & SLJIT_I32_OP) ? "" : "32", + jump_names[type & 0xff], JUMP_POSTFIX(type)); + sljit_verbose_reg(compiler, dst_reg & ~SLJIT_I32_OP); + fprintf(compiler->verbose, ", "); + sljit_verbose_param(compiler, src, srcw); + fprintf(compiler->verbose, "\n"); + } +#endif + CHECK_RETURN_OK; +} + +static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_mem(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 reg, + sljit_s32 mem, sljit_sw memw) +{ +#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) + CHECK_ARGUMENT((type & 0xff) >= SLJIT_MOV && (type & 0xff) <= SLJIT_MOV_P); + CHECK_ARGUMENT(!(type & SLJIT_I32_OP) || ((type & 0xff) != SLJIT_MOV && (type & 0xff) != SLJIT_MOV_U32 && (type & 0xff) != SLJIT_MOV_P)); + CHECK_ARGUMENT((type & SLJIT_MEM_PRE) || (type & SLJIT_MEM_POST)); + CHECK_ARGUMENT((type & (SLJIT_MEM_PRE | SLJIT_MEM_POST)) != (SLJIT_MEM_PRE | SLJIT_MEM_POST)); + CHECK_ARGUMENT((type & ~(0xff | SLJIT_I32_OP | SLJIT_MEM_STORE | SLJIT_MEM_SUPP | SLJIT_MEM_PRE | SLJIT_MEM_POST)) == 0); + + FUNCTION_CHECK_SRC_MEM(mem, memw); + CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(reg)); + + CHECK_ARGUMENT((mem & REG_MASK) != SLJIT_UNUSED && (mem & REG_MASK) != reg); +#endif +#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) + if (!(type & SLJIT_MEM_SUPP) && SLJIT_UNLIKELY(!!compiler->verbose)) { + if (sljit_emit_mem(compiler, type | SLJIT_MEM_SUPP, reg, mem, memw) == SLJIT_ERR_UNSUPPORTED) + fprintf(compiler->verbose, " //"); + + fprintf(compiler->verbose, " mem%s.%s%s%s ", + !(type & SLJIT_I32_OP) ? "" : "32", + (type & SLJIT_MEM_STORE) ? "st" : "ld", + op1_names[(type & 0xff) - SLJIT_OP1_BASE], + (type & SLJIT_MEM_PRE) ? ".pre" : ".post"); + sljit_verbose_reg(compiler, reg); + fprintf(compiler->verbose, ", "); + sljit_verbose_param(compiler, mem, memw); + fprintf(compiler->verbose, "\n"); + } +#endif + CHECK_RETURN_OK; +} + +static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fmem(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 freg, + sljit_s32 mem, sljit_sw memw) +{ +#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) + CHECK_ARGUMENT((type & 0xff) == SLJIT_MOV_F64); + CHECK_ARGUMENT((type & SLJIT_MEM_PRE) || (type & SLJIT_MEM_POST)); + CHECK_ARGUMENT((type & (SLJIT_MEM_PRE | SLJIT_MEM_POST)) != (SLJIT_MEM_PRE | SLJIT_MEM_POST)); + CHECK_ARGUMENT((type & ~(0xff | SLJIT_I32_OP | SLJIT_MEM_STORE | SLJIT_MEM_SUPP | SLJIT_MEM_PRE | SLJIT_MEM_POST)) == 0); + + FUNCTION_CHECK_SRC_MEM(mem, memw); + CHECK_ARGUMENT(FUNCTION_CHECK_IS_FREG(freg)); +#endif +#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) + if (!(type & SLJIT_MEM_SUPP) && SLJIT_UNLIKELY(!!compiler->verbose)) { + if (sljit_emit_fmem(compiler, type | SLJIT_MEM_SUPP, freg, mem, memw) == SLJIT_ERR_UNSUPPORTED) + fprintf(compiler->verbose, " //"); + + fprintf(compiler->verbose, " fmem.%s%s%s ", + (type & SLJIT_MEM_STORE) ? "st" : "ld", + !(type & SLJIT_I32_OP) ? ".f64" : ".f32", + (type & SLJIT_MEM_PRE) ? ".pre" : ".post"); + sljit_verbose_freg(compiler, freg); + fprintf(compiler->verbose, ", "); + sljit_verbose_param(compiler, mem, memw); + fprintf(compiler->verbose, "\n"); + } +#endif + CHECK_RETURN_OK; +} + static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_get_local_base(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw offset) { + /* Any offset is allowed. */ SLJIT_UNUSED_ARG(offset); #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) - FUNCTION_CHECK_DST(dst, dstw); + FUNCTION_CHECK_DST(dst, dstw, 0); #endif #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) if (SLJIT_UNLIKELY(!!compiler->verbose)) { @@ -1503,7 +1885,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_const(struct sljit_compil SLJIT_UNUSED_ARG(init_value); #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) - FUNCTION_CHECK_DST(dst, dstw); + FUNCTION_CHECK_DST(dst, dstw, 0); #endif #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) if (SLJIT_UNLIKELY(!!compiler->verbose)) { @@ -1564,6 +1946,44 @@ static SLJIT_INLINE sljit_s32 emit_mov_before_return(struct sljit_compiler *comp return sljit_emit_op1(compiler, op, SLJIT_RETURN_REG, 0, src, srcw); } +#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86) \ + || (defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC) \ + || (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32) \ + || ((defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS) && !(defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1)) + +static SLJIT_INLINE sljit_s32 sljit_emit_cmov_generic(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 dst_reg, + sljit_s32 src, sljit_sw srcw) +{ + struct sljit_label *label; + struct sljit_jump *jump; + sljit_s32 op = (dst_reg & SLJIT_I32_OP) ? SLJIT_MOV32 : SLJIT_MOV; + +#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \ + || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) + compiler->skip_checks = 1; +#endif + jump = sljit_emit_jump(compiler, type ^ 0x1); + FAIL_IF(!jump); + +#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \ + || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) + compiler->skip_checks = 1; +#endif + FAIL_IF(sljit_emit_op1(compiler, op, dst_reg & ~SLJIT_I32_OP, 0, src, srcw)); + +#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \ + || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) + compiler->skip_checks = 1; +#endif + label = sljit_emit_label(compiler); + FAIL_IF(!label); + sljit_set_label(jump, label); + return SLJIT_SUCCESS; +} + +#endif + /* CPU description section */ #if (defined SLJIT_32BIT_ARCHITECTURE && SLJIT_32BIT_ARCHITECTURE) @@ -1665,6 +2085,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_cmp(struct sljit_compiler condition = SLJIT_SIG_GREATER_EQUAL; break; } + type = condition | (type & (SLJIT_I32_OP | SLJIT_REWRITABLE_JUMP)); tmp_src = src1; src1 = src2; @@ -1675,11 +2096,9 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_cmp(struct sljit_compiler } if (condition <= SLJIT_NOT_ZERO) - flags = SLJIT_SET_E; - else if (condition <= SLJIT_LESS_EQUAL) - flags = SLJIT_SET_U; + flags = SLJIT_SET_Z; else - flags = SLJIT_SET_S; + flags = condition << VARIABLE_FLAG_SHIFT; #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \ || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) @@ -1691,34 +2110,70 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_cmp(struct sljit_compiler || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) compiler->skip_checks = 1; #endif - return sljit_emit_jump(compiler, condition | (type & SLJIT_REWRITABLE_JUMP)); + return sljit_emit_jump(compiler, condition | (type & (SLJIT_REWRITABLE_JUMP | SLJIT_I32_OP))); } +#endif + SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_fcmp(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 src1, sljit_sw src1w, sljit_s32 src2, sljit_sw src2w) { - sljit_s32 flags, condition; - CHECK_ERROR_PTR(); CHECK_PTR(check_sljit_emit_fcmp(compiler, type, src1, src1w, src2, src2w)); - condition = type & 0xff; - flags = (condition <= SLJIT_NOT_EQUAL_F64) ? SLJIT_SET_E : SLJIT_SET_S; - if (type & SLJIT_F32_OP) - flags |= SLJIT_F32_OP; - #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \ || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) compiler->skip_checks = 1; #endif - sljit_emit_fop1(compiler, SLJIT_CMP_F64 | flags, src1, src1w, src2, src2w); + sljit_emit_fop1(compiler, SLJIT_CMP_F64 | ((type & 0xff) << VARIABLE_FLAG_SHIFT) | (type & SLJIT_I32_OP), src1, src1w, src2, src2w); #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \ || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) compiler->skip_checks = 1; #endif - return sljit_emit_jump(compiler, condition | (type & SLJIT_REWRITABLE_JUMP)); + return sljit_emit_jump(compiler, type); +} + +#if !(defined SLJIT_CONFIG_ARM_32 && SLJIT_CONFIG_ARM_32) \ + && !(defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64) \ + && !(defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC) + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 reg, + sljit_s32 mem, sljit_sw memw) +{ + SLJIT_UNUSED_ARG(compiler); + SLJIT_UNUSED_ARG(type); + SLJIT_UNUSED_ARG(reg); + SLJIT_UNUSED_ARG(mem); + SLJIT_UNUSED_ARG(memw); + + CHECK_ERROR(); + CHECK(check_sljit_emit_mem(compiler, type, reg, mem, memw)); + + return SLJIT_ERR_UNSUPPORTED; +} + +#endif + +#if !(defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64) \ + && !(defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC) + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 freg, + sljit_s32 mem, sljit_sw memw) +{ + SLJIT_UNUSED_ARG(compiler); + SLJIT_UNUSED_ARG(type); + SLJIT_UNUSED_ARG(freg); + SLJIT_UNUSED_ARG(mem); + SLJIT_UNUSED_ARG(memw); + + CHECK_ERROR(); + CHECK(check_sljit_emit_fmem(compiler, type, freg, mem, memw)); + + return SLJIT_ERR_UNSUPPORTED; } #endif @@ -1736,7 +2191,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_local_base(struct sljit_compiler *c compiler->skip_checks = 1; #endif if (offset != 0) - return sljit_emit_op2(compiler, SLJIT_ADD | SLJIT_KEEP_FLAGS, dst, dstw, SLJIT_SP, 0, SLJIT_IMM, offset); + return sljit_emit_op2(compiler, SLJIT_ADD, dst, dstw, SLJIT_SP, 0, SLJIT_IMM, offset); return sljit_emit_op1(compiler, SLJIT_MOV, dst, dstw, SLJIT_SP, 0); } @@ -1751,23 +2206,30 @@ SLJIT_API_FUNC_ATTRIBUTE const char* sljit_get_platform_name(void) return "unsupported"; } -SLJIT_API_FUNC_ATTRIBUTE struct sljit_compiler* sljit_create_compiler(void) +SLJIT_API_FUNC_ATTRIBUTE struct sljit_compiler* sljit_create_compiler(void *allocator_data) { - SLJIT_ASSERT_STOP(); + SLJIT_UNUSED_ARG(allocator_data); + SLJIT_UNREACHABLE(); return NULL; } SLJIT_API_FUNC_ATTRIBUTE void sljit_free_compiler(struct sljit_compiler *compiler) { SLJIT_UNUSED_ARG(compiler); - SLJIT_ASSERT_STOP(); + SLJIT_UNREACHABLE(); +} + +SLJIT_API_FUNC_ATTRIBUTE void sljit_set_compiler_memory_error(struct sljit_compiler *compiler) +{ + SLJIT_UNUSED_ARG(compiler); + SLJIT_UNREACHABLE(); } SLJIT_API_FUNC_ATTRIBUTE void* sljit_alloc_memory(struct sljit_compiler *compiler, sljit_s32 size) { SLJIT_UNUSED_ARG(compiler); SLJIT_UNUSED_ARG(size); - SLJIT_ASSERT_STOP(); + SLJIT_UNREACHABLE(); return NULL; } @@ -1776,52 +2238,59 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_compiler_verbose(struct sljit_compiler *comp { SLJIT_UNUSED_ARG(compiler); SLJIT_UNUSED_ARG(verbose); - SLJIT_ASSERT_STOP(); + SLJIT_UNREACHABLE(); } #endif SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compiler) { SLJIT_UNUSED_ARG(compiler); - SLJIT_ASSERT_STOP(); + SLJIT_UNREACHABLE(); return NULL; } +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type) +{ + SLJIT_UNUSED_ARG(feature_type); + SLJIT_UNREACHABLE(); + return 0; +} + SLJIT_API_FUNC_ATTRIBUTE void sljit_free_code(void* code) { SLJIT_UNUSED_ARG(code); - SLJIT_ASSERT_STOP(); + SLJIT_UNREACHABLE(); } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compiler, - sljit_s32 options, sljit_s32 args, sljit_s32 scratches, sljit_s32 saveds, + sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds, sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size) { SLJIT_UNUSED_ARG(compiler); SLJIT_UNUSED_ARG(options); - SLJIT_UNUSED_ARG(args); + SLJIT_UNUSED_ARG(arg_types); SLJIT_UNUSED_ARG(scratches); SLJIT_UNUSED_ARG(saveds); SLJIT_UNUSED_ARG(fscratches); SLJIT_UNUSED_ARG(fsaveds); SLJIT_UNUSED_ARG(local_size); - SLJIT_ASSERT_STOP(); + SLJIT_UNREACHABLE(); return SLJIT_ERR_UNSUPPORTED; } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *compiler, - sljit_s32 options, sljit_s32 args, sljit_s32 scratches, sljit_s32 saveds, + sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds, sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size) { SLJIT_UNUSED_ARG(compiler); SLJIT_UNUSED_ARG(options); - SLJIT_UNUSED_ARG(args); + SLJIT_UNUSED_ARG(arg_types); SLJIT_UNUSED_ARG(scratches); SLJIT_UNUSED_ARG(saveds); SLJIT_UNUSED_ARG(fscratches); SLJIT_UNUSED_ARG(fsaveds); SLJIT_UNUSED_ARG(local_size); - SLJIT_ASSERT_STOP(); + SLJIT_UNREACHABLE(); return SLJIT_ERR_UNSUPPORTED; } @@ -1831,7 +2300,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return(struct sljit_compiler *comp SLJIT_UNUSED_ARG(op); SLJIT_UNUSED_ARG(src); SLJIT_UNUSED_ARG(srcw); - SLJIT_ASSERT_STOP(); + SLJIT_UNREACHABLE(); return SLJIT_ERR_UNSUPPORTED; } @@ -1840,7 +2309,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler * SLJIT_UNUSED_ARG(compiler); SLJIT_UNUSED_ARG(dst); SLJIT_UNUSED_ARG(dstw); - SLJIT_ASSERT_STOP(); + SLJIT_UNREACHABLE(); return SLJIT_ERR_UNSUPPORTED; } @@ -1849,7 +2318,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_return(struct sljit_compiler SLJIT_UNUSED_ARG(compiler); SLJIT_UNUSED_ARG(src); SLJIT_UNUSED_ARG(srcw); - SLJIT_ASSERT_STOP(); + SLJIT_UNREACHABLE(); return SLJIT_ERR_UNSUPPORTED; } @@ -1857,7 +2326,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compile { SLJIT_UNUSED_ARG(compiler); SLJIT_UNUSED_ARG(op); - SLJIT_ASSERT_STOP(); + SLJIT_UNREACHABLE(); return SLJIT_ERR_UNSUPPORTED; } @@ -1871,7 +2340,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile SLJIT_UNUSED_ARG(dstw); SLJIT_UNUSED_ARG(src); SLJIT_UNUSED_ARG(srcw); - SLJIT_ASSERT_STOP(); + SLJIT_UNREACHABLE(); return SLJIT_ERR_UNSUPPORTED; } @@ -1888,13 +2357,13 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile SLJIT_UNUSED_ARG(src1w); SLJIT_UNUSED_ARG(src2); SLJIT_UNUSED_ARG(src2w); - SLJIT_ASSERT_STOP(); + SLJIT_UNREACHABLE(); return SLJIT_ERR_UNSUPPORTED; } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 reg) { - SLJIT_ASSERT_STOP(); + SLJIT_UNREACHABLE(); return reg; } @@ -1904,14 +2373,14 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *c SLJIT_UNUSED_ARG(compiler); SLJIT_UNUSED_ARG(instruction); SLJIT_UNUSED_ARG(size); - SLJIT_ASSERT_STOP(); + SLJIT_UNREACHABLE(); return SLJIT_ERR_UNSUPPORTED; } -SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_is_fpu_available(void) +SLJIT_API_FUNC_ATTRIBUTE void sljit_set_current_flags(struct sljit_compiler *compiler, sljit_s32 current_flags) { - SLJIT_ASSERT_STOP(); - return 0; + SLJIT_UNUSED_ARG(compiler); + SLJIT_UNUSED_ARG(current_flags); } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop1(struct sljit_compiler *compiler, sljit_s32 op, @@ -1924,7 +2393,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop1(struct sljit_compiler *compil SLJIT_UNUSED_ARG(dstw); SLJIT_UNUSED_ARG(src); SLJIT_UNUSED_ARG(srcw); - SLJIT_ASSERT_STOP(); + SLJIT_UNREACHABLE(); return SLJIT_ERR_UNSUPPORTED; } @@ -1941,14 +2410,14 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2(struct sljit_compiler *compil SLJIT_UNUSED_ARG(src1w); SLJIT_UNUSED_ARG(src2); SLJIT_UNUSED_ARG(src2w); - SLJIT_ASSERT_STOP(); + SLJIT_UNREACHABLE(); return SLJIT_ERR_UNSUPPORTED; } SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compiler *compiler) { SLJIT_UNUSED_ARG(compiler); - SLJIT_ASSERT_STOP(); + SLJIT_UNREACHABLE(); return NULL; } @@ -1956,7 +2425,17 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compile { SLJIT_UNUSED_ARG(compiler); SLJIT_UNUSED_ARG(type); - SLJIT_ASSERT_STOP(); + SLJIT_UNREACHABLE(); + return NULL; +} + +SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 arg_types) +{ + SLJIT_UNUSED_ARG(compiler); + SLJIT_UNUSED_ARG(type); + SLJIT_UNUSED_ARG(arg_types); + SLJIT_UNREACHABLE(); return NULL; } @@ -1970,7 +2449,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_cmp(struct sljit_compiler SLJIT_UNUSED_ARG(src1w); SLJIT_UNUSED_ARG(src2); SLJIT_UNUSED_ARG(src2w); - SLJIT_ASSERT_STOP(); + SLJIT_UNREACHABLE(); return NULL; } @@ -1984,7 +2463,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_fcmp(struct sljit_compile SLJIT_UNUSED_ARG(src1w); SLJIT_UNUSED_ARG(src2); SLJIT_UNUSED_ARG(src2w); - SLJIT_ASSERT_STOP(); + SLJIT_UNREACHABLE(); return NULL; } @@ -1992,14 +2471,14 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_label(struct sljit_jump *jump, struct sl { SLJIT_UNUSED_ARG(jump); SLJIT_UNUSED_ARG(label); - SLJIT_ASSERT_STOP(); + SLJIT_UNREACHABLE(); } SLJIT_API_FUNC_ATTRIBUTE void sljit_set_target(struct sljit_jump *jump, sljit_uw target) { SLJIT_UNUSED_ARG(jump); SLJIT_UNUSED_ARG(target); - SLJIT_ASSERT_STOP(); + SLJIT_UNREACHABLE(); } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 src, sljit_sw srcw) @@ -2008,23 +2487,68 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compi SLJIT_UNUSED_ARG(type); SLJIT_UNUSED_ARG(src); SLJIT_UNUSED_ARG(srcw); - SLJIT_ASSERT_STOP(); + SLJIT_UNREACHABLE(); + return SLJIT_ERR_UNSUPPORTED; +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 arg_types, + sljit_s32 src, sljit_sw srcw) +{ + SLJIT_UNUSED_ARG(compiler); + SLJIT_UNUSED_ARG(type); + SLJIT_UNUSED_ARG(arg_types); + SLJIT_UNUSED_ARG(src); + SLJIT_UNUSED_ARG(srcw); + SLJIT_UNREACHABLE(); return SLJIT_ERR_UNSUPPORTED; } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw dstw, - sljit_s32 src, sljit_sw srcw, sljit_s32 type) { SLJIT_UNUSED_ARG(compiler); SLJIT_UNUSED_ARG(op); SLJIT_UNUSED_ARG(dst); SLJIT_UNUSED_ARG(dstw); + SLJIT_UNUSED_ARG(type); + SLJIT_UNREACHABLE(); + return SLJIT_ERR_UNSUPPORTED; +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 dst_reg, + sljit_s32 src, sljit_sw srcw) +{ + SLJIT_UNUSED_ARG(compiler); + SLJIT_UNUSED_ARG(type); + SLJIT_UNUSED_ARG(dst_reg); SLJIT_UNUSED_ARG(src); SLJIT_UNUSED_ARG(srcw); + SLJIT_UNREACHABLE(); + return SLJIT_ERR_UNSUPPORTED; +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 reg, sljit_s32 mem, sljit_sw memw) +{ + SLJIT_UNUSED_ARG(compiler); + SLJIT_UNUSED_ARG(type); + SLJIT_UNUSED_ARG(reg); + SLJIT_UNUSED_ARG(mem); + SLJIT_UNUSED_ARG(memw); + SLJIT_UNREACHABLE(); + return SLJIT_ERR_UNSUPPORTED; +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 freg, sljit_s32 mem, sljit_sw memw) +{ + SLJIT_UNUSED_ARG(compiler); SLJIT_UNUSED_ARG(type); - SLJIT_ASSERT_STOP(); + SLJIT_UNUSED_ARG(freg); + SLJIT_UNUSED_ARG(mem); + SLJIT_UNUSED_ARG(memw); + SLJIT_UNREACHABLE(); return SLJIT_ERR_UNSUPPORTED; } @@ -2034,7 +2558,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_local_base(struct sljit_compiler *c SLJIT_UNUSED_ARG(dst); SLJIT_UNUSED_ARG(dstw); SLJIT_UNUSED_ARG(offset); - SLJIT_ASSERT_STOP(); + SLJIT_UNREACHABLE(); return SLJIT_ERR_UNSUPPORTED; } @@ -2044,7 +2568,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compi SLJIT_UNUSED_ARG(dst); SLJIT_UNUSED_ARG(dstw); SLJIT_UNUSED_ARG(initval); - SLJIT_ASSERT_STOP(); + SLJIT_UNREACHABLE(); return NULL; } @@ -2053,7 +2577,7 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_ta SLJIT_UNUSED_ARG(addr); SLJIT_UNUSED_ARG(new_target); SLJIT_UNUSED_ARG(executable_offset); - SLJIT_ASSERT_STOP(); + SLJIT_UNREACHABLE(); } SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant, sljit_sw executable_offset) @@ -2061,7 +2585,7 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_consta SLJIT_UNUSED_ARG(addr); SLJIT_UNUSED_ARG(new_constant); SLJIT_UNUSED_ARG(executable_offset); - SLJIT_ASSERT_STOP(); + SLJIT_UNREACHABLE(); } #endif diff --git a/thirdparty/pcre2/src/sljit/sljitLir.h b/thirdparty/pcre2/src/sljit/sljitLir.h index f24f556b56..920f6d4f78 100644 --- a/thirdparty/pcre2/src/sljit/sljitLir.h +++ b/thirdparty/pcre2/src/sljit/sljitLir.h @@ -1,7 +1,7 @@ /* * Stack-less Just-In-Time compiler * - * Copyright 2009-2012 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved. + * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are * permitted provided that the following conditions are met: @@ -120,8 +120,8 @@ of sljitConfigInternal.h */ If an architecture provides two scratch and three saved registers, its scratch and saved register sets are the following: - R0 | [S4] | R0 and S4 represent the same physical register - R1 | [S3] | R1 and S3 represent the same physical register + R0 | | R0 is always a scratch register + R1 | | R1 is always a scratch register [R2] | S2 | R2 and S2 represent the same physical register [R3] | S1 | R3 and S1 represent the same physical register [R4] | S0 | R4 and S0 represent the same physical register @@ -129,38 +129,35 @@ of sljitConfigInternal.h */ Note: SLJIT_NUMBER_OF_SCRATCH_REGISTERS would be 2 and SLJIT_NUMBER_OF_SAVED_REGISTERS would be 3 for this architecture. - Note: On all supported architectures SLJIT_NUMBER_OF_REGISTERS >= 10 - and SLJIT_NUMBER_OF_SAVED_REGISTERS >= 5. However, 4 registers + Note: On all supported architectures SLJIT_NUMBER_OF_REGISTERS >= 12 + and SLJIT_NUMBER_OF_SAVED_REGISTERS >= 6. However, 6 registers are virtual on x86-32. See below. - The purpose of this definition is convenience. Although a register - is either scratch register or saved register, SLJIT allows accessing - them from the other set. For example, four registers can be used as - scratch registers and the fifth one as saved register on the architecture - above. Of course the last two scratch registers (R2 and R3) from this - four will be saved on the stack, because they are defined as saved - registers in the application binary interface. Still R2 and R3 can be - used for referencing to these registers instead of S2 and S1, which - makes easier to write platform independent code. Scratch registers - can be saved registers in a similar way, but these extra saved - registers will not be preserved across function calls! Hence the - application must save them on those platforms, where the number of - saved registers is too low. This can be done by copy them onto - the stack and restore them after a function call. + The purpose of this definition is convenience: saved registers can + be used as extra scratch registers. For example four registers can + be specified as scratch registers and the fifth one as saved register + on the CPU above and any user code which requires four scratch + registers can run unmodified. The SLJIT compiler automatically saves + the content of the two extra scrath register on the stack. Scratch + registers can also be preserved by saving their value on the stack + but this needs to be done manually. Note: To emphasize that registers assigned to R2-R4 are saved - registers, they are enclosed by square brackets. S3-S4 - are marked in a similar way. + registers, they are enclosed by square brackets. Note: sljit_emit_enter and sljit_set_context defines whether a register is S or R register. E.g: when 3 scratches and 1 saved is mapped by sljit_emit_enter, the allowed register set will be: R0-R2 and S0. Although S2 is mapped to the same position as R2, it does not - available in the current configuration. Furthermore the R3 (S1) - register does not available as well. + available in the current configuration. Furthermore the S1 register + is not available at all. */ -/* When SLJIT_UNUSED is specified as destination, the result is discarded. */ +/* When SLJIT_UNUSED is specified as the destination of sljit_emit_op1 + or sljit_emit_op2 operations the result is discarded. If no status + flags are set, no instructions are emitted for these operations. Data + prefetch is a special exception, see SLJIT_MOV operation. Other SLJIT + operations do not support SLJIT_UNUSED as a destination operand. */ #define SLJIT_UNUSED 0 /* Scratch registers. */ @@ -216,14 +213,6 @@ of sljitConfigInternal.h */ #define SLJIT_RETURN_REG SLJIT_R0 -/* x86 prefers specific registers for special purposes. In case of shift - by register it supports only SLJIT_R2 for shift argument - (which is the src2 argument of sljit_emit_op2). If another register is - used, sljit must exchange data between registers which cause a minor - slowdown. Other architectures has no such limitation. */ - -#define SLJIT_PREF_SHIFT_REG SLJIT_R2 - /* --------------------------------------------------------------------- */ /* Floating point registers */ /* --------------------------------------------------------------------- */ @@ -261,6 +250,79 @@ of sljitConfigInternal.h */ #define SLJIT_FIRST_SAVED_FLOAT_REG (SLJIT_FS0 - SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS + 1) /* --------------------------------------------------------------------- */ +/* Argument type definitions */ +/* --------------------------------------------------------------------- */ + +/* Argument type definitions. + Used by SLJIT_[DEF_]ARGx and SLJIT_[DEF]_RET macros. */ + +#define SLJIT_ARG_TYPE_VOID 0 +#define SLJIT_ARG_TYPE_SW 1 +#define SLJIT_ARG_TYPE_UW 2 +#define SLJIT_ARG_TYPE_S32 3 +#define SLJIT_ARG_TYPE_U32 4 +#define SLJIT_ARG_TYPE_F32 5 +#define SLJIT_ARG_TYPE_F64 6 + +/* The following argument type definitions are used by sljit_emit_enter, + sljit_set_context, sljit_emit_call, and sljit_emit_icall functions. + The following return type definitions are used by sljit_emit_call + and sljit_emit_icall functions. + + When a function is called, the first integer argument must be placed + in SLJIT_R0, the second in SLJIT_R1, and so on. Similarly the first + floating point argument must be placed in SLJIT_FR0, the second in + SLJIT_FR1, and so on. + + Example function definition: + sljit_f32 SLJIT_FUNC example_c_callback(sljit_sw arg_a, + sljit_f64 arg_b, sljit_u32 arg_c, sljit_f32 arg_d); + + Argument type definition: + SLJIT_DEF_RET(SLJIT_ARG_TYPE_F32) + | SLJIT_DEF_ARG1(SLJIT_ARG_TYPE_SW) | SLJIT_DEF_ARG2(SLJIT_ARG_TYPE_F64) + | SLJIT_DEF_ARG3(SLJIT_ARG_TYPE_U32) | SLJIT_DEF_ARG2(SLJIT_ARG_TYPE_F32) + + Short form of argument type definition: + SLJIT_RET(F32) | SLJIT_ARG1(SW) | SLJIT_ARG2(F64) + | SLJIT_ARG3(S32) | SLJIT_ARG4(F32) + + Argument passing: + arg_a must be placed in SLJIT_R0 + arg_c must be placed in SLJIT_R1 + arg_b must be placed in SLJIT_FR0 + arg_d must be placed in SLJIT_FR1 + +Note: + The SLJIT_ARG_TYPE_VOID type is only supported by + SLJIT_DEF_RET, and SLJIT_ARG_TYPE_VOID is also the + default value when SLJIT_DEF_RET is not specified. */ +#define SLJIT_DEF_SHIFT 4 +#define SLJIT_DEF_RET(type) (type) +#define SLJIT_DEF_ARG1(type) ((type) << SLJIT_DEF_SHIFT) +#define SLJIT_DEF_ARG2(type) ((type) << (2 * SLJIT_DEF_SHIFT)) +#define SLJIT_DEF_ARG3(type) ((type) << (3 * SLJIT_DEF_SHIFT)) +#define SLJIT_DEF_ARG4(type) ((type) << (4 * SLJIT_DEF_SHIFT)) + +/* Short form of the macros above. + + For example the following definition: + SLJIT_DEF_RET(SLJIT_ARG_TYPE_SW) | SLJIT_DEF_ARG1(SLJIT_ARG_TYPE_F32) + + can be shortened to: + SLJIT_RET(SW) | SLJIT_ARG1(F32) + +Note: + The VOID type is only supported by SLJIT_RET, and + VOID is also the default value when SLJIT_RET is + not specified. */ +#define SLJIT_RET(type) SLJIT_DEF_RET(SLJIT_ARG_TYPE_ ## type) +#define SLJIT_ARG1(type) SLJIT_DEF_ARG1(SLJIT_ARG_TYPE_ ## type) +#define SLJIT_ARG2(type) SLJIT_DEF_ARG2(SLJIT_ARG_TYPE_ ## type) +#define SLJIT_ARG3(type) SLJIT_DEF_ARG3(SLJIT_ARG_TYPE_ ## type) +#define SLJIT_ARG4(type) SLJIT_DEF_ARG4(SLJIT_ARG_TYPE_ ## type) + +/* --------------------------------------------------------------------- */ /* Main structures and functions */ /* --------------------------------------------------------------------- */ @@ -332,14 +394,16 @@ struct sljit_compiler { #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) sljit_s32 args; + sljit_s32 locals_offset; + sljit_s32 saveds_offset; + sljit_s32 stack_tmp_size; #endif #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) sljit_s32 mode32; +#ifdef _WIN64 + sljit_s32 locals_offset; #endif - -#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86) - sljit_s32 flags_saved; #endif #if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) @@ -356,24 +420,10 @@ struct sljit_compiler { #if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) || (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7) /* Temporary fields. */ sljit_uw shift_imm; - sljit_s32 cache_arg; - sljit_sw cache_argw; -#endif - -#if (defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2) - sljit_s32 cache_arg; - sljit_sw cache_argw; -#endif - -#if (defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64) - sljit_s32 cache_arg; - sljit_sw cache_argw; #endif #if (defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC) sljit_sw imm; - sljit_s32 cache_arg; - sljit_sw cache_argw; #endif #if (defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS) @@ -399,6 +449,9 @@ struct sljit_compiler { #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) \ || (defined SLJIT_DEBUG && SLJIT_DEBUG) + /* Flags specified by the last arithmetic instruction. + It contains the type of the variable flag. */ + sljit_s32 last_flags; /* Local size passed to the functions. */ sljit_s32 logical_local_size; #endif @@ -406,6 +459,7 @@ struct sljit_compiler { #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) \ || (defined SLJIT_DEBUG && SLJIT_DEBUG) \ || (defined SLJIT_VERBOSE && SLJIT_VERBOSE) + /* Trust arguments when the API function is called. */ sljit_s32 skip_checks; #endif }; @@ -491,31 +545,57 @@ static SLJIT_INLINE sljit_sw sljit_get_executable_offset(struct sljit_compiler * */ static SLJIT_INLINE sljit_uw sljit_get_generated_code_size(struct sljit_compiler *compiler) { return compiler->executable_size; } +/* Returns with non-zero if the feature or limitation type passed as its + argument is present on the current CPU. + + Some features (e.g. floating point operations) require hardware (CPU) + support while others (e.g. move with update) are emulated if not available. + However even if a feature is emulated, specialized code paths can be faster + than the emulation. Some limitations are emulated as well so their general + case is supported but it has extra performance costs. */ + +/* [Not emulated] Floating-point support is available. */ +#define SLJIT_HAS_FPU 0 +/* [Limitation] Some registers are virtual registers. */ +#define SLJIT_HAS_VIRTUAL_REGISTERS 1 +/* [Emulated] Count leading zero is supported. */ +#define SLJIT_HAS_CLZ 2 +/* [Emulated] Conditional move is supported. */ +#define SLJIT_HAS_CMOV 3 + +#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86) +/* [Not emulated] SSE2 support is available on x86. */ +#define SLJIT_HAS_SSE2 100 +#endif + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type); + /* Instruction generation. Returns with any error code. If there is no error, they return with SLJIT_SUCCESS. */ /* - The executable code is a function call from the viewpoint of the C + The executable code is a function from the viewpoint of the C language. The function calls must obey to the ABI (Application Binary Interface) of the platform, which specify the purpose of - all machine registers and stack handling among other things. The + machine registers and stack handling among other things. The sljit_emit_enter function emits the necessary instructions for setting up a new context for the executable code and moves function arguments to the saved registers. Furthermore the options argument can be used to pass configuration options to the compiler. The available options are listed before sljit_emit_enter. - The number of sljit_sw arguments passed to the generated function - are specified in the "args" parameter. The number of arguments must - be less than or equal to 3. The first argument goes to SLJIT_S0, - the second goes to SLJIT_S1 and so on. The register set used by - the function must be declared as well. The number of scratch and - saved registers used by the function must be passed to sljit_emit_enter. - Only R registers between R0 and "scratches" argument can be used - later. E.g. if "scratches" is set to 2, the register set will be - limited to R0 and R1. The S registers and the floating point + The function argument list is the combination of SLJIT_ARGx + (SLJIT_DEF_ARG1) macros. Currently maximum 3 SW / UW + (SLJIT_ARG_TYPE_SW / LJIT_ARG_TYPE_UW) arguments are supported. + The first argument goes to SLJIT_S0, the second goes to SLJIT_S1 + and so on. The register set used by the function must be declared + as well. The number of scratch and saved registers used by the + function must be passed to sljit_emit_enter. Only R registers + between R0 and "scratches" argument can be used later. E.g. if + "scratches" is set to 2, the scratch register set will be limited + to SLJIT_R0 and SLJIT_R1. The S registers and the floating point registers ("fscratches" and "fsaveds") are specified in a similar - way. The sljit_emit_enter is also capable of allocating a stack + manner. The sljit_emit_enter is also capable of allocating a stack space for local variables. The "local_size" argument contains the size in bytes of this local area and its staring address is stored in SLJIT_SP. The memory area between SLJIT_SP (inclusive) and @@ -535,14 +615,14 @@ static SLJIT_INLINE sljit_uw sljit_get_generated_code_size(struct sljit_compiler */ /* The absolute address returned by sljit_get_local_base with -offset 0 is aligned to sljit_d. Otherwise it is aligned to sljit_uw. */ -#define SLJIT_DOUBLE_ALIGNMENT 0x00000001 +offset 0 is aligned to sljit_f64. Otherwise it is aligned to sljit_sw. */ +#define SLJIT_F64_ALIGNMENT 0x00000001 /* The local_size must be >= 0 and <= SLJIT_MAX_LOCAL_SIZE. */ #define SLJIT_MAX_LOCAL_SIZE 65536 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compiler, - sljit_s32 options, sljit_s32 args, sljit_s32 scratches, sljit_s32 saveds, + sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds, sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size); /* The machine code has a context (which contains the local stack space size, @@ -556,7 +636,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi the previous context. */ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *compiler, - sljit_s32 options, sljit_s32 args, sljit_s32 scratches, sljit_s32 saveds, + sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds, sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size); /* Return from machine code. The op argument can be SLJIT_UNUSED which means the @@ -568,26 +648,31 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *comp SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src, sljit_sw srcw); -/* Fast calling mechanism for utility functions (see SLJIT_FAST_CALL). All registers and - even the stack frame is passed to the callee. The return address is preserved in - dst/dstw by sljit_emit_fast_enter (the type of the value stored by this function - is sljit_p), and sljit_emit_fast_return can use this as a return value later. */ +/* Generating entry and exit points for fast call functions (see SLJIT_FAST_CALL). + Both sljit_emit_fast_enter and sljit_emit_fast_return functions preserve the + values of all registers and stack frame. The return address is stored in the + dst argument of sljit_emit_fast_enter, and this return address can be passed + to sljit_emit_fast_return to continue the execution after the fast call. -/* Note: only for sljit specific, non ABI compilant calls. Fast, since only a few machine - instructions are needed. Excellent for small uility functions, where saving registers - and setting up a new stack frame would cost too much performance. However, it is still - possible to return to the address of the caller (or anywhere else). */ + Fast calls are cheap operations (usually only a single call instruction is + emitted) but they do not preserve any registers. However the callee function + can freely use / update any registers and stack values which can be + efficiently exploited by various optimizations. Registers can be saved + manually by the callee function if needed. -/* Note: flags are not changed (unlike sljit_emit_enter / sljit_emit_return). */ + Although returning to different address by sljit_emit_fast_return is possible, + this address usually cannot be predicted by the return address predictor of + modern CPUs which may reduce performance. Furthermore using sljit_emit_ijump + to return is also inefficient since return address prediction is usually + triggered by a specific form of ijump. -/* Note: although sljit_emit_fast_return could be replaced by an ijump, it is not suggested, - since many architectures do clever branch prediction on call / return instruction pairs. */ + Flags: - (does not modify flags). */ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw); SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_return(struct sljit_compiler *compiler, sljit_s32 src, sljit_sw srcw); /* - Source and destination values for arithmetical instructions + Source and destination operands for arithmetical instructions imm - a simple immediate value (cannot be used as a destination) reg - any of the registers (immediate argument must be 0) [imm] - absolute immediate memory address @@ -628,6 +713,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_return(struct sljit_compiler arm-t2: [reg+imm], -255 <= imm <= 4095 [reg+(reg<<imm)] is supported Write back is supported only for [reg+imm], where -255 <= imm <= 255 + arm64: [reg+imm], -256 <= imm <= 255, 0 <= aligned imm <= 4095 * alignment + [reg+(reg<<imm)] is supported + Write back is supported only for [reg+imm], where -256 <= imm <= 255 ppc: [reg+imm], -65536 <= imm <= 65535. 64 bit loads/stores and 32 bit signed load on 64 bit requires immediates divisible by 4. [reg+imm] is not supported for signed 8 bit values. @@ -639,65 +727,104 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_return(struct sljit_compiler [reg+reg] is supported */ -/* Register output: simply the name of the register. - For destination, you can use SLJIT_UNUSED as well. */ +/* Macros for specifying operand types. */ #define SLJIT_MEM 0x80 #define SLJIT_MEM0() (SLJIT_MEM) #define SLJIT_MEM1(r1) (SLJIT_MEM | (r1)) #define SLJIT_MEM2(r1, r2) (SLJIT_MEM | (r1) | ((r2) << 8)) #define SLJIT_IMM 0x40 -/* Set 32 bit operation mode (I) on 64 bit CPUs. This flag is ignored on 32 - bit CPUs. When this flag is set for an arithmetic operation, only the - lower 32 bit of the input register(s) are used, and the CPU status flags - are set according to the 32 bit result. Although the higher 32 bit of - the input and the result registers are not defined by SLJIT, it might be - defined by the CPU architecture (e.g. MIPS). To satisfy these requirements - all source registers must be computed by operations where this flag is - also set. In other words 32 and 64 bit arithmetic operations cannot be - mixed. The only exception is SLJIT_IMOV and SLJIT_IMOVU whose source - register can hold any 32 or 64 bit value. This source register is - converted to a 32 bit compatible format. SLJIT does not generate any - instructions on certain CPUs (e.g. on x86 and ARM) if the source and - destination operands are the same registers. Affects sljit_emit_op0, - sljit_emit_op1 and sljit_emit_op2. */ +/* Set 32 bit operation mode (I) on 64 bit CPUs. This option is ignored on + 32 bit CPUs. When this option is set for an arithmetic operation, only + the lower 32 bit of the input registers are used, and the CPU status + flags are set according to the 32 bit result. Although the higher 32 bit + of the input and the result registers are not defined by SLJIT, it might + be defined by the CPU architecture (e.g. MIPS). To satisfy these CPU + requirements all source registers must be the result of those operations + where this option was also set. Memory loads read 32 bit values rather + than 64 bit ones. In other words 32 bit and 64 bit operations cannot + be mixed. The only exception is SLJIT_MOV32 and SLJIT_MOVU32 whose source + register can hold any 32 or 64 bit value, and it is converted to a 32 bit + compatible format first. This conversion is free (no instructions are + emitted) on most CPUs. A 32 bit value can also be coverted to a 64 bit + value by SLJIT_MOV_S32 (sign extension) or SLJIT_MOV_U32 (zero extension). + + Note: memory addressing always uses 64 bit values on 64 bit systems so + the result of a 32 bit operation must not be used with SLJIT_MEMx + macros. + + This option is part of the instruction name, so there is no need to + manually set it. E.g: + + SLJIT_ADD32 == (SLJIT_ADD | SLJIT_I32_OP) */ #define SLJIT_I32_OP 0x100 -/* F32 precision mode (SP). This flag is similar to SLJIT_I32_OP, just - it applies to floating point registers (it is even the same bit). When - this flag is passed, the CPU performs 32 bit floating point operations. - Similar to SLJIT_I32_OP, all register arguments must be computed by - floating point operations where this flag is also set. Affects - sljit_emit_fop1, sljit_emit_fop2 and sljit_emit_fcmp. */ -#define SLJIT_F32_OP 0x100 - -/* Common CPU status flags for all architectures (x86, ARM, PPC) - - carry flag - - overflow flag - - zero flag - - negative/positive flag (depends on arc) - On mips, these flags are emulated by software. */ - -/* By default, the instructions may, or may not set the CPU status flags. - Forcing to set or keep status flags can be done with the following flags: */ - -/* Note: sljit tries to emit the minimum number of instructions. Using these - flags can increase them, so use them wisely to avoid unnecessary code generation. */ - -/* Set Equal (Zero) status flag (E). */ -#define SLJIT_SET_E 0x0200 -/* Set unsigned status flag (U). */ -#define SLJIT_SET_U 0x0400 -/* Set signed status flag (S). */ -#define SLJIT_SET_S 0x0800 -/* Set signed overflow flag (O). */ -#define SLJIT_SET_O 0x1000 -/* Set carry flag (C). - Note: Kinda unsigned overflow, but behaves differently on various cpus. */ -#define SLJIT_SET_C 0x2000 -/* Do not modify the flags (K). - Note: This flag cannot be combined with any other SLJIT_SET_* flag. */ -#define SLJIT_KEEP_FLAGS 0x4000 +/* Set F32 (single) precision mode for floating-point computation. This + option is similar to SLJIT_I32_OP, it just applies to floating point + registers. When this option is passed, the CPU performs 32 bit floating + point operations, rather than 64 bit one. Similar to SLJIT_I32_OP, all + register arguments must be the result of those operations where this + option was also set. + + This option is part of the instruction name, so there is no need to + manually set it. E.g: + + SLJIT_MOV_F32 = (SLJIT_MOV_F64 | SLJIT_F32_OP) + */ +#define SLJIT_F32_OP SLJIT_I32_OP + +/* Many CPUs (x86, ARM, PPC) has status flags which can be set according + to the result of an operation. Other CPUs (MIPS) does not have status + flags, and results must be stored in registers. To cover both architecture + types efficiently only two flags are defined by SLJIT: + + * Zero (equal) flag: it is set if the result is zero + * Variable flag: its value is defined by the last arithmetic operation + + SLJIT instructions can set any or both of these flags. The value of + these flags is undefined if the instruction does not specify their value. + The description of each instruction contains the list of allowed flag + types. + + Example: SLJIT_ADD can set the Z, OVERFLOW, CARRY flags hence + + sljit_op2(..., SLJIT_ADD, ...) + Both the zero and variable flags are undefined so they can + have any value after the operation is completed. + + sljit_op2(..., SLJIT_ADD | SLJIT_SET_Z, ...) + Sets the zero flag if the result is zero, clears it otherwise. + The variable flag is undefined. + + sljit_op2(..., SLJIT_ADD | SLJIT_SET_OVERFLOW, ...) + Sets the variable flag if an integer overflow occurs, clears + it otherwise. The zero flag is undefined. + + sljit_op2(..., SLJIT_ADD | SLJIT_SET_Z | SLJIT_SET_CARRY, ...) + Sets the zero flag if the result is zero, clears it otherwise. + Sets the variable flag if unsigned overflow (carry) occurs, + clears it otherwise. + + If an instruction (e.g. SLJIT_MOV) does not modify flags the flags are + unchanged. + + Using these flags can reduce the number of emitted instructions. E.g. a + fast loop can be implemented by decreasing a counter register and set the + zero flag to jump back if the counter register is not reached zero. + + Motivation: although CPUs can set a large number of flags, usually their + values are ignored or only one of them is used. Emulating a large number + of flags on systems without flag register is complicated so SLJIT + instructions must specify the flag they want to use and only that flag + will be emulated. The last arithmetic instruction can be repeated if + multiple flags needs to be checked. +*/ + +/* Set Zero status flag. */ +#define SLJIT_SET_Z 0x0200 +/* Set the variable status flag if condition is true. + See comparison types. */ +#define SLJIT_SET(condition) ((condition) << 10) /* Notes: - you cannot postpone conditional jump instructions except if noted that @@ -707,11 +834,11 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_return(struct sljit_compiler /* Starting index of opcodes for sljit_emit_op0. */ #define SLJIT_OP0_BASE 0 -/* Flags: - (never set any flags) +/* Flags: - (does not modify flags) Note: breakpoint instruction is not supported by all architectures (e.g. ppc) It falls back to SLJIT_NOP in those cases. */ #define SLJIT_BREAKPOINT (SLJIT_OP0_BASE + 0) -/* Flags: - (never set any flags) +/* Flags: - (does not modify flags) Note: may or may not cause an extra cycle wait it can even decrease the runtime in a few cases. */ #define SLJIT_NOP (SLJIT_OP0_BASE + 1) @@ -723,13 +850,13 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_return(struct sljit_compiler Signed multiplication of SLJIT_R0 and SLJIT_R1. Result is placed into SLJIT_R1:SLJIT_R0 (high:low) word */ #define SLJIT_LMUL_SW (SLJIT_OP0_BASE + 3) -/* Flags: I - (may destroy flags) +/* Flags: - (may destroy flags) Unsigned divide of the value in SLJIT_R0 by the value in SLJIT_R1. The result is placed into SLJIT_R0 and the remainder into SLJIT_R1. Note: if SLJIT_R1 is 0, the behaviour is undefined. */ #define SLJIT_DIVMOD_UW (SLJIT_OP0_BASE + 4) #define SLJIT_DIVMOD_U32 (SLJIT_DIVMOD_UW | SLJIT_I32_OP) -/* Flags: I - (may destroy flags) +/* Flags: - (may destroy flags) Signed divide of the value in SLJIT_R0 by the value in SLJIT_R1. The result is placed into SLJIT_R0 and the remainder into SLJIT_R1. Note: if SLJIT_R1 is 0, the behaviour is undefined. @@ -737,13 +864,13 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_return(struct sljit_compiler the behaviour is undefined. */ #define SLJIT_DIVMOD_SW (SLJIT_OP0_BASE + 5) #define SLJIT_DIVMOD_S32 (SLJIT_DIVMOD_SW | SLJIT_I32_OP) -/* Flags: I - (may destroy flags) +/* Flags: - (may destroy flags) Unsigned divide of the value in SLJIT_R0 by the value in SLJIT_R1. The result is placed into SLJIT_R0. SLJIT_R1 preserves its value. Note: if SLJIT_R1 is 0, the behaviour is undefined. */ #define SLJIT_DIV_UW (SLJIT_OP0_BASE + 6) #define SLJIT_DIV_U32 (SLJIT_DIV_UW | SLJIT_I32_OP) -/* Flags: I - (may destroy flags) +/* Flags: - (may destroy flags) Signed divide of the value in SLJIT_R0 by the value in SLJIT_R1. The result is placed into SLJIT_R0. SLJIT_R1 preserves its value. Note: if SLJIT_R1 is 0, the behaviour is undefined. @@ -757,76 +884,67 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compile /* Starting index of opcodes for sljit_emit_op1. */ #define SLJIT_OP1_BASE 32 -/* Notes for MOV instructions: - U = Mov with update (pre form). If source or destination defined as SLJIT_MEM1(r1) - or SLJIT_MEM2(r1, r2), r1 is increased by the sum of r2 and the constant argument - UB = unsigned byte (8 bit) - SB = signed byte (8 bit) - UH = unsigned half (16 bit) - SH = signed half (16 bit) - UI = unsigned int (32 bit) - SI = signed int (32 bit) - P = pointer (sljit_p) size */ - -/* Flags: - (never set any flags) */ +/* The MOV instruction transfer data from source to destination. + + MOV instruction suffixes: + + U8 - unsigned 8 bit data transfer + S8 - signed 8 bit data transfer + U16 - unsigned 16 bit data transfer + S16 - signed 16 bit data transfer + U32 - unsigned int (32 bit) data transfer + S32 - signed int (32 bit) data transfer + P - pointer (sljit_p) data transfer + + If the destination of a MOV instruction is SLJIT_UNUSED and the source + operand is a memory address the compiler emits a prefetch instruction + if this instruction is supported by the current CPU. Higher data sizes + bring the data closer to the core: a MOV with word size loads the data + into a higher level cache than a byte size. Otherwise the type does not + affect the prefetch instruction. Furthermore a prefetch instruction + never fails, so it can be used to prefetch a data from an address and + check whether that address is NULL afterwards. +*/ + +/* Flags: - (does not modify flags) */ #define SLJIT_MOV (SLJIT_OP1_BASE + 0) -/* Flags: I - (never set any flags) */ +/* Flags: - (does not modify flags) */ #define SLJIT_MOV_U8 (SLJIT_OP1_BASE + 1) #define SLJIT_MOV32_U8 (SLJIT_MOV_U8 | SLJIT_I32_OP) -/* Flags: I - (never set any flags) */ +/* Flags: - (does not modify flags) */ #define SLJIT_MOV_S8 (SLJIT_OP1_BASE + 2) #define SLJIT_MOV32_S8 (SLJIT_MOV_S8 | SLJIT_I32_OP) -/* Flags: I - (never set any flags) */ +/* Flags: - (does not modify flags) */ #define SLJIT_MOV_U16 (SLJIT_OP1_BASE + 3) #define SLJIT_MOV32_U16 (SLJIT_MOV_U16 | SLJIT_I32_OP) -/* Flags: I - (never set any flags) */ +/* Flags: - (does not modify flags) */ #define SLJIT_MOV_S16 (SLJIT_OP1_BASE + 4) #define SLJIT_MOV32_S16 (SLJIT_MOV_S16 | SLJIT_I32_OP) -/* Flags: I - (never set any flags) +/* Flags: - (does not modify flags) Note: no SLJIT_MOV32_U32 form, since it is the same as SLJIT_MOV32 */ #define SLJIT_MOV_U32 (SLJIT_OP1_BASE + 5) -/* Flags: I - (never set any flags) +/* Flags: - (does not modify flags) Note: no SLJIT_MOV32_S32 form, since it is the same as SLJIT_MOV32 */ #define SLJIT_MOV_S32 (SLJIT_OP1_BASE + 6) -/* Flags: I - (never set any flags) */ +/* Flags: - (does not modify flags) */ #define SLJIT_MOV32 (SLJIT_MOV_S32 | SLJIT_I32_OP) -/* Flags: - (never set any flags) */ +/* Flags: - (does not modify flags) + Note: load a pointer sized data, useful on x32 (a 32 bit mode on x86-64 + where all x64 features are available, e.g. 16 register) or similar + compiling modes */ #define SLJIT_MOV_P (SLJIT_OP1_BASE + 7) -/* Flags: - (never set any flags) */ -#define SLJIT_MOVU (SLJIT_OP1_BASE + 8) -/* Flags: I - (never set any flags) */ -#define SLJIT_MOVU_U8 (SLJIT_OP1_BASE + 9) -#define SLJIT_MOVU32_U8 (SLJIT_MOVU_U8 | SLJIT_I32_OP) -/* Flags: I - (never set any flags) */ -#define SLJIT_MOVU_S8 (SLJIT_OP1_BASE + 10) -#define SLJIT_MOVU32_S8 (SLJIT_MOVU_S8 | SLJIT_I32_OP) -/* Flags: I - (never set any flags) */ -#define SLJIT_MOVU_U16 (SLJIT_OP1_BASE + 11) -#define SLJIT_MOVU32_U16 (SLJIT_MOVU_U16 | SLJIT_I32_OP) -/* Flags: I - (never set any flags) */ -#define SLJIT_MOVU_S16 (SLJIT_OP1_BASE + 12) -#define SLJIT_MOVU32_S16 (SLJIT_MOVU_S16 | SLJIT_I32_OP) -/* Flags: I - (never set any flags) - Note: no SLJIT_MOVU32_U32 form, since it is the same as SLJIT_MOVU32 */ -#define SLJIT_MOVU_U32 (SLJIT_OP1_BASE + 13) -/* Flags: I - (never set any flags) - Note: no SLJIT_MOVU32_S32 form, since it is the same as SLJIT_MOVU32 */ -#define SLJIT_MOVU_S32 (SLJIT_OP1_BASE + 14) -/* Flags: I - (never set any flags) */ -#define SLJIT_MOVU32 (SLJIT_MOVU_S32 | SLJIT_I32_OP) -/* Flags: - (never set any flags) */ -#define SLJIT_MOVU_P (SLJIT_OP1_BASE + 15) -/* Flags: I | E | K */ -#define SLJIT_NOT (SLJIT_OP1_BASE + 16) +/* Flags: Z + Note: immediate source argument is not supported */ +#define SLJIT_NOT (SLJIT_OP1_BASE + 8) #define SLJIT_NOT32 (SLJIT_NOT | SLJIT_I32_OP) -/* Flags: I | E | O | K */ -#define SLJIT_NEG (SLJIT_OP1_BASE + 17) +/* Flags: Z | OVERFLOW + Note: immediate source argument is not supported */ +#define SLJIT_NEG (SLJIT_OP1_BASE + 9) #define SLJIT_NEG32 (SLJIT_NEG | SLJIT_I32_OP) /* Count leading zeroes - Flags: I | E | K - Important note! Sparc 32 does not support K flag, since - the required popc instruction is introduced only in sparc 64. */ -#define SLJIT_CLZ (SLJIT_OP1_BASE + 18) + Flags: - (may destroy flags) + Note: immediate source argument is not supported */ +#define SLJIT_CLZ (SLJIT_OP1_BASE + 10) #define SLJIT_CLZ32 (SLJIT_CLZ | SLJIT_I32_OP) SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compiler, sljit_s32 op, @@ -836,46 +954,48 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile /* Starting index of opcodes for sljit_emit_op2. */ #define SLJIT_OP2_BASE 96 -/* Flags: I | E | O | C | K */ +/* Flags: Z | OVERFLOW | CARRY */ #define SLJIT_ADD (SLJIT_OP2_BASE + 0) #define SLJIT_ADD32 (SLJIT_ADD | SLJIT_I32_OP) -/* Flags: I | C | K */ +/* Flags: CARRY */ #define SLJIT_ADDC (SLJIT_OP2_BASE + 1) #define SLJIT_ADDC32 (SLJIT_ADDC | SLJIT_I32_OP) -/* Flags: I | E | U | S | O | C | K */ +/* Flags: Z | LESS | GREATER_EQUAL | GREATER | LESS_EQUAL + SIG_LESS | SIG_GREATER_EQUAL | SIG_GREATER + SIG_LESS_EQUAL | CARRY */ #define SLJIT_SUB (SLJIT_OP2_BASE + 2) #define SLJIT_SUB32 (SLJIT_SUB | SLJIT_I32_OP) -/* Flags: I | C | K */ +/* Flags: CARRY */ #define SLJIT_SUBC (SLJIT_OP2_BASE + 3) #define SLJIT_SUBC32 (SLJIT_SUBC | SLJIT_I32_OP) /* Note: integer mul - Flags: I | O (see SLJIT_C_MUL_*) | K */ + Flags: MUL_OVERFLOW */ #define SLJIT_MUL (SLJIT_OP2_BASE + 4) #define SLJIT_MUL32 (SLJIT_MUL | SLJIT_I32_OP) -/* Flags: I | E | K */ +/* Flags: Z */ #define SLJIT_AND (SLJIT_OP2_BASE + 5) #define SLJIT_AND32 (SLJIT_AND | SLJIT_I32_OP) -/* Flags: I | E | K */ +/* Flags: Z */ #define SLJIT_OR (SLJIT_OP2_BASE + 6) #define SLJIT_OR32 (SLJIT_OR | SLJIT_I32_OP) -/* Flags: I | E | K */ +/* Flags: Z */ #define SLJIT_XOR (SLJIT_OP2_BASE + 7) #define SLJIT_XOR32 (SLJIT_XOR | SLJIT_I32_OP) -/* Flags: I | E | K +/* Flags: Z Let bit_length be the length of the shift operation: 32 or 64. If src2 is immediate, src2w is masked by (bit_length - 1). Otherwise, if the content of src2 is outside the range from 0 to bit_length - 1, the result is undefined. */ #define SLJIT_SHL (SLJIT_OP2_BASE + 8) #define SLJIT_SHL32 (SLJIT_SHL | SLJIT_I32_OP) -/* Flags: I | E | K +/* Flags: Z Let bit_length be the length of the shift operation: 32 or 64. If src2 is immediate, src2w is masked by (bit_length - 1). Otherwise, if the content of src2 is outside the range from 0 to bit_length - 1, the result is undefined. */ #define SLJIT_LSHR (SLJIT_OP2_BASE + 9) #define SLJIT_LSHR32 (SLJIT_LSHR | SLJIT_I32_OP) -/* Flags: I | E | K +/* Flags: Z Let bit_length be the length of the shift operation: 32 or 64. If src2 is immediate, src2w is masked by (bit_length - 1). Otherwise, if the content of src2 is outside the range from 0 @@ -888,44 +1008,38 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile sljit_s32 src1, sljit_sw src1w, sljit_s32 src2, sljit_sw src2w); -/* Returns with non-zero if fpu is available. */ - -SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_is_fpu_available(void); - /* Starting index of opcodes for sljit_emit_fop1. */ #define SLJIT_FOP1_BASE 128 -/* Flags: SP - (never set any flags) */ +/* Flags: - (does not modify flags) */ #define SLJIT_MOV_F64 (SLJIT_FOP1_BASE + 0) #define SLJIT_MOV_F32 (SLJIT_MOV_F64 | SLJIT_F32_OP) /* Convert opcodes: CONV[DST_TYPE].FROM[SRC_TYPE] SRC/DST TYPE can be: D - double, S - single, W - signed word, I - signed int Rounding mode when the destination is W or I: round towards zero. */ -/* Flags: SP - (never set any flags) */ +/* Flags: - (does not modify flags) */ #define SLJIT_CONV_F64_FROM_F32 (SLJIT_FOP1_BASE + 1) #define SLJIT_CONV_F32_FROM_F64 (SLJIT_CONV_F64_FROM_F32 | SLJIT_F32_OP) -/* Flags: SP - (never set any flags) */ +/* Flags: - (does not modify flags) */ #define SLJIT_CONV_SW_FROM_F64 (SLJIT_FOP1_BASE + 2) #define SLJIT_CONV_SW_FROM_F32 (SLJIT_CONV_SW_FROM_F64 | SLJIT_F32_OP) -/* Flags: SP - (never set any flags) */ +/* Flags: - (does not modify flags) */ #define SLJIT_CONV_S32_FROM_F64 (SLJIT_FOP1_BASE + 3) #define SLJIT_CONV_S32_FROM_F32 (SLJIT_CONV_S32_FROM_F64 | SLJIT_F32_OP) -/* Flags: SP - (never set any flags) */ +/* Flags: - (does not modify flags) */ #define SLJIT_CONV_F64_FROM_SW (SLJIT_FOP1_BASE + 4) #define SLJIT_CONV_F32_FROM_SW (SLJIT_CONV_F64_FROM_SW | SLJIT_F32_OP) -/* Flags: SP - (never set any flags) */ +/* Flags: - (does not modify flags) */ #define SLJIT_CONV_F64_FROM_S32 (SLJIT_FOP1_BASE + 5) #define SLJIT_CONV_F32_FROM_S32 (SLJIT_CONV_F64_FROM_S32 | SLJIT_F32_OP) /* Note: dst is the left and src is the right operand for SLJIT_CMPD. - Note: NaN check is always performed. If SLJIT_C_FLOAT_UNORDERED flag - is set, the comparison result is unpredictable. - Flags: SP | E | S (see SLJIT_C_FLOAT_*) */ + Flags: EQUAL_F | LESS_F | GREATER_EQUAL_F | GREATER_F | LESS_EQUAL_F */ #define SLJIT_CMP_F64 (SLJIT_FOP1_BASE + 6) #define SLJIT_CMP_F32 (SLJIT_CMP_F64 | SLJIT_F32_OP) -/* Flags: SP - (never set any flags) */ +/* Flags: - (does not modify flags) */ #define SLJIT_NEG_F64 (SLJIT_FOP1_BASE + 7) #define SLJIT_NEG_F32 (SLJIT_NEG_F64 | SLJIT_F32_OP) -/* Flags: SP - (never set any flags) */ +/* Flags: - (does not modify flags) */ #define SLJIT_ABS_F64 (SLJIT_FOP1_BASE + 8) #define SLJIT_ABS_F32 (SLJIT_ABS_F64 | SLJIT_F32_OP) @@ -936,16 +1050,16 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop1(struct sljit_compiler *compil /* Starting index of opcodes for sljit_emit_fop2. */ #define SLJIT_FOP2_BASE 160 -/* Flags: SP - (never set any flags) */ +/* Flags: - (does not modify flags) */ #define SLJIT_ADD_F64 (SLJIT_FOP2_BASE + 0) #define SLJIT_ADD_F32 (SLJIT_ADD_F64 | SLJIT_F32_OP) -/* Flags: SP - (never set any flags) */ +/* Flags: - (does not modify flags) */ #define SLJIT_SUB_F64 (SLJIT_FOP2_BASE + 1) #define SLJIT_SUB_F32 (SLJIT_SUB_F64 | SLJIT_F32_OP) -/* Flags: SP - (never set any flags) */ +/* Flags: - (does not modify flags) */ #define SLJIT_MUL_F64 (SLJIT_FOP2_BASE + 2) #define SLJIT_MUL_F32 (SLJIT_MUL_F64 | SLJIT_F32_OP) -/* Flags: SP - (never set any flags) */ +/* Flags: - (does not modify flags) */ #define SLJIT_DIV_F64 (SLJIT_FOP2_BASE + 3) #define SLJIT_DIV_F32 (SLJIT_DIV_F64 | SLJIT_F32_OP) @@ -972,69 +1086,98 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compi #define SLJIT_LESS 2 #define SLJIT_LESS32 (SLJIT_LESS | SLJIT_I32_OP) +#define SLJIT_SET_LESS SLJIT_SET(SLJIT_LESS) #define SLJIT_GREATER_EQUAL 3 #define SLJIT_GREATER_EQUAL32 (SLJIT_GREATER_EQUAL | SLJIT_I32_OP) +#define SLJIT_SET_GREATER_EQUAL SLJIT_SET(SLJIT_GREATER_EQUAL) #define SLJIT_GREATER 4 #define SLJIT_GREATER32 (SLJIT_GREATER | SLJIT_I32_OP) +#define SLJIT_SET_GREATER SLJIT_SET(SLJIT_GREATER) #define SLJIT_LESS_EQUAL 5 #define SLJIT_LESS_EQUAL32 (SLJIT_LESS_EQUAL | SLJIT_I32_OP) +#define SLJIT_SET_LESS_EQUAL SLJIT_SET(SLJIT_LESS_EQUAL) #define SLJIT_SIG_LESS 6 #define SLJIT_SIG_LESS32 (SLJIT_SIG_LESS | SLJIT_I32_OP) +#define SLJIT_SET_SIG_LESS SLJIT_SET(SLJIT_SIG_LESS) #define SLJIT_SIG_GREATER_EQUAL 7 #define SLJIT_SIG_GREATER_EQUAL32 (SLJIT_SIG_GREATER_EQUAL | SLJIT_I32_OP) +#define SLJIT_SET_SIG_GREATER_EQUAL SLJIT_SET(SLJIT_SIG_GREATER_EQUAL) #define SLJIT_SIG_GREATER 8 #define SLJIT_SIG_GREATER32 (SLJIT_SIG_GREATER | SLJIT_I32_OP) +#define SLJIT_SET_SIG_GREATER SLJIT_SET(SLJIT_SIG_GREATER) #define SLJIT_SIG_LESS_EQUAL 9 #define SLJIT_SIG_LESS_EQUAL32 (SLJIT_SIG_LESS_EQUAL | SLJIT_I32_OP) +#define SLJIT_SET_SIG_LESS_EQUAL SLJIT_SET(SLJIT_SIG_LESS_EQUAL) #define SLJIT_OVERFLOW 10 #define SLJIT_OVERFLOW32 (SLJIT_OVERFLOW | SLJIT_I32_OP) +#define SLJIT_SET_OVERFLOW SLJIT_SET(SLJIT_OVERFLOW) #define SLJIT_NOT_OVERFLOW 11 #define SLJIT_NOT_OVERFLOW32 (SLJIT_NOT_OVERFLOW | SLJIT_I32_OP) #define SLJIT_MUL_OVERFLOW 12 #define SLJIT_MUL_OVERFLOW32 (SLJIT_MUL_OVERFLOW | SLJIT_I32_OP) +#define SLJIT_SET_MUL_OVERFLOW SLJIT_SET(SLJIT_MUL_OVERFLOW) #define SLJIT_MUL_NOT_OVERFLOW 13 #define SLJIT_MUL_NOT_OVERFLOW32 (SLJIT_MUL_NOT_OVERFLOW | SLJIT_I32_OP) +/* There is no SLJIT_CARRY or SLJIT_NOT_CARRY. */ +#define SLJIT_SET_CARRY SLJIT_SET(14) + /* Floating point comparison types. */ -#define SLJIT_EQUAL_F64 14 +#define SLJIT_EQUAL_F64 16 #define SLJIT_EQUAL_F32 (SLJIT_EQUAL_F64 | SLJIT_F32_OP) -#define SLJIT_NOT_EQUAL_F64 15 +#define SLJIT_SET_EQUAL_F SLJIT_SET(SLJIT_EQUAL_F64) +#define SLJIT_NOT_EQUAL_F64 17 #define SLJIT_NOT_EQUAL_F32 (SLJIT_NOT_EQUAL_F64 | SLJIT_F32_OP) -#define SLJIT_LESS_F64 16 +#define SLJIT_SET_NOT_EQUAL_F SLJIT_SET(SLJIT_NOT_EQUAL_F64) +#define SLJIT_LESS_F64 18 #define SLJIT_LESS_F32 (SLJIT_LESS_F64 | SLJIT_F32_OP) -#define SLJIT_GREATER_EQUAL_F64 17 +#define SLJIT_SET_LESS_F SLJIT_SET(SLJIT_LESS_F64) +#define SLJIT_GREATER_EQUAL_F64 19 #define SLJIT_GREATER_EQUAL_F32 (SLJIT_GREATER_EQUAL_F64 | SLJIT_F32_OP) -#define SLJIT_GREATER_F64 18 +#define SLJIT_SET_GREATER_EQUAL_F SLJIT_SET(SLJIT_GREATER_EQUAL_F64) +#define SLJIT_GREATER_F64 20 #define SLJIT_GREATER_F32 (SLJIT_GREATER_F64 | SLJIT_F32_OP) -#define SLJIT_LESS_EQUAL_F64 19 +#define SLJIT_SET_GREATER_F SLJIT_SET(SLJIT_GREATER_F64) +#define SLJIT_LESS_EQUAL_F64 21 #define SLJIT_LESS_EQUAL_F32 (SLJIT_LESS_EQUAL_F64 | SLJIT_F32_OP) -#define SLJIT_UNORDERED_F64 20 +#define SLJIT_SET_LESS_EQUAL_F SLJIT_SET(SLJIT_LESS_EQUAL_F64) +#define SLJIT_UNORDERED_F64 22 #define SLJIT_UNORDERED_F32 (SLJIT_UNORDERED_F64 | SLJIT_F32_OP) -#define SLJIT_ORDERED_F64 21 +#define SLJIT_SET_UNORDERED_F SLJIT_SET(SLJIT_UNORDERED_F64) +#define SLJIT_ORDERED_F64 23 #define SLJIT_ORDERED_F32 (SLJIT_ORDERED_F64 | SLJIT_F32_OP) +#define SLJIT_SET_ORDERED_F SLJIT_SET(SLJIT_ORDERED_F64) /* Unconditional jump types. */ -#define SLJIT_JUMP 22 -#define SLJIT_FAST_CALL 23 -#define SLJIT_CALL0 24 -#define SLJIT_CALL1 25 -#define SLJIT_CALL2 26 -#define SLJIT_CALL3 27 - -/* Fast calling method. See sljit_emit_fast_enter / sljit_emit_fast_return. */ +#define SLJIT_JUMP 24 + /* Fast calling method. See sljit_emit_fast_enter / sljit_emit_fast_return. */ +#define SLJIT_FAST_CALL 25 + /* Called function must be declared with the SLJIT_FUNC attribute. */ +#define SLJIT_CALL 26 + /* Called function must be decalred with cdecl attribute. + This is the default attribute for C functions. */ +#define SLJIT_CALL_CDECL 27 /* The target can be changed during runtime (see: sljit_set_jump_addr). */ #define SLJIT_REWRITABLE_JUMP 0x1000 /* Emit a jump instruction. The destination is not set, only the type of the jump. - type must be between SLJIT_EQUAL and SLJIT_CALL3 + type must be between SLJIT_EQUAL and SLJIT_FAST_CALL type can be combined (or'ed) with SLJIT_REWRITABLE_JUMP - Flags: - (never set any flags) for both conditional and unconditional jumps. - Flags: destroy all flags for calls. */ + + Flags: does not modify flags. */ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, sljit_s32 type); +/* Emit a C compiler (ABI) compatible function call. + type must be SLJIT_CALL or SLJIT_CALL_CDECL + type can be combined (or'ed) with SLJIT_REWRITABLE_JUMP + arg_types is the combination of SLJIT_RET / SLJIT_ARGx (SLJIT_DEF_RET / SLJIT_DEF_ARGx) macros + + Flags: destroy all flags. */ +SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 arg_types); + /* Basic arithmetic comparison. In most architectures it is implemented as an SLJIT_SUB operation (with SLJIT_UNUSED destination and setting appropriate flags) followed by a sljit_emit_jump. However some @@ -1042,7 +1185,8 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compile It is suggested to use this comparison form when appropriate. type must be between SLJIT_EQUAL and SLJIT_I_SIG_LESS_EQUAL type can be combined (or'ed) with SLJIT_REWRITABLE_JUMP - Flags: destroy flags. */ + + Flags: may destroy flags. */ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_cmp(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 src1, sljit_sw src1w, sljit_s32 src2, sljit_sw src2w); @@ -1066,40 +1210,112 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_label(struct sljit_jump *jump, struct sl /* Set the destination address of the jump to this label. */ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_target(struct sljit_jump *jump, sljit_uw target); -/* Call function or jump anywhere. Both direct and indirect form - type must be between SLJIT_JUMP and SLJIT_CALL3 - Direct form: set src to SLJIT_IMM() and srcw to the address - Indirect form: any other valid addressing mode - Flags: - (never set any flags) for unconditional jumps. - Flags: destroy all flags for calls. */ +/* Emit an indirect jump or fast call. Both direct and indirect form + Direct form: set src to SLJIT_IMM() and srcw to the address + Indirect form: any other valid addressing mode + type must be between SLJIT_JUMP and SLJIT_FAST_CALL + + Flags: does not modify flags. */ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 src, sljit_sw srcw); +/* Emit a C compiler (ABI) compatible function call. + Direct form: set src to SLJIT_IMM() and srcw to the address + Indirect form: any other valid addressing mode + type must be SLJIT_CALL or SLJIT_CALL_CDECL + arg_types is the combination of SLJIT_RET / SLJIT_ARGx (SLJIT_DEF_RET / SLJIT_DEF_ARGx) macros + + Flags: destroy all flags. */ +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 arg_types, sljit_s32 src, sljit_sw srcw); + /* Perform the operation using the conditional flags as the second argument. - Type must always be between SLJIT_EQUAL and SLJIT_S_ORDERED. The value + Type must always be between SLJIT_EQUAL and SLJIT_ORDERED_F64. The value represented by the type is 1, if the condition represented by the type is fulfilled, and 0 otherwise. - If op == SLJIT_MOV, SLJIT_MOV_S32, SLJIT_MOV_U32: + If op == SLJIT_MOV, SLJIT_MOV32: Set dst to the value represented by the type (0 or 1). - Src must be SLJIT_UNUSED, and srcw must be 0 - Flags: - (never set any flags) + Flags: - (does not modify flags) If op == SLJIT_OR, op == SLJIT_AND, op == SLJIT_XOR - Performs the binary operation using src as the first, and the value - represented by type as the second argument. - Important note: only dst=src and dstw=srcw is supported at the moment! - Flags: I | E | K - Note: sljit_emit_op_flags does nothing, if dst is SLJIT_UNUSED (regardless of op). */ + Performs the binary operation using dst as the first, and the value + represented by type as the second argument. Result is written into dst. + Flags: Z (may destroy flags) */ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw dstw, - sljit_s32 src, sljit_sw srcw, sljit_s32 type); -/* Copies the base address of SLJIT_SP + offset to dst. - Flags: - (never set any flags) */ +/* Emit a conditional mov instruction which moves source to destination, + if the condition is satisfied. Unlike other arithmetic operations this + instruction does not support memory access. + + type must be between SLJIT_EQUAL and SLJIT_ORDERED_F64 + dst_reg must be a valid register and it can be combined + with SLJIT_I32_OP to perform a 32 bit arithmetic operation + src must be register or immediate (SLJIT_IMM) + + Flags: - (does not modify flags) */ +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 dst_reg, + sljit_s32 src, sljit_sw srcw); + +/* The following flags are used by sljit_emit_mem() and sljit_emit_fmem(). */ + +/* When SLJIT_MEM_SUPP is passed, no instructions are emitted. + Instead the function returns with SLJIT_SUCCESS if the instruction + form is supported and SLJIT_ERR_UNSUPPORTED otherwise. This flag + allows runtime checking of available instruction forms. */ +#define SLJIT_MEM_SUPP 0x0200 +/* Memory load operation. This is the default. */ +#define SLJIT_MEM_LOAD 0x0000 +/* Memory store operation. */ +#define SLJIT_MEM_STORE 0x0400 +/* Base register is updated before the memory access. */ +#define SLJIT_MEM_PRE 0x0800 +/* Base register is updated after the memory access. */ +#define SLJIT_MEM_POST 0x1000 + +/* Emit a single memory load or store with update instruction. When the + requested instruction from is not supported by the CPU, it returns + with SLJIT_ERR_UNSUPPORTED instead of emulating the instruction. This + allows specializing tight loops based on the supported instruction + forms (see SLJIT_MEM_SUPP flag). + + type must be between SLJIT_MOV and SLJIT_MOV_P and can be + combined with SLJIT_MEM_* flags. Either SLJIT_MEM_PRE + or SLJIT_MEM_POST must be specified. + reg is the source or destination register, and must be + different from the base register of the mem operand + mem must be a SLJIT_MEM1() or SLJIT_MEM2() operand + + Flags: - (does not modify flags) */ +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 reg, + sljit_s32 mem, sljit_sw memw); + +/* Same as sljit_emit_mem except the followings: + + type must be SLJIT_MOV_F64 or SLJIT_MOV_F32 and can be + combined with SLJIT_MEM_* flags. Either SLJIT_MEM_PRE + or SLJIT_MEM_POST must be specified. + freg is the source or destination floating point register */ + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 freg, + sljit_s32 mem, sljit_sw memw); + +/* Copies the base address of SLJIT_SP + offset to dst. The offset can be + anything to negate the effect of relative addressing. For example if an + array of sljit_sw values is stored on the stack from offset 0x40, and R0 + contains the offset of an array item plus 0x120, this item can be + overwritten by two SLJIT instructions: + + sljit_get_local_base(compiler, SLJIT_R1, 0, 0x40 - 0x120); + sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM2(SLJIT_R1, SLJIT_R0), 0, SLJIT_IMM, 0x5); + + Flags: - (may destroy flags) */ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_local_base(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw offset); /* The constant can be changed runtime (see: sljit_set_const) - Flags: - (never set any flags) */ + Flags: - (does not modify flags) */ SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw init_value); /* After the code generation the address for label, jump and const instructions @@ -1119,7 +1335,7 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_consta /* --------------------------------------------------------------------- */ #define SLJIT_MAJOR_VERSION 0 -#define SLJIT_MINOR_VERSION 93 +#define SLJIT_MINOR_VERSION 94 /* Get the human readable name of the platform. Can be useful on platforms like ARM, where ARM and Thumb2 functions can be mixed, and @@ -1131,53 +1347,58 @@ SLJIT_API_FUNC_ATTRIBUTE const char* sljit_get_platform_name(void); #if (defined SLJIT_UTIL_GLOBAL_LOCK && SLJIT_UTIL_GLOBAL_LOCK) /* This global lock is useful to compile common functions. */ -SLJIT_API_FUNC_ATTRIBUTE void SLJIT_CALL sljit_grab_lock(void); -SLJIT_API_FUNC_ATTRIBUTE void SLJIT_CALL sljit_release_lock(void); +SLJIT_API_FUNC_ATTRIBUTE void SLJIT_FUNC sljit_grab_lock(void); +SLJIT_API_FUNC_ATTRIBUTE void SLJIT_FUNC sljit_release_lock(void); #endif #if (defined SLJIT_UTIL_STACK && SLJIT_UTIL_STACK) -/* The sljit_stack is a utiliy feature of sljit, which allocates a - writable memory region between base (inclusive) and limit (exclusive). - Both base and limit is a pointer, and base is always <= than limit. - This feature uses the "address space reserve" feature - of modern operating systems. Basically we don't need to allocate a - huge memory block in one step for the worst case, we can start with - a smaller chunk and extend it later. Since the address space is - reserved, the data never copied to other regions, thus it is safe - to store pointers here. */ - -/* Note: The base field is aligned to PAGE_SIZE bytes (usually 4k or more). - Note: stack growing should not happen in small steps: 4k, 16k or even - bigger growth is better. - Note: this structure may not be supported by all operating systems. - Some kind of fallback mechanism is suggested when SLJIT_UTIL_STACK - is not defined. */ +/* The sljit_stack structure and its manipulation functions provides + an implementation for a top-down stack. The stack top is stored + in the end field of the sljit_stack structure and the stack goes + down to the min_start field, so the memory region reserved for + this stack is between min_start (inclusive) and end (exclusive) + fields. However the application can only use the region between + start (inclusive) and end (exclusive) fields. The sljit_stack_resize + function can be used to extend this region up to min_start. + + This feature uses the "address space reserve" feature of modern + operating systems. Instead of allocating a large memory block + applications can allocate a small memory region and extend it + later without moving the content of the memory area. Therefore + after a successful resize by sljit_stack_resize all pointers into + this region are still valid. + + Note: + this structure may not be supported by all operating systems. + end and max_limit fields are aligned to PAGE_SIZE bytes (usually + 4 Kbyte or more). + stack should grow in larger steps, e.g. 4Kbyte, 16Kbyte or more. */ struct sljit_stack { /* User data, anything can be stored here. - Starting with the same value as base. */ - sljit_uw top; - /* These members are read only. */ - sljit_uw base; - sljit_uw limit; - sljit_uw max_limit; + Initialized to the same value as the end field. */ + sljit_u8 *top; +/* These members are read only. */ + /* End address of the stack */ + sljit_u8 *end; + /* Current start address of the stack. */ + sljit_u8 *start; + /* Lowest start address of the stack. */ + sljit_u8 *min_start; }; -/* Returns NULL if unsuccessful. - Note: limit and max_limit contains the size for stack allocation. - Note: the top field is initialized to base. +/* Allocates a new stack. Returns NULL if unsuccessful. Note: see sljit_create_compiler for the explanation of allocator_data. */ -SLJIT_API_FUNC_ATTRIBUTE struct sljit_stack* SLJIT_CALL sljit_allocate_stack(sljit_uw limit, sljit_uw max_limit, void *allocator_data); -SLJIT_API_FUNC_ATTRIBUTE void SLJIT_CALL sljit_free_stack(struct sljit_stack *stack, void *allocator_data); +SLJIT_API_FUNC_ATTRIBUTE struct sljit_stack* SLJIT_FUNC sljit_allocate_stack(sljit_uw start_size, sljit_uw max_size, void *allocator_data); +SLJIT_API_FUNC_ATTRIBUTE void SLJIT_FUNC sljit_free_stack(struct sljit_stack *stack, void *allocator_data); -/* Can be used to increase (allocate) or decrease (free) the memory area. - Returns with a non-zero value if unsuccessful. If new_limit is greater than - max_limit, it will fail. It is very easy to implement a stack data structure, - since the growth ratio can be added to the current limit, and sljit_stack_resize - will do all the necessary checks. The fields of the stack are not changed if - sljit_stack_resize fails. */ -SLJIT_API_FUNC_ATTRIBUTE sljit_sw SLJIT_CALL sljit_stack_resize(struct sljit_stack *stack, sljit_uw new_limit); +/* Can be used to increase (extend) or decrease (shrink) the stack + memory area. Returns with new_start if successful and NULL otherwise. + It always fails if new_start is less than min_start or greater or equal + than end fields. The fields of the stack are not changed if the returned + value is NULL (the current memory content is never lost). */ +SLJIT_API_FUNC_ATTRIBUTE sljit_u8 *SLJIT_FUNC sljit_stack_resize(struct sljit_stack *stack, sljit_u8 *new_start); #endif /* (defined SLJIT_UTIL_STACK && SLJIT_UTIL_STACK) */ @@ -1206,6 +1427,15 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_function_context(void** func_ptr, struct #endif /* !(defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL) */ +#if (defined SLJIT_EXECUTABLE_ALLOCATOR && SLJIT_EXECUTABLE_ALLOCATOR) +/* Free unused executable memory. The allocator keeps some free memory + around to reduce the number of OS executable memory allocations. + This improves performance since these calls are costly. However + it is sometimes desired to free all unused memory regions, e.g. + before the application terminates. */ +SLJIT_API_FUNC_ATTRIBUTE void sljit_free_unused_memory_exec(void); +#endif + /* --------------------------------------------------------------------- */ /* CPU specific functions */ /* --------------------------------------------------------------------- */ @@ -1238,32 +1468,10 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_float_register_index(sljit_s32 reg) SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *compiler, void *instruction, sljit_s32 size); -#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86) - -/* Returns with non-zero if sse2 is available. */ - -SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_x86_is_sse2_available(void); - -/* Returns with non-zero if cmov instruction is available. */ - -SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_x86_is_cmov_available(void); - -/* Emit a conditional mov instruction on x86 CPUs. This instruction - moves src to destination, if the condition is satisfied. Unlike - other arithmetic instructions, destination must be a register. - Before such instructions are emitted, cmov support should be - checked by sljit_x86_is_cmov_available function. - type must be between SLJIT_EQUAL and SLJIT_S_ORDERED - dst_reg must be a valid register and it can be combined - with SLJIT_I32_OP to perform 32 bit arithmetic - Flags: I - (never set any flags) - */ +/* Define the currently available CPU status flags. It is usually used after an + sljit_emit_op_custom call to define which flags are set. */ -SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_x86_emit_cmov(struct sljit_compiler *compiler, - sljit_s32 type, - sljit_s32 dst_reg, - sljit_s32 src, sljit_sw srcw); - -#endif +SLJIT_API_FUNC_ATTRIBUTE void sljit_set_current_flags(struct sljit_compiler *compiler, + sljit_s32 current_flags); #endif /* _SLJIT_LIR_H_ */ diff --git a/thirdparty/pcre2/src/sljit/sljitNativeARM_32.c b/thirdparty/pcre2/src/sljit/sljitNativeARM_32.c index 09701d53fc..6d61eed9a7 100644 --- a/thirdparty/pcre2/src/sljit/sljitNativeARM_32.c +++ b/thirdparty/pcre2/src/sljit/sljitNativeARM_32.c @@ -1,7 +1,7 @@ /* * Stack-less Just-In-Time compiler * - * Copyright 2009-2012 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved. + * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are * permitted provided that the following conditions are met: @@ -24,12 +24,18 @@ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#ifdef __SOFTFP__ +#define ARM_ABI_INFO " ABI:softfp" +#else +#define ARM_ABI_INFO " ABI:hardfp" +#endif + SLJIT_API_FUNC_ATTRIBUTE const char* sljit_get_platform_name(void) { #if (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7) - return "ARMv7" SLJIT_CPUINFO; + return "ARMv7" SLJIT_CPUINFO ARM_ABI_INFO; #elif (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) - return "ARMv5" SLJIT_CPUINFO; + return "ARMv5" SLJIT_CPUINFO ARM_ABI_INFO; #else #error "Internal error: Unknown ARM architecture" #endif @@ -38,11 +44,10 @@ SLJIT_API_FUNC_ATTRIBUTE const char* sljit_get_platform_name(void) /* Last register + 1. */ #define TMP_REG1 (SLJIT_NUMBER_OF_REGISTERS + 2) #define TMP_REG2 (SLJIT_NUMBER_OF_REGISTERS + 3) -#define TMP_REG3 (SLJIT_NUMBER_OF_REGISTERS + 4) -#define TMP_PC (SLJIT_NUMBER_OF_REGISTERS + 5) +#define TMP_PC (SLJIT_NUMBER_OF_REGISTERS + 4) -#define TMP_FREG1 (0) -#define TMP_FREG2 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1) +#define TMP_FREG1 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1) +#define TMP_FREG2 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 2) /* In ARM instruction words. Cache lines are usually 32 byte aligned. */ @@ -55,8 +60,12 @@ SLJIT_API_FUNC_ATTRIBUTE const char* sljit_get_platform_name(void) (((max_diff) / (sljit_s32)sizeof(sljit_uw)) - (CONST_POOL_ALIGNMENT - 1)) /* See sljit_emit_enter and sljit_emit_op0 if you want to change them. */ -static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 6] = { - 0, 0, 1, 2, 11, 10, 9, 8, 7, 6, 5, 4, 13, 3, 12, 14, 15 +static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 5] = { + 0, 0, 1, 2, 3, 11, 10, 9, 8, 7, 6, 5, 4, 13, 12, 14, 15 +}; + +static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3] = { + 0, 0, 1, 2, 3, 4, 5, 6, 7 }; #define RM(rm) (reg_map[rm]) @@ -73,31 +82,31 @@ static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 6] = { #define CONDITIONAL 0xe0000000 #define PUSH_POOL 0xff000000 -/* DP - Data Processing instruction (use with EMIT_DATA_PROCESS_INS). */ -#define ADC_DP 0x5 -#define ADD_DP 0x4 -#define AND_DP 0x0 +#define ADC 0xe0a00000 +#define ADD 0xe0800000 +#define AND 0xe0000000 #define B 0xea000000 -#define BIC_DP 0xe +#define BIC 0xe1c00000 #define BL 0xeb000000 #define BLX 0xe12fff30 #define BX 0xe12fff10 #define CLZ 0xe16f0f10 -#define CMP_DP 0xa +#define CMN 0xe1600000 +#define CMP 0xe1400000 #define BKPT 0xe1200070 -#define EOR_DP 0x1 -#define MOV_DP 0xd +#define EOR 0xe0200000 +#define MOV 0xe1a00000 #define MUL 0xe0000090 -#define MVN_DP 0xf +#define MVN 0xe1e00000 #define NOP 0xe1a00000 -#define ORR_DP 0xc +#define ORR 0xe1800000 #define PUSH 0xe92d0000 #define POP 0xe8bd0000 -#define RSB_DP 0x3 -#define RSC_DP 0x7 -#define SBC_DP 0x6 +#define RSB 0xe0600000 +#define RSC 0xe0e00000 +#define SBC 0xe0c00000 #define SMULL 0xe0c00090 -#define SUB_DP 0x2 +#define SUB 0xe0400000 #define UMULL 0xe0800090 #define VABS_F32 0xeeb00ac0 #define VADD_F32 0xee300a00 @@ -108,6 +117,7 @@ static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 6] = { #define VDIV_F32 0xee800a00 #define VMOV_F32 0xeeb00a40 #define VMOV 0xee000a10 +#define VMOV2 0xec400a10 #define VMRS 0xeef1fa10 #define VMUL_F32 0xee200a00 #define VNEG_F32 0xeeb10a40 @@ -260,6 +270,8 @@ static SLJIT_INLINE sljit_s32 emit_blx(struct sljit_compiler *compiler) { /* Must follow tightly the previous instruction (to be able to convert it to bl instruction). */ SLJIT_ASSERT(compiler->cpool_diff == CONST_POOL_EMPTY || compiler->size - compiler->cpool_diff < MAX_DIFFERENCE(4092)); + SLJIT_ASSERT(reg_map[TMP_REG1] != 14); + return push_inst(compiler, BLX | RM(TMP_REG1)); } @@ -814,28 +826,77 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil return code; } +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type) +{ + switch (feature_type) { + case SLJIT_HAS_FPU: +#ifdef SLJIT_IS_FPU_AVAILABLE + return SLJIT_IS_FPU_AVAILABLE; +#else + /* Available by default. */ + return 1; +#endif + + case SLJIT_HAS_CLZ: + case SLJIT_HAS_CMOV: + return 1; + + default: + return 0; + } +} + /* --------------------------------------------------------------------- */ /* Entry, exit */ /* --------------------------------------------------------------------- */ -/* emit_op inp_flags. - WRITE_BACK must be the first, since it is a flag. */ -#define WRITE_BACK 0x01 -#define ALLOW_IMM 0x02 -#define ALLOW_INV_IMM 0x04 +/* Creates an index in data_transfer_insts array. */ +#define WORD_SIZE 0x00 +#define BYTE_SIZE 0x01 +#define HALF_SIZE 0x02 +#define PRELOAD 0x03 +#define SIGNED 0x04 +#define LOAD_DATA 0x08 + +/* Flag bits for emit_op. */ +#define ALLOW_IMM 0x10 +#define ALLOW_INV_IMM 0x20 #define ALLOW_ANY_IMM (ALLOW_IMM | ALLOW_INV_IMM) -#define ARG_TEST 0x08 -/* Creates an index in data_transfer_insts array. */ -#define WORD_DATA 0x00 -#define BYTE_DATA 0x10 -#define HALF_DATA 0x20 -#define SIGNED_DATA 0x40 -#define LOAD_DATA 0x80 +/* s/l - store/load (1 bit) + u/s - signed/unsigned (1 bit) + w/b/h/N - word/byte/half/NOT allowed (2 bit) + Storing signed and unsigned values are the same operations. */ + +static const sljit_uw data_transfer_insts[16] = { +/* s u w */ 0xe5000000 /* str */, +/* s u b */ 0xe5400000 /* strb */, +/* s u h */ 0xe10000b0 /* strh */, +/* s u N */ 0x00000000 /* not allowed */, +/* s s w */ 0xe5000000 /* str */, +/* s s b */ 0xe5400000 /* strb */, +/* s s h */ 0xe10000b0 /* strh */, +/* s s N */ 0x00000000 /* not allowed */, + +/* l u w */ 0xe5100000 /* ldr */, +/* l u b */ 0xe5500000 /* ldrb */, +/* l u h */ 0xe11000b0 /* ldrh */, +/* l u p */ 0xf5500000 /* preload */, +/* l s w */ 0xe5100000 /* ldr */, +/* l s b */ 0xe11000d0 /* ldrsb */, +/* l s h */ 0xe11000f0 /* ldrsh */, +/* l s N */ 0x00000000 /* not allowed */, +}; -/* Condition: AL. */ -#define EMIT_DATA_PROCESS_INS(opcode, set_flags, dst, src1, src2) \ - (0xe0000000 | ((opcode) << 21) | (set_flags) | RD(dst) | RN(src1) | (src2)) +#define EMIT_DATA_TRANSFER(type, add, target_reg, base_reg, arg) \ + (data_transfer_insts[(type) & 0xf] | ((add) << 23) | RD(target_reg) | RN(base_reg) | (arg)) + +/* Normal ldr/str instruction. + Type2: ldrsb, ldrh, ldrsh */ +#define IS_TYPE1_TRANSFER(type) \ + (data_transfer_insts[(type) & 0xf] & 0x04000000) +#define TYPE2_TRANSFER_IMM(imm) \ + (((imm) & 0xf) | (((imm) & 0xf0) << 4) | (1 << 22)) static sljit_s32 emit_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 inp_flags, sljit_s32 dst, sljit_sw dstw, @@ -843,15 +904,15 @@ static sljit_s32 emit_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s3 sljit_s32 src2, sljit_sw src2w); SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compiler, - sljit_s32 options, sljit_s32 args, sljit_s32 scratches, sljit_s32 saveds, + sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds, sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size) { - sljit_s32 size, i, tmp; + sljit_s32 args, size, i, tmp; sljit_uw push; CHECK_ERROR(); - CHECK(check_sljit_emit_enter(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size)); - set_emit_enter(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size); + CHECK(check_sljit_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size)); + set_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size); /* Push saved registers, temporary registers stmdb sp!, {..., lr} */ @@ -873,25 +934,27 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi if (local_size > 0) FAIL_IF(emit_op(compiler, SLJIT_SUB, ALLOW_IMM, SLJIT_SP, 0, SLJIT_SP, 0, SLJIT_IMM, local_size)); + args = get_arg_count(arg_types); + if (args >= 1) - FAIL_IF(push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, 0, SLJIT_S0, SLJIT_UNUSED, RM(SLJIT_R0)))); + FAIL_IF(push_inst(compiler, MOV | RD(SLJIT_S0) | RM(SLJIT_R0))); if (args >= 2) - FAIL_IF(push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, 0, SLJIT_S1, SLJIT_UNUSED, RM(SLJIT_R1)))); + FAIL_IF(push_inst(compiler, MOV | RD(SLJIT_S1) | RM(SLJIT_R1))); if (args >= 3) - FAIL_IF(push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, 0, SLJIT_S2, SLJIT_UNUSED, RM(SLJIT_R2)))); + FAIL_IF(push_inst(compiler, MOV | RD(SLJIT_S2) | RM(SLJIT_R2))); return SLJIT_SUCCESS; } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *compiler, - sljit_s32 options, sljit_s32 args, sljit_s32 scratches, sljit_s32 saveds, + sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds, sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size) { sljit_s32 size; CHECK_ERROR(); - CHECK(check_sljit_set_context(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size)); - set_set_context(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size); + CHECK(check_sljit_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size)); + set_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size); size = GET_SAVED_REGISTERS_SIZE(scratches, saveds, 1); compiler->local_size = ((size + local_size + 7) & ~7) - size; @@ -929,52 +992,15 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return(struct sljit_compiler *comp /* Operators */ /* --------------------------------------------------------------------- */ -/* s/l - store/load (1 bit) - u/s - signed/unsigned (1 bit) - w/b/h/N - word/byte/half/NOT allowed (2 bit) - It contans 16 items, but not all are different. */ - -static sljit_sw data_transfer_insts[16] = { -/* s u w */ 0xe5000000 /* str */, -/* s u b */ 0xe5400000 /* strb */, -/* s u h */ 0xe10000b0 /* strh */, -/* s u N */ 0x00000000 /* not allowed */, -/* s s w */ 0xe5000000 /* str */, -/* s s b */ 0xe5400000 /* strb */, -/* s s h */ 0xe10000b0 /* strh */, -/* s s N */ 0x00000000 /* not allowed */, - -/* l u w */ 0xe5100000 /* ldr */, -/* l u b */ 0xe5500000 /* ldrb */, -/* l u h */ 0xe11000b0 /* ldrh */, -/* l u N */ 0x00000000 /* not allowed */, -/* l s w */ 0xe5100000 /* ldr */, -/* l s b */ 0xe11000d0 /* ldrsb */, -/* l s h */ 0xe11000f0 /* ldrsh */, -/* l s N */ 0x00000000 /* not allowed */, -}; - -#define EMIT_DATA_TRANSFER(type, add, wb, target, base1, base2) \ - (data_transfer_insts[(type) >> 4] | ((add) << 23) | ((wb) << 21) | (reg_map[target] << 12) | (reg_map[base1] << 16) | (base2)) -/* Normal ldr/str instruction. - Type2: ldrsb, ldrh, ldrsh */ -#define IS_TYPE1_TRANSFER(type) \ - (data_transfer_insts[(type) >> 4] & 0x04000000) -#define TYPE2_TRANSFER_IMM(imm) \ - (((imm) & 0xf) | (((imm) & 0xf0) << 4) | (1 << 22)) - /* flags: */ /* Arguments are swapped. */ #define ARGS_SWAPPED 0x01 /* Inverted immediate. */ #define INV_IMM 0x02 /* Source and destination is register. */ -#define REG_DEST 0x04 -#define REG_SOURCE 0x08 - /* One instruction is enough. */ -#define FAST_DEST 0x10 - /* Multiple instructions are required. */ -#define SLOW_DEST 0x20 +#define MOVE_REG_CONV 0x04 + /* Unused return value. */ +#define UNUSED_RETURN 0x08 /* SET_FLAGS must be (1 << 20) as it is also the value of S bit (can be used for optimization). */ #define SET_FLAGS (1 << 20) /* dst: reg @@ -983,157 +1009,127 @@ static sljit_sw data_transfer_insts[16] = { SRC2_IMM must be (1 << 25) as it is also the value of I bit (can be used for optimization). */ #define SRC2_IMM (1 << 25) -#define EMIT_DATA_PROCESS_INS_AND_RETURN(opcode) \ - return push_inst(compiler, EMIT_DATA_PROCESS_INS(opcode, flags & SET_FLAGS, dst, src1, (src2 & SRC2_IMM) ? src2 : RM(src2))) - -#define EMIT_FULL_DATA_PROCESS_INS_AND_RETURN(opcode, dst, src1, src2) \ - return push_inst(compiler, EMIT_DATA_PROCESS_INS(opcode, flags & SET_FLAGS, dst, src1, src2)) - #define EMIT_SHIFT_INS_AND_RETURN(opcode) \ SLJIT_ASSERT(!(flags & INV_IMM) && !(src2 & SRC2_IMM)); \ if (compiler->shift_imm != 0x20) { \ SLJIT_ASSERT(src1 == TMP_REG1); \ SLJIT_ASSERT(!(flags & ARGS_SWAPPED)); \ + \ if (compiler->shift_imm != 0) \ - return push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, flags & SET_FLAGS, dst, SLJIT_UNUSED, (compiler->shift_imm << 7) | (opcode << 5) | reg_map[src2])); \ - return push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, flags & SET_FLAGS, dst, SLJIT_UNUSED, reg_map[src2])); \ + return push_inst(compiler, MOV | (flags & SET_FLAGS) | \ + RD(dst) | (compiler->shift_imm << 7) | (opcode << 5) | RM(src2)); \ + return push_inst(compiler, MOV | (flags & SET_FLAGS) | RD(dst) | RM(src2)); \ } \ - return push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, flags & SET_FLAGS, dst, SLJIT_UNUSED, (reg_map[(flags & ARGS_SWAPPED) ? src1 : src2] << 8) | (opcode << 5) | 0x10 | ((flags & ARGS_SWAPPED) ? reg_map[src2] : reg_map[src1]))); + return push_inst(compiler, MOV | (flags & SET_FLAGS) | RD(dst) | \ + (reg_map[(flags & ARGS_SWAPPED) ? src1 : src2] << 8) | (opcode << 5) | 0x10 | RM((flags & ARGS_SWAPPED) ? src2 : src1)); static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 flags, sljit_s32 dst, sljit_s32 src1, sljit_s32 src2) { - sljit_sw mul_inst; - switch (GET_OPCODE(op)) { case SLJIT_MOV: SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & ARGS_SWAPPED)); if (dst != src2) { if (src2 & SRC2_IMM) { - if (flags & INV_IMM) - EMIT_FULL_DATA_PROCESS_INS_AND_RETURN(MVN_DP, dst, SLJIT_UNUSED, src2); - EMIT_FULL_DATA_PROCESS_INS_AND_RETURN(MOV_DP, dst, SLJIT_UNUSED, src2); + return push_inst(compiler, ((flags & INV_IMM) ? MVN : MOV) | RD(dst) | src2); } - EMIT_FULL_DATA_PROCESS_INS_AND_RETURN(MOV_DP, dst, SLJIT_UNUSED, reg_map[src2]); + return push_inst(compiler, MOV | RD(dst) | RM(src2)); } return SLJIT_SUCCESS; case SLJIT_MOV_U8: case SLJIT_MOV_S8: SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & ARGS_SWAPPED)); - if ((flags & (REG_DEST | REG_SOURCE)) == (REG_DEST | REG_SOURCE)) { + if (flags & MOVE_REG_CONV) { #if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) if (op == SLJIT_MOV_U8) - return push_inst(compiler, EMIT_DATA_PROCESS_INS(AND_DP, 0, dst, src2, SRC2_IMM | 0xff)); - FAIL_IF(push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, 0, dst, SLJIT_UNUSED, (24 << 7) | reg_map[src2]))); - return push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, 0, dst, SLJIT_UNUSED, (24 << 7) | (op == SLJIT_MOV_U8 ? 0x20 : 0x40) | reg_map[dst])); + return push_inst(compiler, AND | RD(dst) | RN(src2) | SRC2_IMM | 0xff); + FAIL_IF(push_inst(compiler, MOV | RD(dst) | (24 << 7) | RM(src2))); + return push_inst(compiler, MOV | RD(dst) | (24 << 7) | (op == SLJIT_MOV_U8 ? 0x20 : 0x40) | RM(dst)); #else return push_inst(compiler, (op == SLJIT_MOV_U8 ? UXTB : SXTB) | RD(dst) | RM(src2)); #endif } else if (dst != src2) { SLJIT_ASSERT(src2 & SRC2_IMM); - if (flags & INV_IMM) - EMIT_FULL_DATA_PROCESS_INS_AND_RETURN(MVN_DP, dst, SLJIT_UNUSED, src2); - EMIT_FULL_DATA_PROCESS_INS_AND_RETURN(MOV_DP, dst, SLJIT_UNUSED, src2); + return push_inst(compiler, ((flags & INV_IMM) ? MVN : MOV) | RD(dst) | src2); } return SLJIT_SUCCESS; case SLJIT_MOV_U16: case SLJIT_MOV_S16: SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & ARGS_SWAPPED)); - if ((flags & (REG_DEST | REG_SOURCE)) == (REG_DEST | REG_SOURCE)) { + if (flags & MOVE_REG_CONV) { #if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) - FAIL_IF(push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, 0, dst, SLJIT_UNUSED, (16 << 7) | reg_map[src2]))); - return push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, 0, dst, SLJIT_UNUSED, (16 << 7) | (op == SLJIT_MOV_U16 ? 0x20 : 0x40) | reg_map[dst])); + FAIL_IF(push_inst(compiler, MOV | RD(dst) | (16 << 7) | RM(src2))); + return push_inst(compiler, MOV | RD(dst) | (16 << 7) | (op == SLJIT_MOV_U16 ? 0x20 : 0x40) | RM(dst)); #else return push_inst(compiler, (op == SLJIT_MOV_U16 ? UXTH : SXTH) | RD(dst) | RM(src2)); #endif } else if (dst != src2) { SLJIT_ASSERT(src2 & SRC2_IMM); - if (flags & INV_IMM) - EMIT_FULL_DATA_PROCESS_INS_AND_RETURN(MVN_DP, dst, SLJIT_UNUSED, src2); - EMIT_FULL_DATA_PROCESS_INS_AND_RETURN(MOV_DP, dst, SLJIT_UNUSED, src2); + return push_inst(compiler, ((flags & INV_IMM) ? MVN : MOV) | RD(dst) | src2); } return SLJIT_SUCCESS; case SLJIT_NOT: if (src2 & SRC2_IMM) { - if (flags & INV_IMM) - EMIT_FULL_DATA_PROCESS_INS_AND_RETURN(MOV_DP, dst, SLJIT_UNUSED, src2); - EMIT_FULL_DATA_PROCESS_INS_AND_RETURN(MVN_DP, dst, SLJIT_UNUSED, src2); + return push_inst(compiler, ((flags & INV_IMM) ? MOV : MVN) | (flags & SET_FLAGS) | RD(dst) | src2); } - EMIT_FULL_DATA_PROCESS_INS_AND_RETURN(MVN_DP, dst, SLJIT_UNUSED, RM(src2)); + return push_inst(compiler, MVN | (flags & SET_FLAGS) | RD(dst) | RM(src2)); case SLJIT_CLZ: SLJIT_ASSERT(!(flags & INV_IMM)); SLJIT_ASSERT(!(src2 & SRC2_IMM)); FAIL_IF(push_inst(compiler, CLZ | RD(dst) | RM(src2))); - if (flags & SET_FLAGS) - EMIT_FULL_DATA_PROCESS_INS_AND_RETURN(CMP_DP, SLJIT_UNUSED, dst, SRC2_IMM); return SLJIT_SUCCESS; case SLJIT_ADD: SLJIT_ASSERT(!(flags & INV_IMM)); - EMIT_DATA_PROCESS_INS_AND_RETURN(ADD_DP); + if ((flags & (UNUSED_RETURN | SET_FLAGS)) == (UNUSED_RETURN | SET_FLAGS) && !(flags & ARGS_SWAPPED)) + return push_inst(compiler, CMN | SET_FLAGS | RN(src1) | ((src2 & SRC2_IMM) ? src2 : RM(src2))); + return push_inst(compiler, ADD | (flags & SET_FLAGS) | RD(dst) | RN(src1) | ((src2 & SRC2_IMM) ? src2 : RM(src2))); case SLJIT_ADDC: SLJIT_ASSERT(!(flags & INV_IMM)); - EMIT_DATA_PROCESS_INS_AND_RETURN(ADC_DP); + return push_inst(compiler, ADC | (flags & SET_FLAGS) | RD(dst) | RN(src1) | ((src2 & SRC2_IMM) ? src2 : RM(src2))); case SLJIT_SUB: SLJIT_ASSERT(!(flags & INV_IMM)); - if (!(flags & ARGS_SWAPPED)) - EMIT_DATA_PROCESS_INS_AND_RETURN(SUB_DP); - EMIT_DATA_PROCESS_INS_AND_RETURN(RSB_DP); + if ((flags & (UNUSED_RETURN | SET_FLAGS)) == (UNUSED_RETURN | SET_FLAGS) && !(flags & ARGS_SWAPPED)) + return push_inst(compiler, CMP | SET_FLAGS | RN(src1) | ((src2 & SRC2_IMM) ? src2 : RM(src2))); + return push_inst(compiler, (!(flags & ARGS_SWAPPED) ? SUB : RSB) | (flags & SET_FLAGS) + | RD(dst) | RN(src1) | ((src2 & SRC2_IMM) ? src2 : RM(src2))); case SLJIT_SUBC: SLJIT_ASSERT(!(flags & INV_IMM)); - if (!(flags & ARGS_SWAPPED)) - EMIT_DATA_PROCESS_INS_AND_RETURN(SBC_DP); - EMIT_DATA_PROCESS_INS_AND_RETURN(RSC_DP); + return push_inst(compiler, (!(flags & ARGS_SWAPPED) ? SBC : RSC) | (flags & SET_FLAGS) + | RD(dst) | RN(src1) | ((src2 & SRC2_IMM) ? src2 : RM(src2))); case SLJIT_MUL: SLJIT_ASSERT(!(flags & INV_IMM)); SLJIT_ASSERT(!(src2 & SRC2_IMM)); - if (SLJIT_UNLIKELY(op & SLJIT_SET_O)) - mul_inst = SMULL | (reg_map[TMP_REG3] << 16) | (reg_map[dst] << 12); - else - mul_inst = MUL | (reg_map[dst] << 16); - if (dst != src2) - FAIL_IF(push_inst(compiler, mul_inst | (reg_map[src1] << 8) | reg_map[src2])); - else if (dst != src1) - FAIL_IF(push_inst(compiler, mul_inst | (reg_map[src2] << 8) | reg_map[src1])); - else { - /* Rm and Rd must not be the same register. */ - SLJIT_ASSERT(dst != TMP_REG1); - FAIL_IF(push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, 0, TMP_REG1, SLJIT_UNUSED, reg_map[src2]))); - FAIL_IF(push_inst(compiler, mul_inst | (reg_map[src2] << 8) | reg_map[TMP_REG1])); - } + if (!HAS_FLAGS(op)) + return push_inst(compiler, MUL | (reg_map[dst] << 16) | (reg_map[src2] << 8) | reg_map[src1]); - if (!(op & SLJIT_SET_O)) - return SLJIT_SUCCESS; + FAIL_IF(push_inst(compiler, SMULL | (reg_map[TMP_REG1] << 16) | (reg_map[dst] << 12) | (reg_map[src2] << 8) | reg_map[src1])); - /* We need to use TMP_REG3. */ - compiler->cache_arg = 0; - compiler->cache_argw = 0; - /* cmp TMP_REG2, dst asr #31. */ - return push_inst(compiler, EMIT_DATA_PROCESS_INS(CMP_DP, SET_FLAGS, SLJIT_UNUSED, TMP_REG3, RM(dst) | 0xfc0)); + /* cmp TMP_REG1, dst asr #31. */ + return push_inst(compiler, CMP | SET_FLAGS | RN(TMP_REG1) | RM(dst) | 0xfc0); case SLJIT_AND: - if (!(flags & INV_IMM)) - EMIT_DATA_PROCESS_INS_AND_RETURN(AND_DP); - EMIT_DATA_PROCESS_INS_AND_RETURN(BIC_DP); + return push_inst(compiler, (!(flags & INV_IMM) ? AND : BIC) | (flags & SET_FLAGS) + | RD(dst) | RN(src1) | ((src2 & SRC2_IMM) ? src2 : RM(src2))); case SLJIT_OR: SLJIT_ASSERT(!(flags & INV_IMM)); - EMIT_DATA_PROCESS_INS_AND_RETURN(ORR_DP); + return push_inst(compiler, ORR | (flags & SET_FLAGS) | RD(dst) | RN(src1) | ((src2 & SRC2_IMM) ? src2 : RM(src2))); case SLJIT_XOR: SLJIT_ASSERT(!(flags & INV_IMM)); - EMIT_DATA_PROCESS_INS_AND_RETURN(EOR_DP); + return push_inst(compiler, EOR | (flags & SET_FLAGS) | RD(dst) | RN(src1) | ((src2 & SRC2_IMM) ? src2 : RM(src2))); case SLJIT_SHL: EMIT_SHIFT_INS_AND_RETURN(0); @@ -1144,12 +1140,11 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl case SLJIT_ASHR: EMIT_SHIFT_INS_AND_RETURN(2); } - SLJIT_ASSERT_STOP(); + + SLJIT_UNREACHABLE(); return SLJIT_SUCCESS; } -#undef EMIT_DATA_PROCESS_INS_AND_RETURN -#undef EMIT_FULL_DATA_PROCESS_INS_AND_RETURN #undef EMIT_SHIFT_INS_AND_RETURN /* Tests whether the immediate can be stored in the 12 bit imm field. @@ -1297,8 +1292,8 @@ static sljit_s32 generate_int(struct sljit_compiler *compiler, sljit_s32 reg, sl return 0; } - FAIL_IF(push_inst(compiler, EMIT_DATA_PROCESS_INS(positive ? MOV_DP : MVN_DP, 0, reg, SLJIT_UNUSED, imm1))); - FAIL_IF(push_inst(compiler, EMIT_DATA_PROCESS_INS(positive ? ORR_DP : BIC_DP, 0, reg, reg, imm2))); + FAIL_IF(push_inst(compiler, (positive ? MOV : MVN) | RD(reg) | imm1)); + FAIL_IF(push_inst(compiler, (positive ? ORR : BIC) | RD(reg) | RN(reg) | imm2)); return 1; } #endif @@ -1315,11 +1310,11 @@ static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 reg, /* Create imm by 1 inst. */ tmp = get_imm(imm); if (tmp) - return push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, 0, reg, SLJIT_UNUSED, tmp)); + return push_inst(compiler, MOV | RD(reg) | tmp); tmp = get_imm(~imm); if (tmp) - return push_inst(compiler, EMIT_DATA_PROCESS_INS(MVN_DP, 0, reg, SLJIT_UNUSED, tmp)); + return push_inst(compiler, MVN | RD(reg) | tmp); #if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) /* Create imm by 2 inst. */ @@ -1327,293 +1322,109 @@ static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 reg, FAIL_IF(generate_int(compiler, reg, ~imm, 0)); /* Load integer. */ - return push_inst_with_literal(compiler, EMIT_DATA_TRANSFER(WORD_DATA | LOAD_DATA, 1, 0, reg, TMP_PC, 0), imm); + return push_inst_with_literal(compiler, EMIT_DATA_TRANSFER(WORD_SIZE | LOAD_DATA, 1, reg, TMP_PC, 0), imm); #else - return emit_imm(compiler, reg, imm); + FAIL_IF(push_inst(compiler, MOVW | RD(reg) | ((imm << 4) & 0xf0000) | (imm & 0xfff))); + if (imm <= 0xffff) + return SLJIT_SUCCESS; + return push_inst(compiler, MOVT | RD(reg) | ((imm >> 12) & 0xf0000) | ((imm >> 16) & 0xfff)); #endif } -/* Helper function. Dst should be reg + value, using at most 1 instruction, flags does not set. */ -static sljit_s32 emit_set_delta(struct sljit_compiler *compiler, sljit_s32 dst, sljit_s32 reg, sljit_sw value) +static SLJIT_INLINE sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, + sljit_s32 arg, sljit_sw argw, sljit_s32 tmp_reg) { - if (value >= 0) { - value = get_imm(value); - if (value) - return push_inst(compiler, EMIT_DATA_PROCESS_INS(ADD_DP, 0, dst, reg, value)); - } - else { - value = get_imm(-value); - if (value) - return push_inst(compiler, EMIT_DATA_PROCESS_INS(SUB_DP, 0, dst, reg, value)); - } - return SLJIT_ERR_UNSUPPORTED; -} + sljit_uw imm, offset_reg; + sljit_uw is_type1_transfer = IS_TYPE1_TRANSFER(flags); -/* Can perform an operation using at most 1 instruction. */ -static sljit_s32 getput_arg_fast(struct sljit_compiler *compiler, sljit_s32 inp_flags, sljit_s32 reg, sljit_s32 arg, sljit_sw argw) -{ - sljit_uw imm; + SLJIT_ASSERT (arg & SLJIT_MEM); + SLJIT_ASSERT((arg & REG_MASK) != tmp_reg); - if (arg & SLJIT_IMM) { - imm = get_imm(argw); - if (imm) { - if (inp_flags & ARG_TEST) - return 1; - FAIL_IF(push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, 0, reg, SLJIT_UNUSED, imm))); - return -1; + if ((arg & REG_MASK) == SLJIT_UNUSED) { + if (is_type1_transfer) { + FAIL_IF(load_immediate(compiler, tmp_reg, argw & ~0xfff)); + argw &= 0xfff; } - imm = get_imm(~argw); - if (imm) { - if (inp_flags & ARG_TEST) - return 1; - FAIL_IF(push_inst(compiler, EMIT_DATA_PROCESS_INS(MVN_DP, 0, reg, SLJIT_UNUSED, imm))); - return -1; + else { + FAIL_IF(load_immediate(compiler, tmp_reg, argw & ~0xff)); + argw &= 0xff; } - return 0; - } - - SLJIT_ASSERT(arg & SLJIT_MEM); - /* Fast loads/stores. */ - if (!(arg & REG_MASK)) - return 0; + return push_inst(compiler, EMIT_DATA_TRANSFER(flags, 1, reg, tmp_reg, + is_type1_transfer ? argw : TYPE2_TRANSFER_IMM(argw))); + } if (arg & OFFS_REG_MASK) { - if ((argw & 0x3) != 0 && !IS_TYPE1_TRANSFER(inp_flags)) - return 0; - - if (inp_flags & ARG_TEST) - return 1; - FAIL_IF(push_inst(compiler, EMIT_DATA_TRANSFER(inp_flags, 1, inp_flags & WRITE_BACK, reg, arg & REG_MASK, - RM(OFFS_REG(arg)) | (IS_TYPE1_TRANSFER(inp_flags) ? SRC2_IMM : 0) | ((argw & 0x3) << 7)))); - return -1; - } + offset_reg = OFFS_REG(arg); + arg &= REG_MASK; + argw &= 0x3; - if (IS_TYPE1_TRANSFER(inp_flags)) { - if (argw >= 0 && argw <= 0xfff) { - if (inp_flags & ARG_TEST) - return 1; - FAIL_IF(push_inst(compiler, EMIT_DATA_TRANSFER(inp_flags, 1, inp_flags & WRITE_BACK, reg, arg & REG_MASK, argw))); - return -1; - } - if (argw < 0 && argw >= -0xfff) { - if (inp_flags & ARG_TEST) - return 1; - FAIL_IF(push_inst(compiler, EMIT_DATA_TRANSFER(inp_flags, 0, inp_flags & WRITE_BACK, reg, arg & REG_MASK, -argw))); - return -1; - } - } - else { - if (argw >= 0 && argw <= 0xff) { - if (inp_flags & ARG_TEST) - return 1; - FAIL_IF(push_inst(compiler, EMIT_DATA_TRANSFER(inp_flags, 1, inp_flags & WRITE_BACK, reg, arg & REG_MASK, TYPE2_TRANSFER_IMM(argw)))); - return -1; - } - if (argw < 0 && argw >= -0xff) { - if (inp_flags & ARG_TEST) - return 1; - argw = -argw; - FAIL_IF(push_inst(compiler, EMIT_DATA_TRANSFER(inp_flags, 0, inp_flags & WRITE_BACK, reg, arg & REG_MASK, TYPE2_TRANSFER_IMM(argw)))); - return -1; + if (argw != 0 && !is_type1_transfer) { + FAIL_IF(push_inst(compiler, ADD | RD(tmp_reg) | RN(arg) | RM(offset_reg) | (argw << 7))); + return push_inst(compiler, EMIT_DATA_TRANSFER(flags, 1, reg, tmp_reg, TYPE2_TRANSFER_IMM(0))); } - } - - return 0; -} -/* See getput_arg below. - Note: can_cache is called only for binary operators. Those - operators always uses word arguments without write back. */ -static sljit_s32 can_cache(sljit_s32 arg, sljit_sw argw, sljit_s32 next_arg, sljit_sw next_argw) -{ - /* Immediate caching is not supported as it would be an operation on constant arguments. */ - if (arg & SLJIT_IMM) - return 0; - - /* Always a simple operation. */ - if (arg & OFFS_REG_MASK) - return 0; - - if (!(arg & REG_MASK)) { - /* Immediate access. */ - if ((next_arg & SLJIT_MEM) && ((sljit_uw)argw - (sljit_uw)next_argw <= 0xfff || (sljit_uw)next_argw - (sljit_uw)argw <= 0xfff)) - return 1; - return 0; + /* Bit 25: RM is offset. */ + return push_inst(compiler, EMIT_DATA_TRANSFER(flags, 1, reg, arg, + RM(offset_reg) | (is_type1_transfer ? (1 << 25) : 0) | (argw << 7))); } - if (argw <= 0xfffff && argw >= -0xfffff) - return 0; + arg &= REG_MASK; - if (argw == next_argw && (next_arg & SLJIT_MEM)) - return 1; - - if (arg == next_arg && ((sljit_uw)argw - (sljit_uw)next_argw <= 0xfff || (sljit_uw)next_argw - (sljit_uw)argw <= 0xfff)) - return 1; - - return 0; -} + if (is_type1_transfer) { + if (argw > 0xfff) { + imm = get_imm(argw & ~0xfff); + if (imm) { + FAIL_IF(push_inst(compiler, ADD | RD(tmp_reg) | RN(arg) | imm)); + argw = argw & 0xfff; + arg = tmp_reg; + } + } + else if (argw < -0xfff) { + imm = get_imm(-argw & ~0xfff); + if (imm) { + FAIL_IF(push_inst(compiler, SUB | RD(tmp_reg) | RN(arg) | imm)); + argw = -(-argw & 0xfff); + arg = tmp_reg; + } + } -#define GETPUT_ARG_DATA_TRANSFER(add, wb, target, base, imm) \ - if (max_delta & 0xf00) \ - FAIL_IF(push_inst(compiler, EMIT_DATA_TRANSFER(inp_flags, add, wb, target, base, imm))); \ - else \ - FAIL_IF(push_inst(compiler, EMIT_DATA_TRANSFER(inp_flags, add, wb, target, base, TYPE2_TRANSFER_IMM(imm)))); - -#define TEST_WRITE_BACK() \ - if (inp_flags & WRITE_BACK) { \ - tmp_r = arg & REG_MASK; \ - if (reg == tmp_r) { \ - /* This can only happen for stores */ \ - /* since ldr reg, [reg, ...]! has no meaning */ \ - SLJIT_ASSERT(!(inp_flags & LOAD_DATA)); \ - FAIL_IF(push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, 0, TMP_REG3, SLJIT_UNUSED, RM(reg)))); \ - reg = TMP_REG3; \ - } \ - } - -/* Emit the necessary instructions. See can_cache above. */ -static sljit_s32 getput_arg(struct sljit_compiler *compiler, sljit_s32 inp_flags, sljit_s32 reg, sljit_s32 arg, sljit_sw argw, sljit_s32 next_arg, sljit_sw next_argw) -{ - sljit_s32 tmp_r; - sljit_sw max_delta; - sljit_sw sign; - sljit_uw imm; + if (argw >= 0 && argw <= 0xfff) + return push_inst(compiler, EMIT_DATA_TRANSFER(flags, 1, reg, arg, argw)); - if (arg & SLJIT_IMM) { - SLJIT_ASSERT(inp_flags & LOAD_DATA); - return load_immediate(compiler, reg, argw); + if (argw < 0 && argw >= -0xfff) + return push_inst(compiler, EMIT_DATA_TRANSFER(flags, 0, reg, arg, -argw)); } - - SLJIT_ASSERT(arg & SLJIT_MEM); - - tmp_r = (inp_flags & LOAD_DATA) ? reg : TMP_REG3; - max_delta = IS_TYPE1_TRANSFER(inp_flags) ? 0xfff : 0xff; - - if ((arg & REG_MASK) == SLJIT_UNUSED) { - /* Write back is not used. */ - imm = (sljit_uw)(argw - compiler->cache_argw); - if ((compiler->cache_arg & SLJIT_IMM) && (imm <= (sljit_uw)max_delta || imm >= (sljit_uw)-max_delta)) { - if (imm <= (sljit_uw)max_delta) { - sign = 1; - argw = argw - compiler->cache_argw; + else { + if (argw > 0xff) { + imm = get_imm(argw & ~0xff); + if (imm) { + FAIL_IF(push_inst(compiler, ADD | RD(tmp_reg) | RN(arg) | imm)); + argw = argw & 0xff; + arg = tmp_reg; } - else { - sign = 0; - argw = compiler->cache_argw - argw; + } + else if (argw < -0xff) { + imm = get_imm(-argw & ~0xff); + if (imm) { + FAIL_IF(push_inst(compiler, SUB | RD(tmp_reg) | RN(arg) | imm)); + argw = -(-argw & 0xff); + arg = tmp_reg; } - - GETPUT_ARG_DATA_TRANSFER(sign, 0, reg, TMP_REG3, argw); - return SLJIT_SUCCESS; } - /* With write back, we can create some sophisticated loads, but - it is hard to decide whether we should convert downward (0s) or upward (1s). */ - imm = (sljit_uw)(argw - next_argw); - if ((next_arg & SLJIT_MEM) && (imm <= (sljit_uw)max_delta || imm >= (sljit_uw)-max_delta)) { - SLJIT_ASSERT(inp_flags & LOAD_DATA); + if (argw >= 0 && argw <= 0xff) + return push_inst(compiler, EMIT_DATA_TRANSFER(flags, 1, reg, arg, TYPE2_TRANSFER_IMM(argw))); - compiler->cache_arg = SLJIT_IMM; - compiler->cache_argw = argw; - tmp_r = TMP_REG3; + if (argw < 0 && argw >= -0xff) { + argw = -argw; + return push_inst(compiler, EMIT_DATA_TRANSFER(flags, 0, reg, arg, TYPE2_TRANSFER_IMM(argw))); } - - FAIL_IF(load_immediate(compiler, tmp_r, argw)); - GETPUT_ARG_DATA_TRANSFER(1, 0, reg, tmp_r, 0); - return SLJIT_SUCCESS; - } - - if (arg & OFFS_REG_MASK) { - SLJIT_ASSERT((argw & 0x3) && !(max_delta & 0xf00)); - if (inp_flags & WRITE_BACK) - tmp_r = arg & REG_MASK; - FAIL_IF(push_inst(compiler, EMIT_DATA_PROCESS_INS(ADD_DP, 0, tmp_r, arg & REG_MASK, RM(OFFS_REG(arg)) | ((argw & 0x3) << 7)))); - return push_inst(compiler, EMIT_DATA_TRANSFER(inp_flags, 1, 0, reg, tmp_r, TYPE2_TRANSFER_IMM(0))); - } - - imm = (sljit_uw)(argw - compiler->cache_argw); - if (compiler->cache_arg == arg && imm <= (sljit_uw)max_delta) { - SLJIT_ASSERT(!(inp_flags & WRITE_BACK)); - GETPUT_ARG_DATA_TRANSFER(1, 0, reg, TMP_REG3, imm); - return SLJIT_SUCCESS; } - if (compiler->cache_arg == arg && imm >= (sljit_uw)-max_delta) { - SLJIT_ASSERT(!(inp_flags & WRITE_BACK)); - imm = (sljit_uw)-(sljit_sw)imm; - GETPUT_ARG_DATA_TRANSFER(0, 0, reg, TMP_REG3, imm); - return SLJIT_SUCCESS; - } - - imm = get_imm(argw & ~max_delta); - if (imm) { - TEST_WRITE_BACK(); - FAIL_IF(push_inst(compiler, EMIT_DATA_PROCESS_INS(ADD_DP, 0, tmp_r, arg & REG_MASK, imm))); - GETPUT_ARG_DATA_TRANSFER(1, inp_flags & WRITE_BACK, reg, tmp_r, argw & max_delta); - return SLJIT_SUCCESS; - } - - imm = get_imm(-argw & ~max_delta); - if (imm) { - argw = -argw; - TEST_WRITE_BACK(); - FAIL_IF(push_inst(compiler, EMIT_DATA_PROCESS_INS(SUB_DP, 0, tmp_r, arg & REG_MASK, imm))); - GETPUT_ARG_DATA_TRANSFER(0, inp_flags & WRITE_BACK, reg, tmp_r, argw & max_delta); - return SLJIT_SUCCESS; - } - - if ((compiler->cache_arg & SLJIT_IMM) && compiler->cache_argw == argw) { - TEST_WRITE_BACK(); - return push_inst(compiler, EMIT_DATA_TRANSFER(inp_flags, 1, inp_flags & WRITE_BACK, reg, arg & REG_MASK, RM(TMP_REG3) | (max_delta & 0xf00 ? SRC2_IMM : 0))); - } - - if (argw == next_argw && (next_arg & SLJIT_MEM)) { - SLJIT_ASSERT(inp_flags & LOAD_DATA); - FAIL_IF(load_immediate(compiler, TMP_REG3, argw)); - - compiler->cache_arg = SLJIT_IMM; - compiler->cache_argw = argw; - - TEST_WRITE_BACK(); - return push_inst(compiler, EMIT_DATA_TRANSFER(inp_flags, 1, inp_flags & WRITE_BACK, reg, arg & REG_MASK, RM(TMP_REG3) | (max_delta & 0xf00 ? SRC2_IMM : 0))); - } - - imm = (sljit_uw)(argw - next_argw); - if (arg == next_arg && !(inp_flags & WRITE_BACK) && (imm <= (sljit_uw)max_delta || imm >= (sljit_uw)-max_delta)) { - SLJIT_ASSERT(inp_flags & LOAD_DATA); - FAIL_IF(load_immediate(compiler, TMP_REG3, argw)); - FAIL_IF(push_inst(compiler, EMIT_DATA_PROCESS_INS(ADD_DP, 0, TMP_REG3, TMP_REG3, reg_map[arg & REG_MASK]))); - - compiler->cache_arg = arg; - compiler->cache_argw = argw; - GETPUT_ARG_DATA_TRANSFER(1, 0, reg, TMP_REG3, 0); - return SLJIT_SUCCESS; - } - - if ((arg & REG_MASK) == tmp_r) { - compiler->cache_arg = SLJIT_IMM; - compiler->cache_argw = argw; - tmp_r = TMP_REG3; - } - - FAIL_IF(load_immediate(compiler, tmp_r, argw)); - return push_inst(compiler, EMIT_DATA_TRANSFER(inp_flags, 1, inp_flags & WRITE_BACK, reg, arg & REG_MASK, reg_map[tmp_r] | (max_delta & 0xf00 ? SRC2_IMM : 0))); -} - -static SLJIT_INLINE sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 arg, sljit_sw argw) -{ - if (getput_arg_fast(compiler, flags, reg, arg, argw)) - return compiler->error; - compiler->cache_arg = 0; - compiler->cache_argw = 0; - return getput_arg(compiler, flags, reg, arg, argw, 0, 0); -} - -static SLJIT_INLINE sljit_s32 emit_op_mem2(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 arg1, sljit_sw arg1w, sljit_s32 arg2, sljit_sw arg2w) -{ - if (getput_arg_fast(compiler, flags, reg, arg1, arg1w)) - return compiler->error; - return getput_arg(compiler, flags, reg, arg1, arg1w, arg2, arg2w); + FAIL_IF(load_immediate(compiler, tmp_reg, argw)); + return push_inst(compiler, EMIT_DATA_TRANSFER(flags, 1, reg, arg, + RM(tmp_reg) | (is_type1_transfer ? (1 << 25) : 0))); } static sljit_s32 emit_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 inp_flags, @@ -1621,68 +1432,66 @@ static sljit_s32 emit_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s3 sljit_s32 src1, sljit_sw src1w, sljit_s32 src2, sljit_sw src2w) { - /* arg1 goes to TMP_REG1 or src reg - arg2 goes to TMP_REG2, imm or src reg - TMP_REG3 can be used for caching - result goes to TMP_REG2, so put result can use TMP_REG1 and TMP_REG3. */ + /* src1 is reg or TMP_REG1 + src2 is reg, TMP_REG2, or imm + result goes to TMP_REG2, so put result can use TMP_REG1. */ /* We prefers register and simple consts. */ - sljit_s32 dst_r; - sljit_s32 src1_r; - sljit_s32 src2_r = 0; - sljit_s32 sugg_src2_r = TMP_REG2; - sljit_s32 flags = GET_FLAGS(op) ? SET_FLAGS : 0; - - compiler->cache_arg = 0; - compiler->cache_argw = 0; + sljit_s32 dst_reg; + sljit_s32 src1_reg; + sljit_s32 src2_reg; + sljit_s32 flags = HAS_FLAGS(op) ? SET_FLAGS : 0; /* Destination check. */ - if (SLJIT_UNLIKELY(dst == SLJIT_UNUSED)) { - if (op >= SLJIT_MOV && op <= SLJIT_MOVU_S32 && !(src2 & SLJIT_MEM)) - return SLJIT_SUCCESS; - dst_r = TMP_REG2; - } - else if (FAST_IS_REG(dst)) { - dst_r = dst; - flags |= REG_DEST; - if (op >= SLJIT_MOV && op <= SLJIT_MOVU_S32) - sugg_src2_r = dst_r; - } - else { - SLJIT_ASSERT(dst & SLJIT_MEM); - if (getput_arg_fast(compiler, inp_flags | ARG_TEST, TMP_REG2, dst, dstw)) { - flags |= FAST_DEST; - dst_r = TMP_REG2; - } - else { - flags |= SLOW_DEST; - dst_r = 0; + if (SLJIT_UNLIKELY(dst == SLJIT_UNUSED)) + flags |= UNUSED_RETURN; + + SLJIT_ASSERT(!(inp_flags & ALLOW_INV_IMM) || (inp_flags & ALLOW_IMM)); + + src2_reg = 0; + + do { + if (!(inp_flags & ALLOW_IMM)) + break; + + if (src2 & SLJIT_IMM) { + src2_reg = get_imm(src2w); + if (src2_reg) + break; + if (inp_flags & ALLOW_INV_IMM) { + src2_reg = get_imm(~src2w); + if (src2_reg) { + flags |= INV_IMM; + break; + } + } + if (GET_OPCODE(op) == SLJIT_ADD) { + src2_reg = get_imm(-src2w); + if (src2_reg) { + op = SLJIT_SUB | GET_ALL_FLAGS(op); + break; + } + } + if (GET_OPCODE(op) == SLJIT_SUB) { + src2_reg = get_imm(-src2w); + if (src2_reg) { + op = SLJIT_ADD | GET_ALL_FLAGS(op); + break; + } + } } - } - /* Source 1. */ - if (FAST_IS_REG(src1)) - src1_r = src1; - else if (FAST_IS_REG(src2)) { - flags |= ARGS_SWAPPED; - src1_r = src2; - src2 = src1; - src2w = src1w; - } - else do { /* do { } while(0) is used because of breaks. */ - src1_r = 0; - if ((inp_flags & ALLOW_ANY_IMM) && (src1 & SLJIT_IMM)) { - /* The second check will generate a hit. */ - src2_r = get_imm(src1w); - if (src2_r) { + if (src1 & SLJIT_IMM) { + src2_reg = get_imm(src1w); + if (src2_reg) { flags |= ARGS_SWAPPED; src1 = src2; src1w = src2w; break; } if (inp_flags & ALLOW_INV_IMM) { - src2_r = get_imm(~src1w); - if (src2_r) { + src2_reg = get_imm(~src1w); + if (src2_reg) { flags |= ARGS_SWAPPED | INV_IMM; src1 = src2; src1w = src2w; @@ -1690,9 +1499,9 @@ static sljit_s32 emit_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s3 } } if (GET_OPCODE(op) == SLJIT_ADD) { - src2_r = get_imm(-src1w); - if (src2_r) { - /* Note: ARGS_SWAPPED is intentionally not applied! */ + src2_reg = get_imm(-src1w); + if (src2_reg) { + /* Note: add is commutative operation. */ src1 = src2; src1w = src2w; op = SLJIT_SUB | GET_ALL_FLAGS(op); @@ -1700,110 +1509,54 @@ static sljit_s32 emit_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s3 } } } + } while(0); - if (getput_arg_fast(compiler, inp_flags | LOAD_DATA, TMP_REG1, src1, src1w)) { - FAIL_IF(compiler->error); - src1_r = TMP_REG1; - } - } while (0); + /* Source 1. */ + if (FAST_IS_REG(src1)) + src1_reg = src1; + else if (src1 & SLJIT_MEM) { + FAIL_IF(emit_op_mem(compiler, inp_flags | LOAD_DATA, TMP_REG1, src1, src1w, TMP_REG1)); + src1_reg = TMP_REG1; + } + else { + FAIL_IF(load_immediate(compiler, TMP_REG1, src1w)); + src1_reg = TMP_REG1; + } - /* Source 2. */ - if (src2_r == 0) { - if (FAST_IS_REG(src2)) { - src2_r = src2; - flags |= REG_SOURCE; - if (!(flags & REG_DEST) && op >= SLJIT_MOV && op <= SLJIT_MOVU_S32) - dst_r = src2_r; - } - else do { /* do { } while(0) is used because of breaks. */ - if ((inp_flags & ALLOW_ANY_IMM) && (src2 & SLJIT_IMM)) { - src2_r = get_imm(src2w); - if (src2_r) - break; - if (inp_flags & ALLOW_INV_IMM) { - src2_r = get_imm(~src2w); - if (src2_r) { - flags |= INV_IMM; - break; - } - } - if (GET_OPCODE(op) == SLJIT_ADD) { - src2_r = get_imm(-src2w); - if (src2_r) { - op = SLJIT_SUB | GET_ALL_FLAGS(op); - flags &= ~ARGS_SWAPPED; - break; - } - } - if (GET_OPCODE(op) == SLJIT_SUB && !(flags & ARGS_SWAPPED)) { - src2_r = get_imm(-src2w); - if (src2_r) { - op = SLJIT_ADD | GET_ALL_FLAGS(op); - flags &= ~ARGS_SWAPPED; - break; - } - } - } + /* Destination. */ + dst_reg = SLOW_IS_REG(dst) ? dst : TMP_REG2; - /* src2_r is 0. */ - if (getput_arg_fast(compiler, inp_flags | LOAD_DATA, sugg_src2_r, src2, src2w)) { - FAIL_IF(compiler->error); - src2_r = sugg_src2_r; - } - } while (0); - } + if (op <= SLJIT_MOV_P) { + if (dst & SLJIT_MEM) { + if (inp_flags & BYTE_SIZE) + inp_flags &= ~SIGNED; - /* src1_r, src2_r and dst_r can be zero (=unprocessed) or non-zero. - If they are zero, they must not be registers. */ - if (src1_r == 0 && src2_r == 0 && dst_r == 0) { - if (!can_cache(src1, src1w, src2, src2w) && can_cache(src1, src1w, dst, dstw)) { - SLJIT_ASSERT(!(flags & ARGS_SWAPPED)); - flags |= ARGS_SWAPPED; - FAIL_IF(getput_arg(compiler, inp_flags | LOAD_DATA, TMP_REG1, src2, src2w, src1, src1w)); - FAIL_IF(getput_arg(compiler, inp_flags | LOAD_DATA, TMP_REG2, src1, src1w, dst, dstw)); + if (FAST_IS_REG(src2)) + return emit_op_mem(compiler, inp_flags, src2, dst, dstw, TMP_REG2); } - else { - FAIL_IF(getput_arg(compiler, inp_flags | LOAD_DATA, TMP_REG1, src1, src1w, src2, src2w)); - FAIL_IF(getput_arg(compiler, inp_flags | LOAD_DATA, TMP_REG2, src2, src2w, dst, dstw)); - } - src1_r = TMP_REG1; - src2_r = TMP_REG2; - } - else if (src1_r == 0 && src2_r == 0) { - FAIL_IF(getput_arg(compiler, inp_flags | LOAD_DATA, TMP_REG1, src1, src1w, src2, src2w)); - src1_r = TMP_REG1; - } - else if (src1_r == 0 && dst_r == 0) { - FAIL_IF(getput_arg(compiler, inp_flags | LOAD_DATA, TMP_REG1, src1, src1w, dst, dstw)); - src1_r = TMP_REG1; - } - else if (src2_r == 0 && dst_r == 0) { - FAIL_IF(getput_arg(compiler, inp_flags | LOAD_DATA, sugg_src2_r, src2, src2w, dst, dstw)); - src2_r = sugg_src2_r; + + if (FAST_IS_REG(src2) && dst_reg != TMP_REG2) + flags |= MOVE_REG_CONV; } - if (dst_r == 0) - dst_r = TMP_REG2; + /* Source 2. */ + if (src2_reg == 0) { + src2_reg = (op <= SLJIT_MOV_P) ? dst_reg : TMP_REG2; - if (src1_r == 0) { - FAIL_IF(getput_arg(compiler, inp_flags | LOAD_DATA, TMP_REG1, src1, src1w, 0, 0)); - src1_r = TMP_REG1; + if (FAST_IS_REG(src2)) + src2_reg = src2; + else if (src2 & SLJIT_MEM) + FAIL_IF(emit_op_mem(compiler, inp_flags | LOAD_DATA, src2_reg, src2, src2w, TMP_REG2)); + else + FAIL_IF(load_immediate(compiler, src2_reg, src2w)); } - if (src2_r == 0) { - FAIL_IF(getput_arg(compiler, inp_flags | LOAD_DATA, sugg_src2_r, src2, src2w, 0, 0)); - src2_r = sugg_src2_r; - } + FAIL_IF(emit_single_op(compiler, op, flags, dst_reg, src1_reg, src2_reg)); - FAIL_IF(emit_single_op(compiler, op, flags, dst_r, src1_r, src2_r)); + if (!(dst & SLJIT_MEM)) + return SLJIT_SUCCESS; - if (flags & (FAST_DEST | SLOW_DEST)) { - if (flags & FAST_DEST) - FAIL_IF(getput_arg_fast(compiler, inp_flags, dst_r, dst, dstw)); - else - FAIL_IF(getput_arg(compiler, inp_flags, dst_r, dst, dstw, 0, 0)); - } - return SLJIT_SUCCESS; + return emit_op_mem(compiler, inp_flags, dst_reg, dst, dstw, TMP_REG1); } #ifdef __cplusplus @@ -1823,6 +1576,9 @@ extern int __aeabi_idivmod(int numerator, int denominator); SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compiler, sljit_s32 op) { + sljit_sw saved_reg_list[3]; + sljit_sw saved_reg_count; + CHECK_ERROR(); CHECK(check_sljit_emit_op0(compiler, op)); @@ -1836,33 +1592,38 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compile break; case SLJIT_LMUL_UW: case SLJIT_LMUL_SW: -#if (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7) return push_inst(compiler, (op == SLJIT_LMUL_UW ? UMULL : SMULL) | (reg_map[SLJIT_R1] << 16) | (reg_map[SLJIT_R0] << 12) | (reg_map[SLJIT_R0] << 8) | reg_map[SLJIT_R1]); -#else - FAIL_IF(push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, 0, TMP_REG1, SLJIT_UNUSED, RM(SLJIT_R1)))); - return push_inst(compiler, (op == SLJIT_LMUL_UW ? UMULL : SMULL) - | (reg_map[SLJIT_R1] << 16) - | (reg_map[SLJIT_R0] << 12) - | (reg_map[SLJIT_R0] << 8) - | reg_map[TMP_REG1]); -#endif case SLJIT_DIVMOD_UW: case SLJIT_DIVMOD_SW: case SLJIT_DIV_UW: case SLJIT_DIV_SW: SLJIT_COMPILE_ASSERT((SLJIT_DIVMOD_UW & 0x2) == 0 && SLJIT_DIV_UW - 0x2 == SLJIT_DIVMOD_UW, bad_div_opcode_assignments); - SLJIT_COMPILE_ASSERT(reg_map[2] == 1 && reg_map[3] == 2, bad_register_mapping); - - if ((op >= SLJIT_DIV_UW) && (compiler->scratches >= 3)) { - FAIL_IF(push_inst(compiler, 0xe52d2008 /* str r2, [sp, #-8]! */)); - FAIL_IF(push_inst(compiler, 0xe58d1004 /* str r1, [sp, #4] */)); + SLJIT_ASSERT(reg_map[2] == 1 && reg_map[3] == 2 && reg_map[4] == 3); + + saved_reg_count = 0; + if (compiler->scratches >= 4) + saved_reg_list[saved_reg_count++] = 3; + if (compiler->scratches >= 3) + saved_reg_list[saved_reg_count++] = 2; + if (op >= SLJIT_DIV_UW) + saved_reg_list[saved_reg_count++] = 1; + + if (saved_reg_count > 0) { + FAIL_IF(push_inst(compiler, 0xe52d0000 | (saved_reg_count >= 3 ? 16 : 8) + | (saved_reg_list[0] << 12) /* str rX, [sp, #-8/-16]! */)); + if (saved_reg_count >= 2) { + SLJIT_ASSERT(saved_reg_list[1] < 8); + FAIL_IF(push_inst(compiler, 0xe58d0004 | (saved_reg_list[1] << 12) /* str rX, [sp, #4] */)); + } + if (saved_reg_count >= 3) { + SLJIT_ASSERT(saved_reg_list[2] < 8); + FAIL_IF(push_inst(compiler, 0xe58d0008 | (saved_reg_list[2] << 12) /* str rX, [sp, #8] */)); + } } - else if ((op >= SLJIT_DIV_UW) || (compiler->scratches >= 3)) - FAIL_IF(push_inst(compiler, 0xe52d0008 | (op >= SLJIT_DIV_UW ? 0x1000 : 0x2000) /* str r1/r2, [sp, #-8]! */)); #if defined(__GNUC__) FAIL_IF(sljit_emit_ijump(compiler, SLJIT_FAST_CALL, SLJIT_IMM, @@ -1871,12 +1632,18 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compile #error "Software divmod functions are needed" #endif - if ((op >= SLJIT_DIV_UW) && (compiler->scratches >= 3)) { - FAIL_IF(push_inst(compiler, 0xe59d1004 /* ldr r1, [sp, #4] */)); - FAIL_IF(push_inst(compiler, 0xe49d2008 /* ldr r2, [sp], #8 */)); + if (saved_reg_count > 0) { + if (saved_reg_count >= 3) { + SLJIT_ASSERT(saved_reg_list[2] < 8); + FAIL_IF(push_inst(compiler, 0xe59d0008 | (saved_reg_list[2] << 12) /* ldr rX, [sp, #8] */)); + } + if (saved_reg_count >= 2) { + SLJIT_ASSERT(saved_reg_list[1] < 8); + FAIL_IF(push_inst(compiler, 0xe59d0004 | (saved_reg_list[1] << 12) /* ldr rX, [sp, #4] */)); + } + return push_inst(compiler, 0xe49d0000 | (saved_reg_count >= 3 ? 16 : 8) + | (saved_reg_list[0] << 12) /* ldr rX, [sp], #8/16 */); } - else if ((op >= SLJIT_DIV_UW) || (compiler->scratches >= 3)) - return push_inst(compiler, 0xe49d0008 | (op >= SLJIT_DIV_UW ? 0x1000 : 0x2000) /* ldr r1/r2, [sp], #8 */); return SLJIT_SUCCESS; } @@ -1892,6 +1659,14 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile ADJUST_LOCAL_OFFSET(dst, dstw); ADJUST_LOCAL_OFFSET(src, srcw); + if (dst == SLJIT_UNUSED && !HAS_FLAGS(op)) { +#if (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7) + if (op <= SLJIT_MOV_P && (src & SLJIT_MEM)) + return emit_op_mem(compiler, PRELOAD | LOAD_DATA, TMP_PC, src, srcw, TMP_REG1); +#endif + return SLJIT_SUCCESS; + } + switch (GET_OPCODE(op)) { case SLJIT_MOV: case SLJIT_MOV_U32: @@ -1900,34 +1675,16 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile return emit_op(compiler, SLJIT_MOV, ALLOW_ANY_IMM, dst, dstw, TMP_REG1, 0, src, srcw); case SLJIT_MOV_U8: - return emit_op(compiler, SLJIT_MOV_U8, ALLOW_ANY_IMM | BYTE_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_u8)srcw : srcw); + return emit_op(compiler, SLJIT_MOV_U8, ALLOW_ANY_IMM | BYTE_SIZE, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_u8)srcw : srcw); case SLJIT_MOV_S8: - return emit_op(compiler, SLJIT_MOV_S8, ALLOW_ANY_IMM | SIGNED_DATA | BYTE_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_s8)srcw : srcw); + return emit_op(compiler, SLJIT_MOV_S8, ALLOW_ANY_IMM | SIGNED | BYTE_SIZE, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_s8)srcw : srcw); case SLJIT_MOV_U16: - return emit_op(compiler, SLJIT_MOV_U16, ALLOW_ANY_IMM | HALF_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_u16)srcw : srcw); + return emit_op(compiler, SLJIT_MOV_U16, ALLOW_ANY_IMM | HALF_SIZE, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_u16)srcw : srcw); case SLJIT_MOV_S16: - return emit_op(compiler, SLJIT_MOV_S16, ALLOW_ANY_IMM | SIGNED_DATA | HALF_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_s16)srcw : srcw); - - case SLJIT_MOVU: - case SLJIT_MOVU_U32: - case SLJIT_MOVU_S32: - case SLJIT_MOVU_P: - return emit_op(compiler, SLJIT_MOV, ALLOW_ANY_IMM | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, srcw); - - case SLJIT_MOVU_U8: - return emit_op(compiler, SLJIT_MOV_U8, ALLOW_ANY_IMM | BYTE_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_u8)srcw : srcw); - - case SLJIT_MOVU_S8: - return emit_op(compiler, SLJIT_MOV_S8, ALLOW_ANY_IMM | SIGNED_DATA | BYTE_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_s8)srcw : srcw); - - case SLJIT_MOVU_U16: - return emit_op(compiler, SLJIT_MOV_U16, ALLOW_ANY_IMM | HALF_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_u16)srcw : srcw); - - case SLJIT_MOVU_S16: - return emit_op(compiler, SLJIT_MOV_S16, ALLOW_ANY_IMM | SIGNED_DATA | HALF_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_s16)srcw : srcw); + return emit_op(compiler, SLJIT_MOV_S16, ALLOW_ANY_IMM | SIGNED | HALF_SIZE, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_s16)srcw : srcw); case SLJIT_NOT: return emit_op(compiler, op, ALLOW_ANY_IMM, dst, dstw, TMP_REG1, 0, src, srcw); @@ -1957,6 +1714,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile ADJUST_LOCAL_OFFSET(src1, src1w); ADJUST_LOCAL_OFFSET(src2, src2w); + if (dst == SLJIT_UNUSED && !HAS_FLAGS(op)) + return SLJIT_SUCCESS; + switch (GET_OPCODE(op)) { case SLJIT_ADD: case SLJIT_ADDC: @@ -1997,7 +1757,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 reg) SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_float_register_index(sljit_s32 reg) { CHECK_REG_INDEX(check_sljit_get_float_register_index(reg)); - return reg << 1; + return (freg_map[reg] << 1); } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *compiler, @@ -2013,118 +1773,63 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *c /* Floating point operators */ /* --------------------------------------------------------------------- */ -#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) - -/* 0 - no fpu - 1 - vfp */ -static sljit_s32 arm_fpu_type = -1; - -static void init_compiler(void) -{ - if (arm_fpu_type != -1) - return; - - /* TODO: Only the OS can help to determine the correct fpu type. */ - arm_fpu_type = 1; -} - -SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_is_fpu_available(void) -{ -#ifdef SLJIT_IS_FPU_AVAILABLE - return SLJIT_IS_FPU_AVAILABLE; -#else - if (arm_fpu_type == -1) - init_compiler(); - return arm_fpu_type; -#endif -} - -#else - -#define arm_fpu_type 1 - -SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_is_fpu_available(void) -{ - /* Always available. */ - return 1; -} - -#endif #define FPU_LOAD (1 << 20) #define EMIT_FPU_DATA_TRANSFER(inst, add, base, freg, offs) \ - ((inst) | ((add) << 23) | (reg_map[base] << 16) | (freg << 12) | (offs)) + ((inst) | ((add) << 23) | (reg_map[base] << 16) | (freg_map[freg] << 12) | (offs)) #define EMIT_FPU_OPERATION(opcode, mode, dst, src1, src2) \ - ((opcode) | (mode) | ((dst) << 12) | (src1) | ((src2) << 16)) + ((opcode) | (mode) | (freg_map[dst] << 12) | freg_map[src1] | (freg_map[src2] << 16)) static sljit_s32 emit_fop_mem(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 arg, sljit_sw argw) { - sljit_sw tmp; sljit_uw imm; sljit_sw inst = VSTR_F32 | (flags & (SLJIT_F32_OP | FPU_LOAD)); + SLJIT_ASSERT(arg & SLJIT_MEM); + arg &= ~SLJIT_MEM; if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) { - FAIL_IF(push_inst(compiler, EMIT_DATA_PROCESS_INS(ADD_DP, 0, TMP_REG1, arg & REG_MASK, RM(OFFS_REG(arg)) | ((argw & 0x3) << 7)))); - arg = SLJIT_MEM | TMP_REG1; + FAIL_IF(push_inst(compiler, ADD | RD(TMP_REG2) | RN(arg & REG_MASK) | RM(OFFS_REG(arg)) | ((argw & 0x3) << 7))); + arg = TMP_REG2; argw = 0; } /* Fast loads and stores. */ - if ((arg & REG_MASK)) { + if (arg) { if (!(argw & ~0x3fc)) return push_inst(compiler, EMIT_FPU_DATA_TRANSFER(inst, 1, arg & REG_MASK, reg, argw >> 2)); if (!(-argw & ~0x3fc)) return push_inst(compiler, EMIT_FPU_DATA_TRANSFER(inst, 0, arg & REG_MASK, reg, (-argw) >> 2)); - } - - if (compiler->cache_arg == arg) { - tmp = argw - compiler->cache_argw; - if (!(tmp & ~0x3fc)) - return push_inst(compiler, EMIT_FPU_DATA_TRANSFER(inst, 1, TMP_REG3, reg, tmp >> 2)); - if (!(-tmp & ~0x3fc)) - return push_inst(compiler, EMIT_FPU_DATA_TRANSFER(inst, 0, TMP_REG3, reg, -tmp >> 2)); - if (emit_set_delta(compiler, TMP_REG3, TMP_REG3, tmp) != SLJIT_ERR_UNSUPPORTED) { - FAIL_IF(compiler->error); - compiler->cache_argw = argw; - return push_inst(compiler, EMIT_FPU_DATA_TRANSFER(inst, 1, TMP_REG3, reg, 0)); - } - } - if (arg & REG_MASK) { - if (emit_set_delta(compiler, TMP_REG1, arg & REG_MASK, argw) != SLJIT_ERR_UNSUPPORTED) { - FAIL_IF(compiler->error); - return push_inst(compiler, EMIT_FPU_DATA_TRANSFER(inst, 1, TMP_REG1, reg, 0)); - } imm = get_imm(argw & ~0x3fc); if (imm) { - FAIL_IF(push_inst(compiler, EMIT_DATA_PROCESS_INS(ADD_DP, 0, TMP_REG1, arg & REG_MASK, imm))); - return push_inst(compiler, EMIT_FPU_DATA_TRANSFER(inst, 1, TMP_REG1, reg, (argw & 0x3fc) >> 2)); + FAIL_IF(push_inst(compiler, ADD | RD(TMP_REG2) | RN(arg & REG_MASK) | imm)); + return push_inst(compiler, EMIT_FPU_DATA_TRANSFER(inst, 1, TMP_REG2, reg, (argw & 0x3fc) >> 2)); } imm = get_imm(-argw & ~0x3fc); if (imm) { argw = -argw; - FAIL_IF(push_inst(compiler, EMIT_DATA_PROCESS_INS(SUB_DP, 0, TMP_REG1, arg & REG_MASK, imm))); - return push_inst(compiler, EMIT_FPU_DATA_TRANSFER(inst, 0, TMP_REG1, reg, (argw & 0x3fc) >> 2)); + FAIL_IF(push_inst(compiler, SUB | RD(TMP_REG2) | RN(arg & REG_MASK) | imm)); + return push_inst(compiler, EMIT_FPU_DATA_TRANSFER(inst, 0, TMP_REG2, reg, (argw & 0x3fc) >> 2)); } } - compiler->cache_arg = arg; - compiler->cache_argw = argw; - if (arg & REG_MASK) { - FAIL_IF(load_immediate(compiler, TMP_REG1, argw)); - FAIL_IF(push_inst(compiler, EMIT_DATA_PROCESS_INS(ADD_DP, 0, TMP_REG3, arg & REG_MASK, reg_map[TMP_REG1]))); + if (arg) { + FAIL_IF(load_immediate(compiler, TMP_REG2, argw)); + FAIL_IF(push_inst(compiler, ADD | RD(TMP_REG2) | RN(arg & REG_MASK) | RM(TMP_REG2))); } else - FAIL_IF(load_immediate(compiler, TMP_REG3, argw)); + FAIL_IF(load_immediate(compiler, TMP_REG2, argw)); - return push_inst(compiler, EMIT_FPU_DATA_TRANSFER(inst, 1, TMP_REG3, reg, 0)); + return push_inst(compiler, EMIT_FPU_DATA_TRANSFER(inst, 1, TMP_REG2, reg, 0)); } static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_sw_from_f64(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw dstw, sljit_s32 src, sljit_sw srcw) { + op ^= SLJIT_F32_OP; + if (src & SLJIT_MEM) { FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_F32_OP) | FPU_LOAD, TMP_FREG1, src, srcw)); src = TMP_FREG1; @@ -2132,11 +1837,8 @@ static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_sw_from_f64(struct sljit_comp FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VCVT_S32_F32, op & SLJIT_F32_OP, TMP_FREG1, src, 0))); - if (dst == SLJIT_UNUSED) - return SLJIT_SUCCESS; - if (FAST_IS_REG(dst)) - return push_inst(compiler, VMOV | (1 << 20) | RD(dst) | (TMP_FREG1 << 16)); + return push_inst(compiler, VMOV | (1 << 20) | RD(dst) | (freg_map[TMP_FREG1] << 16)); /* Store the integer value from a VFP register. */ return emit_fop_mem(compiler, 0, TMP_FREG1, dst, dstw); @@ -2148,15 +1850,17 @@ static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_sw(struct sljit_comp { sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1; + op ^= SLJIT_F32_OP; + if (FAST_IS_REG(src)) - FAIL_IF(push_inst(compiler, VMOV | RD(src) | (TMP_FREG1 << 16))); + FAIL_IF(push_inst(compiler, VMOV | RD(src) | (freg_map[TMP_FREG1] << 16))); else if (src & SLJIT_MEM) { /* Load the integer value into a VFP register. */ FAIL_IF(emit_fop_mem(compiler, FPU_LOAD, TMP_FREG1, src, srcw)); } else { FAIL_IF(load_immediate(compiler, TMP_REG1, srcw)); - FAIL_IF(push_inst(compiler, VMOV | RD(TMP_REG1) | (TMP_FREG1 << 16))); + FAIL_IF(push_inst(compiler, VMOV | RD(TMP_REG1) | (freg_map[TMP_FREG1] << 16))); } FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VCVT_F32_S32, op & SLJIT_F32_OP, dst_r, TMP_FREG1, 0))); @@ -2170,6 +1874,8 @@ static SLJIT_INLINE sljit_s32 sljit_emit_fop1_cmp(struct sljit_compiler *compile sljit_s32 src1, sljit_sw src1w, sljit_s32 src2, sljit_sw src2w) { + op ^= SLJIT_F32_OP; + if (src1 & SLJIT_MEM) { FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_F32_OP) | FPU_LOAD, TMP_FREG1, src1, src1w)); src1 = TMP_FREG1; @@ -2191,16 +1897,15 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop1(struct sljit_compiler *compil sljit_s32 dst_r; CHECK_ERROR(); - compiler->cache_arg = 0; - compiler->cache_argw = 0; - if (GET_OPCODE(op) != SLJIT_CONV_F64_FROM_F32) - op ^= SLJIT_F32_OP; SLJIT_COMPILE_ASSERT((SLJIT_F32_OP == 0x100), float_transfer_bit_error); SELECT_FOP1_OPERATION_WITH_CHECKS(compiler, op, dst, dstw, src, srcw); dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1; + if (GET_OPCODE(op) != SLJIT_CONV_F64_FROM_F32) + op ^= SLJIT_F32_OP; + if (src & SLJIT_MEM) { FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_F32_OP) | FPU_LOAD, dst_r, src, srcw)); src = dst_r; @@ -2245,8 +1950,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2(struct sljit_compiler *compil ADJUST_LOCAL_OFFSET(src1, src1w); ADJUST_LOCAL_OFFSET(src2, src2w); - compiler->cache_arg = 0; - compiler->cache_argw = 0; op ^= SLJIT_F32_OP; dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1; @@ -2287,7 +1990,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2(struct sljit_compiler *compil #undef FPU_LOAD #undef EMIT_FPU_DATA_TRANSFER -#undef EMIT_FPU_OPERATION /* --------------------------------------------------------------------- */ /* Other instructions */ @@ -2299,21 +2001,13 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler * CHECK(check_sljit_emit_fast_enter(compiler, dst, dstw)); ADJUST_LOCAL_OFFSET(dst, dstw); - /* For UNUSED dst. Uncommon, but possible. */ - if (dst == SLJIT_UNUSED) - return SLJIT_SUCCESS; + SLJIT_ASSERT(reg_map[TMP_REG2] == 14); if (FAST_IS_REG(dst)) - return push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, 0, dst, SLJIT_UNUSED, RM(TMP_REG3))); + return push_inst(compiler, MOV | RD(dst) | RM(TMP_REG2)); /* Memory. */ - if (getput_arg_fast(compiler, WORD_DATA, TMP_REG3, dst, dstw)) - return compiler->error; - /* TMP_REG3 is used for caching. */ - FAIL_IF(push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, 0, TMP_REG2, SLJIT_UNUSED, RM(TMP_REG3)))); - compiler->cache_arg = 0; - compiler->cache_argw = 0; - return getput_arg(compiler, WORD_DATA, TMP_REG2, dst, dstw, 0, 0); + return emit_op_mem(compiler, WORD_SIZE, TMP_REG2, dst, dstw, TMP_REG1); } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_return(struct sljit_compiler *compiler, sljit_s32 src, sljit_sw srcw) @@ -2322,21 +2016,14 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_return(struct sljit_compiler CHECK(check_sljit_emit_fast_return(compiler, src, srcw)); ADJUST_LOCAL_OFFSET(src, srcw); + SLJIT_ASSERT(reg_map[TMP_REG2] == 14); + if (FAST_IS_REG(src)) - FAIL_IF(push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, 0, TMP_REG3, SLJIT_UNUSED, RM(src)))); - else if (src & SLJIT_MEM) { - if (getput_arg_fast(compiler, WORD_DATA | LOAD_DATA, TMP_REG3, src, srcw)) - FAIL_IF(compiler->error); - else { - compiler->cache_arg = 0; - compiler->cache_argw = 0; - FAIL_IF(getput_arg(compiler, WORD_DATA | LOAD_DATA, TMP_REG2, src, srcw, 0, 0)); - FAIL_IF(push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, 0, TMP_REG3, SLJIT_UNUSED, RM(TMP_REG2)))); - } - } - else if (src & SLJIT_IMM) - FAIL_IF(load_immediate(compiler, TMP_REG3, srcw)); - return push_inst(compiler, BLX | RM(TMP_REG3)); + FAIL_IF(push_inst(compiler, MOV | RD(TMP_REG2) | RM(src))); + else + FAIL_IF(emit_op_mem(compiler, WORD_SIZE | LOAD_DATA, TMP_REG2, src, srcw, TMP_REG1)); + + return push_inst(compiler, BX | RM(TMP_REG2)); } /* --------------------------------------------------------------------- */ @@ -2393,7 +2080,7 @@ static sljit_uw get_cc(sljit_s32 type) return 0x70000000; default: - SLJIT_ASSERT(type >= SLJIT_JUMP && type <= SLJIT_CALL3); + SLJIT_ASSERT(type >= SLJIT_JUMP && type <= SLJIT_CALL_CDECL); return 0xe0000000; } } @@ -2426,11 +2113,12 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compile set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP); type &= 0xff; - /* In ARM, we don't need to touch the arguments. */ + SLJIT_ASSERT(reg_map[TMP_REG1] != 14); + #if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) if (type >= SLJIT_FAST_CALL) PTR_FAIL_IF(prepare_blx(compiler)); - PTR_FAIL_IF(push_inst_with_unique_literal(compiler, ((EMIT_DATA_TRANSFER(WORD_DATA | LOAD_DATA, 1, 0, + PTR_FAIL_IF(push_inst_with_unique_literal(compiler, ((EMIT_DATA_TRANSFER(WORD_SIZE | LOAD_DATA, 1, type <= SLJIT_JUMP ? TMP_PC : TMP_REG1, TMP_PC, 0)) & ~COND_MASK) | get_cc(type), 0)); if (jump->flags & SLJIT_REWRITABLE_JUMP) { @@ -2455,6 +2143,241 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compile return jump; } +#ifdef __SOFTFP__ + +static sljit_s32 softfloat_call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_types, sljit_s32 *src) +{ + sljit_s32 stack_offset = 0; + sljit_s32 arg_count = 0; + sljit_s32 word_arg_offset = 0; + sljit_s32 float_arg_count = 0; + sljit_s32 types = 0; + sljit_s32 src_offset = 4 * sizeof(sljit_sw); + sljit_u8 offsets[4]; + + if (src && FAST_IS_REG(*src)) + src_offset = reg_map[*src] * sizeof(sljit_sw); + + arg_types >>= SLJIT_DEF_SHIFT; + + while (arg_types) { + types = (types << SLJIT_DEF_SHIFT) | (arg_types & SLJIT_DEF_MASK); + + switch (arg_types & SLJIT_DEF_MASK) { + case SLJIT_ARG_TYPE_F32: + offsets[arg_count] = (sljit_u8)stack_offset; + stack_offset += sizeof(sljit_f32); + arg_count++; + float_arg_count++; + break; + case SLJIT_ARG_TYPE_F64: + if (stack_offset & 0x7) + stack_offset += sizeof(sljit_sw); + offsets[arg_count] = (sljit_u8)stack_offset; + stack_offset += sizeof(sljit_f64); + arg_count++; + float_arg_count++; + break; + default: + offsets[arg_count] = (sljit_u8)stack_offset; + stack_offset += sizeof(sljit_sw); + arg_count++; + word_arg_offset += sizeof(sljit_sw); + break; + } + + arg_types >>= SLJIT_DEF_SHIFT; + } + + if (stack_offset > 16) + FAIL_IF(push_inst(compiler, SUB | RD(SLJIT_SP) | RN(SLJIT_SP) | SRC2_IMM | (((stack_offset - 16) + 0x7) & ~0x7))); + + /* Process arguments in reversed direction. */ + while (types) { + switch (types & SLJIT_DEF_MASK) { + case SLJIT_ARG_TYPE_F32: + arg_count--; + float_arg_count--; + stack_offset = offsets[arg_count]; + + if (stack_offset < 16) { + if (src_offset == stack_offset) { + FAIL_IF(push_inst(compiler, MOV | RD(TMP_REG1) | (src_offset >> 2))); + *src = TMP_REG1; + } + FAIL_IF(push_inst(compiler, VMOV | 0x100000 | (float_arg_count << 16) | (stack_offset << 10))); + } else + FAIL_IF(push_inst(compiler, VSTR_F32 | 0x800000 | RN(SLJIT_SP) | (float_arg_count << 12) | ((stack_offset - 16) >> 2))); + break; + case SLJIT_ARG_TYPE_F64: + arg_count--; + float_arg_count--; + stack_offset = offsets[arg_count]; + + SLJIT_ASSERT((stack_offset & 0x7) == 0); + + if (stack_offset < 16) { + if (src_offset == stack_offset || src_offset == stack_offset + sizeof(sljit_sw)) { + FAIL_IF(push_inst(compiler, MOV | RD(TMP_REG1) | (src_offset >> 2))); + *src = TMP_REG1; + } + FAIL_IF(push_inst(compiler, VMOV2 | 0x100000 | (stack_offset << 10) | ((stack_offset + sizeof(sljit_sw)) << 14) | float_arg_count)); + } else + FAIL_IF(push_inst(compiler, VSTR_F32 | 0x800100 | RN(SLJIT_SP) | (float_arg_count << 12) | ((stack_offset - 16) >> 2))); + break; + default: + arg_count--; + word_arg_offset -= sizeof(sljit_sw); + stack_offset = offsets[arg_count]; + + SLJIT_ASSERT(stack_offset >= word_arg_offset); + + if (stack_offset != word_arg_offset) { + if (stack_offset < 16) { + if (src_offset == stack_offset) { + FAIL_IF(push_inst(compiler, MOV | RD(TMP_REG1) | (src_offset >> 2))); + *src = TMP_REG1; + } + else if (src_offset == word_arg_offset) { + *src = 1 + (stack_offset >> 2); + src_offset = stack_offset; + } + FAIL_IF(push_inst(compiler, MOV | (stack_offset << 10) | (word_arg_offset >> 2))); + } else + FAIL_IF(push_inst(compiler, data_transfer_insts[WORD_SIZE] | 0x800000 | RN(SLJIT_SP) | (word_arg_offset << 10) | (stack_offset - 16))); + } + break; + } + + types >>= SLJIT_DEF_SHIFT; + } + + return SLJIT_SUCCESS; +} + +static sljit_s32 softfloat_post_call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_types) +{ + sljit_s32 stack_size = 0; + + if ((arg_types & SLJIT_DEF_MASK) == SLJIT_ARG_TYPE_F32) + FAIL_IF(push_inst(compiler, VMOV | (0 << 16) | (0 << 12))); + if ((arg_types & SLJIT_DEF_MASK) == SLJIT_ARG_TYPE_F64) + FAIL_IF(push_inst(compiler, VMOV2 | (1 << 16) | (0 << 12) | 0)); + + arg_types >>= SLJIT_DEF_SHIFT; + + while (arg_types) { + switch (arg_types & SLJIT_DEF_MASK) { + case SLJIT_ARG_TYPE_F32: + stack_size += sizeof(sljit_f32); + break; + case SLJIT_ARG_TYPE_F64: + if (stack_size & 0x7) + stack_size += sizeof(sljit_sw); + stack_size += sizeof(sljit_f64); + break; + default: + stack_size += sizeof(sljit_sw); + break; + } + + arg_types >>= SLJIT_DEF_SHIFT; + } + + if (stack_size <= 16) + return SLJIT_SUCCESS; + + return push_inst(compiler, ADD | RD(SLJIT_SP) | RN(SLJIT_SP) | SRC2_IMM | (((stack_size - 16) + 0x7) & ~0x7)); +} + +#else /* !__SOFTFP__ */ + +static sljit_s32 hardfloat_call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_types) +{ + sljit_u32 remap = 0; + sljit_u32 offset = 0; + sljit_u32 new_offset, mask; + + /* Remove return value. */ + arg_types >>= SLJIT_DEF_SHIFT; + + while (arg_types) { + if ((arg_types & SLJIT_DEF_MASK) == SLJIT_ARG_TYPE_F32) { + new_offset = 0; + mask = 1; + + while (remap & mask) { + new_offset++; + mask <<= 1; + } + remap |= mask; + + if (offset != new_offset) + FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VMOV_F32, + 0, (new_offset >> 1) + 1, (offset >> 1) + 1, 0) | ((new_offset & 0x1) ? 0x400000 : 0))); + + offset += 2; + } + else if ((arg_types & SLJIT_DEF_MASK) == SLJIT_ARG_TYPE_F64) { + new_offset = 0; + mask = 3; + + while (remap & mask) { + new_offset += 2; + mask <<= 2; + } + remap |= mask; + + if (offset != new_offset) + FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VMOV_F32, SLJIT_F32_OP, (new_offset >> 1) + 1, (offset >> 1) + 1, 0))); + + offset += 2; + } + arg_types >>= SLJIT_DEF_SHIFT; + } + + return SLJIT_SUCCESS; +} + +#endif /* __SOFTFP__ */ + +#undef EMIT_FPU_OPERATION + +SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 arg_types) +{ +#ifdef __SOFTFP__ + struct sljit_jump *jump; +#endif + + CHECK_ERROR_PTR(); + CHECK_PTR(check_sljit_emit_call(compiler, type, arg_types)); + +#ifdef __SOFTFP__ + PTR_FAIL_IF(softfloat_call_with_args(compiler, arg_types, NULL)); + +#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \ + || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) + compiler->skip_checks = 1; +#endif + + jump = sljit_emit_jump(compiler, type); + PTR_FAIL_IF(jump == NULL); + + PTR_FAIL_IF(softfloat_post_call_with_args(compiler, arg_types)); + return jump; +#else /* !__SOFTFP__ */ + PTR_FAIL_IF(hardfloat_call_with_args(compiler, arg_types)); + +#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \ + || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) + compiler->skip_checks = 1; +#endif + + return sljit_emit_jump(compiler, type); +#endif /* __SOFTFP__ */ +} + SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 src, sljit_sw srcw) { struct sljit_jump *jump; @@ -2463,16 +2386,20 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compi CHECK(check_sljit_emit_ijump(compiler, type, src, srcw)); ADJUST_LOCAL_OFFSET(src, srcw); - /* In ARM, we don't need to touch the arguments. */ + SLJIT_ASSERT(reg_map[TMP_REG1] != 14); + if (!(src & SLJIT_IMM)) { - if (FAST_IS_REG(src)) + if (FAST_IS_REG(src)) { + SLJIT_ASSERT(reg_map[src] != 14); return push_inst(compiler, (type <= SLJIT_JUMP ? BX : BLX) | RM(src)); + } SLJIT_ASSERT(src & SLJIT_MEM); - FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, TMP_REG2, src, srcw)); - return push_inst(compiler, (type <= SLJIT_JUMP ? BX : BLX) | RM(TMP_REG2)); + FAIL_IF(emit_op_mem(compiler, WORD_SIZE | LOAD_DATA, TMP_REG1, src, srcw, TMP_REG1)); + return push_inst(compiler, (type <= SLJIT_JUMP ? BX : BLX) | RM(TMP_REG1)); } + /* These jumps are converted to jump/call instructions when possible. */ jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump)); FAIL_IF(!jump); set_jump(jump, compiler, JUMP_ADDR | ((type >= SLJIT_FAST_CALL) ? IS_BL : 0)); @@ -2481,7 +2408,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compi #if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) if (type >= SLJIT_FAST_CALL) FAIL_IF(prepare_blx(compiler)); - FAIL_IF(push_inst_with_unique_literal(compiler, EMIT_DATA_TRANSFER(WORD_DATA | LOAD_DATA, 1, 0, type <= SLJIT_JUMP ? TMP_PC : TMP_REG1, TMP_PC, 0), 0)); + FAIL_IF(push_inst_with_unique_literal(compiler, EMIT_DATA_TRANSFER(WORD_SIZE | LOAD_DATA, 1, type <= SLJIT_JUMP ? TMP_PC : TMP_REG1, TMP_PC, 0), 0)); if (type >= SLJIT_FAST_CALL) FAIL_IF(emit_blx(compiler)); #else @@ -2492,57 +2419,221 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compi return SLJIT_SUCCESS; } +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 arg_types, + sljit_s32 src, sljit_sw srcw) +{ + CHECK_ERROR(); + CHECK(check_sljit_emit_icall(compiler, type, arg_types, src, srcw)); + +#ifdef __SOFTFP__ + if (src & SLJIT_MEM) { + FAIL_IF(emit_op_mem(compiler, WORD_SIZE | LOAD_DATA, TMP_REG1, src, srcw, TMP_REG1)); + src = TMP_REG1; + } + + FAIL_IF(softfloat_call_with_args(compiler, arg_types, &src)); + +#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \ + || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) + compiler->skip_checks = 1; +#endif + + FAIL_IF(sljit_emit_ijump(compiler, type, src, srcw)); + + return softfloat_post_call_with_args(compiler, arg_types); +#else /* !__SOFTFP__ */ + FAIL_IF(hardfloat_call_with_args(compiler, arg_types)); + +#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \ + || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) + compiler->skip_checks = 1; +#endif + + return sljit_emit_ijump(compiler, type, src, srcw); +#endif /* __SOFTFP__ */ +} + SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw dstw, - sljit_s32 src, sljit_sw srcw, sljit_s32 type) { - sljit_s32 dst_r, flags = GET_ALL_FLAGS(op); + sljit_s32 dst_reg, flags = GET_ALL_FLAGS(op); sljit_uw cc, ins; CHECK_ERROR(); - CHECK(check_sljit_emit_op_flags(compiler, op, dst, dstw, src, srcw, type)); + CHECK(check_sljit_emit_op_flags(compiler, op, dst, dstw, type)); ADJUST_LOCAL_OFFSET(dst, dstw); - ADJUST_LOCAL_OFFSET(src, srcw); - - if (dst == SLJIT_UNUSED) - return SLJIT_SUCCESS; op = GET_OPCODE(op); cc = get_cc(type & 0xff); - dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2; + dst_reg = FAST_IS_REG(dst) ? dst : TMP_REG1; if (op < SLJIT_ADD) { - FAIL_IF(push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, 0, dst_r, SLJIT_UNUSED, SRC2_IMM | 0))); - FAIL_IF(push_inst(compiler, (EMIT_DATA_PROCESS_INS(MOV_DP, 0, dst_r, SLJIT_UNUSED, SRC2_IMM | 1) & ~COND_MASK) | cc)); - return (dst_r == TMP_REG2) ? emit_op_mem(compiler, WORD_DATA, TMP_REG2, dst, dstw) : SLJIT_SUCCESS; + FAIL_IF(push_inst(compiler, MOV | RD(dst_reg) | SRC2_IMM | 0)); + FAIL_IF(push_inst(compiler, ((MOV | RD(dst_reg) | SRC2_IMM | 1) & ~COND_MASK) | cc)); + if (dst & SLJIT_MEM) + return emit_op_mem(compiler, WORD_SIZE, TMP_REG1, dst, dstw, TMP_REG2); + return SLJIT_SUCCESS; } - ins = (op == SLJIT_AND ? AND_DP : (op == SLJIT_OR ? ORR_DP : EOR_DP)); - if ((op == SLJIT_OR || op == SLJIT_XOR) && FAST_IS_REG(dst) && dst == src) { - FAIL_IF(push_inst(compiler, (EMIT_DATA_PROCESS_INS(ins, 0, dst, dst, SRC2_IMM | 1) & ~COND_MASK) | cc)); - /* The condition must always be set, even if the ORR/EOR is not executed above. */ - return (flags & SLJIT_SET_E) ? push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, SET_FLAGS, TMP_REG1, SLJIT_UNUSED, RM(dst))) : SLJIT_SUCCESS; - } + ins = (op == SLJIT_AND ? AND : (op == SLJIT_OR ? ORR : EOR)); - compiler->cache_arg = 0; - compiler->cache_argw = 0; - if (src & SLJIT_MEM) { - FAIL_IF(emit_op_mem2(compiler, WORD_DATA | LOAD_DATA, TMP_REG1, src, srcw, dst, dstw)); - src = TMP_REG1; - srcw = 0; - } else if (src & SLJIT_IMM) { + if (dst & SLJIT_MEM) + FAIL_IF(emit_op_mem(compiler, WORD_SIZE | LOAD_DATA, TMP_REG1, dst, dstw, TMP_REG2)); + + FAIL_IF(push_inst(compiler, ((ins | RD(dst_reg) | RN(dst_reg) | SRC2_IMM | 1) & ~COND_MASK) | cc)); + + if (op == SLJIT_AND) + FAIL_IF(push_inst(compiler, ((ins | RD(dst_reg) | RN(dst_reg) | SRC2_IMM | 0) & ~COND_MASK) | (cc ^ 0x10000000))); + + if (dst & SLJIT_MEM) + FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG1, dst, dstw, TMP_REG2)); + + if (flags & SLJIT_SET_Z) + return push_inst(compiler, MOV | SET_FLAGS | RD(TMP_REG2) | RM(dst_reg)); + return SLJIT_SUCCESS; +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 dst_reg, + sljit_s32 src, sljit_sw srcw) +{ + sljit_uw cc, tmp; + + CHECK_ERROR(); + CHECK(check_sljit_emit_cmov(compiler, type, dst_reg, src, srcw)); + + dst_reg &= ~SLJIT_I32_OP; + + cc = get_cc(type & 0xff); + + if (SLJIT_UNLIKELY(src & SLJIT_IMM)) { + tmp = get_imm(srcw); + if (tmp) + return push_inst(compiler, ((MOV | RD(dst_reg) | tmp) & ~COND_MASK) | cc); + + tmp = get_imm(~srcw); + if (tmp) + return push_inst(compiler, ((MVN | RD(dst_reg) | tmp) & ~COND_MASK) | cc); + +#if (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7) + tmp = (sljit_uw) srcw; + FAIL_IF(push_inst(compiler, (MOVW & ~COND_MASK) | cc | RD(dst_reg) | ((tmp << 4) & 0xf0000) | (tmp & 0xfff))); + if (tmp <= 0xffff) + return SLJIT_SUCCESS; + return push_inst(compiler, (MOVT & ~COND_MASK) | cc | RD(dst_reg) | ((tmp >> 12) & 0xf0000) | ((tmp >> 16) & 0xfff)); +#else FAIL_IF(load_immediate(compiler, TMP_REG1, srcw)); src = TMP_REG1; - srcw = 0; +#endif } - FAIL_IF(push_inst(compiler, (EMIT_DATA_PROCESS_INS(ins, 0, dst_r, src, SRC2_IMM | 1) & ~COND_MASK) | cc)); - FAIL_IF(push_inst(compiler, (EMIT_DATA_PROCESS_INS(ins, 0, dst_r, src, SRC2_IMM | 0) & ~COND_MASK) | (cc ^ 0x10000000))); - if (dst_r == TMP_REG2) - FAIL_IF(emit_op_mem2(compiler, WORD_DATA, TMP_REG2, dst, dstw, 0, 0)); + return push_inst(compiler, ((MOV | RD(dst_reg) | RM(src)) & ~COND_MASK) | cc); +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 reg, + sljit_s32 mem, sljit_sw memw) +{ + sljit_s32 flags; + sljit_uw is_type1_transfer, inst; + + CHECK_ERROR(); + CHECK(check_sljit_emit_mem(compiler, type, reg, mem, memw)); + + is_type1_transfer = 1; + + switch (type & 0xff) { + case SLJIT_MOV: + case SLJIT_MOV_U32: + case SLJIT_MOV_S32: + case SLJIT_MOV_P: + flags = WORD_SIZE; + break; + case SLJIT_MOV_U8: + flags = BYTE_SIZE; + break; + case SLJIT_MOV_S8: + if (!(type & SLJIT_MEM_STORE)) + is_type1_transfer = 0; + flags = BYTE_SIZE | SIGNED; + break; + case SLJIT_MOV_U16: + is_type1_transfer = 0; + flags = HALF_SIZE; + break; + case SLJIT_MOV_S16: + is_type1_transfer = 0; + flags = HALF_SIZE | SIGNED; + break; + default: + SLJIT_UNREACHABLE(); + flags = WORD_SIZE; + break; + } + + if (!(type & SLJIT_MEM_STORE)) + flags |= LOAD_DATA; + + SLJIT_ASSERT(is_type1_transfer == !!IS_TYPE1_TRANSFER(flags)); + + if (SLJIT_UNLIKELY(mem & OFFS_REG_MASK)) { + if (!is_type1_transfer && memw != 0) + return SLJIT_ERR_UNSUPPORTED; + } + else { + if (is_type1_transfer) { + if (memw > 4095 && memw < -4095) + return SLJIT_ERR_UNSUPPORTED; + } + else { + if (memw > 255 && memw < -255) + return SLJIT_ERR_UNSUPPORTED; + } + } + + if (type & SLJIT_MEM_SUPP) + return SLJIT_SUCCESS; + + if (SLJIT_UNLIKELY(mem & OFFS_REG_MASK)) { + memw &= 0x3; + + inst = EMIT_DATA_TRANSFER(flags, 1, reg, mem & REG_MASK, RM(OFFS_REG(mem)) | (memw << 7)); + + if (is_type1_transfer) + inst |= (1 << 25); + + if (type & SLJIT_MEM_PRE) + inst |= (1 << 21); + else + inst ^= (1 << 24); + + return push_inst(compiler, inst); + } + + inst = EMIT_DATA_TRANSFER(flags, 0, reg, mem & REG_MASK, 0); + + if (type & SLJIT_MEM_PRE) + inst |= (1 << 21); + else + inst ^= (1 << 24); + + if (is_type1_transfer) { + if (memw >= 0) + inst |= (1 << 23); + else + memw = -memw; + + return push_inst(compiler, inst | memw); + } + + if (memw >= 0) + inst |= (1 << 23); + else + memw = -memw; - return (flags & SLJIT_SET_E) ? push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, SET_FLAGS, TMP_REG1, SLJIT_UNUSED, RM(dst_r))) : SLJIT_SUCCESS; + return push_inst(compiler, inst | TYPE2_TRANSFER_IMM(memw)); } SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw init_value) @@ -2560,7 +2651,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compi reg = SLOW_IS_REG(dst) ? dst : TMP_REG2; #if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) - PTR_FAIL_IF(push_inst_with_unique_literal(compiler, EMIT_DATA_TRANSFER(WORD_DATA | LOAD_DATA, 1, 0, reg, TMP_PC, 0), init_value)); + PTR_FAIL_IF(push_inst_with_unique_literal(compiler, EMIT_DATA_TRANSFER(WORD_SIZE | LOAD_DATA, 1, reg, TMP_PC, 0), init_value)); compiler->patches++; #else PTR_FAIL_IF(emit_imm(compiler, reg, init_value)); @@ -2568,7 +2659,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compi set_const(const_, compiler); if (dst & SLJIT_MEM) - PTR_FAIL_IF(emit_op_mem(compiler, WORD_DATA, TMP_REG2, dst, dstw)); + PTR_FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG2, dst, dstw, TMP_REG1)); return const_; } diff --git a/thirdparty/pcre2/src/sljit/sljitNativeARM_64.c b/thirdparty/pcre2/src/sljit/sljitNativeARM_64.c index 2062d80b0a..8a437bd6a0 100644 --- a/thirdparty/pcre2/src/sljit/sljitNativeARM_64.c +++ b/thirdparty/pcre2/src/sljit/sljitNativeARM_64.c @@ -1,7 +1,7 @@ /* * Stack-less Just-In-Time compiler * - * Copyright 2009-2012 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved. + * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are * permitted provided that the following conditions are met: @@ -36,15 +36,19 @@ typedef sljit_u32 sljit_ins; #define TMP_REG1 (SLJIT_NUMBER_OF_REGISTERS + 2) #define TMP_REG2 (SLJIT_NUMBER_OF_REGISTERS + 3) -#define TMP_REG3 (SLJIT_NUMBER_OF_REGISTERS + 4) -#define TMP_LR (SLJIT_NUMBER_OF_REGISTERS + 5) -#define TMP_SP (SLJIT_NUMBER_OF_REGISTERS + 6) +#define TMP_LR (SLJIT_NUMBER_OF_REGISTERS + 4) +#define TMP_SP (SLJIT_NUMBER_OF_REGISTERS + 5) -#define TMP_FREG1 (0) -#define TMP_FREG2 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1) +#define TMP_FREG1 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1) +#define TMP_FREG2 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 2) +/* r18 - platform register, currently not used */ static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 8] = { - 31, 0, 1, 2, 3, 4, 5, 6, 7, 12, 13, 14, 15, 16, 17, 8, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 29, 9, 10, 11, 30, 31 + 31, 0, 1, 2, 3, 4, 5, 6, 7, 11, 12, 13, 14, 15, 16, 17, 8, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 29, 9, 10, 30, 31 +}; + +static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3] = { + 0, 0, 1, 2, 3, 4, 5, 6, 7 }; #define W_OP (1 << 31) @@ -53,10 +57,10 @@ static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 8] = { #define RN(rn) (reg_map[rn] << 5) #define RT2(rt2) (reg_map[rt2] << 10) #define RM(rm) (reg_map[rm] << 16) -#define VD(vd) (vd) -#define VT(vt) (vt) -#define VN(vn) ((vn) << 5) -#define VM(vm) ((vm) << 16) +#define VD(vd) (freg_map[vd]) +#define VT(vt) (freg_map[vt]) +#define VN(vn) (freg_map[vn] << 5) +#define VM(vm) (freg_map[vm] << 16) /* --------------------------------------------------------------------- */ /* Instrucion forms */ @@ -76,6 +80,7 @@ static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 8] = { #define BRK 0xd4200000 #define CBZ 0xb4000000 #define CLZ 0xdac01000 +#define CSEL 0x9a800000 #define CSINC 0x9a800400 #define EOR 0xca000000 #define EORI 0xd2000000 @@ -111,10 +116,13 @@ static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 8] = { #define SMULH 0x9b403c00 #define STP 0xa9000000 #define STP_PRE 0xa9800000 +#define STRB 0x38206800 +#define STRBI 0x39000000 #define STRI 0xf9000000 #define STR_FI 0x3d000000 #define STR_FR 0x3c206800 #define STUR_FI 0x3c000000 +#define STURBI 0x38000000 #define SUB 0xcb000000 #define SUBI 0xd1000000 #define SUBS 0xeb000000 @@ -192,6 +200,7 @@ static SLJIT_INLINE sljit_s32 detect_jump_type(struct sljit_jump *jump, sljit_in code_ptr[-2] = code_ptr[0]; return 2; } + if (target_addr <= 0xffffffffffffl) { if (jump->flags & IS_COND) code_ptr[-5] -= (1 << 5); @@ -323,6 +332,26 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil return code; } +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type) +{ + switch (feature_type) { + case SLJIT_HAS_FPU: +#ifdef SLJIT_IS_FPU_AVAILABLE + return SLJIT_IS_FPU_AVAILABLE; +#else + /* Available by default. */ + return 1; +#endif + + case SLJIT_HAS_CLZ: + case SLJIT_HAS_CMOV: + return 1; + + default: + return 0; + } +} + /* --------------------------------------------------------------------- */ /* Core code generator functions. */ /* --------------------------------------------------------------------- */ @@ -372,12 +401,14 @@ static sljit_ins logical_imm(sljit_sw imm, sljit_s32 len) SLJIT_ASSERT((len == 32 && imm != 0 && imm != -1) || (len == 16 && (sljit_s32)imm != 0 && (sljit_s32)imm != -1)); + uimm = (sljit_uw)imm; while (1) { if (len <= 0) { - SLJIT_ASSERT_STOP(); + SLJIT_UNREACHABLE(); return 0; } + mask = ((sljit_uw)1 << len) - 1; if ((uimm & mask) != ((uimm >> len) & mask)) break; @@ -426,39 +457,42 @@ static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 dst, sljit_s32 i, zeros, ones, first; sljit_ins bitmask; + /* Handling simple immediates first. */ if (imm <= 0xffff) return push_inst(compiler, MOVZ | RD(dst) | (imm << 5)); - if (simm >= -0x10000 && simm < 0) + if (simm < 0 && simm >= -0x10000) return push_inst(compiler, MOVN | RD(dst) | ((~imm & 0xffff) << 5)); if (imm <= 0xffffffffl) { + if ((imm & 0xffff) == 0) + return push_inst(compiler, MOVZ | RD(dst) | ((imm >> 16) << 5) | (1 << 21)); if ((imm & 0xffff0000l) == 0xffff0000) return push_inst(compiler, (MOVN ^ W_OP) | RD(dst) | ((~imm & 0xffff) << 5)); if ((imm & 0xffff) == 0xffff) return push_inst(compiler, (MOVN ^ W_OP) | RD(dst) | ((~imm & 0xffff0000l) >> (16 - 5)) | (1 << 21)); + bitmask = logical_imm(simm, 16); if (bitmask != 0) return push_inst(compiler, (ORRI ^ W_OP) | RD(dst) | RN(TMP_ZERO) | bitmask); - } - else { - bitmask = logical_imm(simm, 32); - if (bitmask != 0) - return push_inst(compiler, ORRI | RD(dst) | RN(TMP_ZERO) | bitmask); - } - if (imm <= 0xffffffffl) { FAIL_IF(push_inst(compiler, MOVZ | RD(dst) | ((imm & 0xffff) << 5))); return push_inst(compiler, MOVK | RD(dst) | ((imm & 0xffff0000l) >> (16 - 5)) | (1 << 21)); } - if (simm >= -0x100000000l && simm < 0) { + bitmask = logical_imm(simm, 32); + if (bitmask != 0) + return push_inst(compiler, ORRI | RD(dst) | RN(TMP_ZERO) | bitmask); + + if (simm < 0 && simm >= -0x100000000l) { + if ((imm & 0xffff) == 0xffff) + return push_inst(compiler, MOVN | RD(dst) | ((~imm & 0xffff0000l) >> (16 - 5)) | (1 << 21)); + FAIL_IF(push_inst(compiler, MOVN | RD(dst) | ((~imm & 0xffff) << 5))); return push_inst(compiler, MOVK | RD(dst) | ((imm & 0xffff0000l) >> (16 - 5)) | (1 << 21)); } - /* A large amount of number can be constructed from ORR and MOVx, - but computing them is costly. We don't */ + /* A large amount of number can be constructed from ORR and MOVx, but computing them is costly. */ zeros = 0; ones = 0; @@ -511,9 +545,6 @@ static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 dst, #define INT_OP 0x0040000 #define SET_FLAGS 0x0080000 #define UNUSED_RETURN 0x0100000 -#define SLOW_DEST 0x0200000 -#define SLOW_SRC1 0x0400000 -#define SLOW_SRC2 0x0800000 #define CHECK_FLAGS(flag_bits) \ if (flags & SET_FLAGS) { \ @@ -645,7 +676,7 @@ static sljit_s32 emit_op_imm(struct sljit_compiler *compiler, sljit_s32 flags, s } goto set_flags; default: - SLJIT_ASSERT_STOP(); + SLJIT_UNREACHABLE(); break; } @@ -671,40 +702,32 @@ static sljit_s32 emit_op_imm(struct sljit_compiler *compiler, sljit_s32 flags, s switch (op) { case SLJIT_MOV: case SLJIT_MOV_P: - case SLJIT_MOVU: - case SLJIT_MOVU_P: SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG1); if (dst == arg2) return SLJIT_SUCCESS; return push_inst(compiler, ORR | RD(dst) | RN(TMP_ZERO) | RM(arg2)); case SLJIT_MOV_U8: - case SLJIT_MOVU_U8: SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG1); return push_inst(compiler, (UBFM ^ (1 << 31)) | RD(dst) | RN(arg2) | (7 << 10)); case SLJIT_MOV_S8: - case SLJIT_MOVU_S8: SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG1); if (!(flags & INT_OP)) inv_bits |= 1 << 22; return push_inst(compiler, (SBFM ^ inv_bits) | RD(dst) | RN(arg2) | (7 << 10)); case SLJIT_MOV_U16: - case SLJIT_MOVU_U16: SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG1); return push_inst(compiler, (UBFM ^ (1 << 31)) | RD(dst) | RN(arg2) | (15 << 10)); case SLJIT_MOV_S16: - case SLJIT_MOVU_S16: SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG1); if (!(flags & INT_OP)) inv_bits |= 1 << 22; return push_inst(compiler, (SBFM ^ inv_bits) | RD(dst) | RN(arg2) | (15 << 10)); case SLJIT_MOV_U32: - case SLJIT_MOVU_U32: SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG1); if ((flags & INT_OP) && dst == arg2) return SLJIT_SUCCESS; return push_inst(compiler, (ORR ^ (1 << 31)) | RD(dst) | RN(TMP_ZERO) | RM(arg2)); case SLJIT_MOV_S32: - case SLJIT_MOVU_S32: SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG1); if ((flags & INT_OP) && dst == arg2) return SLJIT_SUCCESS; @@ -712,7 +735,7 @@ static sljit_s32 emit_op_imm(struct sljit_compiler *compiler, sljit_s32 flags, s case SLJIT_NOT: SLJIT_ASSERT(arg1 == TMP_REG1); FAIL_IF(push_inst(compiler, (ORN ^ inv_bits) | RD(dst) | RN(TMP_ZERO) | RM(arg2))); - goto set_flags; + break; /* Set flags. */ case SLJIT_NEG: SLJIT_ASSERT(arg1 == TMP_REG1); if (flags & SET_FLAGS) @@ -720,8 +743,7 @@ static sljit_s32 emit_op_imm(struct sljit_compiler *compiler, sljit_s32 flags, s return push_inst(compiler, (SUB ^ inv_bits) | RD(dst) | RN(TMP_ZERO) | RM(arg2)); case SLJIT_CLZ: SLJIT_ASSERT(arg1 == TMP_REG1); - FAIL_IF(push_inst(compiler, (CLZ ^ inv_bits) | RD(dst) | RN(arg2))); - goto set_flags; + return push_inst(compiler, (CLZ ^ inv_bits) | RD(dst) | RN(arg2)); case SLJIT_ADD: CHECK_FLAGS(1 << 29); return push_inst(compiler, (ADD ^ inv_bits) | RD(dst) | RN(arg1) | RM(arg2)); @@ -750,320 +772,91 @@ static sljit_s32 emit_op_imm(struct sljit_compiler *compiler, sljit_s32 flags, s return push_inst(compiler, (AND ^ inv_bits) | RD(dst) | RN(arg1) | RM(arg2)); case SLJIT_OR: FAIL_IF(push_inst(compiler, (ORR ^ inv_bits) | RD(dst) | RN(arg1) | RM(arg2))); - goto set_flags; + break; /* Set flags. */ case SLJIT_XOR: FAIL_IF(push_inst(compiler, (EOR ^ inv_bits) | RD(dst) | RN(arg1) | RM(arg2))); - goto set_flags; + break; /* Set flags. */ case SLJIT_SHL: FAIL_IF(push_inst(compiler, (LSLV ^ inv_bits) | RD(dst) | RN(arg1) | RM(arg2))); - goto set_flags; + break; /* Set flags. */ case SLJIT_LSHR: FAIL_IF(push_inst(compiler, (LSRV ^ inv_bits) | RD(dst) | RN(arg1) | RM(arg2))); - goto set_flags; + break; /* Set flags. */ case SLJIT_ASHR: FAIL_IF(push_inst(compiler, (ASRV ^ inv_bits) | RD(dst) | RN(arg1) | RM(arg2))); - goto set_flags; + break; /* Set flags. */ + default: + SLJIT_UNREACHABLE(); + return SLJIT_SUCCESS; } - SLJIT_ASSERT_STOP(); - return SLJIT_SUCCESS; - set_flags: if (flags & SET_FLAGS) return push_inst(compiler, (SUBS ^ inv_bits) | RD(TMP_ZERO) | RN(dst) | RM(TMP_ZERO)); return SLJIT_SUCCESS; } -#define STORE 0x01 -#define SIGNED 0x02 - -#define UPDATE 0x04 -#define ARG_TEST 0x08 - -#define BYTE_SIZE 0x000 -#define HALF_SIZE 0x100 -#define INT_SIZE 0x200 -#define WORD_SIZE 0x300 - -#define MEM_SIZE_SHIFT(flags) ((flags) >> 8) - -static const sljit_ins sljit_mem_imm[4] = { -/* u l */ 0x39400000 /* ldrb [reg,imm] */, -/* u s */ 0x39000000 /* strb [reg,imm] */, -/* s l */ 0x39800000 /* ldrsb [reg,imm] */, -/* s s */ 0x39000000 /* strb [reg,imm] */, -}; - -static const sljit_ins sljit_mem_simm[4] = { -/* u l */ 0x38400000 /* ldurb [reg,imm] */, -/* u s */ 0x38000000 /* sturb [reg,imm] */, -/* s l */ 0x38800000 /* ldursb [reg,imm] */, -/* s s */ 0x38000000 /* sturb [reg,imm] */, -}; +#define STORE 0x10 +#define SIGNED 0x20 -static const sljit_ins sljit_mem_pre_simm[4] = { -/* u l */ 0x38400c00 /* ldrb [reg,imm]! */, -/* u s */ 0x38000c00 /* strb [reg,imm]! */, -/* s l */ 0x38800c00 /* ldrsb [reg,imm]! */, -/* s s */ 0x38000c00 /* strb [reg,imm]! */, -}; - -static const sljit_ins sljit_mem_reg[4] = { -/* u l */ 0x38606800 /* ldrb [reg,reg] */, -/* u s */ 0x38206800 /* strb [reg,reg] */, -/* s l */ 0x38a06800 /* ldrsb [reg,reg] */, -/* s s */ 0x38206800 /* strb [reg,reg] */, -}; +#define BYTE_SIZE 0x0 +#define HALF_SIZE 0x1 +#define INT_SIZE 0x2 +#define WORD_SIZE 0x3 -/* Helper function. Dst should be reg + value, using at most 1 instruction, flags does not set. */ -static sljit_s32 emit_set_delta(struct sljit_compiler *compiler, sljit_s32 dst, sljit_s32 reg, sljit_sw value) -{ - if (value >= 0) { - if (value <= 0xfff) - return push_inst(compiler, ADDI | RD(dst) | RN(reg) | (value << 10)); - if (value <= 0xffffff && !(value & 0xfff)) - return push_inst(compiler, ADDI | (1 << 22) | RD(dst) | RN(reg) | (value >> 2)); - } - else { - value = -value; - if (value <= 0xfff) - return push_inst(compiler, SUBI | RD(dst) | RN(reg) | (value << 10)); - if (value <= 0xffffff && !(value & 0xfff)) - return push_inst(compiler, SUBI | (1 << 22) | RD(dst) | RN(reg) | (value >> 2)); - } - return SLJIT_ERR_UNSUPPORTED; -} +#define MEM_SIZE_SHIFT(flags) ((flags) & 0x3) -/* Can perform an operation using at most 1 instruction. */ -static sljit_s32 getput_arg_fast(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 arg, sljit_sw argw) +static sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, + sljit_s32 arg, sljit_sw argw, sljit_s32 tmp_reg) { sljit_u32 shift = MEM_SIZE_SHIFT(flags); + sljit_u32 type = (shift << 30); - SLJIT_ASSERT(arg & SLJIT_MEM); - - if (SLJIT_UNLIKELY(flags & UPDATE)) { - if ((arg & REG_MASK) && !(arg & OFFS_REG_MASK) && argw <= 255 && argw >= -256) { - if (SLJIT_UNLIKELY(flags & ARG_TEST)) - return 1; + if (!(flags & STORE)) + type |= (flags & SIGNED) ? 0x00800000 : 0x00400000; - arg &= REG_MASK; - argw &= 0x1ff; - FAIL_IF(push_inst(compiler, sljit_mem_pre_simm[flags & 0x3] - | (shift << 30) | RT(reg) | RN(arg) | (argw << 12))); - return -1; - } - return 0; - } + SLJIT_ASSERT(arg & SLJIT_MEM); if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) { argw &= 0x3; - if (argw && argw != shift) - return 0; - if (SLJIT_UNLIKELY(flags & ARG_TEST)) - return 1; + if (argw == 0 || argw == shift) + return push_inst(compiler, STRB | type | RT(reg) + | RN(arg & REG_MASK) | RM(OFFS_REG(arg)) | (argw ? (1 << 12) : 0)); - FAIL_IF(push_inst(compiler, sljit_mem_reg[flags & 0x3] | (shift << 30) | RT(reg) - | RN(arg & REG_MASK) | RM(OFFS_REG(arg)) | (argw ? (1 << 12) : 0))); - return -1; + FAIL_IF(push_inst(compiler, ADD | RD(tmp_reg) | RN(arg & REG_MASK) | RM(OFFS_REG(arg)) | (argw << 10))); + return push_inst(compiler, STRBI | type | RT(reg) | RN(tmp_reg)); } arg &= REG_MASK; - if (argw >= 0 && (argw >> shift) <= 0xfff && (argw & ((1 << shift) - 1)) == 0) { - if (SLJIT_UNLIKELY(flags & ARG_TEST)) - return 1; - FAIL_IF(push_inst(compiler, sljit_mem_imm[flags & 0x3] | (shift << 30) - | RT(reg) | RN(arg) | (argw << (10 - shift)))); - return -1; - } + if (arg == SLJIT_UNUSED) { + FAIL_IF(load_immediate(compiler, tmp_reg, argw & ~(0xfff << shift))); - if (argw > 255 || argw < -256) - return 0; - - if (SLJIT_UNLIKELY(flags & ARG_TEST)) - return 1; - - FAIL_IF(push_inst(compiler, sljit_mem_simm[flags & 0x3] | (shift << 30) - | RT(reg) | RN(arg) | ((argw & 0x1ff) << 12))); - return -1; -} - -/* see getput_arg below. - Note: can_cache is called only for binary operators. Those - operators always uses word arguments without write back. */ -static sljit_s32 can_cache(sljit_s32 arg, sljit_sw argw, sljit_s32 next_arg, sljit_sw next_argw) -{ - sljit_sw diff; - if ((arg & OFFS_REG_MASK) || !(next_arg & SLJIT_MEM)) - return 0; + argw = (argw >> shift) & 0xfff; - if (!(arg & REG_MASK)) { - diff = argw - next_argw; - if (diff <= 0xfff && diff >= -0xfff) - return 1; - return 0; + return push_inst(compiler, STRBI | type | RT(reg) | RN(tmp_reg) | (argw << 10)); } - if (argw == next_argw) - return 1; - - diff = argw - next_argw; - if (arg == next_arg && diff <= 0xfff && diff >= -0xfff) - return 1; - - return 0; -} - -/* Emit the necessary instructions. See can_cache above. */ -static sljit_s32 getput_arg(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, - sljit_s32 arg, sljit_sw argw, sljit_s32 next_arg, sljit_sw next_argw) -{ - sljit_u32 shift = MEM_SIZE_SHIFT(flags); - sljit_s32 tmp_r, other_r; - sljit_sw diff; - - SLJIT_ASSERT(arg & SLJIT_MEM); - if (!(next_arg & SLJIT_MEM)) { - next_arg = 0; - next_argw = 0; - } - - tmp_r = (flags & STORE) ? TMP_REG3 : reg; - - if (SLJIT_UNLIKELY((flags & UPDATE) && (arg & REG_MASK))) { - /* Update only applies if a base register exists. */ - other_r = OFFS_REG(arg); - if (!other_r) { - other_r = arg & REG_MASK; - if (other_r != reg && argw >= 0 && argw <= 0xffffff) { - if ((argw & 0xfff) != 0) - FAIL_IF(push_inst(compiler, ADDI | RD(other_r) | RN(other_r) | ((argw & 0xfff) << 10))); - if (argw >> 12) - FAIL_IF(push_inst(compiler, ADDI | (1 << 22) | RD(other_r) | RN(other_r) | ((argw >> 12) << 10))); - return push_inst(compiler, sljit_mem_imm[flags & 0x3] | (shift << 30) | RT(reg) | RN(other_r)); - } - else if (other_r != reg && argw < 0 && argw >= -0xffffff) { - argw = -argw; - if ((argw & 0xfff) != 0) - FAIL_IF(push_inst(compiler, SUBI | RD(other_r) | RN(other_r) | ((argw & 0xfff) << 10))); - if (argw >> 12) - FAIL_IF(push_inst(compiler, SUBI | (1 << 22) | RD(other_r) | RN(other_r) | ((argw >> 12) << 10))); - return push_inst(compiler, sljit_mem_imm[flags & 0x3] | (shift << 30) | RT(reg) | RN(other_r)); - } - - if (compiler->cache_arg == SLJIT_MEM) { - if (argw == compiler->cache_argw) { - other_r = TMP_REG3; - argw = 0; - } - else if (emit_set_delta(compiler, TMP_REG3, TMP_REG3, argw - compiler->cache_argw) != SLJIT_ERR_UNSUPPORTED) { - FAIL_IF(compiler->error); - compiler->cache_argw = argw; - other_r = TMP_REG3; - argw = 0; - } - } - - if (argw) { - FAIL_IF(load_immediate(compiler, TMP_REG3, argw)); - compiler->cache_arg = SLJIT_MEM; - compiler->cache_argw = argw; - other_r = TMP_REG3; - argw = 0; - } - } - - /* No caching here. */ - arg &= REG_MASK; - argw &= 0x3; - if (!argw || argw == shift) { - FAIL_IF(push_inst(compiler, sljit_mem_reg[flags & 0x3] | (shift << 30) | RT(reg) | RN(arg) | RM(other_r) | (argw ? (1 << 12) : 0))); - return push_inst(compiler, ADD | RD(arg) | RN(arg) | RM(other_r) | (argw << 10)); - } - if (arg != reg) { - FAIL_IF(push_inst(compiler, ADD | RD(arg) | RN(arg) | RM(other_r) | (argw << 10))); - return push_inst(compiler, sljit_mem_imm[flags & 0x3] | (shift << 30) | RT(reg) | RN(arg)); + if (argw >= 0 && (argw & ((1 << shift) - 1)) == 0) { + if ((argw >> shift) <= 0xfff) { + return push_inst(compiler, STRBI | type | RT(reg) | RN(arg) | (argw << (10 - shift))); } - FAIL_IF(push_inst(compiler, ADD | RD(TMP_LR) | RN(arg) | RM(other_r) | (argw << 10))); - FAIL_IF(push_inst(compiler, sljit_mem_imm[flags & 0x3] | (shift << 30) | RT(reg) | RN(TMP_LR))); - return push_inst(compiler, ORR | RD(arg) | RN(TMP_ZERO) | RM(TMP_LR)); - } - - if (arg & OFFS_REG_MASK) { - other_r = OFFS_REG(arg); - arg &= REG_MASK; - FAIL_IF(push_inst(compiler, ADD | RD(tmp_r) | RN(arg) | RM(other_r) | ((argw & 0x3) << 10))); - return push_inst(compiler, sljit_mem_imm[flags & 0x3] | (shift << 30) | RT(reg) | RN(tmp_r)); - } - - if (compiler->cache_arg == arg) { - diff = argw - compiler->cache_argw; - if (diff <= 255 && diff >= -256) - return push_inst(compiler, sljit_mem_simm[flags & 0x3] | (shift << 30) - | RT(reg) | RN(TMP_REG3) | ((diff & 0x1ff) << 12)); - if (emit_set_delta(compiler, TMP_REG3, TMP_REG3, diff) != SLJIT_ERR_UNSUPPORTED) { - FAIL_IF(compiler->error); - return push_inst(compiler, sljit_mem_imm[flags & 0x3] | (shift << 30) | RT(reg) | RN(arg)); - } - } - - if (argw >= 0 && argw <= 0xffffff && (argw & ((1 << shift) - 1)) == 0) { - FAIL_IF(push_inst(compiler, ADDI | (1 << 22) | RD(tmp_r) | RN(arg & REG_MASK) | ((argw >> 12) << 10))); - return push_inst(compiler, sljit_mem_imm[flags & 0x3] | (shift << 30) - | RT(reg) | RN(tmp_r) | ((argw & 0xfff) << (10 - shift))); - } - diff = argw - next_argw; - next_arg = (arg & REG_MASK) && (arg == next_arg) && diff <= 0xfff && diff >= -0xfff && diff != 0; - arg &= REG_MASK; + if (argw <= 0xffffff) { + FAIL_IF(push_inst(compiler, ADDI | (1 << 22) | RD(tmp_reg) | RN(arg) | ((argw >> 12) << 10))); - if (arg && compiler->cache_arg == SLJIT_MEM) { - if (compiler->cache_argw == argw) - return push_inst(compiler, sljit_mem_reg[flags & 0x3] | (shift << 30) | RT(reg) | RN(arg) | RM(TMP_REG3)); - if (emit_set_delta(compiler, TMP_REG3, TMP_REG3, argw - compiler->cache_argw) != SLJIT_ERR_UNSUPPORTED) { - FAIL_IF(compiler->error); - compiler->cache_argw = argw; - return push_inst(compiler, sljit_mem_reg[flags & 0x3] | (shift << 30) | RT(reg) | RN(arg) | RM(TMP_REG3)); + argw = ((argw & 0xfff) >> shift); + return push_inst(compiler, STRBI | type | RT(reg) | RN(tmp_reg) | (argw << 10)); } } - compiler->cache_argw = argw; - if (next_arg && emit_set_delta(compiler, TMP_REG3, arg, argw) != SLJIT_ERR_UNSUPPORTED) { - FAIL_IF(compiler->error); - compiler->cache_arg = SLJIT_MEM | arg; - arg = 0; - } - else { - FAIL_IF(load_immediate(compiler, TMP_REG3, argw)); - compiler->cache_arg = SLJIT_MEM; + if (argw <= 255 && argw >= -256) + return push_inst(compiler, STURBI | type | RT(reg) | RN(arg) | ((argw & 0x1ff) << 12)); - if (next_arg) { - FAIL_IF(push_inst(compiler, ADD | RD(TMP_REG3) | RN(TMP_REG3) | RM(arg))); - compiler->cache_arg = SLJIT_MEM | arg; - arg = 0; - } - } + FAIL_IF(load_immediate(compiler, tmp_reg, argw)); - if (arg) - return push_inst(compiler, sljit_mem_reg[flags & 0x3] | (shift << 30) | RT(reg) | RN(arg) | RM(TMP_REG3)); - return push_inst(compiler, sljit_mem_imm[flags & 0x3] | (shift << 30) | RT(reg) | RN(TMP_REG3)); -} - -static SLJIT_INLINE sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 arg, sljit_sw argw) -{ - if (getput_arg_fast(compiler, flags, reg, arg, argw)) - return compiler->error; - compiler->cache_arg = 0; - compiler->cache_argw = 0; - return getput_arg(compiler, flags, reg, arg, argw, 0, 0); -} - -static SLJIT_INLINE sljit_s32 emit_op_mem2(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 arg1, sljit_sw arg1w, sljit_s32 arg2, sljit_sw arg2w) -{ - if (getput_arg_fast(compiler, flags, reg, arg1, arg1w)) - return compiler->error; - return getput_arg(compiler, flags, reg, arg1, arg1w, arg2, arg2w); + return push_inst(compiler, STRB | type | RT(reg) | RN(arg) | RM(tmp_reg)); } /* --------------------------------------------------------------------- */ @@ -1071,14 +864,14 @@ static SLJIT_INLINE sljit_s32 emit_op_mem2(struct sljit_compiler *compiler, slji /* --------------------------------------------------------------------- */ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compiler, - sljit_s32 options, sljit_s32 args, sljit_s32 scratches, sljit_s32 saveds, + sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds, sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size) { - sljit_s32 i, tmp, offs, prev, saved_regs_size; + sljit_s32 args, i, tmp, offs, prev, saved_regs_size; CHECK_ERROR(); - CHECK(check_sljit_emit_enter(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size)); - set_emit_enter(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size); + CHECK(check_sljit_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size)); + set_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size); saved_regs_size = GET_SAVED_REGISTERS_SIZE(scratches, saveds, 0); local_size += saved_regs_size + SLJIT_LOCALS_OFFSET; @@ -1148,6 +941,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi FAIL_IF(push_inst(compiler, ADDI | RD(SLJIT_SP) | RN(TMP_SP) | (0 << 10))); } + args = get_arg_count(arg_types); + if (args >= 1) FAIL_IF(push_inst(compiler, ORR | RD(SLJIT_S0) | RN(TMP_ZERO) | RM(SLJIT_R0))); if (args >= 2) @@ -1159,12 +954,12 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *compiler, - sljit_s32 options, sljit_s32 args, sljit_s32 scratches, sljit_s32 saveds, + sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds, sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size) { CHECK_ERROR(); - CHECK(check_sljit_set_context(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size)); - set_set_context(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size); + CHECK(check_sljit_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size)); + set_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size); local_size += GET_SAVED_REGISTERS_SIZE(scratches, saveds, 0) + SLJIT_LOCALS_OFFSET; local_size = (local_size + 15) & ~0xf; @@ -1297,112 +1092,87 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile ADJUST_LOCAL_OFFSET(dst, dstw); ADJUST_LOCAL_OFFSET(src, srcw); - compiler->cache_arg = 0; - compiler->cache_argw = 0; + if (dst == SLJIT_UNUSED && !HAS_FLAGS(op)) { + if (op <= SLJIT_MOV_P && (src & SLJIT_MEM)) { + SLJIT_ASSERT(reg_map[1] == 0 && reg_map[3] == 2 && reg_map[5] == 4); + + if (op >= SLJIT_MOV_U8 && op <= SLJIT_MOV_S8) + dst = 5; + else if (op >= SLJIT_MOV_U16 && op <= SLJIT_MOV_S16) + dst = 3; + else + dst = 1; + + /* Signed word sized load is the prefetch instruction. */ + return emit_op_mem(compiler, WORD_SIZE | SIGNED, dst, src, srcw, TMP_REG1); + } + return SLJIT_SUCCESS; + } dst_r = SLOW_IS_REG(dst) ? dst : TMP_REG1; op = GET_OPCODE(op); - if (op >= SLJIT_MOV && op <= SLJIT_MOVU_P) { + if (op >= SLJIT_MOV && op <= SLJIT_MOV_P) { + /* Both operands are registers. */ + if (dst_r != TMP_REG1 && FAST_IS_REG(src)) + return emit_op_imm(compiler, op | ((op_flags & SLJIT_I32_OP) ? INT_OP : 0), dst_r, TMP_REG1, src); + switch (op) { case SLJIT_MOV: case SLJIT_MOV_P: - flags = WORD_SIZE; + mem_flags = WORD_SIZE; break; case SLJIT_MOV_U8: - flags = BYTE_SIZE; + mem_flags = BYTE_SIZE; if (src & SLJIT_IMM) srcw = (sljit_u8)srcw; break; case SLJIT_MOV_S8: - flags = BYTE_SIZE | SIGNED; + mem_flags = BYTE_SIZE | SIGNED; if (src & SLJIT_IMM) srcw = (sljit_s8)srcw; break; case SLJIT_MOV_U16: - flags = HALF_SIZE; + mem_flags = HALF_SIZE; if (src & SLJIT_IMM) srcw = (sljit_u16)srcw; break; case SLJIT_MOV_S16: - flags = HALF_SIZE | SIGNED; + mem_flags = HALF_SIZE | SIGNED; if (src & SLJIT_IMM) srcw = (sljit_s16)srcw; break; case SLJIT_MOV_U32: - flags = INT_SIZE; + mem_flags = INT_SIZE; if (src & SLJIT_IMM) srcw = (sljit_u32)srcw; break; case SLJIT_MOV_S32: - flags = INT_SIZE | SIGNED; - if (src & SLJIT_IMM) - srcw = (sljit_s32)srcw; - break; - case SLJIT_MOVU: - case SLJIT_MOVU_P: - flags = WORD_SIZE | UPDATE; - break; - case SLJIT_MOVU_U8: - flags = BYTE_SIZE | UPDATE; - if (src & SLJIT_IMM) - srcw = (sljit_u8)srcw; - break; - case SLJIT_MOVU_S8: - flags = BYTE_SIZE | SIGNED | UPDATE; - if (src & SLJIT_IMM) - srcw = (sljit_s8)srcw; - break; - case SLJIT_MOVU_U16: - flags = HALF_SIZE | UPDATE; - if (src & SLJIT_IMM) - srcw = (sljit_u16)srcw; - break; - case SLJIT_MOVU_S16: - flags = HALF_SIZE | SIGNED | UPDATE; - if (src & SLJIT_IMM) - srcw = (sljit_s16)srcw; - break; - case SLJIT_MOVU_U32: - flags = INT_SIZE | UPDATE; - if (src & SLJIT_IMM) - srcw = (sljit_u32)srcw; - break; - case SLJIT_MOVU_S32: - flags = INT_SIZE | SIGNED | UPDATE; + mem_flags = INT_SIZE | SIGNED; if (src & SLJIT_IMM) srcw = (sljit_s32)srcw; break; default: - SLJIT_ASSERT_STOP(); - flags = 0; + SLJIT_UNREACHABLE(); + mem_flags = 0; break; } if (src & SLJIT_IMM) FAIL_IF(emit_op_imm(compiler, SLJIT_MOV | ARG2_IMM, dst_r, TMP_REG1, srcw)); - else if (src & SLJIT_MEM) { - if (getput_arg_fast(compiler, flags, dst_r, src, srcw)) - FAIL_IF(compiler->error); - else - FAIL_IF(getput_arg(compiler, flags, dst_r, src, srcw, dst, dstw)); - } else { - if (dst_r != TMP_REG1) - return emit_op_imm(compiler, op | ((op_flags & SLJIT_I32_OP) ? INT_OP : 0), dst_r, TMP_REG1, src); + else if (!(src & SLJIT_MEM)) dst_r = src; - } + else + FAIL_IF(emit_op_mem(compiler, mem_flags, dst_r, src, srcw, TMP_REG1)); - if (dst & SLJIT_MEM) { - if (getput_arg_fast(compiler, flags | STORE, dst_r, dst, dstw)) - return compiler->error; - else - return getput_arg(compiler, flags | STORE, dst_r, dst, dstw, 0, 0); - } + if (dst & SLJIT_MEM) + return emit_op_mem(compiler, mem_flags | STORE, dst_r, dst, dstw, TMP_REG2); return SLJIT_SUCCESS; } - flags = GET_FLAGS(op_flags) ? SET_FLAGS : 0; + flags = HAS_FLAGS(op_flags) ? SET_FLAGS : 0; mem_flags = WORD_SIZE; + if (op_flags & SLJIT_I32_OP) { flags |= INT_OP; mem_flags = INT_SIZE; @@ -1412,28 +1182,14 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile flags |= UNUSED_RETURN; if (src & SLJIT_MEM) { - if (getput_arg_fast(compiler, mem_flags, TMP_REG2, src, srcw)) - FAIL_IF(compiler->error); - else - FAIL_IF(getput_arg(compiler, mem_flags, TMP_REG2, src, srcw, dst, dstw)); + FAIL_IF(emit_op_mem(compiler, mem_flags, TMP_REG2, src, srcw, TMP_REG2)); src = TMP_REG2; } - if (src & SLJIT_IMM) { - flags |= ARG2_IMM; - if (op_flags & SLJIT_I32_OP) - srcw = (sljit_s32)srcw; - } else - srcw = src; - - emit_op_imm(compiler, flags | op, dst_r, TMP_REG1, srcw); + emit_op_imm(compiler, flags | op, dst_r, TMP_REG1, src); - if (dst & SLJIT_MEM) { - if (getput_arg_fast(compiler, mem_flags | STORE, dst_r, dst, dstw)) - return compiler->error; - else - return getput_arg(compiler, mem_flags | STORE, dst_r, dst, dstw, 0, 0); - } + if (SLJIT_UNLIKELY(dst & SLJIT_MEM)) + return emit_op_mem(compiler, mem_flags | STORE, dst_r, dst, dstw, TMP_REG2); return SLJIT_SUCCESS; } @@ -1450,12 +1206,13 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile ADJUST_LOCAL_OFFSET(src1, src1w); ADJUST_LOCAL_OFFSET(src2, src2w); - compiler->cache_arg = 0; - compiler->cache_argw = 0; + if (dst == SLJIT_UNUSED && !HAS_FLAGS(op)) + return SLJIT_SUCCESS; dst_r = SLOW_IS_REG(dst) ? dst : TMP_REG1; - flags = GET_FLAGS(op) ? SET_FLAGS : 0; + flags = HAS_FLAGS(op) ? SET_FLAGS : 0; mem_flags = WORD_SIZE; + if (op & SLJIT_I32_OP) { flags |= INT_OP; mem_flags = INT_SIZE; @@ -1464,46 +1221,21 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile if (dst == SLJIT_UNUSED) flags |= UNUSED_RETURN; - if ((dst & SLJIT_MEM) && !getput_arg_fast(compiler, mem_flags | STORE | ARG_TEST, TMP_REG1, dst, dstw)) - flags |= SLOW_DEST; - if (src1 & SLJIT_MEM) { - if (getput_arg_fast(compiler, mem_flags, TMP_REG1, src1, src1w)) - FAIL_IF(compiler->error); - else - flags |= SLOW_SRC1; - } - if (src2 & SLJIT_MEM) { - if (getput_arg_fast(compiler, mem_flags, TMP_REG2, src2, src2w)) - FAIL_IF(compiler->error); - else - flags |= SLOW_SRC2; - } - - if ((flags & (SLOW_SRC1 | SLOW_SRC2)) == (SLOW_SRC1 | SLOW_SRC2)) { - if (!can_cache(src1, src1w, src2, src2w) && can_cache(src1, src1w, dst, dstw)) { - FAIL_IF(getput_arg(compiler, mem_flags, TMP_REG2, src2, src2w, src1, src1w)); - FAIL_IF(getput_arg(compiler, mem_flags, TMP_REG1, src1, src1w, dst, dstw)); - } - else { - FAIL_IF(getput_arg(compiler, mem_flags, TMP_REG1, src1, src1w, src2, src2w)); - FAIL_IF(getput_arg(compiler, mem_flags, TMP_REG2, src2, src2w, dst, dstw)); - } + FAIL_IF(emit_op_mem(compiler, mem_flags, TMP_REG1, src1, src1w, TMP_REG1)); + src1 = TMP_REG1; } - else if (flags & SLOW_SRC1) - FAIL_IF(getput_arg(compiler, mem_flags, TMP_REG1, src1, src1w, dst, dstw)); - else if (flags & SLOW_SRC2) - FAIL_IF(getput_arg(compiler, mem_flags, TMP_REG2, src2, src2w, dst, dstw)); - if (src1 & SLJIT_MEM) - src1 = TMP_REG1; - if (src2 & SLJIT_MEM) + if (src2 & SLJIT_MEM) { + FAIL_IF(emit_op_mem(compiler, mem_flags, TMP_REG2, src2, src2w, TMP_REG2)); src2 = TMP_REG2; + } if (src1 & SLJIT_IMM) flags |= ARG1_IMM; else src1w = src1; + if (src2 & SLJIT_IMM) flags |= ARG2_IMM; else @@ -1511,14 +1243,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile emit_op_imm(compiler, flags | GET_OPCODE(op), dst_r, src1w, src2w); - if (dst & SLJIT_MEM) { - if (!(flags & SLOW_DEST)) { - getput_arg_fast(compiler, mem_flags | STORE, dst_r, dst, dstw); - return compiler->error; - } - return getput_arg(compiler, mem_flags | STORE, TMP_REG1, dst, dstw, 0, 0); - } - + if (dst & SLJIT_MEM) + return emit_op_mem(compiler, mem_flags | STORE, dst_r, dst, dstw, TMP_REG2); return SLJIT_SUCCESS; } @@ -1531,7 +1257,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 reg) SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_float_register_index(sljit_s32 reg) { CHECK_REG_INDEX(check_sljit_get_float_register_index(reg)); - return reg; + return freg_map[reg]; } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *compiler, @@ -1547,74 +1273,60 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *c /* Floating point operators */ /* --------------------------------------------------------------------- */ -SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_is_fpu_available(void) -{ -#ifdef SLJIT_IS_FPU_AVAILABLE - return SLJIT_IS_FPU_AVAILABLE; -#else - /* Available by default. */ - return 1; -#endif -} - static sljit_s32 emit_fop_mem(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 arg, sljit_sw argw) { sljit_u32 shift = MEM_SIZE_SHIFT(flags); - sljit_ins ins_bits = (shift << 30); - sljit_s32 other_r; - sljit_sw diff; + sljit_ins type = (shift << 30); SLJIT_ASSERT(arg & SLJIT_MEM); if (!(flags & STORE)) - ins_bits |= 1 << 22; + type |= 0x00400000; if (arg & OFFS_REG_MASK) { argw &= 3; - if (!argw || argw == shift) - return push_inst(compiler, STR_FR | ins_bits | VT(reg) + if (argw == 0 || argw == shift) + return push_inst(compiler, STR_FR | type | VT(reg) | RN(arg & REG_MASK) | RM(OFFS_REG(arg)) | (argw ? (1 << 12) : 0)); - other_r = OFFS_REG(arg); - arg &= REG_MASK; - FAIL_IF(push_inst(compiler, ADD | RD(TMP_REG1) | RN(arg) | RM(other_r) | (argw << 10))); - arg = TMP_REG1; - argw = 0; + + FAIL_IF(push_inst(compiler, ADD | RD(TMP_REG1) | RN(arg & REG_MASK) | RM(OFFS_REG(arg)) | (argw << 10))); + return push_inst(compiler, STR_FI | type | VT(reg) | RN(TMP_REG1)); } arg &= REG_MASK; - if (arg && argw >= 0 && ((argw >> shift) <= 0xfff) && (argw & ((1 << shift) - 1)) == 0) - return push_inst(compiler, STR_FI | ins_bits | VT(reg) | RN(arg) | (argw << (10 - shift))); - - if (arg && argw <= 255 && argw >= -256) - return push_inst(compiler, STUR_FI | ins_bits | VT(reg) | RN(arg) | ((argw & 0x1ff) << 12)); - - /* Slow cases */ - if (compiler->cache_arg == SLJIT_MEM && argw != compiler->cache_argw) { - diff = argw - compiler->cache_argw; - if (!arg && diff <= 255 && diff >= -256) - return push_inst(compiler, STUR_FI | ins_bits | VT(reg) | RN(TMP_REG3) | ((diff & 0x1ff) << 12)); - if (emit_set_delta(compiler, TMP_REG3, TMP_REG3, argw - compiler->cache_argw) != SLJIT_ERR_UNSUPPORTED) { - FAIL_IF(compiler->error); - compiler->cache_argw = argw; - } + + if (arg == SLJIT_UNUSED) { + FAIL_IF(load_immediate(compiler, TMP_REG1, argw & ~(0xfff << shift))); + + argw = (argw >> shift) & 0xfff; + + return push_inst(compiler, STR_FI | type | VT(reg) | RN(TMP_REG1) | (argw << 10)); } - if (compiler->cache_arg != SLJIT_MEM || argw != compiler->cache_argw) { - compiler->cache_arg = SLJIT_MEM; - compiler->cache_argw = argw; - FAIL_IF(load_immediate(compiler, TMP_REG3, argw)); + if (argw >= 0 && (argw & ((1 << shift) - 1)) == 0) { + if ((argw >> shift) <= 0xfff) + return push_inst(compiler, STR_FI | type | VT(reg) | RN(arg) | (argw << (10 - shift))); + + if (argw <= 0xffffff) { + FAIL_IF(push_inst(compiler, ADDI | (1 << 22) | RD(TMP_REG1) | RN(arg) | ((argw >> 12) << 10))); + + argw = ((argw & 0xfff) >> shift); + return push_inst(compiler, STR_FI | type | VT(reg) | RN(TMP_REG1) | (argw << 10)); + } } - if (arg & REG_MASK) - return push_inst(compiler, STR_FR | ins_bits | VT(reg) | RN(arg) | RM(TMP_REG3)); - return push_inst(compiler, STR_FI | ins_bits | VT(reg) | RN(TMP_REG3)); + if (argw <= 255 && argw >= -256) + return push_inst(compiler, STUR_FI | type | VT(reg) | RN(arg) | ((argw & 0x1ff) << 12)); + + FAIL_IF(load_immediate(compiler, TMP_REG1, argw)); + return push_inst(compiler, STR_FR | type | VT(reg) | RN(arg) | RM(TMP_REG1)); } static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_sw_from_f64(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw dstw, sljit_s32 src, sljit_sw srcw) { - sljit_s32 dst_r = SLOW_IS_REG(dst) ? dst : TMP_REG1; + sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1; sljit_ins inv_bits = (op & SLJIT_F32_OP) ? (1 << 22) : 0; if (GET_OPCODE(op) == SLJIT_CONV_S32_FROM_F64) @@ -1627,8 +1339,8 @@ static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_sw_from_f64(struct sljit_comp FAIL_IF(push_inst(compiler, (FCVTZS ^ inv_bits) | RD(dst_r) | VN(src))); - if (dst_r == TMP_REG1 && dst != SLJIT_UNUSED) - return emit_op_mem(compiler, ((GET_OPCODE(op) == SLJIT_CONV_S32_FROM_F64) ? INT_SIZE : WORD_SIZE) | STORE, TMP_REG1, dst, dstw); + if (dst & SLJIT_MEM) + return emit_op_mem(compiler, ((GET_OPCODE(op) == SLJIT_CONV_S32_FROM_F64) ? INT_SIZE : WORD_SIZE) | STORE, TMP_REG1, dst, dstw, TMP_REG2); return SLJIT_SUCCESS; } @@ -1643,7 +1355,7 @@ static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_sw(struct sljit_comp inv_bits |= (1 << 31); if (src & SLJIT_MEM) { - emit_op_mem(compiler, ((GET_OPCODE(op) == SLJIT_CONV_F64_FROM_S32) ? INT_SIZE : WORD_SIZE), TMP_REG1, src, srcw); + emit_op_mem(compiler, ((GET_OPCODE(op) == SLJIT_CONV_F64_FROM_S32) ? INT_SIZE : WORD_SIZE), TMP_REG1, src, srcw, TMP_REG1); src = TMP_REG1; } else if (src & SLJIT_IMM) { #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) @@ -1689,17 +1401,15 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop1(struct sljit_compiler *compil sljit_ins inv_bits; CHECK_ERROR(); - compiler->cache_arg = 0; - compiler->cache_argw = 0; - SLJIT_COMPILE_ASSERT((INT_SIZE ^ 0x100) == WORD_SIZE, must_be_one_bit_difference); + SLJIT_COMPILE_ASSERT((INT_SIZE ^ 0x1) == WORD_SIZE, must_be_one_bit_difference); SELECT_FOP1_OPERATION_WITH_CHECKS(compiler, op, dst, dstw, src, srcw); inv_bits = (op & SLJIT_F32_OP) ? (1 << 22) : 0; dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1; if (src & SLJIT_MEM) { - emit_fop_mem(compiler, (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_F32) ? (mem_flags ^ 0x100) : mem_flags, dst_r, src, srcw); + emit_fop_mem(compiler, (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_F32) ? (mem_flags ^ 0x1) : mem_flags, dst_r, src, srcw); src = dst_r; } @@ -1742,9 +1452,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2(struct sljit_compiler *compil ADJUST_LOCAL_OFFSET(src1, src1w); ADJUST_LOCAL_OFFSET(src2, src2w); - compiler->cache_arg = 0; - compiler->cache_argw = 0; - dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1; if (src1 & SLJIT_MEM) { emit_fop_mem(compiler, mem_flags, TMP_FREG1, src1, src1w); @@ -1785,15 +1492,11 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler * CHECK(check_sljit_emit_fast_enter(compiler, dst, dstw)); ADJUST_LOCAL_OFFSET(dst, dstw); - /* For UNUSED dst. Uncommon, but possible. */ - if (dst == SLJIT_UNUSED) - return SLJIT_SUCCESS; - if (FAST_IS_REG(dst)) return push_inst(compiler, ORR | RD(dst) | RN(TMP_ZERO) | RM(TMP_LR)); /* Memory. */ - return emit_op_mem(compiler, WORD_SIZE | STORE, TMP_LR, dst, dstw); + return emit_op_mem(compiler, WORD_SIZE | STORE, TMP_LR, dst, dstw, TMP_REG1); } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_return(struct sljit_compiler *compiler, sljit_s32 src, sljit_sw srcw) @@ -1804,10 +1507,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_return(struct sljit_compiler if (FAST_IS_REG(src)) FAIL_IF(push_inst(compiler, ORR | RD(TMP_LR) | RN(TMP_ZERO) | RM(src))); - else if (src & SLJIT_MEM) - FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_LR, src, srcw)); - else if (src & SLJIT_IMM) - FAIL_IF(load_immediate(compiler, TMP_LR, srcw)); + else + FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_LR, src, srcw, TMP_REG1)); return push_inst(compiler, RET | RN(TMP_LR)); } @@ -1866,7 +1567,7 @@ static sljit_uw get_cc(sljit_s32 type) return 0x6; default: - SLJIT_ASSERT_STOP(); + SLJIT_UNREACHABLE(); return 0xe; } } @@ -1913,6 +1614,20 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compile return jump; } +SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 arg_types) +{ + CHECK_ERROR_PTR(); + CHECK_PTR(check_sljit_emit_call(compiler, type, arg_types)); + +#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \ + || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) + compiler->skip_checks = 1; +#endif + + return sljit_emit_jump(compiler, type); +} + static SLJIT_INLINE struct sljit_jump* emit_cmp_to0(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 src, sljit_sw srcw) { @@ -1928,13 +1643,14 @@ static SLJIT_INLINE struct sljit_jump* emit_cmp_to0(struct sljit_compiler *compi jump->flags |= IS_CBZ | IS_COND; if (src & SLJIT_MEM) { - PTR_FAIL_IF(emit_op_mem(compiler, inv_bits ? INT_SIZE : WORD_SIZE, TMP_REG1, src, srcw)); + PTR_FAIL_IF(emit_op_mem(compiler, inv_bits ? INT_SIZE : WORD_SIZE, TMP_REG1, src, srcw, TMP_REG1)); src = TMP_REG1; } else if (src & SLJIT_IMM) { PTR_FAIL_IF(load_immediate(compiler, TMP_REG1, srcw)); src = TMP_REG1; } + SLJIT_ASSERT(FAST_IS_REG(src)); if ((type & 0xff) == SLJIT_EQUAL) @@ -1955,15 +1671,15 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compi CHECK(check_sljit_emit_ijump(compiler, type, src, srcw)); ADJUST_LOCAL_OFFSET(src, srcw); - /* In ARM, we don't need to touch the arguments. */ if (!(src & SLJIT_IMM)) { if (src & SLJIT_MEM) { - FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG1, src, srcw)); + FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG1, src, srcw, TMP_REG1)); src = TMP_REG1; } return push_inst(compiler, ((type >= SLJIT_FAST_CALL) ? BLR : BR) | RN(src)); } + /* These jumps are converted to jump/call instructions when possible. */ jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump)); FAIL_IF(!jump); set_jump(jump, compiler, JUMP_ADDR | ((type >= SLJIT_FAST_CALL) ? IS_BL : 0)); @@ -1974,54 +1690,170 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compi return push_inst(compiler, ((type >= SLJIT_FAST_CALL) ? BLR : BR) | RN(TMP_REG1)); } +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 arg_types, + sljit_s32 src, sljit_sw srcw) +{ + CHECK_ERROR(); + CHECK(check_sljit_emit_icall(compiler, type, arg_types, src, srcw)); + +#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \ + || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) + compiler->skip_checks = 1; +#endif + + return sljit_emit_ijump(compiler, type, src, srcw); +} + SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw dstw, - sljit_s32 src, sljit_sw srcw, sljit_s32 type) { - sljit_s32 dst_r, flags, mem_flags; + sljit_s32 dst_r, src_r, flags, mem_flags; sljit_ins cc; CHECK_ERROR(); - CHECK(check_sljit_emit_op_flags(compiler, op, dst, dstw, src, srcw, type)); + CHECK(check_sljit_emit_op_flags(compiler, op, dst, dstw, type)); ADJUST_LOCAL_OFFSET(dst, dstw); - ADJUST_LOCAL_OFFSET(src, srcw); - - if (dst == SLJIT_UNUSED) - return SLJIT_SUCCESS; cc = get_cc(type & 0xff); dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1; if (GET_OPCODE(op) < SLJIT_ADD) { FAIL_IF(push_inst(compiler, CSINC | (cc << 12) | RD(dst_r) | RN(TMP_ZERO) | RM(TMP_ZERO))); - if (dst_r != TMP_REG1) - return SLJIT_SUCCESS; - return emit_op_mem(compiler, (GET_OPCODE(op) == SLJIT_MOV ? WORD_SIZE : INT_SIZE) | STORE, TMP_REG1, dst, dstw); + + if (dst_r == TMP_REG1) { + mem_flags = (GET_OPCODE(op) == SLJIT_MOV ? WORD_SIZE : INT_SIZE) | STORE; + return emit_op_mem(compiler, mem_flags, TMP_REG1, dst, dstw, TMP_REG2); + } + + return SLJIT_SUCCESS; } - compiler->cache_arg = 0; - compiler->cache_argw = 0; - flags = GET_FLAGS(op) ? SET_FLAGS : 0; + flags = HAS_FLAGS(op) ? SET_FLAGS : 0; mem_flags = WORD_SIZE; + if (op & SLJIT_I32_OP) { flags |= INT_OP; mem_flags = INT_SIZE; } - if (src & SLJIT_MEM) { - FAIL_IF(emit_op_mem2(compiler, mem_flags, TMP_REG1, src, srcw, dst, dstw)); + src_r = dst; + + if (dst & SLJIT_MEM) { + FAIL_IF(emit_op_mem(compiler, mem_flags, TMP_REG1, dst, dstw, TMP_REG1)); + src_r = TMP_REG1; + } + + FAIL_IF(push_inst(compiler, CSINC | (cc << 12) | RD(TMP_REG2) | RN(TMP_ZERO) | RM(TMP_ZERO))); + emit_op_imm(compiler, flags | GET_OPCODE(op), dst_r, src_r, TMP_REG2); + + if (dst & SLJIT_MEM) + return emit_op_mem(compiler, mem_flags | STORE, TMP_REG1, dst, dstw, TMP_REG2); + return SLJIT_SUCCESS; +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 dst_reg, + sljit_s32 src, sljit_sw srcw) +{ + sljit_ins inv_bits = (dst_reg & SLJIT_I32_OP) ? (1 << 31) : 0; + sljit_ins cc; + + CHECK_ERROR(); + CHECK(check_sljit_emit_cmov(compiler, type, dst_reg, src, srcw)); + + if (SLJIT_UNLIKELY(src & SLJIT_IMM)) { + if (dst_reg & SLJIT_I32_OP) + srcw = (sljit_s32)srcw; + FAIL_IF(load_immediate(compiler, TMP_REG1, srcw)); src = TMP_REG1; srcw = 0; - } else if (src & SLJIT_IMM) - flags |= ARG1_IMM; + } - FAIL_IF(push_inst(compiler, CSINC | (cc << 12) | RD(TMP_REG2) | RN(TMP_ZERO) | RM(TMP_ZERO))); - emit_op_imm(compiler, flags | GET_OPCODE(op), dst_r, src, TMP_REG2); + cc = get_cc(type & 0xff); + dst_reg &= ~SLJIT_I32_OP; + + return push_inst(compiler, (CSEL ^ inv_bits) | (cc << 12) | RD(dst_reg) | RN(dst_reg) | RM(src)); +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 reg, + sljit_s32 mem, sljit_sw memw) +{ + sljit_u32 sign = 0, inst; + + CHECK_ERROR(); + CHECK(check_sljit_emit_mem(compiler, type, reg, mem, memw)); - if (dst_r != TMP_REG1) + if ((mem & OFFS_REG_MASK) || (memw > 255 && memw < -256)) + return SLJIT_ERR_UNSUPPORTED; + + if (type & SLJIT_MEM_SUPP) return SLJIT_SUCCESS; - return emit_op_mem2(compiler, mem_flags | STORE, TMP_REG1, dst, dstw, 0, 0); + + switch (type & 0xff) { + case SLJIT_MOV: + case SLJIT_MOV_P: + inst = STURBI | (MEM_SIZE_SHIFT(WORD_SIZE) << 30) | 0x400; + break; + case SLJIT_MOV_S8: + sign = 1; + case SLJIT_MOV_U8: + inst = STURBI | (MEM_SIZE_SHIFT(BYTE_SIZE) << 30) | 0x400; + break; + case SLJIT_MOV_S16: + sign = 1; + case SLJIT_MOV_U16: + inst = STURBI | (MEM_SIZE_SHIFT(HALF_SIZE) << 30) | 0x400; + break; + case SLJIT_MOV_S32: + sign = 1; + case SLJIT_MOV_U32: + inst = STURBI | (MEM_SIZE_SHIFT(INT_SIZE) << 30) | 0x400; + break; + default: + SLJIT_UNREACHABLE(); + inst = STURBI | (MEM_SIZE_SHIFT(WORD_SIZE) << 30) | 0x400; + break; + } + + if (!(type & SLJIT_MEM_STORE)) + inst |= sign ? 0x00800000 : 0x00400000; + + if (type & SLJIT_MEM_PRE) + inst |= 0x800; + + return push_inst(compiler, inst | RT(reg) | RN(mem & REG_MASK) | ((memw & 0x1ff) << 12)); +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 freg, + sljit_s32 mem, sljit_sw memw) +{ + sljit_u32 inst; + + CHECK_ERROR(); + CHECK(check_sljit_emit_fmem(compiler, type, freg, mem, memw)); + + if ((mem & OFFS_REG_MASK) || (memw > 255 && memw < -256)) + return SLJIT_ERR_UNSUPPORTED; + + if (type & SLJIT_MEM_SUPP) + return SLJIT_SUCCESS; + + inst = STUR_FI | 0x80000400; + + if (!(type & SLJIT_F32_OP)) + inst |= 0x40000000; + + if (!(type & SLJIT_MEM_STORE)) + inst |= 0x00400000; + + if (type & SLJIT_MEM_PRE) + inst |= 0x800; + + return push_inst(compiler, inst | VT(freg) | RN(mem & REG_MASK) | ((memw & 0x1ff) << 12)); } SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw init_value) @@ -2037,11 +1869,11 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compi PTR_FAIL_IF(!const_); set_const(const_, compiler); - dst_r = SLOW_IS_REG(dst) ? dst : TMP_REG1; + dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1; PTR_FAIL_IF(emit_imm64_const(compiler, dst_r, init_value)); if (dst & SLJIT_MEM) - PTR_FAIL_IF(emit_op_mem(compiler, WORD_SIZE | STORE, dst_r, dst, dstw)); + PTR_FAIL_IF(emit_op_mem(compiler, WORD_SIZE | STORE, dst_r, dst, dstw, TMP_REG2)); return const_; } diff --git a/thirdparty/pcre2/src/sljit/sljitNativeARM_T2_32.c b/thirdparty/pcre2/src/sljit/sljitNativeARM_T2_32.c index 95afc5231f..75e7a38b5f 100644 --- a/thirdparty/pcre2/src/sljit/sljitNativeARM_T2_32.c +++ b/thirdparty/pcre2/src/sljit/sljitNativeARM_T2_32.c @@ -1,7 +1,7 @@ /* * Stack-less Just-In-Time compiler * - * Copyright 2009-2012 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved. + * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are * permitted provided that the following conditions are met: @@ -26,7 +26,11 @@ SLJIT_API_FUNC_ATTRIBUTE const char* sljit_get_platform_name(void) { - return "ARM-Thumb2" SLJIT_CPUINFO; +#ifdef __SOFTFP__ + return "ARM-Thumb2" SLJIT_CPUINFO " ABI:softfp"; +#else + return "ARM-Thumb2" SLJIT_CPUINFO " ABI:hardfp"; +#endif } /* Length of an instruction word. */ @@ -35,15 +39,18 @@ typedef sljit_u32 sljit_ins; /* Last register + 1. */ #define TMP_REG1 (SLJIT_NUMBER_OF_REGISTERS + 2) #define TMP_REG2 (SLJIT_NUMBER_OF_REGISTERS + 3) -#define TMP_REG3 (SLJIT_NUMBER_OF_REGISTERS + 4) -#define TMP_PC (SLJIT_NUMBER_OF_REGISTERS + 5) +#define TMP_PC (SLJIT_NUMBER_OF_REGISTERS + 4) -#define TMP_FREG1 (0) -#define TMP_FREG2 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1) +#define TMP_FREG1 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1) +#define TMP_FREG2 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 2) /* See sljit_emit_enter and sljit_emit_op0 if you want to change them. */ -static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 6] = { - 0, 0, 1, 2, 12, 11, 10, 9, 8, 7, 6, 5, 13, 3, 4, 14, 15 +static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 5] = { + 0, 0, 1, 2, 3, 11, 10, 9, 8, 7, 6, 5, 4, 13, 12, 14, 15 +}; + +static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3] = { + 0, 0, 1, 2, 3, 4, 5, 6, 7 }; #define COPY_BITS(src, from, to, bits) \ @@ -70,9 +77,9 @@ static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 6] = { #define RN4(rn) (reg_map[rn] << 16) #define RM4(rm) (reg_map[rm]) #define RT4(rt) (reg_map[rt] << 12) -#define DD4(dd) ((dd) << 12) -#define DN4(dn) ((dn) << 16) -#define DM4(dm) (dm) +#define DD4(dd) (freg_map[dd] << 12) +#define DN4(dn) (freg_map[dn] << 16) +#define DM4(dm) (freg_map[dm]) #define IMM5(imm) \ (COPY_BITS(imm, 2, 12, 3) | ((imm & 0x3) << 6)) #define IMM12(imm) \ @@ -108,7 +115,11 @@ static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 6] = { #define BLX 0x4780 #define BX 0x4700 #define CLZ 0xfab0f080 +#define CMNI_W 0xf1100f00 +#define CMP 0x4280 #define CMPI 0x2800 +#define CMPI_W 0xf1b00f00 +#define CMP_X 0x4500 #define CMP_W 0xebb00f00 #define EORI 0xf0800000 #define EORS 0x4040 @@ -175,6 +186,7 @@ static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 6] = { #define VDIV_F32 0xee800a00 #define VMOV_F32 0xeeb00a40 #define VMOV 0xee000a10 +#define VMOV2 0xec400a10 #define VMRS 0xeef1fa10 #define VMUL_F32 0xee200a00 #define VNEG_F32 0xeeb10a40 @@ -205,10 +217,10 @@ static sljit_s32 push_inst32(struct sljit_compiler *compiler, sljit_ins inst) static SLJIT_INLINE sljit_s32 emit_imm32_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_uw imm) { - FAIL_IF(push_inst32(compiler, MOVW | RD4(dst) | - COPY_BITS(imm, 12, 16, 4) | COPY_BITS(imm, 11, 26, 1) | COPY_BITS(imm, 8, 12, 3) | (imm & 0xff))); - return push_inst32(compiler, MOVT | RD4(dst) | - COPY_BITS(imm, 12 + 16, 16, 4) | COPY_BITS(imm, 11 + 16, 26, 1) | COPY_BITS(imm, 8 + 16, 12, 3) | ((imm & 0xff0000) >> 16)); + FAIL_IF(push_inst32(compiler, MOVW | RD4(dst) + | COPY_BITS(imm, 12, 16, 4) | COPY_BITS(imm, 11, 26, 1) | COPY_BITS(imm, 8, 12, 3) | (imm & 0xff))); + return push_inst32(compiler, MOVT | RD4(dst) + | COPY_BITS(imm, 12 + 16, 16, 4) | COPY_BITS(imm, 11 + 16, 26, 1) | COPY_BITS(imm, 8 + 16, 12, 3) | ((imm & 0xff0000) >> 16)); } static SLJIT_INLINE void modify_imm32_const(sljit_u16 *inst, sljit_uw new_imm) @@ -338,7 +350,7 @@ static SLJIT_INLINE void set_jump_instruction(struct sljit_jump *jump, sljit_sw else if (type == 6) /* Encoding T1 of 'BL' instruction */ jump_inst[1] |= 0xd000; else - SLJIT_ASSERT_STOP(); + SLJIT_UNREACHABLE(); } SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compiler) @@ -430,6 +442,26 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil return (void*)((sljit_uw)code | 0x1); } +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type) +{ + switch (feature_type) { + case SLJIT_HAS_FPU: +#ifdef SLJIT_IS_FPU_AVAILABLE + return SLJIT_IS_FPU_AVAILABLE; +#else + /* Available by default. */ + return 1; +#endif + + case SLJIT_HAS_CLZ: + case SLJIT_HAS_CMOV: + return 1; + + default: + return 0; + } +} + /* --------------------------------------------------------------------- */ /* Core code generator functions. */ /* --------------------------------------------------------------------- */ @@ -498,36 +530,32 @@ static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 dst, } /* set low 16 bits, set hi 16 bits to 0. */ - FAIL_IF(push_inst32(compiler, MOVW | RD4(dst) | - COPY_BITS(imm, 12, 16, 4) | COPY_BITS(imm, 11, 26, 1) | COPY_BITS(imm, 8, 12, 3) | (imm & 0xff))); + FAIL_IF(push_inst32(compiler, MOVW | RD4(dst) + | COPY_BITS(imm, 12, 16, 4) | COPY_BITS(imm, 11, 26, 1) | COPY_BITS(imm, 8, 12, 3) | (imm & 0xff))); /* set hi 16 bit if needed. */ if (imm >= 0x10000) - return push_inst32(compiler, MOVT | RD4(dst) | - COPY_BITS(imm, 12 + 16, 16, 4) | COPY_BITS(imm, 11 + 16, 26, 1) | COPY_BITS(imm, 8 + 16, 12, 3) | ((imm & 0xff0000) >> 16)); + return push_inst32(compiler, MOVT | RD4(dst) + | COPY_BITS(imm, 12 + 16, 16, 4) | COPY_BITS(imm, 11 + 16, 26, 1) | COPY_BITS(imm, 8 + 16, 12, 3) | ((imm & 0xff0000) >> 16)); return SLJIT_SUCCESS; } #define ARG1_IMM 0x0010000 #define ARG2_IMM 0x0020000 -#define KEEP_FLAGS 0x0040000 /* SET_FLAGS must be 0x100000 as it is also the value of S bit (can be used for optimization). */ #define SET_FLAGS 0x0100000 #define UNUSED_RETURN 0x0200000 -#define SLOW_DEST 0x0400000 -#define SLOW_SRC1 0x0800000 -#define SLOW_SRC2 0x1000000 static sljit_s32 emit_op_imm(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 dst, sljit_uw arg1, sljit_uw arg2) { /* dst must be register, TMP_REG1 - arg1 must be register, TMP_REG1, imm - arg2 must be register, TMP_REG2, imm */ + arg1 must be register, imm + arg2 must be register, imm */ sljit_s32 reg; sljit_uw imm, nimm; if (SLJIT_UNLIKELY((flags & (ARG1_IMM | ARG2_IMM)) == (ARG1_IMM | ARG2_IMM))) { - /* Both are immediates. */ + /* Both are immediates, no temporaries are used. */ flags &= ~ARG1_IMM; FAIL_IF(load_immediate(compiler, TMP_REG1, arg1)); arg1 = TMP_REG1; @@ -543,7 +571,7 @@ static sljit_s32 emit_op_imm(struct sljit_compiler *compiler, sljit_s32 flags, s /* No form with immediate operand. */ break; case SLJIT_MOV: - SLJIT_ASSERT(!(flags & SET_FLAGS) && (flags & ARG2_IMM) && arg1 == TMP_REG1); + SLJIT_ASSERT(!(flags & SET_FLAGS) && (flags & ARG2_IMM) && arg1 == TMP_REG2); return load_immediate(compiler, dst, imm); case SLJIT_NOT: if (!(flags & SET_FLAGS)) @@ -553,7 +581,7 @@ static sljit_s32 emit_op_imm(struct sljit_compiler *compiler, sljit_s32 flags, s break; case SLJIT_ADD: nimm = -imm; - if (!(flags & KEEP_FLAGS) && IS_2_LO_REGS(reg, dst)) { + if (IS_2_LO_REGS(reg, dst)) { if (imm <= 0x7) return push_inst16(compiler, ADDSI3 | IMM3(imm) | RD3(dst) | RN3(reg)); if (nimm <= 0x7) @@ -571,9 +599,12 @@ static sljit_s32 emit_op_imm(struct sljit_compiler *compiler, sljit_s32 flags, s if (nimm <= 0xfff) return push_inst32(compiler, SUBWI | RD4(dst) | RN4(reg) | IMM12(nimm)); } - imm = get_imm(imm); - if (imm != INVALID_IMM) - return push_inst32(compiler, ADD_WI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | imm); + nimm = get_imm(imm); + if (nimm != INVALID_IMM) + return push_inst32(compiler, ADD_WI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | nimm); + nimm = get_imm(-imm); + if (nimm != INVALID_IMM) + return push_inst32(compiler, SUB_WI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | nimm); break; case SLJIT_ADDC: imm = get_imm(imm); @@ -581,16 +612,27 @@ static sljit_s32 emit_op_imm(struct sljit_compiler *compiler, sljit_s32 flags, s return push_inst32(compiler, ADCI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | imm); break; case SLJIT_SUB: + /* SUB operation can be replaced by ADD because of the negative carry flag. */ if (flags & ARG1_IMM) { - if (!(flags & KEEP_FLAGS) && imm == 0 && IS_2_LO_REGS(reg, dst)) + if (imm == 0 && IS_2_LO_REGS(reg, dst)) return push_inst16(compiler, RSBSI | RD3(dst) | RN3(reg)); imm = get_imm(imm); if (imm != INVALID_IMM) return push_inst32(compiler, RSB_WI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | imm); break; } + if (flags & UNUSED_RETURN) { + if (imm <= 0xff && reg_map[reg] <= 7) + return push_inst16(compiler, CMPI | IMM8(imm) | RDN3(reg)); + nimm = get_imm(imm); + if (nimm != INVALID_IMM) + return push_inst32(compiler, CMPI_W | RN4(reg) | nimm); + nimm = get_imm(-imm); + if (nimm != INVALID_IMM) + return push_inst32(compiler, CMNI_W | RN4(reg) | nimm); + } nimm = -imm; - if (!(flags & KEEP_FLAGS) && IS_2_LO_REGS(reg, dst)) { + if (IS_2_LO_REGS(reg, dst)) { if (imm <= 0x7) return push_inst16(compiler, SUBSI3 | IMM3(imm) | RD3(dst) | RN3(reg)); if (nimm <= 0x7) @@ -601,8 +643,6 @@ static sljit_s32 emit_op_imm(struct sljit_compiler *compiler, sljit_s32 flags, s if (nimm <= 0xff) return push_inst16(compiler, ADDSI8 | IMM8(nimm) | RDN3(dst)); } - if (imm <= 0xff && (flags & UNUSED_RETURN)) - return push_inst16(compiler, CMPI | IMM8(imm) | RDN3(reg)); } if (!(flags & SET_FLAGS)) { if (imm <= 0xfff) @@ -610,9 +650,12 @@ static sljit_s32 emit_op_imm(struct sljit_compiler *compiler, sljit_s32 flags, s if (nimm <= 0xfff) return push_inst32(compiler, ADDWI | RD4(dst) | RN4(reg) | IMM12(nimm)); } - imm = get_imm(imm); - if (imm != INVALID_IMM) - return push_inst32(compiler, SUB_WI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | imm); + nimm = get_imm(imm); + if (nimm != INVALID_IMM) + return push_inst32(compiler, SUB_WI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | nimm); + nimm = get_imm(-imm); + if (nimm != INVALID_IMM) + return push_inst32(compiler, ADD_WI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | nimm); break; case SLJIT_SUBC: if (flags & ARG1_IMM) @@ -657,31 +700,35 @@ static sljit_s32 emit_op_imm(struct sljit_compiler *compiler, sljit_s32 flags, s } switch (flags & 0xffff) { case SLJIT_SHL: - if (!(flags & KEEP_FLAGS) && IS_2_LO_REGS(dst, reg)) + if (IS_2_LO_REGS(dst, reg)) return push_inst16(compiler, LSLSI | RD3(dst) | RN3(reg) | (imm << 6)); return push_inst32(compiler, LSL_WI | (flags & SET_FLAGS) | RD4(dst) | RM4(reg) | IMM5(imm)); case SLJIT_LSHR: - if (!(flags & KEEP_FLAGS) && IS_2_LO_REGS(dst, reg)) + if (IS_2_LO_REGS(dst, reg)) return push_inst16(compiler, LSRSI | RD3(dst) | RN3(reg) | (imm << 6)); return push_inst32(compiler, LSR_WI | (flags & SET_FLAGS) | RD4(dst) | RM4(reg) | IMM5(imm)); default: /* SLJIT_ASHR */ - if (!(flags & KEEP_FLAGS) && IS_2_LO_REGS(dst, reg)) + if (IS_2_LO_REGS(dst, reg)) return push_inst16(compiler, ASRSI | RD3(dst) | RN3(reg) | (imm << 6)); return push_inst32(compiler, ASR_WI | (flags & SET_FLAGS) | RD4(dst) | RM4(reg) | IMM5(imm)); } default: - SLJIT_ASSERT_STOP(); + SLJIT_UNREACHABLE(); break; } if (flags & ARG2_IMM) { - FAIL_IF(load_immediate(compiler, TMP_REG2, arg2)); - arg2 = TMP_REG2; + imm = arg2; + arg2 = (arg1 == TMP_REG1) ? TMP_REG2 : TMP_REG1; + FAIL_IF(load_immediate(compiler, arg2, imm)); } else { - FAIL_IF(load_immediate(compiler, TMP_REG1, arg1)); - arg1 = TMP_REG1; + imm = arg1; + arg1 = (arg2 == TMP_REG1) ? TMP_REG2 : TMP_REG1; + FAIL_IF(load_immediate(compiler, arg1, imm)); } + + SLJIT_ASSERT(arg1 != arg2); } /* Both arguments are registers. */ @@ -690,108 +737,98 @@ static sljit_s32 emit_op_imm(struct sljit_compiler *compiler, sljit_s32 flags, s case SLJIT_MOV_U32: case SLJIT_MOV_S32: case SLJIT_MOV_P: - case SLJIT_MOVU: - case SLJIT_MOVU_U32: - case SLJIT_MOVU_S32: - case SLJIT_MOVU_P: - SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG1); + SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG2); if (dst == arg2) return SLJIT_SUCCESS; return push_inst16(compiler, MOV | SET_REGS44(dst, arg2)); case SLJIT_MOV_U8: - case SLJIT_MOVU_U8: - SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG1); + SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG2); if (IS_2_LO_REGS(dst, arg2)) return push_inst16(compiler, UXTB | RD3(dst) | RN3(arg2)); return push_inst32(compiler, UXTB_W | RD4(dst) | RM4(arg2)); case SLJIT_MOV_S8: - case SLJIT_MOVU_S8: - SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG1); + SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG2); if (IS_2_LO_REGS(dst, arg2)) return push_inst16(compiler, SXTB | RD3(dst) | RN3(arg2)); return push_inst32(compiler, SXTB_W | RD4(dst) | RM4(arg2)); case SLJIT_MOV_U16: - case SLJIT_MOVU_U16: - SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG1); + SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG2); if (IS_2_LO_REGS(dst, arg2)) return push_inst16(compiler, UXTH | RD3(dst) | RN3(arg2)); return push_inst32(compiler, UXTH_W | RD4(dst) | RM4(arg2)); case SLJIT_MOV_S16: - case SLJIT_MOVU_S16: - SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG1); + SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG2); if (IS_2_LO_REGS(dst, arg2)) return push_inst16(compiler, SXTH | RD3(dst) | RN3(arg2)); return push_inst32(compiler, SXTH_W | RD4(dst) | RM4(arg2)); case SLJIT_NOT: - SLJIT_ASSERT(arg1 == TMP_REG1); - if (!(flags & KEEP_FLAGS) && IS_2_LO_REGS(dst, arg2)) + SLJIT_ASSERT(arg1 == TMP_REG2); + if (IS_2_LO_REGS(dst, arg2)) return push_inst16(compiler, MVNS | RD3(dst) | RN3(arg2)); return push_inst32(compiler, MVN_W | (flags & SET_FLAGS) | RD4(dst) | RM4(arg2)); case SLJIT_CLZ: - SLJIT_ASSERT(arg1 == TMP_REG1); + SLJIT_ASSERT(arg1 == TMP_REG2); FAIL_IF(push_inst32(compiler, CLZ | RN4(arg2) | RD4(dst) | RM4(arg2))); - if (flags & SET_FLAGS) { - if (reg_map[dst] <= 7) - return push_inst16(compiler, CMPI | RDN3(dst)); - return push_inst32(compiler, ADD_WI | SET_FLAGS | RN4(dst) | RD4(dst)); - } return SLJIT_SUCCESS; case SLJIT_ADD: - if (!(flags & KEEP_FLAGS) && IS_3_LO_REGS(dst, arg1, arg2)) + if (IS_3_LO_REGS(dst, arg1, arg2)) return push_inst16(compiler, ADDS | RD3(dst) | RN3(arg1) | RM3(arg2)); if (dst == arg1 && !(flags & SET_FLAGS)) return push_inst16(compiler, ADD | SET_REGS44(dst, arg2)); return push_inst32(compiler, ADD_W | (flags & SET_FLAGS) | RD4(dst) | RN4(arg1) | RM4(arg2)); case SLJIT_ADDC: - if (dst == arg1 && !(flags & KEEP_FLAGS) && IS_2_LO_REGS(dst, arg2)) + if (dst == arg1 && IS_2_LO_REGS(dst, arg2)) return push_inst16(compiler, ADCS | RD3(dst) | RN3(arg2)); return push_inst32(compiler, ADC_W | (flags & SET_FLAGS) | RD4(dst) | RN4(arg1) | RM4(arg2)); case SLJIT_SUB: - if (!(flags & KEEP_FLAGS) && IS_3_LO_REGS(dst, arg1, arg2)) + if (flags & UNUSED_RETURN) { + if (IS_2_LO_REGS(arg1, arg2)) + return push_inst16(compiler, CMP | RD3(arg1) | RN3(arg2)); + return push_inst16(compiler, CMP_X | SET_REGS44(arg1, arg2)); + } + if (IS_3_LO_REGS(dst, arg1, arg2)) return push_inst16(compiler, SUBS | RD3(dst) | RN3(arg1) | RM3(arg2)); return push_inst32(compiler, SUB_W | (flags & SET_FLAGS) | RD4(dst) | RN4(arg1) | RM4(arg2)); case SLJIT_SUBC: - if (dst == arg1 && !(flags & KEEP_FLAGS) && IS_2_LO_REGS(dst, arg2)) + if (dst == arg1 && IS_2_LO_REGS(dst, arg2)) return push_inst16(compiler, SBCS | RD3(dst) | RN3(arg2)); return push_inst32(compiler, SBC_W | (flags & SET_FLAGS) | RD4(dst) | RN4(arg1) | RM4(arg2)); case SLJIT_MUL: if (!(flags & SET_FLAGS)) return push_inst32(compiler, MUL | RD4(dst) | RN4(arg1) | RM4(arg2)); - SLJIT_ASSERT(reg_map[TMP_REG2] <= 7 && dst != TMP_REG2); + SLJIT_ASSERT(dst != TMP_REG2); FAIL_IF(push_inst32(compiler, SMULL | RT4(dst) | RD4(TMP_REG2) | RN4(arg1) | RM4(arg2))); /* cmp TMP_REG2, dst asr #31. */ return push_inst32(compiler, CMP_W | RN4(TMP_REG2) | 0x70e0 | RM4(dst)); case SLJIT_AND: - if (!(flags & KEEP_FLAGS)) { - if (dst == arg1 && IS_2_LO_REGS(dst, arg2)) - return push_inst16(compiler, ANDS | RD3(dst) | RN3(arg2)); - if ((flags & UNUSED_RETURN) && IS_2_LO_REGS(arg1, arg2)) - return push_inst16(compiler, TST | RD3(arg1) | RN3(arg2)); - } + if (dst == arg1 && IS_2_LO_REGS(dst, arg2)) + return push_inst16(compiler, ANDS | RD3(dst) | RN3(arg2)); + if ((flags & UNUSED_RETURN) && IS_2_LO_REGS(arg1, arg2)) + return push_inst16(compiler, TST | RD3(arg1) | RN3(arg2)); return push_inst32(compiler, AND_W | (flags & SET_FLAGS) | RD4(dst) | RN4(arg1) | RM4(arg2)); case SLJIT_OR: - if (dst == arg1 && !(flags & KEEP_FLAGS) && IS_2_LO_REGS(dst, arg2)) + if (dst == arg1 && IS_2_LO_REGS(dst, arg2)) return push_inst16(compiler, ORRS | RD3(dst) | RN3(arg2)); return push_inst32(compiler, ORR_W | (flags & SET_FLAGS) | RD4(dst) | RN4(arg1) | RM4(arg2)); case SLJIT_XOR: - if (dst == arg1 && !(flags & KEEP_FLAGS) && IS_2_LO_REGS(dst, arg2)) + if (dst == arg1 && IS_2_LO_REGS(dst, arg2)) return push_inst16(compiler, EORS | RD3(dst) | RN3(arg2)); return push_inst32(compiler, EOR_W | (flags & SET_FLAGS) | RD4(dst) | RN4(arg1) | RM4(arg2)); case SLJIT_SHL: - if (dst == arg1 && !(flags & KEEP_FLAGS) && IS_2_LO_REGS(dst, arg2)) + if (dst == arg1 && IS_2_LO_REGS(dst, arg2)) return push_inst16(compiler, LSLS | RD3(dst) | RN3(arg2)); return push_inst32(compiler, LSL_W | (flags & SET_FLAGS) | RD4(dst) | RN4(arg1) | RM4(arg2)); case SLJIT_LSHR: - if (dst == arg1 && !(flags & KEEP_FLAGS) && IS_2_LO_REGS(dst, arg2)) + if (dst == arg1 && IS_2_LO_REGS(dst, arg2)) return push_inst16(compiler, LSRS | RD3(dst) | RN3(arg2)); return push_inst32(compiler, LSR_W | (flags & SET_FLAGS) | RD4(dst) | RN4(arg1) | RM4(arg2)); case SLJIT_ASHR: - if (dst == arg1 && !(flags & KEEP_FLAGS) && IS_2_LO_REGS(dst, arg2)) + if (dst == arg1 && IS_2_LO_REGS(dst, arg2)) return push_inst16(compiler, ASRS | RD3(dst) | RN3(arg2)); return push_inst32(compiler, ASR_W | (flags & SET_FLAGS) | RD4(dst) | RN4(arg1) | RM4(arg2)); } - SLJIT_ASSERT_STOP(); + SLJIT_UNREACHABLE(); return SLJIT_SUCCESS; } @@ -801,9 +838,7 @@ static sljit_s32 emit_op_imm(struct sljit_compiler *compiler, sljit_s32 flags, s #define WORD_SIZE 0x00 #define BYTE_SIZE 0x04 #define HALF_SIZE 0x08 - -#define UPDATE 0x10 -#define ARG_TEST 0x20 +#define PRELOAD 0x0c #define IS_WORD_SIZE(flags) (!(flags & (BYTE_SIZE | HALF_SIZE))) #define OFFSET_CHECK(imm, shift) (!(argw & ~(imm << shift))) @@ -859,7 +894,7 @@ static const sljit_ins sljit_mem16_imm5[12] = { #define MEM_IMM8 0xc00 #define MEM_IMM12 0x800000 -static const sljit_ins sljit_mem32[12] = { +static const sljit_ins sljit_mem32[13] = { /* w u l */ 0xf8500000 /* ldr.w */, /* w u s */ 0xf8400000 /* str.w */, /* w s l */ 0xf8500000 /* ldr.w */, @@ -874,6 +909,8 @@ static const sljit_ins sljit_mem32[12] = { /* h u s */ 0xf8200000 /* strsh.w */, /* h s l */ 0xf9300000 /* ldrsh.w */, /* h s s */ 0xf8200000 /* strsh.w */, + +/* p u l */ 0xf8100000 /* pld */, }; /* Helper function. Dst should be reg + value, using at most 1 instruction, flags does not set. */ @@ -897,240 +934,92 @@ static sljit_s32 emit_set_delta(struct sljit_compiler *compiler, sljit_s32 dst, return SLJIT_ERR_UNSUPPORTED; } -/* Can perform an operation using at most 1 instruction. */ -static sljit_s32 getput_arg_fast(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 arg, sljit_sw argw) +static SLJIT_INLINE sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, + sljit_s32 arg, sljit_sw argw, sljit_s32 tmp_reg) { - sljit_s32 other_r, shift; + sljit_s32 other_r; + sljit_uw tmp; SLJIT_ASSERT(arg & SLJIT_MEM); - - if (SLJIT_UNLIKELY(flags & UPDATE)) { - if ((arg & REG_MASK) && !(arg & OFFS_REG_MASK) && argw <= 0xff && argw >= -0xff) { - if (SLJIT_UNLIKELY(flags & ARG_TEST)) - return 1; - - flags &= ~UPDATE; - arg &= 0xf; - if (argw >= 0) - argw |= 0x200; - else { - argw = -argw; - } - - SLJIT_ASSERT(argw >= 0 && (argw & 0xff) <= 0xff); - FAIL_IF(push_inst32(compiler, sljit_mem32[flags] | MEM_IMM8 | RT4(reg) | RN4(arg) | 0x100 | argw)); - return -1; + SLJIT_ASSERT((arg & REG_MASK) != tmp_reg); + arg &= ~SLJIT_MEM; + + if (SLJIT_UNLIKELY(!(arg & REG_MASK))) { + tmp = get_imm(argw & ~0xfff); + if (tmp != INVALID_IMM) { + FAIL_IF(push_inst32(compiler, MOV_WI | RD4(tmp_reg) | tmp)); + return push_inst32(compiler, sljit_mem32[flags] | MEM_IMM12 | RT4(reg) | RN4(tmp_reg) | (argw & 0xfff)); } - return 0; + + FAIL_IF(load_immediate(compiler, tmp_reg, argw)); + if (IS_2_LO_REGS(reg, tmp_reg) && sljit_mem16_imm5[flags]) + return push_inst16(compiler, sljit_mem16_imm5[flags] | RD3(reg) | RN3(tmp_reg)); + return push_inst32(compiler, sljit_mem32[flags] | MEM_IMM12 | RT4(reg) | RN4(tmp_reg)); } if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) { - if (SLJIT_UNLIKELY(flags & ARG_TEST)) - return 1; - argw &= 0x3; other_r = OFFS_REG(arg); arg &= 0xf; if (!argw && IS_3_LO_REGS(reg, arg, other_r)) - FAIL_IF(push_inst16(compiler, sljit_mem16[flags] | RD3(reg) | RN3(arg) | RM3(other_r))); - else - FAIL_IF(push_inst32(compiler, sljit_mem32[flags] | RT4(reg) | RN4(arg) | RM4(other_r) | (argw << 4))); - return -1; + return push_inst16(compiler, sljit_mem16[flags] | RD3(reg) | RN3(arg) | RM3(other_r)); + return push_inst32(compiler, sljit_mem32[flags] | RT4(reg) | RN4(arg) | RM4(other_r) | (argw << 4)); } - if (!(arg & REG_MASK) || argw > 0xfff || argw < -0xff) - return 0; - - if (SLJIT_UNLIKELY(flags & ARG_TEST)) - return 1; + if (argw > 0xfff) { + tmp = get_imm(argw & ~0xfff); + if (tmp != INVALID_IMM) { + push_inst32(compiler, ADD_WI | RD4(tmp_reg) | RN4(arg) | tmp); + arg = tmp_reg; + argw = argw & 0xfff; + } + } + else if (argw < -0xff) { + tmp = get_imm(-argw & ~0xff); + if (tmp != INVALID_IMM) { + push_inst32(compiler, SUB_WI | RD4(tmp_reg) | RN4(arg) | tmp); + arg = tmp_reg; + argw = -(-argw & 0xff); + } + } - arg &= 0xf; if (IS_2_LO_REGS(reg, arg) && sljit_mem16_imm5[flags]) { - shift = 3; + tmp = 3; if (IS_WORD_SIZE(flags)) { if (OFFSET_CHECK(0x1f, 2)) - shift = 2; + tmp = 2; } else if (flags & BYTE_SIZE) { if (OFFSET_CHECK(0x1f, 0)) - shift = 0; + tmp = 0; } else { SLJIT_ASSERT(flags & HALF_SIZE); if (OFFSET_CHECK(0x1f, 1)) - shift = 1; + tmp = 1; } - if (shift != 3) { - FAIL_IF(push_inst16(compiler, sljit_mem16_imm5[flags] | RD3(reg) | RN3(arg) | (argw << (6 - shift)))); - return -1; - } - } - - /* SP based immediate. */ - if (SLJIT_UNLIKELY(arg == SLJIT_SP) && OFFSET_CHECK(0xff, 2) && IS_WORD_SIZE(flags) && reg_map[reg] <= 7) { - FAIL_IF(push_inst16(compiler, STR_SP | ((flags & STORE) ? 0 : 0x800) | RDN3(reg) | (argw >> 2))); - return -1; + if (tmp < 3) + return push_inst16(compiler, sljit_mem16_imm5[flags] | RD3(reg) | RN3(arg) | (argw << (6 - tmp))); } - - if (argw >= 0) - FAIL_IF(push_inst32(compiler, sljit_mem32[flags] | MEM_IMM12 | RT4(reg) | RN4(arg) | argw)); - else - FAIL_IF(push_inst32(compiler, sljit_mem32[flags] | MEM_IMM8 | RT4(reg) | RN4(arg) | -argw)); - return -1; -} - -/* see getput_arg below. - Note: can_cache is called only for binary operators. Those - operators always uses word arguments without write back. */ -static sljit_s32 can_cache(sljit_s32 arg, sljit_sw argw, sljit_s32 next_arg, sljit_sw next_argw) -{ - sljit_sw diff; - if ((arg & OFFS_REG_MASK) || !(next_arg & SLJIT_MEM)) - return 0; - - if (!(arg & REG_MASK)) { - diff = argw - next_argw; - if (diff <= 0xfff && diff >= -0xfff) - return 1; - return 0; + else if (SLJIT_UNLIKELY(arg == SLJIT_SP) && IS_WORD_SIZE(flags) && OFFSET_CHECK(0xff, 2) && reg_map[reg] <= 7) { + /* SP based immediate. */ + return push_inst16(compiler, STR_SP | ((flags & STORE) ? 0 : 0x800) | RDN3(reg) | (argw >> 2)); } - if (argw == next_argw) - return 1; + if (argw >= 0 && argw <= 0xfff) + return push_inst32(compiler, sljit_mem32[flags] | MEM_IMM12 | RT4(reg) | RN4(arg) | argw); + else if (argw < 0 && argw >= -0xff) + return push_inst32(compiler, sljit_mem32[flags] | MEM_IMM8 | RT4(reg) | RN4(arg) | -argw); - diff = argw - next_argw; - if (arg == next_arg && diff <= 0xfff && diff >= -0xfff) - return 1; + SLJIT_ASSERT(arg != tmp_reg); - return 0; -} - -/* Emit the necessary instructions. See can_cache above. */ -static sljit_s32 getput_arg(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, - sljit_s32 arg, sljit_sw argw, sljit_s32 next_arg, sljit_sw next_argw) -{ - sljit_s32 tmp_r, other_r; - sljit_sw diff; - - SLJIT_ASSERT(arg & SLJIT_MEM); - if (!(next_arg & SLJIT_MEM)) { - next_arg = 0; - next_argw = 0; - } - - tmp_r = (flags & STORE) ? TMP_REG3 : reg; - - if (SLJIT_UNLIKELY((flags & UPDATE) && (arg & REG_MASK))) { - /* Update only applies if a base register exists. */ - /* There is no caching here. */ - other_r = OFFS_REG(arg); - arg &= 0xf; - flags &= ~UPDATE; - - if (!other_r) { - if (!(argw & ~0xfff)) { - FAIL_IF(push_inst32(compiler, sljit_mem32[flags] | MEM_IMM12 | RT4(reg) | RN4(arg) | argw)); - return push_inst32(compiler, ADDWI | RD4(arg) | RN4(arg) | IMM12(argw)); - } - - if (compiler->cache_arg == SLJIT_MEM) { - if (argw == compiler->cache_argw) { - other_r = TMP_REG3; - argw = 0; - } - else if (emit_set_delta(compiler, TMP_REG3, TMP_REG3, argw - compiler->cache_argw) != SLJIT_ERR_UNSUPPORTED) { - FAIL_IF(compiler->error); - compiler->cache_argw = argw; - other_r = TMP_REG3; - argw = 0; - } - } - - if (argw) { - FAIL_IF(load_immediate(compiler, TMP_REG3, argw)); - compiler->cache_arg = SLJIT_MEM; - compiler->cache_argw = argw; - other_r = TMP_REG3; - argw = 0; - } - } - - argw &= 0x3; - if (!argw && IS_3_LO_REGS(reg, arg, other_r)) { - FAIL_IF(push_inst16(compiler, sljit_mem16[flags] | RD3(reg) | RN3(arg) | RM3(other_r))); - return push_inst16(compiler, ADD | SET_REGS44(arg, other_r)); - } - FAIL_IF(push_inst32(compiler, sljit_mem32[flags] | RT4(reg) | RN4(arg) | RM4(other_r) | (argw << 4))); - return push_inst32(compiler, ADD_W | RD4(arg) | RN4(arg) | RM4(other_r) | (argw << 6)); - } - flags &= ~UPDATE; - - SLJIT_ASSERT(!(arg & OFFS_REG_MASK)); - - if (compiler->cache_arg == arg) { - diff = argw - compiler->cache_argw; - if (!(diff & ~0xfff)) - return push_inst32(compiler, sljit_mem32[flags] | MEM_IMM12 | RT4(reg) | RN4(TMP_REG3) | diff); - if (!((compiler->cache_argw - argw) & ~0xff)) - return push_inst32(compiler, sljit_mem32[flags] | MEM_IMM8 | RT4(reg) | RN4(TMP_REG3) | (compiler->cache_argw - argw)); - if (emit_set_delta(compiler, TMP_REG3, TMP_REG3, diff) != SLJIT_ERR_UNSUPPORTED) { - FAIL_IF(compiler->error); - return push_inst32(compiler, sljit_mem32[flags] | MEM_IMM12 | RT4(reg) | RN4(TMP_REG3) | 0); - } - } - - next_arg = (arg & REG_MASK) && (arg == next_arg) && (argw != next_argw); - arg &= 0xf; - if (arg && compiler->cache_arg == SLJIT_MEM) { - if (compiler->cache_argw == argw) - return push_inst32(compiler, sljit_mem32[flags] | RT4(reg) | RN4(arg) | RM4(TMP_REG3)); - if (emit_set_delta(compiler, TMP_REG3, TMP_REG3, argw - compiler->cache_argw) != SLJIT_ERR_UNSUPPORTED) { - FAIL_IF(compiler->error); - compiler->cache_argw = argw; - return push_inst32(compiler, sljit_mem32[flags] | RT4(reg) | RN4(arg) | RM4(TMP_REG3)); - } - } - - compiler->cache_argw = argw; - if (next_arg && emit_set_delta(compiler, TMP_REG3, arg, argw) != SLJIT_ERR_UNSUPPORTED) { - FAIL_IF(compiler->error); - compiler->cache_arg = SLJIT_MEM | arg; - arg = 0; - } - else { - FAIL_IF(load_immediate(compiler, TMP_REG3, argw)); - compiler->cache_arg = SLJIT_MEM; - - diff = argw - next_argw; - if (next_arg && diff <= 0xfff && diff >= -0xfff) { - FAIL_IF(push_inst16(compiler, ADD | SET_REGS44(TMP_REG3, arg))); - compiler->cache_arg = SLJIT_MEM | arg; - arg = 0; - } - } - - if (arg) - return push_inst32(compiler, sljit_mem32[flags] | RT4(reg) | RN4(arg) | RM4(TMP_REG3)); - return push_inst32(compiler, sljit_mem32[flags] | MEM_IMM12 | RT4(reg) | RN4(TMP_REG3) | 0); -} - -static SLJIT_INLINE sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 arg, sljit_sw argw) -{ - if (getput_arg_fast(compiler, flags, reg, arg, argw)) - return compiler->error; - compiler->cache_arg = 0; - compiler->cache_argw = 0; - return getput_arg(compiler, flags, reg, arg, argw, 0, 0); -} - -static SLJIT_INLINE sljit_s32 emit_op_mem2(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 arg1, sljit_sw arg1w, sljit_s32 arg2, sljit_sw arg2w) -{ - if (getput_arg_fast(compiler, flags, reg, arg1, arg1w)) - return compiler->error; - return getput_arg(compiler, flags, reg, arg1, arg1w, arg2, arg2w); + FAIL_IF(load_immediate(compiler, tmp_reg, argw)); + if (IS_3_LO_REGS(reg, arg, tmp_reg)) + return push_inst16(compiler, sljit_mem16[flags] | RD3(reg) | RN3(arg) | RM3(tmp_reg)); + return push_inst32(compiler, sljit_mem32[flags] | RT4(reg) | RN4(arg) | RM4(tmp_reg)); } /* --------------------------------------------------------------------- */ @@ -1138,17 +1027,15 @@ static SLJIT_INLINE sljit_s32 emit_op_mem2(struct sljit_compiler *compiler, slji /* --------------------------------------------------------------------- */ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compiler, - sljit_s32 options, sljit_s32 args, sljit_s32 scratches, sljit_s32 saveds, + sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds, sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size) { - sljit_s32 size, i, tmp; - sljit_ins push; + sljit_s32 args, size, i, tmp; + sljit_ins push = 0; CHECK_ERROR(); - CHECK(check_sljit_emit_enter(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size)); - set_emit_enter(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size); - - push = (1 << 4); + CHECK(check_sljit_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size)); + set_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size); tmp = saveds < SLJIT_NUMBER_OF_SAVED_REGISTERS ? (SLJIT_S0 + 1 - saveds) : SLJIT_FIRST_SAVED_REG; for (i = SLJIT_S0; i >= tmp; i--) @@ -1162,7 +1049,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi : push_inst16(compiler, PUSH | (1 << 8) | push)); /* Stack must be aligned to 8 bytes: (LR, R4) */ - size = GET_SAVED_REGISTERS_SIZE(scratches, saveds, 2); + size = GET_SAVED_REGISTERS_SIZE(scratches, saveds, 1); local_size = ((size + local_size + 7) & ~7) - size; compiler->local_size = local_size; if (local_size > 0) { @@ -1172,6 +1059,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi FAIL_IF(emit_op_imm(compiler, SLJIT_SUB | ARG2_IMM, SLJIT_SP, SLJIT_SP, local_size)); } + args = get_arg_count(arg_types); + if (args >= 1) FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(SLJIT_S0, SLJIT_R0))); if (args >= 2) @@ -1183,16 +1072,16 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *compiler, - sljit_s32 options, sljit_s32 args, sljit_s32 scratches, sljit_s32 saveds, + sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds, sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size) { sljit_s32 size; CHECK_ERROR(); - CHECK(check_sljit_set_context(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size)); - set_set_context(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size); + CHECK(check_sljit_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size)); + set_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size); - size = GET_SAVED_REGISTERS_SIZE(scratches, saveds, 2); + size = GET_SAVED_REGISTERS_SIZE(scratches, saveds, 1); compiler->local_size = ((size + local_size + 7) & ~7) - size; return SLJIT_SUCCESS; } @@ -1200,7 +1089,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *comp SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src, sljit_sw srcw) { sljit_s32 i, tmp; - sljit_ins pop; + sljit_ins pop = 0; CHECK_ERROR(); CHECK(check_sljit_emit_return(compiler, op, src, srcw)); @@ -1214,8 +1103,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return(struct sljit_compiler *comp FAIL_IF(emit_op_imm(compiler, SLJIT_ADD | ARG2_IMM, SLJIT_SP, SLJIT_SP, compiler->local_size)); } - pop = (1 << 4); - tmp = compiler->saveds < SLJIT_NUMBER_OF_SAVED_REGISTERS ? (SLJIT_S0 + 1 - compiler->saveds) : SLJIT_FIRST_SAVED_REG; for (i = SLJIT_S0; i >= tmp; i--) pop |= 1 << reg_map[i]; @@ -1273,11 +1160,11 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compile case SLJIT_DIV_UW: case SLJIT_DIV_SW: SLJIT_COMPILE_ASSERT((SLJIT_DIVMOD_UW & 0x2) == 0 && SLJIT_DIV_UW - 0x2 == SLJIT_DIVMOD_UW, bad_div_opcode_assignments); - SLJIT_COMPILE_ASSERT(reg_map[2] == 1 && reg_map[3] == 2 && reg_map[4] == 12, bad_register_mapping); + SLJIT_ASSERT(reg_map[2] == 1 && reg_map[3] == 2 && reg_map[4] == 3); saved_reg_count = 0; if (compiler->scratches >= 4) - saved_reg_list[saved_reg_count++] = 12; + saved_reg_list[saved_reg_count++] = 3; if (compiler->scratches >= 3) saved_reg_list[saved_reg_count++] = 2; if (op >= SLJIT_DIV_UW) @@ -1333,13 +1220,17 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile ADJUST_LOCAL_OFFSET(dst, dstw); ADJUST_LOCAL_OFFSET(src, srcw); - compiler->cache_arg = 0; - compiler->cache_argw = 0; + if (dst == SLJIT_UNUSED && !HAS_FLAGS(op)) { + /* Since TMP_PC has index 15, IS_2_LO_REGS and IS_3_LO_REGS checks always fail. */ + if (op <= SLJIT_MOV_P && (src & SLJIT_MEM)) + return emit_op_mem(compiler, PRELOAD, TMP_PC, src, srcw, TMP_REG1); + return SLJIT_SUCCESS; + } dst_r = SLOW_IS_REG(dst) ? dst : TMP_REG1; op = GET_OPCODE(op); - if (op >= SLJIT_MOV && op <= SLJIT_MOVU_P) { + if (op >= SLJIT_MOV && op <= SLJIT_MOV_P) { switch (op) { case SLJIT_MOV: case SLJIT_MOV_U32: @@ -1367,58 +1258,26 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile if (src & SLJIT_IMM) srcw = (sljit_s16)srcw; break; - case SLJIT_MOVU: - case SLJIT_MOVU_U32: - case SLJIT_MOVU_S32: - case SLJIT_MOVU_P: - flags = WORD_SIZE | UPDATE; - break; - case SLJIT_MOVU_U8: - flags = BYTE_SIZE | UPDATE; - if (src & SLJIT_IMM) - srcw = (sljit_u8)srcw; - break; - case SLJIT_MOVU_S8: - flags = BYTE_SIZE | SIGNED | UPDATE; - if (src & SLJIT_IMM) - srcw = (sljit_s8)srcw; - break; - case SLJIT_MOVU_U16: - flags = HALF_SIZE | UPDATE; - if (src & SLJIT_IMM) - srcw = (sljit_u16)srcw; - break; - case SLJIT_MOVU_S16: - flags = HALF_SIZE | SIGNED | UPDATE; - if (src & SLJIT_IMM) - srcw = (sljit_s16)srcw; - break; default: - SLJIT_ASSERT_STOP(); + SLJIT_UNREACHABLE(); flags = 0; break; } if (src & SLJIT_IMM) - FAIL_IF(emit_op_imm(compiler, SLJIT_MOV | ARG2_IMM, dst_r, TMP_REG1, srcw)); + FAIL_IF(emit_op_imm(compiler, SLJIT_MOV | ARG2_IMM, dst_r, TMP_REG2, srcw)); else if (src & SLJIT_MEM) { - if (getput_arg_fast(compiler, flags, dst_r, src, srcw)) - FAIL_IF(compiler->error); - else - FAIL_IF(getput_arg(compiler, flags, dst_r, src, srcw, dst, dstw)); + FAIL_IF(emit_op_mem(compiler, flags, dst_r, src, srcw, TMP_REG1)); } else { if (dst_r != TMP_REG1) - return emit_op_imm(compiler, op, dst_r, TMP_REG1, src); + return emit_op_imm(compiler, op, dst_r, TMP_REG2, src); dst_r = src; } - if (dst & SLJIT_MEM) { - if (getput_arg_fast(compiler, flags | STORE, dst_r, dst, dstw)) - return compiler->error; - else - return getput_arg(compiler, flags | STORE, dst_r, dst, dstw, 0, 0); - } - return SLJIT_SUCCESS; + if (!(dst & SLJIT_MEM)) + return SLJIT_SUCCESS; + + return emit_op_mem(compiler, flags | STORE, dst_r, dst, dstw, TMP_REG2); } if (op == SLJIT_NEG) { @@ -1429,28 +1288,17 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile return sljit_emit_op2(compiler, SLJIT_SUB | op_flags, dst, dstw, SLJIT_IMM, 0, src, srcw); } - flags = (GET_FLAGS(op_flags) ? SET_FLAGS : 0) | ((op_flags & SLJIT_KEEP_FLAGS) ? KEEP_FLAGS : 0); + flags = HAS_FLAGS(op_flags) ? SET_FLAGS : 0; + if (src & SLJIT_MEM) { - if (getput_arg_fast(compiler, WORD_SIZE, TMP_REG2, src, srcw)) - FAIL_IF(compiler->error); - else - FAIL_IF(getput_arg(compiler, WORD_SIZE, TMP_REG2, src, srcw, dst, dstw)); - src = TMP_REG2; + FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG1, src, srcw, TMP_REG1)); + src = TMP_REG1; } - if (src & SLJIT_IMM) - flags |= ARG2_IMM; - else - srcw = src; - - emit_op_imm(compiler, flags | op, dst_r, TMP_REG1, srcw); + emit_op_imm(compiler, flags | op, dst_r, TMP_REG2, src); - if (dst & SLJIT_MEM) { - if (getput_arg_fast(compiler, flags | STORE, dst_r, dst, dstw)) - return compiler->error; - else - return getput_arg(compiler, flags | STORE, dst_r, dst, dstw, 0, 0); - } + if (SLJIT_UNLIKELY(dst & SLJIT_MEM)) + return emit_op_mem(compiler, flags | STORE, dst_r, dst, dstw, TMP_REG2); return SLJIT_SUCCESS; } @@ -1459,7 +1307,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile sljit_s32 src1, sljit_sw src1w, sljit_s32 src2, sljit_sw src2w) { - sljit_s32 dst_r, flags; + sljit_s32 dst_reg, flags, src2_reg; CHECK_ERROR(); CHECK(check_sljit_emit_op2(compiler, op, dst, dstw, src1, src1w, src2, src2w)); @@ -1467,70 +1315,39 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile ADJUST_LOCAL_OFFSET(src1, src1w); ADJUST_LOCAL_OFFSET(src2, src2w); - compiler->cache_arg = 0; - compiler->cache_argw = 0; - - dst_r = SLOW_IS_REG(dst) ? dst : TMP_REG1; - flags = (GET_FLAGS(op) ? SET_FLAGS : 0) | ((op & SLJIT_KEEP_FLAGS) ? KEEP_FLAGS : 0); - - if ((dst & SLJIT_MEM) && !getput_arg_fast(compiler, WORD_SIZE | STORE | ARG_TEST, TMP_REG1, dst, dstw)) - flags |= SLOW_DEST; - - if (src1 & SLJIT_MEM) { - if (getput_arg_fast(compiler, WORD_SIZE, TMP_REG1, src1, src1w)) - FAIL_IF(compiler->error); - else - flags |= SLOW_SRC1; - } - if (src2 & SLJIT_MEM) { - if (getput_arg_fast(compiler, WORD_SIZE, TMP_REG2, src2, src2w)) - FAIL_IF(compiler->error); - else - flags |= SLOW_SRC2; - } - - if ((flags & (SLOW_SRC1 | SLOW_SRC2)) == (SLOW_SRC1 | SLOW_SRC2)) { - if (!can_cache(src1, src1w, src2, src2w) && can_cache(src1, src1w, dst, dstw)) { - FAIL_IF(getput_arg(compiler, WORD_SIZE, TMP_REG2, src2, src2w, src1, src1w)); - FAIL_IF(getput_arg(compiler, WORD_SIZE, TMP_REG1, src1, src1w, dst, dstw)); - } - else { - FAIL_IF(getput_arg(compiler, WORD_SIZE, TMP_REG1, src1, src1w, src2, src2w)); - FAIL_IF(getput_arg(compiler, WORD_SIZE, TMP_REG2, src2, src2w, dst, dstw)); - } - } - else if (flags & SLOW_SRC1) - FAIL_IF(getput_arg(compiler, WORD_SIZE, TMP_REG1, src1, src1w, dst, dstw)); - else if (flags & SLOW_SRC2) - FAIL_IF(getput_arg(compiler, WORD_SIZE, TMP_REG2, src2, src2w, dst, dstw)); + if (dst == SLJIT_UNUSED && !HAS_FLAGS(op)) + return SLJIT_SUCCESS; - if (src1 & SLJIT_MEM) - src1 = TMP_REG1; - if (src2 & SLJIT_MEM) - src2 = TMP_REG2; + dst_reg = SLOW_IS_REG(dst) ? dst : TMP_REG1; + flags = HAS_FLAGS(op) ? SET_FLAGS : 0; if (src1 & SLJIT_IMM) flags |= ARG1_IMM; + else if (src1 & SLJIT_MEM) { + emit_op_mem(compiler, WORD_SIZE, TMP_REG1, src1, src1w, TMP_REG1); + src1w = TMP_REG1; + } else src1w = src1; + if (src2 & SLJIT_IMM) flags |= ARG2_IMM; + else if (src2 & SLJIT_MEM) { + src2_reg = (!(flags & ARG1_IMM) && (src1w == TMP_REG1)) ? TMP_REG2 : TMP_REG1; + emit_op_mem(compiler, WORD_SIZE, src2_reg, src2, src2w, src2_reg); + src2w = src2_reg; + } else src2w = src2; if (dst == SLJIT_UNUSED) flags |= UNUSED_RETURN; - emit_op_imm(compiler, flags | GET_OPCODE(op), dst_r, src1w, src2w); + emit_op_imm(compiler, flags | GET_OPCODE(op), dst_reg, src1w, src2w); - if (dst & SLJIT_MEM) { - if (!(flags & SLOW_DEST)) { - getput_arg_fast(compiler, WORD_SIZE | STORE, dst_r, dst, dstw); - return compiler->error; - } - return getput_arg(compiler, WORD_SIZE | STORE, TMP_REG1, dst, dstw, 0, 0); - } - return SLJIT_SUCCESS; + if (!(dst & SLJIT_MEM)) + return SLJIT_SUCCESS; + return emit_op_mem(compiler, WORD_SIZE | STORE, dst_reg, dst, dstw, TMP_REG2); } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 reg) @@ -1542,7 +1359,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 reg) SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_float_register_index(sljit_s32 reg) { CHECK_REG_INDEX(check_sljit_get_float_register_index(reg)); - return reg << 1; + return (freg_map[reg] << 1); } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *compiler, @@ -1560,21 +1377,10 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *c /* Floating point operators */ /* --------------------------------------------------------------------- */ -SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_is_fpu_available(void) -{ -#ifdef SLJIT_IS_FPU_AVAILABLE - return SLJIT_IS_FPU_AVAILABLE; -#else - /* Available by default. */ - return 1; -#endif -} - #define FPU_LOAD (1 << 20) static sljit_s32 emit_fop_mem(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 arg, sljit_sw argw) { - sljit_sw tmp; sljit_uw imm; sljit_sw inst = VSTR_F32 | (flags & (SLJIT_F32_OP | FPU_LOAD)); @@ -1582,8 +1388,8 @@ static sljit_s32 emit_fop_mem(struct sljit_compiler *compiler, sljit_s32 flags, /* Fast loads and stores. */ if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) { - FAIL_IF(push_inst32(compiler, ADD_W | RD4(TMP_REG2) | RN4(arg & REG_MASK) | RM4(OFFS_REG(arg)) | ((argw & 0x3) << 6))); - arg = SLJIT_MEM | TMP_REG2; + FAIL_IF(push_inst32(compiler, ADD_W | RD4(TMP_REG1) | RN4(arg & REG_MASK) | RM4(OFFS_REG(arg)) | ((argw & 0x3) << 6))); + arg = SLJIT_MEM | TMP_REG1; argw = 0; } @@ -1594,21 +1400,6 @@ static sljit_s32 emit_fop_mem(struct sljit_compiler *compiler, sljit_s32 flags, return push_inst32(compiler, inst | RN4(arg & REG_MASK) | DD4(reg) | (-argw >> 2)); } - /* Slow cases */ - SLJIT_ASSERT(!(arg & OFFS_REG_MASK)); - if (compiler->cache_arg == arg) { - tmp = argw - compiler->cache_argw; - if (!(tmp & ~0x3fc)) - return push_inst32(compiler, inst | 0x800000 | RN4(TMP_REG3) | DD4(reg) | (tmp >> 2)); - if (!(-tmp & ~0x3fc)) - return push_inst32(compiler, inst | RN4(TMP_REG3) | DD4(reg) | (-tmp >> 2)); - if (emit_set_delta(compiler, TMP_REG3, TMP_REG3, tmp) != SLJIT_ERR_UNSUPPORTED) { - FAIL_IF(compiler->error); - compiler->cache_argw = argw; - return push_inst32(compiler, inst | 0x800000 | RN4(TMP_REG3) | DD4(reg)); - } - } - if (arg & REG_MASK) { if (emit_set_delta(compiler, TMP_REG1, arg & REG_MASK, argw) != SLJIT_ERR_UNSUPPORTED) { FAIL_IF(compiler->error); @@ -1627,19 +1418,18 @@ static sljit_s32 emit_fop_mem(struct sljit_compiler *compiler, sljit_s32 flags, } } - compiler->cache_arg = arg; - compiler->cache_argw = argw; - - FAIL_IF(load_immediate(compiler, TMP_REG3, argw)); + FAIL_IF(load_immediate(compiler, TMP_REG1, argw)); if (arg & REG_MASK) - FAIL_IF(push_inst16(compiler, ADD | SET_REGS44(TMP_REG3, (arg & REG_MASK)))); - return push_inst32(compiler, inst | 0x800000 | RN4(TMP_REG3) | DD4(reg)); + FAIL_IF(push_inst16(compiler, ADD | SET_REGS44(TMP_REG1, (arg & REG_MASK)))); + return push_inst32(compiler, inst | 0x800000 | RN4(TMP_REG1) | DD4(reg)); } static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_sw_from_f64(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw dstw, sljit_s32 src, sljit_sw srcw) { + op ^= SLJIT_F32_OP; + if (src & SLJIT_MEM) { FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_F32_OP) | FPU_LOAD, TMP_FREG1, src, srcw)); src = TMP_FREG1; @@ -1647,9 +1437,6 @@ static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_sw_from_f64(struct sljit_comp FAIL_IF(push_inst32(compiler, VCVT_S32_F32 | (op & SLJIT_F32_OP) | DD4(TMP_FREG1) | DM4(src))); - if (dst == SLJIT_UNUSED) - return SLJIT_SUCCESS; - if (FAST_IS_REG(dst)) return push_inst32(compiler, VMOV | (1 << 20) | RT4(dst) | DN4(TMP_FREG1)); @@ -1663,6 +1450,8 @@ static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_sw(struct sljit_comp { sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1; + op ^= SLJIT_F32_OP; + if (FAST_IS_REG(src)) FAIL_IF(push_inst32(compiler, VMOV | RT4(src) | DN4(TMP_FREG1))); else if (src & SLJIT_MEM) { @@ -1685,6 +1474,8 @@ static SLJIT_INLINE sljit_s32 sljit_emit_fop1_cmp(struct sljit_compiler *compile sljit_s32 src1, sljit_sw src1w, sljit_s32 src2, sljit_sw src2w) { + op ^= SLJIT_F32_OP; + if (src1 & SLJIT_MEM) { emit_fop_mem(compiler, (op & SLJIT_F32_OP) | FPU_LOAD, TMP_FREG1, src1, src1w); src1 = TMP_FREG1; @@ -1706,16 +1497,15 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop1(struct sljit_compiler *compil sljit_s32 dst_r; CHECK_ERROR(); - compiler->cache_arg = 0; - compiler->cache_argw = 0; - if (GET_OPCODE(op) != SLJIT_CONV_F64_FROM_F32) - op ^= SLJIT_F32_OP; SLJIT_COMPILE_ASSERT((SLJIT_F32_OP == 0x100), float_transfer_bit_error); SELECT_FOP1_OPERATION_WITH_CHECKS(compiler, op, dst, dstw, src, srcw); dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1; + if (GET_OPCODE(op) != SLJIT_CONV_F64_FROM_F32) + op ^= SLJIT_F32_OP; + if (src & SLJIT_MEM) { emit_fop_mem(compiler, (op & SLJIT_F32_OP) | FPU_LOAD, dst_r, src, srcw); src = dst_r; @@ -1760,8 +1550,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2(struct sljit_compiler *compil ADJUST_LOCAL_OFFSET(src1, src1w); ADJUST_LOCAL_OFFSET(src2, src2w); - compiler->cache_arg = 0; - compiler->cache_argw = 0; op ^= SLJIT_F32_OP; dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1; @@ -1806,21 +1594,13 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler * CHECK(check_sljit_emit_fast_enter(compiler, dst, dstw)); ADJUST_LOCAL_OFFSET(dst, dstw); - /* For UNUSED dst. Uncommon, but possible. */ - if (dst == SLJIT_UNUSED) - return SLJIT_SUCCESS; + SLJIT_ASSERT(reg_map[TMP_REG2] == 14); if (FAST_IS_REG(dst)) - return push_inst16(compiler, MOV | SET_REGS44(dst, TMP_REG3)); + return push_inst16(compiler, MOV | SET_REGS44(dst, TMP_REG2)); /* Memory. */ - if (getput_arg_fast(compiler, WORD_SIZE | STORE, TMP_REG3, dst, dstw)) - return compiler->error; - /* TMP_REG3 is used for caching. */ - FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(TMP_REG2, TMP_REG3))); - compiler->cache_arg = 0; - compiler->cache_argw = 0; - return getput_arg(compiler, WORD_SIZE | STORE, TMP_REG2, dst, dstw, 0, 0); + return emit_op_mem(compiler, WORD_SIZE | STORE, TMP_REG2, dst, dstw, TMP_REG1); } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_return(struct sljit_compiler *compiler, sljit_s32 src, sljit_sw srcw) @@ -1829,21 +1609,14 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_return(struct sljit_compiler CHECK(check_sljit_emit_fast_return(compiler, src, srcw)); ADJUST_LOCAL_OFFSET(src, srcw); + SLJIT_ASSERT(reg_map[TMP_REG2] == 14); + if (FAST_IS_REG(src)) - FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(TMP_REG3, src))); - else if (src & SLJIT_MEM) { - if (getput_arg_fast(compiler, WORD_SIZE, TMP_REG3, src, srcw)) - FAIL_IF(compiler->error); - else { - compiler->cache_arg = 0; - compiler->cache_argw = 0; - FAIL_IF(getput_arg(compiler, WORD_SIZE, TMP_REG2, src, srcw, 0, 0)); - FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(TMP_REG3, TMP_REG2))); - } - } - else if (src & SLJIT_IMM) - FAIL_IF(load_immediate(compiler, TMP_REG3, srcw)); - return push_inst16(compiler, BLX | RN3(TMP_REG3)); + FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(TMP_REG2, src))); + else + FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG2, src, srcw, TMP_REG2)); + + return push_inst16(compiler, BX | RN3(TMP_REG2)); } /* --------------------------------------------------------------------- */ @@ -1900,7 +1673,7 @@ static sljit_uw get_cc(sljit_s32 type) return 0x7; default: /* SLJIT_JUMP */ - SLJIT_ASSERT_STOP(); + SLJIT_UNREACHABLE(); return 0xe; } } @@ -1934,7 +1707,6 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compile set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP); type &= 0xff; - /* In ARM, we don't need to touch the arguments. */ PTR_FAIL_IF(emit_imm32_const(compiler, TMP_REG1, 0)); if (type < SLJIT_JUMP) { jump->flags |= IS_COND; @@ -1954,6 +1726,241 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compile return jump; } +#ifdef __SOFTFP__ + +static sljit_s32 softfloat_call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_types, sljit_s32 *src) +{ + sljit_s32 stack_offset = 0; + sljit_s32 arg_count = 0; + sljit_s32 word_arg_offset = 0; + sljit_s32 float_arg_count = 0; + sljit_s32 types = 0; + sljit_s32 src_offset = 4 * sizeof(sljit_sw); + sljit_u8 offsets[4]; + + if (src && FAST_IS_REG(*src)) + src_offset = reg_map[*src] * sizeof(sljit_sw); + + arg_types >>= SLJIT_DEF_SHIFT; + + while (arg_types) { + types = (types << SLJIT_DEF_SHIFT) | (arg_types & SLJIT_DEF_MASK); + + switch (arg_types & SLJIT_DEF_MASK) { + case SLJIT_ARG_TYPE_F32: + offsets[arg_count] = (sljit_u8)stack_offset; + stack_offset += sizeof(sljit_f32); + arg_count++; + float_arg_count++; + break; + case SLJIT_ARG_TYPE_F64: + if (stack_offset & 0x7) + stack_offset += sizeof(sljit_sw); + offsets[arg_count] = (sljit_u8)stack_offset; + stack_offset += sizeof(sljit_f64); + arg_count++; + float_arg_count++; + break; + default: + offsets[arg_count] = (sljit_u8)stack_offset; + stack_offset += sizeof(sljit_sw); + arg_count++; + word_arg_offset += sizeof(sljit_sw); + break; + } + + arg_types >>= SLJIT_DEF_SHIFT; + } + + if (stack_offset > 16) + FAIL_IF(push_inst16(compiler, SUB_SP | (((stack_offset - 16) + 0x7) & ~0x7) >> 2)); + + SLJIT_ASSERT(reg_map[TMP_REG1] == 12); + + /* Process arguments in reversed direction. */ + while (types) { + switch (types & SLJIT_DEF_MASK) { + case SLJIT_ARG_TYPE_F32: + arg_count--; + float_arg_count--; + stack_offset = offsets[arg_count]; + + if (stack_offset < 16) { + if (src_offset == stack_offset) { + FAIL_IF(push_inst16(compiler, MOV | (src_offset << 1) | 4 | (1 << 7))); + *src = TMP_REG1; + } + FAIL_IF(push_inst32(compiler, VMOV | 0x100000 | (float_arg_count << 16) | (stack_offset << 10))); + } else + FAIL_IF(push_inst32(compiler, VSTR_F32 | 0x800000 | RN4(SLJIT_SP) | (float_arg_count << 12) | ((stack_offset - 16) >> 2))); + break; + case SLJIT_ARG_TYPE_F64: + arg_count--; + float_arg_count--; + stack_offset = offsets[arg_count]; + + SLJIT_ASSERT((stack_offset & 0x7) == 0); + + if (stack_offset < 16) { + if (src_offset == stack_offset || src_offset == stack_offset + sizeof(sljit_sw)) { + FAIL_IF(push_inst16(compiler, MOV | (src_offset << 1) | 4 | (1 << 7))); + *src = TMP_REG1; + } + FAIL_IF(push_inst32(compiler, VMOV2 | 0x100000 | (stack_offset << 10) | ((stack_offset + sizeof(sljit_sw)) << 14) | float_arg_count)); + } else + FAIL_IF(push_inst32(compiler, VSTR_F32 | 0x800100 | RN4(SLJIT_SP) | (float_arg_count << 12) | ((stack_offset - 16) >> 2))); + break; + default: + arg_count--; + word_arg_offset -= sizeof(sljit_sw); + stack_offset = offsets[arg_count]; + + SLJIT_ASSERT(stack_offset >= word_arg_offset); + + if (stack_offset != word_arg_offset) { + if (stack_offset < 16) { + if (src_offset == stack_offset) { + FAIL_IF(push_inst16(compiler, MOV | (src_offset << 1) | 4 | (1 << 7))); + *src = TMP_REG1; + } + else if (src_offset == word_arg_offset) { + *src = 1 + (stack_offset >> 2); + src_offset = stack_offset; + } + FAIL_IF(push_inst16(compiler, MOV | (stack_offset >> 2) | (word_arg_offset << 1))); + } else + FAIL_IF(push_inst16(compiler, STR_SP | (word_arg_offset << 6) | ((stack_offset - 16) >> 2))); + } + break; + } + + types >>= SLJIT_DEF_SHIFT; + } + + return SLJIT_SUCCESS; +} + +static sljit_s32 softfloat_post_call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_types) +{ + sljit_s32 stack_size = 0; + + if ((arg_types & SLJIT_DEF_MASK) == SLJIT_ARG_TYPE_F32) + FAIL_IF(push_inst32(compiler, VMOV | (0 << 16) | (0 << 12))); + if ((arg_types & SLJIT_DEF_MASK) == SLJIT_ARG_TYPE_F64) + FAIL_IF(push_inst32(compiler, VMOV2 | (1 << 16) | (0 << 12) | 0)); + + arg_types >>= SLJIT_DEF_SHIFT; + + while (arg_types) { + switch (arg_types & SLJIT_DEF_MASK) { + case SLJIT_ARG_TYPE_F32: + stack_size += sizeof(sljit_f32); + break; + case SLJIT_ARG_TYPE_F64: + if (stack_size & 0x7) + stack_size += sizeof(sljit_sw); + stack_size += sizeof(sljit_f64); + break; + default: + stack_size += sizeof(sljit_sw); + break; + } + + arg_types >>= SLJIT_DEF_SHIFT; + } + + if (stack_size <= 16) + return SLJIT_SUCCESS; + + return push_inst16(compiler, ADD_SP | ((((stack_size - 16) + 0x7) & ~0x7) >> 2)); +} + +#else + +static sljit_s32 hardfloat_call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_types) +{ + sljit_u32 remap = 0; + sljit_u32 offset = 0; + sljit_u32 new_offset, mask; + + /* Remove return value. */ + arg_types >>= SLJIT_DEF_SHIFT; + + while (arg_types) { + if ((arg_types & SLJIT_DEF_MASK) == SLJIT_ARG_TYPE_F32) { + new_offset = 0; + mask = 1; + + while (remap & mask) { + new_offset++; + mask <<= 1; + } + remap |= mask; + + if (offset != new_offset) + FAIL_IF(push_inst32(compiler, VMOV_F32 | DD4((new_offset >> 1) + 1) + | ((new_offset & 0x1) ? 0x400000 : 0) | DM4((offset >> 1) + 1))); + + offset += 2; + } + else if ((arg_types & SLJIT_DEF_MASK) == SLJIT_ARG_TYPE_F64) { + new_offset = 0; + mask = 3; + + while (remap & mask) { + new_offset += 2; + mask <<= 2; + } + remap |= mask; + + if (offset != new_offset) + FAIL_IF(push_inst32(compiler, VMOV_F32 | SLJIT_F32_OP | DD4((new_offset >> 1) + 1) | DM4((offset >> 1) + 1))); + + offset += 2; + } + arg_types >>= SLJIT_DEF_SHIFT; + } + + return SLJIT_SUCCESS; +} + +#endif + +SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 arg_types) +{ +#ifdef __SOFTFP__ + struct sljit_jump *jump; +#endif + + CHECK_ERROR_PTR(); + CHECK_PTR(check_sljit_emit_call(compiler, type, arg_types)); + +#ifdef __SOFTFP__ + PTR_FAIL_IF(softfloat_call_with_args(compiler, arg_types, NULL)); + +#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \ + || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) + compiler->skip_checks = 1; +#endif + + jump = sljit_emit_jump(compiler, type); + PTR_FAIL_IF(jump == NULL); + + PTR_FAIL_IF(softfloat_post_call_with_args(compiler, arg_types)); + return jump; +#else + PTR_FAIL_IF(hardfloat_call_with_args(compiler, arg_types)); + +#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \ + || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) + compiler->skip_checks = 1; +#endif + + return sljit_emit_jump(compiler, type); +#endif +} + SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 src, sljit_sw srcw) { struct sljit_jump *jump; @@ -1962,16 +1969,20 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compi CHECK(check_sljit_emit_ijump(compiler, type, src, srcw)); ADJUST_LOCAL_OFFSET(src, srcw); - /* In ARM, we don't need to touch the arguments. */ + SLJIT_ASSERT(reg_map[TMP_REG1] != 14); + if (!(src & SLJIT_IMM)) { - if (FAST_IS_REG(src)) + if (FAST_IS_REG(src)) { + SLJIT_ASSERT(reg_map[src] != 14); return push_inst16(compiler, (type <= SLJIT_JUMP ? BX : BLX) | RN3(src)); + } - FAIL_IF(emit_op_mem(compiler, WORD_SIZE, type <= SLJIT_JUMP ? TMP_PC : TMP_REG1, src, srcw)); + FAIL_IF(emit_op_mem(compiler, WORD_SIZE, type <= SLJIT_JUMP ? TMP_PC : TMP_REG1, src, srcw, TMP_REG1)); if (type >= SLJIT_FAST_CALL) return push_inst16(compiler, BLX | RN3(TMP_REG1)); } + /* These jumps are converted to jump/call instructions when possible. */ jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump)); FAIL_IF(!jump); set_jump(jump, compiler, JUMP_ADDR | ((type >= SLJIT_FAST_CALL) ? IS_BL : 0)); @@ -1982,25 +1993,55 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compi return push_inst16(compiler, (type <= SLJIT_JUMP ? BX : BLX) | RN3(TMP_REG1)); } +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 arg_types, + sljit_s32 src, sljit_sw srcw) +{ + CHECK_ERROR(); + CHECK(check_sljit_emit_icall(compiler, type, arg_types, src, srcw)); + +#ifdef __SOFTFP__ + if (src & SLJIT_MEM) { + FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG1, src, srcw, TMP_REG1)); + src = TMP_REG1; + } + + FAIL_IF(softfloat_call_with_args(compiler, arg_types, &src)); + +#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \ + || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) + compiler->skip_checks = 1; +#endif + + FAIL_IF(sljit_emit_ijump(compiler, type, src, srcw)); + + return softfloat_post_call_with_args(compiler, arg_types); +#else /* !__SOFTFP__ */ + FAIL_IF(hardfloat_call_with_args(compiler, arg_types)); + +#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \ + || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) + compiler->skip_checks = 1; +#endif + + return sljit_emit_ijump(compiler, type, src, srcw); +#endif /* __SOFTFP__ */ +} + SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw dstw, - sljit_s32 src, sljit_sw srcw, sljit_s32 type) { sljit_s32 dst_r, flags = GET_ALL_FLAGS(op); - sljit_ins cc, ins; + sljit_ins cc; CHECK_ERROR(); - CHECK(check_sljit_emit_op_flags(compiler, op, dst, dstw, src, srcw, type)); + CHECK(check_sljit_emit_op_flags(compiler, op, dst, dstw, type)); ADJUST_LOCAL_OFFSET(dst, dstw); - ADJUST_LOCAL_OFFSET(src, srcw); - - if (dst == SLJIT_UNUSED) - return SLJIT_SUCCESS; op = GET_OPCODE(op); cc = get_cc(type & 0xff); - dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2; + dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1; if (op < SLJIT_ADD) { FAIL_IF(push_inst16(compiler, IT | (cc << 4) | (((cc & 0x1) ^ 0x1) << 3) | 0x4)); @@ -2008,60 +2049,141 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *co FAIL_IF(push_inst32(compiler, MOV_WI | RD4(dst_r) | 1)); FAIL_IF(push_inst32(compiler, MOV_WI | RD4(dst_r) | 0)); } else { + /* The movsi (immediate) instruction does not set flags in IT block. */ FAIL_IF(push_inst16(compiler, MOVSI | RDN3(dst_r) | 1)); FAIL_IF(push_inst16(compiler, MOVSI | RDN3(dst_r) | 0)); } - if (dst_r != TMP_REG2) + if (!(dst & SLJIT_MEM)) return SLJIT_SUCCESS; - return emit_op_mem(compiler, WORD_SIZE | STORE, TMP_REG2, dst, dstw); + return emit_op_mem(compiler, WORD_SIZE | STORE, TMP_REG1, dst, dstw, TMP_REG2); } - ins = (op == SLJIT_AND ? ANDI : (op == SLJIT_OR ? ORRI : EORI)); - if ((op == SLJIT_OR || op == SLJIT_XOR) && FAST_IS_REG(dst) && dst == src) { - /* Does not change the other bits. */ + if (dst & SLJIT_MEM) + FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG1, dst, dstw, TMP_REG2)); + + if (op == SLJIT_AND) { + FAIL_IF(push_inst16(compiler, IT | (cc << 4) | (((cc & 0x1) ^ 0x1) << 3) | 0x4)); + FAIL_IF(push_inst32(compiler, ANDI | RN4(dst_r) | RD4(dst_r) | 1)); + FAIL_IF(push_inst32(compiler, ANDI | RN4(dst_r) | RD4(dst_r) | 0)); + } + else { FAIL_IF(push_inst16(compiler, IT | (cc << 4) | 0x8)); - FAIL_IF(push_inst32(compiler, ins | RN4(src) | RD4(dst) | 1)); - if (flags & SLJIT_SET_E) { - /* The condition must always be set, even if the ORRI/EORI is not executed above. */ - if (reg_map[dst] <= 7) - return push_inst16(compiler, MOVS | RD3(TMP_REG1) | RN3(dst)); - return push_inst32(compiler, MOV_W | SET_FLAGS | RD4(TMP_REG1) | RM4(dst)); - } + FAIL_IF(push_inst32(compiler, ((op == SLJIT_OR) ? ORRI : EORI) | RN4(dst_r) | RD4(dst_r) | 1)); + } + + if (dst & SLJIT_MEM) + FAIL_IF(emit_op_mem(compiler, WORD_SIZE | STORE, TMP_REG1, dst, dstw, TMP_REG2)); + + if (!(flags & SLJIT_SET_Z)) return SLJIT_SUCCESS; + + /* The condition must always be set, even if the ORR/EORI is not executed above. */ + return push_inst32(compiler, MOV_W | SET_FLAGS | RD4(TMP_REG1) | RM4(dst_r)); +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 dst_reg, + sljit_s32 src, sljit_sw srcw) +{ + sljit_uw cc, tmp; + + CHECK_ERROR(); + CHECK(check_sljit_emit_cmov(compiler, type, dst_reg, src, srcw)); + + dst_reg &= ~SLJIT_I32_OP; + + cc = get_cc(type & 0xff); + + if (!(src & SLJIT_IMM)) { + FAIL_IF(push_inst16(compiler, IT | (cc << 4) | 0x8)); + return push_inst16(compiler, MOV | SET_REGS44(dst_reg, src)); } - compiler->cache_arg = 0; - compiler->cache_argw = 0; - if (src & SLJIT_MEM) { - FAIL_IF(emit_op_mem2(compiler, WORD_SIZE, TMP_REG2, src, srcw, dst, dstw)); - src = TMP_REG2; - srcw = 0; - } else if (src & SLJIT_IMM) { - FAIL_IF(load_immediate(compiler, TMP_REG2, srcw)); - src = TMP_REG2; - srcw = 0; + tmp = (sljit_uw) srcw; + + if (tmp < 0x10000) { + /* set low 16 bits, set hi 16 bits to 0. */ + FAIL_IF(push_inst16(compiler, IT | (cc << 4) | 0x8)); + return push_inst32(compiler, MOVW | RD4(dst_reg) + | COPY_BITS(tmp, 12, 16, 4) | COPY_BITS(tmp, 11, 26, 1) | COPY_BITS(tmp, 8, 12, 3) | (tmp & 0xff)); } - if (op == SLJIT_AND || src != dst_r) { - FAIL_IF(push_inst16(compiler, IT | (cc << 4) | (((cc & 0x1) ^ 0x1) << 3) | 0x4)); - FAIL_IF(push_inst32(compiler, ins | RN4(src) | RD4(dst_r) | 1)); - FAIL_IF(push_inst32(compiler, ins | RN4(src) | RD4(dst_r) | 0)); + tmp = get_imm(srcw); + if (tmp != INVALID_IMM) { + FAIL_IF(push_inst16(compiler, IT | (cc << 4) | 0x8)); + return push_inst32(compiler, MOV_WI | RD4(dst_reg) | tmp); } - else { + + tmp = get_imm(~srcw); + if (tmp != INVALID_IMM) { FAIL_IF(push_inst16(compiler, IT | (cc << 4) | 0x8)); - FAIL_IF(push_inst32(compiler, ins | RN4(src) | RD4(dst_r) | 1)); + return push_inst32(compiler, MVN_WI | RD4(dst_reg) | tmp); } - if (dst_r == TMP_REG2) - FAIL_IF(emit_op_mem2(compiler, WORD_SIZE | STORE, TMP_REG2, dst, dstw, 0, 0)); + FAIL_IF(push_inst16(compiler, IT | (cc << 4) | ((cc & 0x1) << 3) | 0x4)); + + tmp = (sljit_uw) srcw; + FAIL_IF(push_inst32(compiler, MOVW | RD4(dst_reg) + | COPY_BITS(tmp, 12, 16, 4) | COPY_BITS(tmp, 11, 26, 1) | COPY_BITS(tmp, 8, 12, 3) | (tmp & 0xff))); + return push_inst32(compiler, MOVT | RD4(dst_reg) + | COPY_BITS(tmp, 12 + 16, 16, 4) | COPY_BITS(tmp, 11 + 16, 26, 1) | COPY_BITS(tmp, 8 + 16, 12, 3) | ((tmp & 0xff0000) >> 16)); +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 reg, + sljit_s32 mem, sljit_sw memw) +{ + sljit_s32 flags; + sljit_ins inst; + + CHECK_ERROR(); + CHECK(check_sljit_emit_mem(compiler, type, reg, mem, memw)); + + if ((mem & OFFS_REG_MASK) || (memw > 255 && memw < -255)) + return SLJIT_ERR_UNSUPPORTED; - if (flags & SLJIT_SET_E) { - /* The condition must always be set, even if the ORR/EORI is not executed above. */ - if (reg_map[dst_r] <= 7) - return push_inst16(compiler, MOVS | RD3(TMP_REG1) | RN3(dst_r)); - return push_inst32(compiler, MOV_W | SET_FLAGS | RD4(TMP_REG1) | RM4(dst_r)); + if (type & SLJIT_MEM_SUPP) + return SLJIT_SUCCESS; + + switch (type & 0xff) { + case SLJIT_MOV: + case SLJIT_MOV_U32: + case SLJIT_MOV_S32: + case SLJIT_MOV_P: + flags = WORD_SIZE; + break; + case SLJIT_MOV_U8: + flags = BYTE_SIZE; + break; + case SLJIT_MOV_S8: + flags = BYTE_SIZE | SIGNED; + break; + case SLJIT_MOV_U16: + flags = HALF_SIZE; + break; + case SLJIT_MOV_S16: + flags = HALF_SIZE | SIGNED; + break; + default: + SLJIT_UNREACHABLE(); + flags = WORD_SIZE; + break; } - return SLJIT_SUCCESS; + + if (type & SLJIT_MEM_STORE) + flags |= STORE; + + inst = sljit_mem32[flags] | 0x900; + + if (type & SLJIT_MEM_PRE) + inst |= 0x400; + + if (memw >= 0) + inst |= 0x200; + else + memw = -memw; + + return push_inst32(compiler, inst | RT4(reg) | RN4(mem & REG_MASK) | memw); } SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw init_value) @@ -2077,11 +2199,11 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compi PTR_FAIL_IF(!const_); set_const(const_, compiler); - dst_r = SLOW_IS_REG(dst) ? dst : TMP_REG1; + dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1; PTR_FAIL_IF(emit_imm32_const(compiler, dst_r, init_value)); if (dst & SLJIT_MEM) - PTR_FAIL_IF(emit_op_mem(compiler, WORD_SIZE | STORE, dst_r, dst, dstw)); + PTR_FAIL_IF(emit_op_mem(compiler, WORD_SIZE | STORE, dst_r, dst, dstw, TMP_REG2)); return const_; } diff --git a/thirdparty/pcre2/src/sljit/sljitNativeMIPS_32.c b/thirdparty/pcre2/src/sljit/sljitNativeMIPS_32.c index b15a57dfdb..9f9e157a05 100644 --- a/thirdparty/pcre2/src/sljit/sljitNativeMIPS_32.c +++ b/thirdparty/pcre2/src/sljit/sljitNativeMIPS_32.c @@ -1,7 +1,7 @@ /* * Stack-less Just-In-Time compiler * - * Copyright 2009-2012 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved. + * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are * permitted provided that the following conditions are met: @@ -40,35 +40,37 @@ static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 dst_a #define EMIT_LOGICAL(op_imm, op_norm) \ if (flags & SRC2_IMM) { \ - if (op & SLJIT_SET_E) \ + if (op & SLJIT_SET_Z) \ FAIL_IF(push_inst(compiler, op_imm | S(src1) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG)); \ - if (CHECK_FLAGS(SLJIT_SET_E)) \ + if (!(flags & UNUSED_DEST)) \ FAIL_IF(push_inst(compiler, op_imm | S(src1) | T(dst) | IMM(src2), DR(dst))); \ } \ else { \ - if (op & SLJIT_SET_E) \ + if (op & SLJIT_SET_Z) \ FAIL_IF(push_inst(compiler, op_norm | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG)); \ - if (CHECK_FLAGS(SLJIT_SET_E)) \ + if (!(flags & UNUSED_DEST)) \ FAIL_IF(push_inst(compiler, op_norm | S(src1) | T(src2) | D(dst), DR(dst))); \ } #define EMIT_SHIFT(op_imm, op_v) \ if (flags & SRC2_IMM) { \ - if (op & SLJIT_SET_E) \ + if (op & SLJIT_SET_Z) \ FAIL_IF(push_inst(compiler, op_imm | T(src1) | DA(EQUAL_FLAG) | SH_IMM(src2), EQUAL_FLAG)); \ - if (CHECK_FLAGS(SLJIT_SET_E)) \ + if (!(flags & UNUSED_DEST)) \ FAIL_IF(push_inst(compiler, op_imm | T(src1) | D(dst) | SH_IMM(src2), DR(dst))); \ } \ else { \ - if (op & SLJIT_SET_E) \ + if (op & SLJIT_SET_Z) \ FAIL_IF(push_inst(compiler, op_v | S(src2) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG)); \ - if (CHECK_FLAGS(SLJIT_SET_E)) \ + if (!(flags & UNUSED_DEST)) \ FAIL_IF(push_inst(compiler, op_v | S(src2) | T(src1) | D(dst), DR(dst))); \ } static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 flags, sljit_s32 dst, sljit_s32 src1, sljit_sw src2) { + sljit_s32 is_overflow, is_carry, is_handled; + switch (GET_OPCODE(op)) { case SLJIT_MOV: case SLJIT_MOV_U32: @@ -93,8 +95,9 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl } return push_inst(compiler, ANDI | S(src2) | T(dst) | IMM(0xff), DR(dst)); } - else if (dst != src2) - SLJIT_ASSERT_STOP(); + else { + SLJIT_ASSERT(dst == src2); + } return SLJIT_SUCCESS; case SLJIT_MOV_U16: @@ -111,24 +114,25 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl } return push_inst(compiler, ANDI | S(src2) | T(dst) | IMM(0xffff), DR(dst)); } - else if (dst != src2) - SLJIT_ASSERT_STOP(); + else { + SLJIT_ASSERT(dst == src2); + } return SLJIT_SUCCESS; case SLJIT_NOT: SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM)); - if (op & SLJIT_SET_E) + if (op & SLJIT_SET_Z) FAIL_IF(push_inst(compiler, NOR | S(src2) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG)); - if (CHECK_FLAGS(SLJIT_SET_E)) + if (!(flags & UNUSED_DEST)) FAIL_IF(push_inst(compiler, NOR | S(src2) | T(src2) | D(dst), DR(dst))); return SLJIT_SUCCESS; case SLJIT_CLZ: SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM)); #if (defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1) - if (op & SLJIT_SET_E) + if (op & SLJIT_SET_Z) FAIL_IF(push_inst(compiler, CLZ | S(src2) | TA(EQUAL_FLAG) | DA(EQUAL_FLAG), EQUAL_FLAG)); - if (CHECK_FLAGS(SLJIT_SET_E)) + if (!(flags & UNUSED_DEST)) FAIL_IF(push_inst(compiler, CLZ | S(src2) | T(dst) | D(dst), DR(dst))); #else if (SLJIT_UNLIKELY(flags & UNUSED_DEST)) { @@ -145,130 +149,192 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl FAIL_IF(push_inst(compiler, ADDIU | S(dst) | T(dst) | IMM(1), DR(dst))); FAIL_IF(push_inst(compiler, BGEZ | S(TMP_REG1) | IMM(-2), UNMOVABLE_INS)); FAIL_IF(push_inst(compiler, SLL | T(TMP_REG1) | D(TMP_REG1) | SH_IMM(1), UNMOVABLE_INS)); - if (op & SLJIT_SET_E) - return push_inst(compiler, ADDU | S(dst) | TA(0) | DA(EQUAL_FLAG), EQUAL_FLAG); #endif return SLJIT_SUCCESS; case SLJIT_ADD: + is_overflow = GET_FLAG_TYPE(op) == SLJIT_OVERFLOW; + is_carry = GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY); + if (flags & SRC2_IMM) { - if (op & SLJIT_SET_O) { + if (is_overflow) { if (src2 >= 0) - FAIL_IF(push_inst(compiler, OR | S(src1) | T(src1) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG)); + FAIL_IF(push_inst(compiler, OR | S(src1) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG)); else - FAIL_IF(push_inst(compiler, NOR | S(src1) | T(src1) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG)); + FAIL_IF(push_inst(compiler, NOR | S(src1) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG)); } - if (op & SLJIT_SET_E) + else if (op & SLJIT_SET_Z) FAIL_IF(push_inst(compiler, ADDIU | S(src1) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG)); - if (op & (SLJIT_SET_C | SLJIT_SET_O)) { + + if (is_overflow || is_carry) { if (src2 >= 0) - FAIL_IF(push_inst(compiler, ORI | S(src1) | TA(ULESS_FLAG) | IMM(src2), ULESS_FLAG)); + FAIL_IF(push_inst(compiler, ORI | S(src1) | TA(OTHER_FLAG) | IMM(src2), OTHER_FLAG)); else { - FAIL_IF(push_inst(compiler, ADDIU | SA(0) | TA(ULESS_FLAG) | IMM(src2), ULESS_FLAG)); - FAIL_IF(push_inst(compiler, OR | S(src1) | TA(ULESS_FLAG) | DA(ULESS_FLAG), ULESS_FLAG)); + FAIL_IF(push_inst(compiler, ADDIU | SA(0) | TA(OTHER_FLAG) | IMM(src2), OTHER_FLAG)); + FAIL_IF(push_inst(compiler, OR | S(src1) | TA(OTHER_FLAG) | DA(OTHER_FLAG), OTHER_FLAG)); } } /* dst may be the same as src1 or src2. */ - if (CHECK_FLAGS(SLJIT_SET_E)) + if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK)) FAIL_IF(push_inst(compiler, ADDIU | S(src1) | T(dst) | IMM(src2), DR(dst))); } else { - if (op & SLJIT_SET_O) - FAIL_IF(push_inst(compiler, XOR | S(src1) | T(src2) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG)); - if (op & SLJIT_SET_E) + if (is_overflow) + FAIL_IF(push_inst(compiler, XOR | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG)); + else if (op & SLJIT_SET_Z) FAIL_IF(push_inst(compiler, ADDU | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG)); - if (op & (SLJIT_SET_C | SLJIT_SET_O)) - FAIL_IF(push_inst(compiler, OR | S(src1) | T(src2) | DA(ULESS_FLAG), ULESS_FLAG)); + + if (is_overflow || is_carry) + FAIL_IF(push_inst(compiler, OR | S(src1) | T(src2) | DA(OTHER_FLAG), OTHER_FLAG)); /* dst may be the same as src1 or src2. */ - if (CHECK_FLAGS(SLJIT_SET_E)) + if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK)) FAIL_IF(push_inst(compiler, ADDU | S(src1) | T(src2) | D(dst), DR(dst))); } /* a + b >= a | b (otherwise, the carry should be set to 1). */ - if (op & (SLJIT_SET_C | SLJIT_SET_O)) - FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(ULESS_FLAG) | DA(ULESS_FLAG), ULESS_FLAG)); - if (!(op & SLJIT_SET_O)) + if (is_overflow || is_carry) + FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(OTHER_FLAG) | DA(OTHER_FLAG), OTHER_FLAG)); + if (!is_overflow) return SLJIT_SUCCESS; - FAIL_IF(push_inst(compiler, SLL | TA(ULESS_FLAG) | D(TMP_REG1) | SH_IMM(31), DR(TMP_REG1))); - FAIL_IF(push_inst(compiler, XOR | S(TMP_REG1) | TA(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG)); - FAIL_IF(push_inst(compiler, XOR | S(dst) | TA(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG)); - return push_inst(compiler, SLL | TA(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG) | SH_IMM(31), OVERFLOW_FLAG); + FAIL_IF(push_inst(compiler, SLL | TA(OTHER_FLAG) | D(TMP_REG1) | SH_IMM(31), DR(TMP_REG1))); + FAIL_IF(push_inst(compiler, XOR | S(TMP_REG1) | TA(EQUAL_FLAG) | DA(EQUAL_FLAG), EQUAL_FLAG)); + FAIL_IF(push_inst(compiler, XOR | S(dst) | TA(EQUAL_FLAG) | DA(OTHER_FLAG), OTHER_FLAG)); + if (op & SLJIT_SET_Z) + FAIL_IF(push_inst(compiler, ADDU | S(dst) | TA(0) | DA(EQUAL_FLAG), EQUAL_FLAG)); + return push_inst(compiler, SRL | TA(OTHER_FLAG) | DA(OTHER_FLAG) | SH_IMM(31), OTHER_FLAG); case SLJIT_ADDC: + is_carry = GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY); + if (flags & SRC2_IMM) { - if (op & SLJIT_SET_C) { + if (is_carry) { if (src2 >= 0) - FAIL_IF(push_inst(compiler, ORI | S(src1) | TA(OVERFLOW_FLAG) | IMM(src2), OVERFLOW_FLAG)); + FAIL_IF(push_inst(compiler, ORI | S(src1) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG)); else { - FAIL_IF(push_inst(compiler, ADDIU | SA(0) | TA(OVERFLOW_FLAG) | IMM(src2), OVERFLOW_FLAG)); - FAIL_IF(push_inst(compiler, OR | S(src1) | TA(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG)); + FAIL_IF(push_inst(compiler, ADDIU | SA(0) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG)); + FAIL_IF(push_inst(compiler, OR | S(src1) | TA(EQUAL_FLAG) | DA(EQUAL_FLAG), EQUAL_FLAG)); } } FAIL_IF(push_inst(compiler, ADDIU | S(src1) | T(dst) | IMM(src2), DR(dst))); } else { - if (op & SLJIT_SET_C) - FAIL_IF(push_inst(compiler, OR | S(src1) | T(src2) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG)); + if (is_carry) + FAIL_IF(push_inst(compiler, OR | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG)); /* dst may be the same as src1 or src2. */ FAIL_IF(push_inst(compiler, ADDU | S(src1) | T(src2) | D(dst), DR(dst))); } - if (op & SLJIT_SET_C) - FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG)); + if (is_carry) + FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(EQUAL_FLAG) | DA(EQUAL_FLAG), EQUAL_FLAG)); - FAIL_IF(push_inst(compiler, ADDU | S(dst) | TA(ULESS_FLAG) | D(dst), DR(dst))); - if (!(op & SLJIT_SET_C)) + FAIL_IF(push_inst(compiler, ADDU | S(dst) | TA(OTHER_FLAG) | D(dst), DR(dst))); + if (!is_carry) return SLJIT_SUCCESS; - /* Set ULESS_FLAG (dst == 0) && (ULESS_FLAG == 1). */ - FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(ULESS_FLAG) | DA(ULESS_FLAG), ULESS_FLAG)); + /* Set ULESS_FLAG (dst == 0) && (OTHER_FLAG == 1). */ + FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(OTHER_FLAG) | DA(OTHER_FLAG), OTHER_FLAG)); /* Set carry flag. */ - return push_inst(compiler, OR | SA(ULESS_FLAG) | TA(OVERFLOW_FLAG) | DA(ULESS_FLAG), ULESS_FLAG); + return push_inst(compiler, OR | SA(OTHER_FLAG) | TA(EQUAL_FLAG) | DA(OTHER_FLAG), OTHER_FLAG); case SLJIT_SUB: - if ((flags & SRC2_IMM) && ((op & (SLJIT_SET_U | SLJIT_SET_S)) || src2 == SIMM_MIN)) { + if ((flags & SRC2_IMM) && src2 == SIMM_MIN) { FAIL_IF(push_inst(compiler, ADDIU | SA(0) | T(TMP_REG2) | IMM(src2), DR(TMP_REG2))); src2 = TMP_REG2; flags &= ~SRC2_IMM; } + is_handled = 0; + + if (flags & SRC2_IMM) { + if (GET_FLAG_TYPE(op) == SLJIT_LESS || GET_FLAG_TYPE(op) == SLJIT_GREATER_EQUAL) { + FAIL_IF(push_inst(compiler, SLTIU | S(src1) | TA(OTHER_FLAG) | IMM(src2), OTHER_FLAG)); + is_handled = 1; + } + else if (GET_FLAG_TYPE(op) == SLJIT_SIG_LESS || GET_FLAG_TYPE(op) == SLJIT_SIG_GREATER_EQUAL) { + FAIL_IF(push_inst(compiler, SLTI | S(src1) | TA(OTHER_FLAG) | IMM(src2), OTHER_FLAG)); + is_handled = 1; + } + } + + if (!is_handled && GET_FLAG_TYPE(op) >= SLJIT_LESS && GET_FLAG_TYPE(op) <= SLJIT_SIG_LESS_EQUAL) { + is_handled = 1; + + if (flags & SRC2_IMM) { + FAIL_IF(push_inst(compiler, ADDIU | SA(0) | T(TMP_REG2) | IMM(src2), DR(TMP_REG2))); + src2 = TMP_REG2; + flags &= ~SRC2_IMM; + } + + if (GET_FLAG_TYPE(op) == SLJIT_LESS || GET_FLAG_TYPE(op) == SLJIT_GREATER_EQUAL) { + FAIL_IF(push_inst(compiler, SLTU | S(src1) | T(src2) | DA(OTHER_FLAG), OTHER_FLAG)); + } + else if (GET_FLAG_TYPE(op) == SLJIT_GREATER || GET_FLAG_TYPE(op) == SLJIT_LESS_EQUAL) + { + FAIL_IF(push_inst(compiler, SLTU | S(src2) | T(src1) | DA(OTHER_FLAG), OTHER_FLAG)); + } + else if (GET_FLAG_TYPE(op) == SLJIT_SIG_LESS || GET_FLAG_TYPE(op) == SLJIT_SIG_GREATER_EQUAL) { + FAIL_IF(push_inst(compiler, SLT | S(src1) | T(src2) | DA(OTHER_FLAG), OTHER_FLAG)); + } + else if (GET_FLAG_TYPE(op) == SLJIT_SIG_GREATER || GET_FLAG_TYPE(op) == SLJIT_SIG_LESS_EQUAL) + { + FAIL_IF(push_inst(compiler, SLT | S(src2) | T(src1) | DA(OTHER_FLAG), OTHER_FLAG)); + } + } + + if (is_handled) { + if (flags & SRC2_IMM) { + if (op & SLJIT_SET_Z) + FAIL_IF(push_inst(compiler, ADDIU | S(src1) | TA(EQUAL_FLAG) | IMM(-src2), EQUAL_FLAG)); + if (!(flags & UNUSED_DEST)) + return push_inst(compiler, ADDIU | S(src1) | T(dst) | IMM(-src2), DR(dst)); + } + else { + if (op & SLJIT_SET_Z) + FAIL_IF(push_inst(compiler, SUBU | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG)); + if (!(flags & UNUSED_DEST)) + return push_inst(compiler, SUBU | S(src1) | T(src2) | D(dst), DR(dst)); + } + return SLJIT_SUCCESS; + } + + is_overflow = GET_FLAG_TYPE(op) == SLJIT_OVERFLOW; + is_carry = GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY); + if (flags & SRC2_IMM) { - if (op & SLJIT_SET_O) { + if (is_overflow) { if (src2 >= 0) - FAIL_IF(push_inst(compiler, OR | S(src1) | T(src1) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG)); + FAIL_IF(push_inst(compiler, OR | S(src1) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG)); else - FAIL_IF(push_inst(compiler, NOR | S(src1) | T(src1) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG)); + FAIL_IF(push_inst(compiler, NOR | S(src1) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG)); } - if (op & SLJIT_SET_E) + else if (op & SLJIT_SET_Z) FAIL_IF(push_inst(compiler, ADDIU | S(src1) | TA(EQUAL_FLAG) | IMM(-src2), EQUAL_FLAG)); - if (op & (SLJIT_SET_C | SLJIT_SET_O)) - FAIL_IF(push_inst(compiler, SLTIU | S(src1) | TA(ULESS_FLAG) | IMM(src2), ULESS_FLAG)); + + if (is_overflow || is_carry) + FAIL_IF(push_inst(compiler, SLTIU | S(src1) | TA(OTHER_FLAG) | IMM(src2), OTHER_FLAG)); /* dst may be the same as src1 or src2. */ - if (CHECK_FLAGS(SLJIT_SET_E)) + if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK)) FAIL_IF(push_inst(compiler, ADDIU | S(src1) | T(dst) | IMM(-src2), DR(dst))); } else { - if (op & SLJIT_SET_O) - FAIL_IF(push_inst(compiler, XOR | S(src1) | T(src2) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG)); - if (op & SLJIT_SET_E) + if (is_overflow) + FAIL_IF(push_inst(compiler, XOR | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG)); + else if (op & SLJIT_SET_Z) FAIL_IF(push_inst(compiler, SUBU | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG)); - if (op & (SLJIT_SET_U | SLJIT_SET_C | SLJIT_SET_O)) - FAIL_IF(push_inst(compiler, SLTU | S(src1) | T(src2) | DA(ULESS_FLAG), ULESS_FLAG)); - if (op & SLJIT_SET_U) - FAIL_IF(push_inst(compiler, SLTU | S(src2) | T(src1) | DA(UGREATER_FLAG), UGREATER_FLAG)); - if (op & SLJIT_SET_S) { - FAIL_IF(push_inst(compiler, SLT | S(src1) | T(src2) | DA(LESS_FLAG), LESS_FLAG)); - FAIL_IF(push_inst(compiler, SLT | S(src2) | T(src1) | DA(GREATER_FLAG), GREATER_FLAG)); - } + + if (is_overflow || is_carry) + FAIL_IF(push_inst(compiler, SLTU | S(src1) | T(src2) | DA(OTHER_FLAG), OTHER_FLAG)); /* dst may be the same as src1 or src2. */ - if (CHECK_FLAGS(SLJIT_SET_E | SLJIT_SET_U | SLJIT_SET_S | SLJIT_SET_C)) + if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK)) FAIL_IF(push_inst(compiler, SUBU | S(src1) | T(src2) | D(dst), DR(dst))); } - if (!(op & SLJIT_SET_O)) + if (!is_overflow) return SLJIT_SUCCESS; - FAIL_IF(push_inst(compiler, SLL | TA(ULESS_FLAG) | D(TMP_REG1) | SH_IMM(31), DR(TMP_REG1))); - FAIL_IF(push_inst(compiler, XOR | S(TMP_REG1) | TA(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG)); - FAIL_IF(push_inst(compiler, XOR | S(dst) | TA(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG)); - return push_inst(compiler, SRL | TA(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG) | SH_IMM(31), OVERFLOW_FLAG); + FAIL_IF(push_inst(compiler, SLL | TA(OTHER_FLAG) | D(TMP_REG1) | SH_IMM(31), DR(TMP_REG1))); + FAIL_IF(push_inst(compiler, XOR | S(TMP_REG1) | TA(EQUAL_FLAG) | DA(EQUAL_FLAG), EQUAL_FLAG)); + FAIL_IF(push_inst(compiler, XOR | S(dst) | TA(EQUAL_FLAG) | DA(OTHER_FLAG), OTHER_FLAG)); + if (op & SLJIT_SET_Z) + FAIL_IF(push_inst(compiler, ADDU | S(dst) | TA(0) | DA(EQUAL_FLAG), EQUAL_FLAG)); + return push_inst(compiler, SRL | TA(OTHER_FLAG) | DA(OTHER_FLAG) | SH_IMM(31), OTHER_FLAG); case SLJIT_SUBC: if ((flags & SRC2_IMM) && src2 == SIMM_MIN) { @@ -277,28 +343,31 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl flags &= ~SRC2_IMM; } + is_carry = GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY); + if (flags & SRC2_IMM) { - if (op & SLJIT_SET_C) - FAIL_IF(push_inst(compiler, SLTIU | S(src1) | TA(OVERFLOW_FLAG) | IMM(src2), OVERFLOW_FLAG)); + if (is_carry) + FAIL_IF(push_inst(compiler, SLTIU | S(src1) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG)); /* dst may be the same as src1 or src2. */ FAIL_IF(push_inst(compiler, ADDIU | S(src1) | T(dst) | IMM(-src2), DR(dst))); } else { - if (op & SLJIT_SET_C) - FAIL_IF(push_inst(compiler, SLTU | S(src1) | T(src2) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG)); + if (is_carry) + FAIL_IF(push_inst(compiler, SLTU | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG)); /* dst may be the same as src1 or src2. */ FAIL_IF(push_inst(compiler, SUBU | S(src1) | T(src2) | D(dst), DR(dst))); } - if (op & SLJIT_SET_C) - FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(ULESS_FLAG) | DA(LESS_FLAG), LESS_FLAG)); + if (is_carry) + FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(OTHER_FLAG) | D(TMP_REG1), DR(TMP_REG1))); - FAIL_IF(push_inst(compiler, SUBU | S(dst) | TA(ULESS_FLAG) | D(dst), DR(dst))); - return (op & SLJIT_SET_C) ? push_inst(compiler, OR | SA(OVERFLOW_FLAG) | TA(LESS_FLAG) | DA(ULESS_FLAG), ULESS_FLAG) : SLJIT_SUCCESS; + FAIL_IF(push_inst(compiler, SUBU | S(dst) | TA(OTHER_FLAG) | D(dst), DR(dst))); + return (is_carry) ? push_inst(compiler, OR | SA(EQUAL_FLAG) | T(TMP_REG1) | DA(OTHER_FLAG), OTHER_FLAG) : SLJIT_SUCCESS; case SLJIT_MUL: SLJIT_ASSERT(!(flags & SRC2_IMM)); - if (!(op & SLJIT_SET_O)) { + + if (GET_FLAG_TYPE(op) != SLJIT_MUL_OVERFLOW) { #if (defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1) return push_inst(compiler, MUL | S(src1) | T(src2) | D(dst), DR(dst)); #else @@ -307,10 +376,10 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl #endif } FAIL_IF(push_inst(compiler, MULT | S(src1) | T(src2), MOVABLE_INS)); - FAIL_IF(push_inst(compiler, MFHI | DA(ULESS_FLAG), ULESS_FLAG)); + FAIL_IF(push_inst(compiler, MFHI | DA(EQUAL_FLAG), EQUAL_FLAG)); FAIL_IF(push_inst(compiler, MFLO | D(dst), DR(dst))); - FAIL_IF(push_inst(compiler, SRA | T(dst) | DA(UGREATER_FLAG) | SH_IMM(31), UGREATER_FLAG)); - return push_inst(compiler, SUBU | SA(ULESS_FLAG) | TA(UGREATER_FLAG) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG); + FAIL_IF(push_inst(compiler, SRA | T(dst) | DA(OTHER_FLAG) | SH_IMM(31), OTHER_FLAG)); + return push_inst(compiler, SUBU | SA(EQUAL_FLAG) | TA(OTHER_FLAG) | DA(OTHER_FLAG), OTHER_FLAG); case SLJIT_AND: EMIT_LOGICAL(ANDI, AND); @@ -337,7 +406,7 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl return SLJIT_SUCCESS; } - SLJIT_ASSERT_STOP(); + SLJIT_UNREACHABLE(); return SLJIT_SUCCESS; } @@ -366,3 +435,232 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_consta inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset); SLJIT_CACHE_FLUSH(inst, inst + 2); } + +static sljit_s32 call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_types, sljit_ins *ins_ptr) +{ + sljit_s32 stack_offset = 0; + sljit_s32 arg_count = 0; + sljit_s32 float_arg_count = 0; + sljit_s32 word_arg_count = 0; + sljit_s32 types = 0; + sljit_s32 arg_count_save, types_save; + sljit_ins prev_ins = NOP; + sljit_ins ins = NOP; + sljit_u8 offsets[4]; + + SLJIT_ASSERT(reg_map[TMP_REG3] == 4 && freg_map[TMP_FREG1] == 12); + + arg_types >>= SLJIT_DEF_SHIFT; + + while (arg_types) { + types = (types << SLJIT_DEF_SHIFT) | (arg_types & SLJIT_DEF_MASK); + + switch (arg_types & SLJIT_DEF_MASK) { + case SLJIT_ARG_TYPE_F32: + offsets[arg_count] = (sljit_u8)stack_offset; + + if (word_arg_count == 0 && arg_count <= 1) + offsets[arg_count] = 254 + arg_count; + + stack_offset += sizeof(sljit_f32); + arg_count++; + float_arg_count++; + break; + case SLJIT_ARG_TYPE_F64: + if (stack_offset & 0x7) + stack_offset += sizeof(sljit_sw); + offsets[arg_count] = (sljit_u8)stack_offset; + + if (word_arg_count == 0 && arg_count <= 1) + offsets[arg_count] = 254 + arg_count; + + stack_offset += sizeof(sljit_f64); + arg_count++; + float_arg_count++; + break; + default: + offsets[arg_count] = (sljit_u8)stack_offset; + stack_offset += sizeof(sljit_sw); + arg_count++; + word_arg_count++; + break; + } + + arg_types >>= SLJIT_DEF_SHIFT; + } + + /* Stack is aligned to 16 bytes, max two doubles can be placed on the stack. */ + if (stack_offset > 16) + FAIL_IF(push_inst(compiler, ADDIU | S(SLJIT_SP) | T(SLJIT_SP) | IMM(-16), DR(SLJIT_SP))); + + types_save = types; + arg_count_save = arg_count; + + while (types) { + switch (types & SLJIT_DEF_MASK) { + case SLJIT_ARG_TYPE_F32: + arg_count--; + if (offsets[arg_count] < 254) + ins = SWC1 | S(SLJIT_SP) | FT(float_arg_count) | IMM(offsets[arg_count]); + float_arg_count--; + break; + case SLJIT_ARG_TYPE_F64: + arg_count--; + if (offsets[arg_count] < 254) + ins = SDC1 | S(SLJIT_SP) | FT(float_arg_count) | IMM(offsets[arg_count]); + float_arg_count--; + break; + default: + if (offsets[arg_count - 1] >= 16) + ins = SW | S(SLJIT_SP) | T(word_arg_count) | IMM(offsets[arg_count - 1]); + else if (arg_count != word_arg_count) + ins = ADDU | S(word_arg_count) | TA(0) | DA(4 + (offsets[arg_count - 1] >> 2)); + else if (arg_count == 1) + ins = ADDU | S(SLJIT_R0) | TA(0) | D(TMP_REG3); + + arg_count--; + word_arg_count--; + break; + } + + if (ins != NOP) { + if (prev_ins != NOP) + FAIL_IF(push_inst(compiler, prev_ins, MOVABLE_INS)); + prev_ins = ins; + ins = NOP; + } + + types >>= SLJIT_DEF_SHIFT; + } + + types = types_save; + arg_count = arg_count_save; + + while (types) { + switch (types & SLJIT_DEF_MASK) { + case SLJIT_ARG_TYPE_F32: + arg_count--; + if (offsets[arg_count] == 254) + ins = MOV_S | FMT_S | FS(SLJIT_FR0) | FD(TMP_FREG1); + else if (offsets[arg_count] < 16) + ins = LW | S(SLJIT_SP) | TA(4 + (offsets[arg_count] >> 2)) | IMM(offsets[arg_count]); + break; + case SLJIT_ARG_TYPE_F64: + arg_count--; + if (offsets[arg_count] == 254) + ins = MOV_S | FMT_D | FS(SLJIT_FR0) | FD(TMP_FREG1); + else if (offsets[arg_count] < 16) { + if (prev_ins != NOP) + FAIL_IF(push_inst(compiler, prev_ins, MOVABLE_INS)); + prev_ins = LW | S(SLJIT_SP) | TA(4 + (offsets[arg_count] >> 2)) | IMM(offsets[arg_count]); + ins = LW | S(SLJIT_SP) | TA(5 + (offsets[arg_count] >> 2)) | IMM(offsets[arg_count] + sizeof(sljit_sw)); + } + break; + default: + arg_count--; + break; + } + + if (ins != NOP) { + if (prev_ins != NOP) + FAIL_IF(push_inst(compiler, prev_ins, MOVABLE_INS)); + prev_ins = ins; + ins = NOP; + } + + types >>= SLJIT_DEF_SHIFT; + } + + *ins_ptr = prev_ins; + + return SLJIT_SUCCESS; +} + +static sljit_s32 post_call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_types) +{ + sljit_s32 stack_offset = 0; + + arg_types >>= SLJIT_DEF_SHIFT; + + while (arg_types) { + switch (arg_types & SLJIT_DEF_MASK) { + case SLJIT_ARG_TYPE_F32: + stack_offset += sizeof(sljit_f32); + break; + case SLJIT_ARG_TYPE_F64: + if (stack_offset & 0x7) + stack_offset += sizeof(sljit_sw); + stack_offset += sizeof(sljit_f64); + break; + default: + stack_offset += sizeof(sljit_sw); + break; + } + + arg_types >>= SLJIT_DEF_SHIFT; + } + + /* Stack is aligned to 16 bytes, max two doubles can be placed on the stack. */ + if (stack_offset > 16) + return push_inst(compiler, ADDIU | S(SLJIT_SP) | T(SLJIT_SP) | IMM(16), DR(SLJIT_SP)); + + return SLJIT_SUCCESS; +} + +SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 arg_types) +{ + struct sljit_jump *jump; + sljit_ins ins; + + CHECK_ERROR_PTR(); + CHECK_PTR(check_sljit_emit_call(compiler, type, arg_types)); + + jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump)); + PTR_FAIL_IF(!jump); + set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP); + type &= 0xff; + + PTR_FAIL_IF(call_with_args(compiler, arg_types, &ins)); + + SLJIT_ASSERT(DR(PIC_ADDR_REG) == 25 && PIC_ADDR_REG == TMP_REG2); + + PTR_FAIL_IF(emit_const(compiler, PIC_ADDR_REG, 0)); + + jump->flags |= IS_JAL | IS_CALL; + PTR_FAIL_IF(push_inst(compiler, JALR | S(PIC_ADDR_REG) | DA(RETURN_ADDR_REG), UNMOVABLE_INS)); + jump->addr = compiler->size; + PTR_FAIL_IF(push_inst(compiler, ins, UNMOVABLE_INS)); + + PTR_FAIL_IF(post_call_with_args(compiler, arg_types)); + + return jump; +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 arg_types, + sljit_s32 src, sljit_sw srcw) +{ + sljit_ins ins; + + CHECK_ERROR(); + CHECK(check_sljit_emit_icall(compiler, type, arg_types, src, srcw)); + + SLJIT_ASSERT(DR(PIC_ADDR_REG) == 25 && PIC_ADDR_REG == TMP_REG2); + + if (src & SLJIT_IMM) + FAIL_IF(load_immediate(compiler, DR(PIC_ADDR_REG), srcw)); + else if (FAST_IS_REG(src)) + FAIL_IF(push_inst(compiler, ADDU | S(src) | TA(0) | D(PIC_ADDR_REG), DR(PIC_ADDR_REG))); + else if (src & SLJIT_MEM) { + ADJUST_LOCAL_OFFSET(src, srcw); + FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, DR(PIC_ADDR_REG), src, srcw)); + } + + FAIL_IF(call_with_args(compiler, arg_types, &ins)); + + /* Register input. */ + FAIL_IF(push_inst(compiler, JALR | S(PIC_ADDR_REG) | DA(RETURN_ADDR_REG), UNMOVABLE_INS)); + FAIL_IF(push_inst(compiler, ins, UNMOVABLE_INS)); + return post_call_with_args(compiler, arg_types); +} diff --git a/thirdparty/pcre2/src/sljit/sljitNativeMIPS_64.c b/thirdparty/pcre2/src/sljit/sljitNativeMIPS_64.c index 8b96d5b73d..ff6f048659 100644 --- a/thirdparty/pcre2/src/sljit/sljitNativeMIPS_64.c +++ b/thirdparty/pcre2/src/sljit/sljitNativeMIPS_64.c @@ -1,7 +1,7 @@ /* * Stack-less Just-In-Time compiler * - * Copyright 2009-2012 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved. + * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are * permitted provided that the following conditions are met: @@ -123,15 +123,15 @@ static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 dst_a #define EMIT_LOGICAL(op_imm, op_norm) \ if (flags & SRC2_IMM) { \ - if (op & SLJIT_SET_E) \ + if (op & SLJIT_SET_Z) \ FAIL_IF(push_inst(compiler, op_imm | S(src1) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG)); \ - if (CHECK_FLAGS(SLJIT_SET_E)) \ + if (!(flags & UNUSED_DEST)) \ FAIL_IF(push_inst(compiler, op_imm | S(src1) | T(dst) | IMM(src2), DR(dst))); \ } \ else { \ - if (op & SLJIT_SET_E) \ + if (op & SLJIT_SET_Z) \ FAIL_IF(push_inst(compiler, op_norm | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG)); \ - if (CHECK_FLAGS(SLJIT_SET_E)) \ + if (!(flags & UNUSED_DEST)) \ FAIL_IF(push_inst(compiler, op_norm | S(src1) | T(src2) | D(dst), DR(dst))); \ } @@ -144,16 +144,16 @@ static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 dst_a } \ else \ ins = (op & SLJIT_I32_OP) ? op_imm : op_dimm; \ - if (op & SLJIT_SET_E) \ + if (op & SLJIT_SET_Z) \ FAIL_IF(push_inst(compiler, ins | T(src1) | DA(EQUAL_FLAG) | SH_IMM(src2), EQUAL_FLAG)); \ - if (CHECK_FLAGS(SLJIT_SET_E)) \ + if (!(flags & UNUSED_DEST)) \ FAIL_IF(push_inst(compiler, ins | T(src1) | D(dst) | SH_IMM(src2), DR(dst))); \ } \ else { \ ins = (op & SLJIT_I32_OP) ? op_v : op_dv; \ - if (op & SLJIT_SET_E) \ + if (op & SLJIT_SET_Z) \ FAIL_IF(push_inst(compiler, ins | S(src2) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG)); \ - if (CHECK_FLAGS(SLJIT_SET_E)) \ + if (!(flags & UNUSED_DEST)) \ FAIL_IF(push_inst(compiler, ins | S(src2) | T(src1) | D(dst), DR(dst))); \ } @@ -161,6 +161,7 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl sljit_s32 dst, sljit_s32 src1, sljit_sw src2) { sljit_ins ins; + sljit_s32 is_overflow, is_carry, is_handled; switch (GET_OPCODE(op)) { case SLJIT_MOV: @@ -180,8 +181,9 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl } return push_inst(compiler, ANDI | S(src2) | T(dst) | IMM(0xff), DR(dst)); } - else if (dst != src2) - SLJIT_ASSERT_STOP(); + else { + SLJIT_ASSERT(dst == src2); + } return SLJIT_SUCCESS; case SLJIT_MOV_U16: @@ -194,8 +196,9 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl } return push_inst(compiler, ANDI | S(src2) | T(dst) | IMM(0xffff), DR(dst)); } - else if (dst != src2) - SLJIT_ASSERT_STOP(); + else { + SLJIT_ASSERT(dst == src2); + } return SLJIT_SUCCESS; case SLJIT_MOV_U32: @@ -209,18 +212,18 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl case SLJIT_NOT: SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM)); - if (op & SLJIT_SET_E) + if (op & SLJIT_SET_Z) FAIL_IF(push_inst(compiler, NOR | S(src2) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG)); - if (CHECK_FLAGS(SLJIT_SET_E)) + if (!(flags & UNUSED_DEST)) FAIL_IF(push_inst(compiler, NOR | S(src2) | T(src2) | D(dst), DR(dst))); return SLJIT_SUCCESS; case SLJIT_CLZ: SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM)); #if (defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1) - if (op & SLJIT_SET_E) + if (op & SLJIT_SET_Z) FAIL_IF(push_inst(compiler, SELECT_OP(DCLZ, CLZ) | S(src2) | TA(EQUAL_FLAG) | DA(EQUAL_FLAG), EQUAL_FLAG)); - if (CHECK_FLAGS(SLJIT_SET_E)) + if (!(flags & UNUSED_DEST)) FAIL_IF(push_inst(compiler, SELECT_OP(DCLZ, CLZ) | S(src2) | T(dst) | D(dst), DR(dst))); #else if (SLJIT_UNLIKELY(flags & UNUSED_DEST)) { @@ -237,130 +240,192 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(dst) | T(dst) | IMM(1), DR(dst))); FAIL_IF(push_inst(compiler, BGEZ | S(TMP_REG1) | IMM(-2), UNMOVABLE_INS)); FAIL_IF(push_inst(compiler, SELECT_OP(DSLL, SLL) | T(TMP_REG1) | D(TMP_REG1) | SH_IMM(1), UNMOVABLE_INS)); - if (op & SLJIT_SET_E) - return push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(dst) | TA(0) | DA(EQUAL_FLAG), EQUAL_FLAG); #endif return SLJIT_SUCCESS; case SLJIT_ADD: + is_overflow = GET_FLAG_TYPE(op) == SLJIT_OVERFLOW; + is_carry = GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY); + if (flags & SRC2_IMM) { - if (op & SLJIT_SET_O) { + if (is_overflow) { if (src2 >= 0) - FAIL_IF(push_inst(compiler, OR | S(src1) | T(src1) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG)); + FAIL_IF(push_inst(compiler, OR | S(src1) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG)); else - FAIL_IF(push_inst(compiler, NOR | S(src1) | T(src1) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG)); + FAIL_IF(push_inst(compiler, NOR | S(src1) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG)); } - if (op & SLJIT_SET_E) + else if (op & SLJIT_SET_Z) FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG)); - if (op & (SLJIT_SET_C | SLJIT_SET_O)) { + + if (is_overflow || is_carry) { if (src2 >= 0) - FAIL_IF(push_inst(compiler, ORI | S(src1) | TA(ULESS_FLAG) | IMM(src2), ULESS_FLAG)); + FAIL_IF(push_inst(compiler, ORI | S(src1) | TA(OTHER_FLAG) | IMM(src2), OTHER_FLAG)); else { - FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | SA(0) | TA(ULESS_FLAG) | IMM(src2), ULESS_FLAG)); - FAIL_IF(push_inst(compiler, OR | S(src1) | TA(ULESS_FLAG) | DA(ULESS_FLAG), ULESS_FLAG)); + FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | SA(0) | TA(OTHER_FLAG) | IMM(src2), OTHER_FLAG)); + FAIL_IF(push_inst(compiler, OR | S(src1) | TA(OTHER_FLAG) | DA(OTHER_FLAG), OTHER_FLAG)); } } /* dst may be the same as src1 or src2. */ - if (CHECK_FLAGS(SLJIT_SET_E)) + if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK)) FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | T(dst) | IMM(src2), DR(dst))); } else { - if (op & SLJIT_SET_O) - FAIL_IF(push_inst(compiler, XOR | S(src1) | T(src2) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG)); - if (op & SLJIT_SET_E) + if (is_overflow) + FAIL_IF(push_inst(compiler, XOR | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG)); + else if (op & SLJIT_SET_Z) FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG)); - if (op & (SLJIT_SET_C | SLJIT_SET_O)) - FAIL_IF(push_inst(compiler, OR | S(src1) | T(src2) | DA(ULESS_FLAG), ULESS_FLAG)); + + if (is_overflow || is_carry) + FAIL_IF(push_inst(compiler, OR | S(src1) | T(src2) | DA(OTHER_FLAG), OTHER_FLAG)); /* dst may be the same as src1 or src2. */ - if (CHECK_FLAGS(SLJIT_SET_E)) + if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK)) FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src1) | T(src2) | D(dst), DR(dst))); } /* a + b >= a | b (otherwise, the carry should be set to 1). */ - if (op & (SLJIT_SET_C | SLJIT_SET_O)) - FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(ULESS_FLAG) | DA(ULESS_FLAG), ULESS_FLAG)); - if (!(op & SLJIT_SET_O)) + if (is_overflow || is_carry) + FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(OTHER_FLAG) | DA(OTHER_FLAG), OTHER_FLAG)); + if (!is_overflow) return SLJIT_SUCCESS; - FAIL_IF(push_inst(compiler, SELECT_OP(DSLL32, SLL) | TA(ULESS_FLAG) | D(TMP_REG1) | SH_IMM(31), DR(TMP_REG1))); - FAIL_IF(push_inst(compiler, XOR | S(TMP_REG1) | TA(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG)); - FAIL_IF(push_inst(compiler, XOR | S(dst) | TA(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG)); - return push_inst(compiler, SELECT_OP(DSRL32, SLL) | TA(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG) | SH_IMM(31), OVERFLOW_FLAG); + FAIL_IF(push_inst(compiler, SELECT_OP(DSLL32, SLL) | TA(OTHER_FLAG) | D(TMP_REG1) | SH_IMM(31), DR(TMP_REG1))); + FAIL_IF(push_inst(compiler, XOR | S(TMP_REG1) | TA(EQUAL_FLAG) | DA(EQUAL_FLAG), EQUAL_FLAG)); + FAIL_IF(push_inst(compiler, XOR | S(dst) | TA(EQUAL_FLAG) | DA(OTHER_FLAG), OTHER_FLAG)); + if (op & SLJIT_SET_Z) + FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(dst) | TA(0) | DA(EQUAL_FLAG), EQUAL_FLAG)); + return push_inst(compiler, SELECT_OP(DSRL32, SRL) | TA(OTHER_FLAG) | DA(OTHER_FLAG) | SH_IMM(31), OTHER_FLAG); case SLJIT_ADDC: + is_carry = GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY); + if (flags & SRC2_IMM) { - if (op & SLJIT_SET_C) { + if (is_carry) { if (src2 >= 0) - FAIL_IF(push_inst(compiler, ORI | S(src1) | TA(OVERFLOW_FLAG) | IMM(src2), OVERFLOW_FLAG)); + FAIL_IF(push_inst(compiler, ORI | S(src1) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG)); else { - FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | SA(0) | TA(OVERFLOW_FLAG) | IMM(src2), OVERFLOW_FLAG)); - FAIL_IF(push_inst(compiler, OR | S(src1) | TA(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG)); + FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | SA(0) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG)); + FAIL_IF(push_inst(compiler, OR | S(src1) | TA(EQUAL_FLAG) | DA(EQUAL_FLAG), EQUAL_FLAG)); } } FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | T(dst) | IMM(src2), DR(dst))); } else { - if (op & SLJIT_SET_C) - FAIL_IF(push_inst(compiler, OR | S(src1) | T(src2) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG)); + if (is_carry) + FAIL_IF(push_inst(compiler, OR | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG)); /* dst may be the same as src1 or src2. */ FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src1) | T(src2) | D(dst), DR(dst))); } - if (op & SLJIT_SET_C) - FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG)); + if (is_carry) + FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(EQUAL_FLAG) | DA(EQUAL_FLAG), EQUAL_FLAG)); - FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(dst) | TA(ULESS_FLAG) | D(dst), DR(dst))); - if (!(op & SLJIT_SET_C)) + FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(dst) | TA(OTHER_FLAG) | D(dst), DR(dst))); + if (!is_carry) return SLJIT_SUCCESS; - /* Set ULESS_FLAG (dst == 0) && (ULESS_FLAG == 1). */ - FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(ULESS_FLAG) | DA(ULESS_FLAG), ULESS_FLAG)); + /* Set ULESS_FLAG (dst == 0) && (OTHER_FLAG == 1). */ + FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(OTHER_FLAG) | DA(OTHER_FLAG), OTHER_FLAG)); /* Set carry flag. */ - return push_inst(compiler, OR | SA(ULESS_FLAG) | TA(OVERFLOW_FLAG) | DA(ULESS_FLAG), ULESS_FLAG); + return push_inst(compiler, OR | SA(OTHER_FLAG) | TA(EQUAL_FLAG) | DA(OTHER_FLAG), OTHER_FLAG); case SLJIT_SUB: - if ((flags & SRC2_IMM) && ((op & (SLJIT_SET_U | SLJIT_SET_S)) || src2 == SIMM_MIN)) { + if ((flags & SRC2_IMM) && src2 == SIMM_MIN) { FAIL_IF(push_inst(compiler, ADDIU | SA(0) | T(TMP_REG2) | IMM(src2), DR(TMP_REG2))); src2 = TMP_REG2; flags &= ~SRC2_IMM; } + is_handled = 0; + + if (flags & SRC2_IMM) { + if (GET_FLAG_TYPE(op) == SLJIT_LESS || GET_FLAG_TYPE(op) == SLJIT_GREATER_EQUAL) { + FAIL_IF(push_inst(compiler, SLTIU | S(src1) | TA(OTHER_FLAG) | IMM(src2), OTHER_FLAG)); + is_handled = 1; + } + else if (GET_FLAG_TYPE(op) == SLJIT_SIG_LESS || GET_FLAG_TYPE(op) == SLJIT_SIG_GREATER_EQUAL) { + FAIL_IF(push_inst(compiler, SLTI | S(src1) | TA(OTHER_FLAG) | IMM(src2), OTHER_FLAG)); + is_handled = 1; + } + } + + if (!is_handled && GET_FLAG_TYPE(op) >= SLJIT_LESS && GET_FLAG_TYPE(op) <= SLJIT_SIG_LESS_EQUAL) { + is_handled = 1; + + if (flags & SRC2_IMM) { + FAIL_IF(push_inst(compiler, ADDIU | SA(0) | T(TMP_REG2) | IMM(src2), DR(TMP_REG2))); + src2 = TMP_REG2; + flags &= ~SRC2_IMM; + } + + if (GET_FLAG_TYPE(op) == SLJIT_LESS || GET_FLAG_TYPE(op) == SLJIT_GREATER_EQUAL) { + FAIL_IF(push_inst(compiler, SLTU | S(src1) | T(src2) | DA(OTHER_FLAG), OTHER_FLAG)); + } + else if (GET_FLAG_TYPE(op) == SLJIT_GREATER || GET_FLAG_TYPE(op) == SLJIT_LESS_EQUAL) + { + FAIL_IF(push_inst(compiler, SLTU | S(src2) | T(src1) | DA(OTHER_FLAG), OTHER_FLAG)); + } + else if (GET_FLAG_TYPE(op) == SLJIT_SIG_LESS || GET_FLAG_TYPE(op) == SLJIT_SIG_GREATER_EQUAL) { + FAIL_IF(push_inst(compiler, SLT | S(src1) | T(src2) | DA(OTHER_FLAG), OTHER_FLAG)); + } + else if (GET_FLAG_TYPE(op) == SLJIT_SIG_GREATER || GET_FLAG_TYPE(op) == SLJIT_SIG_LESS_EQUAL) + { + FAIL_IF(push_inst(compiler, SLT | S(src2) | T(src1) | DA(OTHER_FLAG), OTHER_FLAG)); + } + } + + if (is_handled) { + if (flags & SRC2_IMM) { + if (op & SLJIT_SET_Z) + FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | TA(EQUAL_FLAG) | IMM(-src2), EQUAL_FLAG)); + if (!(flags & UNUSED_DEST)) + return push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | T(dst) | IMM(-src2), DR(dst)); + } + else { + if (op & SLJIT_SET_Z) + FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG)); + if (!(flags & UNUSED_DEST)) + return push_inst(compiler, SELECT_OP(DSUBU, SUBU) | S(src1) | T(src2) | D(dst), DR(dst)); + } + return SLJIT_SUCCESS; + } + + is_overflow = GET_FLAG_TYPE(op) == SLJIT_OVERFLOW; + is_carry = GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY); + if (flags & SRC2_IMM) { - if (op & SLJIT_SET_O) { + if (is_overflow) { if (src2 >= 0) - FAIL_IF(push_inst(compiler, OR | S(src1) | T(src1) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG)); + FAIL_IF(push_inst(compiler, OR | S(src1) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG)); else - FAIL_IF(push_inst(compiler, NOR | S(src1) | T(src1) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG)); + FAIL_IF(push_inst(compiler, NOR | S(src1) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG)); } - if (op & SLJIT_SET_E) + else if (op & SLJIT_SET_Z) FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | TA(EQUAL_FLAG) | IMM(-src2), EQUAL_FLAG)); - if (op & (SLJIT_SET_C | SLJIT_SET_O)) - FAIL_IF(push_inst(compiler, SLTIU | S(src1) | TA(ULESS_FLAG) | IMM(src2), ULESS_FLAG)); + + if (is_overflow || is_carry) + FAIL_IF(push_inst(compiler, SLTIU | S(src1) | TA(OTHER_FLAG) | IMM(src2), OTHER_FLAG)); /* dst may be the same as src1 or src2. */ - if (CHECK_FLAGS(SLJIT_SET_E)) + if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK)) FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | T(dst) | IMM(-src2), DR(dst))); } else { - if (op & SLJIT_SET_O) - FAIL_IF(push_inst(compiler, XOR | S(src1) | T(src2) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG)); - if (op & SLJIT_SET_E) + if (is_overflow) + FAIL_IF(push_inst(compiler, XOR | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG)); + else if (op & SLJIT_SET_Z) FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG)); - if (op & (SLJIT_SET_U | SLJIT_SET_C | SLJIT_SET_O)) - FAIL_IF(push_inst(compiler, SLTU | S(src1) | T(src2) | DA(ULESS_FLAG), ULESS_FLAG)); - if (op & SLJIT_SET_U) - FAIL_IF(push_inst(compiler, SLTU | S(src2) | T(src1) | DA(UGREATER_FLAG), UGREATER_FLAG)); - if (op & SLJIT_SET_S) { - FAIL_IF(push_inst(compiler, SLT | S(src1) | T(src2) | DA(LESS_FLAG), LESS_FLAG)); - FAIL_IF(push_inst(compiler, SLT | S(src2) | T(src1) | DA(GREATER_FLAG), GREATER_FLAG)); - } + + if (is_overflow || is_carry) + FAIL_IF(push_inst(compiler, SLTU | S(src1) | T(src2) | DA(OTHER_FLAG), OTHER_FLAG)); /* dst may be the same as src1 or src2. */ - if (CHECK_FLAGS(SLJIT_SET_E | SLJIT_SET_U | SLJIT_SET_S | SLJIT_SET_C)) + if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK)) FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | S(src1) | T(src2) | D(dst), DR(dst))); } - if (!(op & SLJIT_SET_O)) + if (!is_overflow) return SLJIT_SUCCESS; - FAIL_IF(push_inst(compiler, SELECT_OP(DSLL32, SLL) | TA(ULESS_FLAG) | D(TMP_REG1) | SH_IMM(31), DR(TMP_REG1))); - FAIL_IF(push_inst(compiler, XOR | S(TMP_REG1) | TA(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG)); - FAIL_IF(push_inst(compiler, XOR | S(dst) | TA(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG)); - return push_inst(compiler, SELECT_OP(DSRL32, SRL) | TA(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG) | SH_IMM(31), OVERFLOW_FLAG); + FAIL_IF(push_inst(compiler, SELECT_OP(DSLL32, SLL) | TA(OTHER_FLAG) | D(TMP_REG1) | SH_IMM(31), DR(TMP_REG1))); + FAIL_IF(push_inst(compiler, XOR | S(TMP_REG1) | TA(EQUAL_FLAG) | DA(EQUAL_FLAG), EQUAL_FLAG)); + FAIL_IF(push_inst(compiler, XOR | S(dst) | TA(EQUAL_FLAG) | DA(OTHER_FLAG), OTHER_FLAG)); + if (op & SLJIT_SET_Z) + FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(dst) | TA(0) | DA(EQUAL_FLAG), EQUAL_FLAG)); + return push_inst(compiler, SELECT_OP(DSRL32, SRL) | TA(OTHER_FLAG) | DA(OTHER_FLAG) | SH_IMM(31), OTHER_FLAG); case SLJIT_SUBC: if ((flags & SRC2_IMM) && src2 == SIMM_MIN) { @@ -369,28 +434,31 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl flags &= ~SRC2_IMM; } + is_carry = GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY); + if (flags & SRC2_IMM) { - if (op & SLJIT_SET_C) - FAIL_IF(push_inst(compiler, SLTIU | S(src1) | TA(OVERFLOW_FLAG) | IMM(src2), OVERFLOW_FLAG)); + if (is_carry) + FAIL_IF(push_inst(compiler, SLTIU | S(src1) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG)); /* dst may be the same as src1 or src2. */ FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | T(dst) | IMM(-src2), DR(dst))); } else { - if (op & SLJIT_SET_C) - FAIL_IF(push_inst(compiler, SLTU | S(src1) | T(src2) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG)); + if (is_carry) + FAIL_IF(push_inst(compiler, SLTU | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG)); /* dst may be the same as src1 or src2. */ FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | S(src1) | T(src2) | D(dst), DR(dst))); } - if (op & SLJIT_SET_C) - FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(ULESS_FLAG) | DA(LESS_FLAG), LESS_FLAG)); + if (is_carry) + FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(OTHER_FLAG) | D(TMP_REG1), DR(TMP_REG1))); - FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | S(dst) | TA(ULESS_FLAG) | D(dst), DR(dst))); - return (op & SLJIT_SET_C) ? push_inst(compiler, OR | SA(OVERFLOW_FLAG) | TA(LESS_FLAG) | DA(ULESS_FLAG), ULESS_FLAG) : SLJIT_SUCCESS; + FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | S(dst) | TA(OTHER_FLAG) | D(dst), DR(dst))); + return (is_carry) ? push_inst(compiler, OR | SA(EQUAL_FLAG) | T(TMP_REG1) | DA(OTHER_FLAG), OTHER_FLAG) : SLJIT_SUCCESS; case SLJIT_MUL: SLJIT_ASSERT(!(flags & SRC2_IMM)); - if (!(op & SLJIT_SET_O)) { + + if (GET_FLAG_TYPE(op) != SLJIT_MUL_OVERFLOW) { #if (defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1) if (op & SLJIT_I32_OP) return push_inst(compiler, MUL | S(src1) | T(src2) | D(dst), DR(dst)); @@ -402,10 +470,10 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl #endif } FAIL_IF(push_inst(compiler, SELECT_OP(DMULT, MULT) | S(src1) | T(src2), MOVABLE_INS)); - FAIL_IF(push_inst(compiler, MFHI | DA(ULESS_FLAG), ULESS_FLAG)); + FAIL_IF(push_inst(compiler, MFHI | DA(EQUAL_FLAG), EQUAL_FLAG)); FAIL_IF(push_inst(compiler, MFLO | D(dst), DR(dst))); - FAIL_IF(push_inst(compiler, SELECT_OP(DSRA32, SRA) | T(dst) | DA(UGREATER_FLAG) | SH_IMM(31), UGREATER_FLAG)); - return push_inst(compiler, SELECT_OP(DSUBU, SUBU) | SA(ULESS_FLAG) | TA(UGREATER_FLAG) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG); + FAIL_IF(push_inst(compiler, SELECT_OP(DSRA32, SRA) | T(dst) | DA(OTHER_FLAG) | SH_IMM(31), OTHER_FLAG)); + return push_inst(compiler, SELECT_OP(DSUBU, SUBU) | SA(EQUAL_FLAG) | TA(OTHER_FLAG) | DA(OTHER_FLAG), OTHER_FLAG); case SLJIT_AND: EMIT_LOGICAL(ANDI, AND); @@ -432,7 +500,7 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl return SLJIT_SUCCESS; } - SLJIT_ASSERT_STOP(); + SLJIT_UNREACHABLE(); return SLJIT_SUCCESS; } @@ -469,3 +537,132 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_consta inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset); SLJIT_CACHE_FLUSH(inst, inst + 6); } + +static sljit_s32 call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_types, sljit_ins *ins_ptr) +{ + sljit_s32 arg_count = 0; + sljit_s32 word_arg_count = 0; + sljit_s32 float_arg_count = 0; + sljit_s32 types = 0; + sljit_ins prev_ins = NOP; + sljit_ins ins = NOP; + + SLJIT_ASSERT(reg_map[TMP_REG3] == 4 && freg_map[TMP_FREG1] == 12); + + arg_types >>= SLJIT_DEF_SHIFT; + + while (arg_types) { + types = (types << SLJIT_DEF_SHIFT) | (arg_types & SLJIT_DEF_MASK); + + switch (arg_types & SLJIT_DEF_MASK) { + case SLJIT_ARG_TYPE_F32: + case SLJIT_ARG_TYPE_F64: + arg_count++; + float_arg_count++; + break; + default: + arg_count++; + word_arg_count++; + break; + } + + arg_types >>= SLJIT_DEF_SHIFT; + } + + while (types) { + switch (types & SLJIT_DEF_MASK) { + case SLJIT_ARG_TYPE_F32: + if (arg_count != float_arg_count) + ins = MOV_S | FMT_S | FS(float_arg_count) | FD(arg_count); + else if (arg_count == 1) + ins = MOV_S | FMT_S | FS(SLJIT_FR0) | FD(TMP_FREG1); + arg_count--; + float_arg_count--; + break; + case SLJIT_ARG_TYPE_F64: + if (arg_count != float_arg_count) + ins = MOV_S | FMT_D | FS(float_arg_count) | FD(arg_count); + else if (arg_count == 1) + ins = MOV_S | FMT_D | FS(SLJIT_FR0) | FD(TMP_FREG1); + arg_count--; + float_arg_count--; + break; + default: + if (arg_count != word_arg_count) + ins = DADDU | S(word_arg_count) | TA(0) | D(arg_count); + else if (arg_count == 1) + ins = DADDU | S(SLJIT_R0) | TA(0) | D(TMP_REG3); + arg_count--; + word_arg_count--; + break; + } + + if (ins != NOP) { + if (prev_ins != NOP) + FAIL_IF(push_inst(compiler, prev_ins, MOVABLE_INS)); + prev_ins = ins; + ins = NOP; + } + + types >>= SLJIT_DEF_SHIFT; + } + + *ins_ptr = prev_ins; + + return SLJIT_SUCCESS; +} + +SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 arg_types) +{ + struct sljit_jump *jump; + sljit_ins ins; + + CHECK_ERROR_PTR(); + CHECK_PTR(check_sljit_emit_call(compiler, type, arg_types)); + + jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump)); + PTR_FAIL_IF(!jump); + set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP); + type &= 0xff; + + PTR_FAIL_IF(call_with_args(compiler, arg_types, &ins)); + + SLJIT_ASSERT(DR(PIC_ADDR_REG) == 25 && PIC_ADDR_REG == TMP_REG2); + + PTR_FAIL_IF(emit_const(compiler, PIC_ADDR_REG, 0)); + + jump->flags |= IS_JAL | IS_CALL; + PTR_FAIL_IF(push_inst(compiler, JALR | S(PIC_ADDR_REG) | DA(RETURN_ADDR_REG), UNMOVABLE_INS)); + jump->addr = compiler->size; + PTR_FAIL_IF(push_inst(compiler, ins, UNMOVABLE_INS)); + + return jump; +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 arg_types, + sljit_s32 src, sljit_sw srcw) +{ + sljit_ins ins; + + CHECK_ERROR(); + CHECK(check_sljit_emit_icall(compiler, type, arg_types, src, srcw)); + + SLJIT_ASSERT(DR(PIC_ADDR_REG) == 25 && PIC_ADDR_REG == TMP_REG2); + + if (src & SLJIT_IMM) + FAIL_IF(load_immediate(compiler, DR(PIC_ADDR_REG), srcw)); + else if (FAST_IS_REG(src)) + FAIL_IF(push_inst(compiler, DADDU | S(src) | TA(0) | D(PIC_ADDR_REG), DR(PIC_ADDR_REG))); + else if (src & SLJIT_MEM) { + ADJUST_LOCAL_OFFSET(src, srcw); + FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, DR(PIC_ADDR_REG), src, srcw)); + } + + FAIL_IF(call_with_args(compiler, arg_types, &ins)); + + /* Register input. */ + FAIL_IF(push_inst(compiler, JALR | S(PIC_ADDR_REG) | DA(RETURN_ADDR_REG), UNMOVABLE_INS)); + return push_inst(compiler, ins, UNMOVABLE_INS); +} diff --git a/thirdparty/pcre2/src/sljit/sljitNativeMIPS_common.c b/thirdparty/pcre2/src/sljit/sljitNativeMIPS_common.c index fe37e3ef00..e108433f70 100644 --- a/thirdparty/pcre2/src/sljit/sljitNativeMIPS_common.c +++ b/thirdparty/pcre2/src/sljit/sljitNativeMIPS_common.c @@ -1,7 +1,7 @@ /* * Stack-less Just-In-Time compiler * - * Copyright 2009-2012 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved. + * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are * permitted provided that the following conditions are met: @@ -57,21 +57,30 @@ typedef sljit_u32 sljit_ins; #define RETURN_ADDR_REG 31 /* Flags are kept in volatile registers. */ -#define EQUAL_FLAG 12 -/* And carry flag as well. */ -#define ULESS_FLAG 13 -#define UGREATER_FLAG 14 -#define LESS_FLAG 15 -#define GREATER_FLAG 31 -#define OVERFLOW_FLAG 1 +#define EQUAL_FLAG 31 +#define OTHER_FLAG 1 -#define TMP_FREG1 (0) -#define TMP_FREG2 ((SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1) << 1) +#define TMP_FREG1 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1) +#define TMP_FREG2 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 2) static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 5] = { - 0, 2, 5, 6, 7, 8, 9, 10, 11, 24, 23, 22, 21, 20, 19, 18, 17, 16, 29, 3, 25, 4 + 0, 2, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 24, 23, 22, 21, 20, 19, 18, 17, 16, 29, 3, 25, 4 }; +#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) + +static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3] = { + 0, 0, 14, 2, 4, 6, 8, 12, 10 +}; + +#else + +static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3] = { + 0, 0, 13, 14, 15, 16, 17, 12, 18 +}; + +#endif + /* --------------------------------------------------------------------- */ /* Instrucion forms */ /* --------------------------------------------------------------------- */ @@ -79,21 +88,23 @@ static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 5] = { #define S(s) (reg_map[s] << 21) #define T(t) (reg_map[t] << 16) #define D(d) (reg_map[d] << 11) +#define FT(t) (freg_map[t] << 16) +#define FS(s) (freg_map[s] << 11) +#define FD(d) (freg_map[d] << 6) /* Absolute registers. */ #define SA(s) ((s) << 21) #define TA(t) ((t) << 16) #define DA(d) ((d) << 11) -#define FT(t) ((t) << 16) -#define FS(s) ((s) << 11) -#define FD(d) ((d) << 6) #define IMM(imm) ((imm) & 0xffff) #define SH_IMM(imm) ((imm) << 6) #define DR(dr) (reg_map[dr]) +#define FR(dr) (freg_map[dr]) #define HI(opcode) ((opcode) << 26) #define LO(opcode) (opcode) /* S = (16 << 21) D = (17 << 21) */ #define FMT_S (16 << 21) +#define FMT_D (17 << 21) #define ABS_S (HI(17) | FMT_S | LO(5)) #define ADD_S (HI(17) | FMT_S | LO(0)) @@ -158,6 +169,7 @@ static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 5] = { #define OR (HI(0) | LO(37)) #define ORI (HI(13)) #define SD (HI(63)) +#define SDC1 (HI(61)) #define SLT (HI(0) | LO(42)) #define SLTI (HI(10)) #define SLTIU (HI(11)) @@ -171,6 +183,7 @@ static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 5] = { #define SUB_S (HI(17) | FMT_S | LO(1)) #define SUBU (HI(0) | LO(35)) #define SW (HI(43)) +#define SWC1 (HI(57)) #define TRUNC_W_S (HI(17) | FMT_S | LO(13)) #define XOR (HI(0) | LO(38)) #define XORI (HI(14)) @@ -178,7 +191,13 @@ static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 5] = { #if (defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1) #define CLZ (HI(28) | LO(32)) #define DCLZ (HI(28) | LO(36)) +#define MOVF (HI(0) | (0 << 16) | LO(1)) +#define MOVN (HI(0) | LO(11)) +#define MOVT (HI(0) | (1 << 16) | LO(1)) +#define MOVZ (HI(0) | LO(10)) #define MUL (HI(28) | LO(2)) +#define PREF (HI(51)) +#define PREFX (HI(19) | LO(15)) #define SEB (HI(31) | (16 << 6) | LO(32)) #define SEH (HI(31) | (24 << 6) | LO(32)) #endif @@ -495,6 +514,32 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil return code; } +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type) +{ + sljit_sw fir = 0; + + switch (feature_type) { + case SLJIT_HAS_FPU: +#ifdef SLJIT_IS_FPU_AVAILABLE + return SLJIT_IS_FPU_AVAILABLE; +#elif defined(__GNUC__) + asm ("cfc1 %0, $0" : "=r"(fir)); + return (fir >> 22) & 0x1; +#else +#error "FIR check is not implemented for this architecture" +#endif + +#if (defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1) + case SLJIT_HAS_CLZ: + case SLJIT_HAS_CMOV: + return 1; +#endif + + default: + return fir; + } +} + /* --------------------------------------------------------------------- */ /* Entry, exit */ /* --------------------------------------------------------------------- */ @@ -513,25 +558,20 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil #define MEM_MASK 0x1f -#define WRITE_BACK 0x00020 -#define ARG_TEST 0x00040 -#define ALT_KEEP_CACHE 0x00080 -#define CUMULATIVE_OP 0x00100 -#define LOGICAL_OP 0x00200 -#define IMM_OP 0x00400 -#define SRC2_IMM 0x00800 - -#define UNUSED_DEST 0x01000 -#define REG_DEST 0x02000 -#define REG1_SOURCE 0x04000 -#define REG2_SOURCE 0x08000 -#define SLOW_SRC1 0x10000 -#define SLOW_SRC2 0x20000 -#define SLOW_DEST 0x40000 - -/* Only these flags are set. UNUSED_DEST is not set when no flags should be set. */ -#define CHECK_FLAGS(list) \ - (!(flags & UNUSED_DEST) || (op & GET_FLAGS(~(list)))) +#define ARG_TEST 0x00020 +#define ALT_KEEP_CACHE 0x00040 +#define CUMULATIVE_OP 0x00080 +#define LOGICAL_OP 0x00100 +#define IMM_OP 0x00200 +#define SRC2_IMM 0x00400 + +#define UNUSED_DEST 0x00800 +#define REG_DEST 0x01000 +#define REG1_SOURCE 0x02000 +#define REG2_SOURCE 0x04000 +#define SLOW_SRC1 0x08000 +#define SLOW_SRC2 0x10000 +#define SLOW_DEST 0x20000 #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) #define STACK_STORE SW @@ -541,6 +581,8 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil #define STACK_LOAD LD #endif +static SLJIT_INLINE sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg_ar, sljit_s32 arg, sljit_sw argw); + #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) #include "sljitNativeMIPS_32.c" #else @@ -548,15 +590,15 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil #endif SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compiler, - sljit_s32 options, sljit_s32 args, sljit_s32 scratches, sljit_s32 saveds, + sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds, sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size) { sljit_ins base; - sljit_s32 i, tmp, offs; + sljit_s32 args, i, tmp, offs; CHECK_ERROR(); - CHECK(check_sljit_emit_enter(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size)); - set_emit_enter(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size); + CHECK(check_sljit_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size)); + set_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size); local_size += GET_SAVED_REGISTERS_SIZE(scratches, saveds, 1) + SLJIT_LOCALS_OFFSET; #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) @@ -593,6 +635,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi FAIL_IF(push_inst(compiler, STACK_STORE | base | T(i) | IMM(offs), MOVABLE_INS)); } + args = get_arg_count(arg_types); + if (args >= 1) FAIL_IF(push_inst(compiler, ADDU_W | SA(4) | TA(0) | D(SLJIT_S0), DR(SLJIT_S0))); if (args >= 2) @@ -604,12 +648,12 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *compiler, - sljit_s32 options, sljit_s32 args, sljit_s32 scratches, sljit_s32 saveds, + sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds, sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size) { CHECK_ERROR(); - CHECK(check_sljit_set_context(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size)); - set_set_context(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size); + CHECK(check_sljit_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size)); + set_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size); local_size += GET_SAVED_REGISTERS_SIZE(scratches, saveds, 1) + SLJIT_LOCALS_OFFSET; #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) @@ -711,7 +755,7 @@ static sljit_s32 getput_arg_fast(struct sljit_compiler *compiler, sljit_s32 flag { SLJIT_ASSERT(arg & SLJIT_MEM); - if ((!(flags & WRITE_BACK) || !(arg & REG_MASK)) && !(arg & OFFS_REG_MASK) && argw <= SIMM_MAX && argw >= SIMM_MIN) { + if (!(arg & OFFS_REG_MASK) && argw <= SIMM_MAX && argw >= SIMM_MIN) { /* Works for both absoulte and relative addresses. */ if (SLJIT_UNLIKELY(flags & ARG_TEST)) return 1; @@ -769,33 +813,21 @@ static sljit_s32 getput_arg(struct sljit_compiler *compiler, sljit_s32 flags, sl if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) { argw &= 0x3; - if ((flags & WRITE_BACK) && reg_ar == DR(base)) { - SLJIT_ASSERT(!(flags & LOAD_DATA) && DR(TMP_REG1) != reg_ar); - FAIL_IF(push_inst(compiler, ADDU_W | SA(reg_ar) | TA(0) | D(TMP_REG1), DR(TMP_REG1))); - reg_ar = DR(TMP_REG1); - } /* Using the cache. */ if (argw == compiler->cache_argw) { - if (!(flags & WRITE_BACK)) { - if (arg == compiler->cache_arg) + if (arg == compiler->cache_arg) + return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(TMP_REG3) | TA(reg_ar), delay_slot); + + if ((SLJIT_MEM | (arg & OFFS_REG_MASK)) == compiler->cache_arg) { + if (arg == next_arg && argw == (next_argw & 0x3)) { + compiler->cache_arg = arg; + compiler->cache_argw = argw; + FAIL_IF(push_inst(compiler, ADDU_W | S(base) | T(TMP_REG3) | D(TMP_REG3), DR(TMP_REG3))); return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(TMP_REG3) | TA(reg_ar), delay_slot); - if ((SLJIT_MEM | (arg & OFFS_REG_MASK)) == compiler->cache_arg) { - if (arg == next_arg && argw == (next_argw & 0x3)) { - compiler->cache_arg = arg; - compiler->cache_argw = argw; - FAIL_IF(push_inst(compiler, ADDU_W | S(base) | T(TMP_REG3) | D(TMP_REG3), DR(TMP_REG3))); - return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(TMP_REG3) | TA(reg_ar), delay_slot); - } - FAIL_IF(push_inst(compiler, ADDU_W | S(base) | T(TMP_REG3) | DA(tmp_ar), tmp_ar)); - return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | SA(tmp_ar) | TA(reg_ar), delay_slot); - } - } - else { - if ((SLJIT_MEM | (arg & OFFS_REG_MASK)) == compiler->cache_arg) { - FAIL_IF(push_inst(compiler, ADDU_W | S(base) | T(TMP_REG3) | D(base), DR(base))); - return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(base) | TA(reg_ar), delay_slot); } + FAIL_IF(push_inst(compiler, ADDU_W | S(base) | T(TMP_REG3) | DA(tmp_ar), tmp_ar)); + return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | SA(tmp_ar) | TA(reg_ar), delay_slot); } } @@ -805,55 +837,15 @@ static sljit_s32 getput_arg(struct sljit_compiler *compiler, sljit_s32 flags, sl FAIL_IF(push_inst(compiler, SLL_W | T(OFFS_REG(arg)) | D(TMP_REG3) | SH_IMM(argw), DR(TMP_REG3))); } - if (!(flags & WRITE_BACK)) { - if (arg == next_arg && argw == (next_argw & 0x3)) { - compiler->cache_arg = arg; - compiler->cache_argw = argw; - FAIL_IF(push_inst(compiler, ADDU_W | S(base) | T(!argw ? OFFS_REG(arg) : TMP_REG3) | D(TMP_REG3), DR(TMP_REG3))); - tmp_ar = DR(TMP_REG3); - } - else - FAIL_IF(push_inst(compiler, ADDU_W | S(base) | T(!argw ? OFFS_REG(arg) : TMP_REG3) | DA(tmp_ar), tmp_ar)); - return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | SA(tmp_ar) | TA(reg_ar), delay_slot); - } - FAIL_IF(push_inst(compiler, ADDU_W | S(base) | T(!argw ? OFFS_REG(arg) : TMP_REG3) | D(base), DR(base))); - return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(base) | TA(reg_ar), delay_slot); - } - - if (SLJIT_UNLIKELY(flags & WRITE_BACK) && base) { - /* Update only applies if a base register exists. */ - if (reg_ar == DR(base)) { - SLJIT_ASSERT(!(flags & LOAD_DATA) && DR(TMP_REG1) != reg_ar); - if (argw <= SIMM_MAX && argw >= SIMM_MIN) { - FAIL_IF(push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(base) | TA(reg_ar) | IMM(argw), MOVABLE_INS)); - if (argw) - return push_inst(compiler, ADDIU_W | S(base) | T(base) | IMM(argw), DR(base)); - return SLJIT_SUCCESS; - } - FAIL_IF(push_inst(compiler, ADDU_W | SA(reg_ar) | TA(0) | D(TMP_REG1), DR(TMP_REG1))); - reg_ar = DR(TMP_REG1); - } - - if (argw <= SIMM_MAX && argw >= SIMM_MIN) { - if (argw) - FAIL_IF(push_inst(compiler, ADDIU_W | S(base) | T(base) | IMM(argw), DR(base))); - } - else { - if (compiler->cache_arg == SLJIT_MEM && argw - compiler->cache_argw <= SIMM_MAX && argw - compiler->cache_argw >= SIMM_MIN) { - if (argw != compiler->cache_argw) { - FAIL_IF(push_inst(compiler, ADDIU_W | S(TMP_REG3) | T(TMP_REG3) | IMM(argw - compiler->cache_argw), DR(TMP_REG3))); - compiler->cache_argw = argw; - } - FAIL_IF(push_inst(compiler, ADDU_W | S(base) | T(TMP_REG3) | D(base), DR(base))); - } - else { - compiler->cache_arg = SLJIT_MEM; - compiler->cache_argw = argw; - FAIL_IF(load_immediate(compiler, DR(TMP_REG3), argw)); - FAIL_IF(push_inst(compiler, ADDU_W | S(base) | T(TMP_REG3) | D(base), DR(base))); - } + if (arg == next_arg && argw == (next_argw & 0x3)) { + compiler->cache_arg = arg; + compiler->cache_argw = argw; + FAIL_IF(push_inst(compiler, ADDU_W | S(base) | T(!argw ? OFFS_REG(arg) : TMP_REG3) | D(TMP_REG3), DR(TMP_REG3))); + tmp_ar = DR(TMP_REG3); } - return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(base) | TA(reg_ar), delay_slot); + else + FAIL_IF(push_inst(compiler, ADDU_W | S(base) | T(!argw ? OFFS_REG(arg) : TMP_REG3) | DA(tmp_ar), tmp_ar)); + return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | SA(tmp_ar) | TA(reg_ar), delay_slot); } if (compiler->cache_arg == arg && argw - compiler->cache_argw <= SIMM_MAX && argw - compiler->cache_argw >= SIMM_MIN) { @@ -923,15 +915,13 @@ static sljit_s32 emit_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s3 } if (SLJIT_UNLIKELY(dst == SLJIT_UNUSED)) { - if (op >= SLJIT_MOV && op <= SLJIT_MOVU_S32 && !(src2 & SLJIT_MEM)) - return SLJIT_SUCCESS; - if (GET_FLAGS(op)) - flags |= UNUSED_DEST; + SLJIT_ASSERT(HAS_FLAGS(op)); + flags |= UNUSED_DEST; } else if (FAST_IS_REG(dst)) { dst_r = dst; flags |= REG_DEST; - if (op >= SLJIT_MOV && op <= SLJIT_MOVU_S32) + if (op >= SLJIT_MOV && op <= SLJIT_MOV_P) sugg_src2_r = dst_r; } else if ((dst & SLJIT_MEM) && !getput_arg_fast(compiler, flags | ARG_TEST, DR(TMP_REG1), dst, dstw)) @@ -985,7 +975,7 @@ static sljit_s32 emit_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s3 if (FAST_IS_REG(src2)) { src2_r = src2; flags |= REG2_SOURCE; - if (!(flags & REG_DEST) && op >= SLJIT_MOV && op <= SLJIT_MOVU_S32) + if (!(flags & REG_DEST) && op >= SLJIT_MOV && op <= SLJIT_MOV_P) dst_r = src2_r; } else if (src2 & SLJIT_IMM) { @@ -996,7 +986,7 @@ static sljit_s32 emit_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s3 } else { src2_r = 0; - if ((op >= SLJIT_MOV && op <= SLJIT_MOVU_S32) && (dst & SLJIT_MEM)) + if ((op >= SLJIT_MOV && op <= SLJIT_MOV_P) && (dst & SLJIT_MEM)) dst_r = 0; } } @@ -1088,6 +1078,29 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compile return SLJIT_SUCCESS; } +#if (defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1) +static sljit_s32 emit_prefetch(struct sljit_compiler *compiler, + sljit_s32 src, sljit_sw srcw) +{ + if (!(src & OFFS_REG_MASK)) { + if (srcw <= SIMM_MAX && srcw >= SIMM_MIN) + return push_inst(compiler, PREF | S(src & REG_MASK) | IMM(srcw), MOVABLE_INS); + + FAIL_IF(load_immediate(compiler, DR(TMP_REG1), srcw)); + return push_inst(compiler, PREFX | S(src & REG_MASK) | T(TMP_REG1), MOVABLE_INS); + } + + srcw &= 0x3; + + if (SLJIT_UNLIKELY(srcw != 0)) { + FAIL_IF(push_inst(compiler, SLL_W | T(OFFS_REG(src)) | D(TMP_REG1) | SH_IMM(srcw), DR(TMP_REG1))); + return push_inst(compiler, PREFX | S(src & REG_MASK) | T(TMP_REG1), MOVABLE_INS); + } + + return push_inst(compiler, PREFX | S(src & REG_MASK) | T(OFFS_REG(src)), MOVABLE_INS); +} +#endif + SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw dstw, sljit_s32 src, sljit_sw srcw) @@ -1103,12 +1116,17 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile ADJUST_LOCAL_OFFSET(dst, dstw); ADJUST_LOCAL_OFFSET(src, srcw); + if (dst == SLJIT_UNUSED && !HAS_FLAGS(op)) { +#if (defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1) + if (op <= SLJIT_MOV_P && (src & SLJIT_MEM)) + return emit_prefetch(compiler, src, srcw); +#endif + return SLJIT_SUCCESS; + } + #if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64) - if ((op & SLJIT_I32_OP) && GET_OPCODE(op) >= SLJIT_NOT) { + if ((op & SLJIT_I32_OP) && GET_OPCODE(op) >= SLJIT_NOT) flags |= INT_DATA | SIGNED_DATA; - if (src & SLJIT_IMM) - srcw = (sljit_s32)srcw; - } #endif switch (GET_OPCODE(op)) { @@ -1142,36 +1160,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile case SLJIT_MOV_S16: return emit_op(compiler, SLJIT_MOV_S16, HALF_DATA | SIGNED_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_s16)srcw : srcw); - case SLJIT_MOVU: - case SLJIT_MOVU_P: - return emit_op(compiler, SLJIT_MOV, WORD_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, srcw); - - case SLJIT_MOVU_U32: -#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) - return emit_op(compiler, SLJIT_MOV_U32, INT_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, srcw); -#else - return emit_op(compiler, SLJIT_MOV_U32, INT_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_u32)srcw : srcw); -#endif - - case SLJIT_MOVU_S32: -#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) - return emit_op(compiler, SLJIT_MOV_S32, INT_DATA | SIGNED_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, srcw); -#else - return emit_op(compiler, SLJIT_MOV_S32, INT_DATA | SIGNED_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_s32)srcw : srcw); -#endif - - case SLJIT_MOVU_U8: - return emit_op(compiler, SLJIT_MOV_U8, BYTE_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_u8)srcw : srcw); - - case SLJIT_MOVU_S8: - return emit_op(compiler, SLJIT_MOV_S8, BYTE_DATA | SIGNED_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_s8)srcw : srcw); - - case SLJIT_MOVU_U16: - return emit_op(compiler, SLJIT_MOV_U16, HALF_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_u16)srcw : srcw); - - case SLJIT_MOVU_S16: - return emit_op(compiler, SLJIT_MOV_S16, HALF_DATA | SIGNED_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_s16)srcw : srcw); - case SLJIT_NOT: return emit_op(compiler, op, flags, dst, dstw, TMP_REG1, 0, src, srcw); @@ -1182,6 +1170,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile return emit_op(compiler, op, flags, dst, dstw, TMP_REG1, 0, src, srcw); } + SLJIT_UNREACHABLE(); return SLJIT_SUCCESS; #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) @@ -1206,6 +1195,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile ADJUST_LOCAL_OFFSET(src1, src1w); ADJUST_LOCAL_OFFSET(src2, src2w); + if (dst == SLJIT_UNUSED && !HAS_FLAGS(op)) + return SLJIT_SUCCESS; + #if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64) if (op & SLJIT_I32_OP) { flags |= INT_DATA | SIGNED_DATA; @@ -1250,6 +1242,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile return emit_op(compiler, op, flags | IMM_OP, dst, dstw, src1, src1w, src2, src2w); } + SLJIT_UNREACHABLE(); return SLJIT_SUCCESS; #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) @@ -1266,7 +1259,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 reg) SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_float_register_index(sljit_s32 reg) { CHECK_REG_INDEX(check_sljit_get_float_register_index(reg)); - return reg << 1; + return FR(reg); } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *compiler, @@ -1282,19 +1275,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *c /* Floating point operators */ /* --------------------------------------------------------------------- */ -SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_is_fpu_available(void) -{ -#ifdef SLJIT_IS_FPU_AVAILABLE - return SLJIT_IS_FPU_AVAILABLE; -#elif defined(__GNUC__) - sljit_sw fir; - asm ("cfc1 %0, $0" : "=r"(fir)); - return (fir >> 22) & 0x1; -#else -#error "FIR check is not implemented for this architecture" -#endif -} - #define FLOAT_DATA(op) (DOUBLE_DATA | ((op & SLJIT_F32_OP) >> 7)) #define FMT(op) (((op & SLJIT_F32_OP) ^ SLJIT_F32_OP) << (21 - 8)) @@ -1309,22 +1289,17 @@ static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_sw_from_f64(struct sljit_comp #endif if (src & SLJIT_MEM) { - FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src, srcw, dst, dstw)); + FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG1), src, srcw, dst, dstw)); src = TMP_FREG1; } - else - src <<= 1; FAIL_IF(push_inst(compiler, (TRUNC_W_S ^ (flags >> 19)) | FMT(op) | FS(src) | FD(TMP_FREG1), MOVABLE_INS)); - if (dst == SLJIT_UNUSED) - return SLJIT_SUCCESS; - if (FAST_IS_REG(dst)) return push_inst(compiler, MFC1 | flags | T(dst) | FS(TMP_FREG1), MOVABLE_INS); /* Store the integer value from a VFP register. */ - return emit_op_mem2(compiler, flags ? DOUBLE_DATA : SINGLE_DATA, TMP_FREG1, dst, dstw, 0, 0); + return emit_op_mem2(compiler, flags ? DOUBLE_DATA : SINGLE_DATA, FR(TMP_FREG1), dst, dstw, 0, 0); #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) # undef is_long @@ -1341,13 +1316,13 @@ static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_sw(struct sljit_comp sljit_s32 flags = (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_SW) << 21; #endif - sljit_s32 dst_r = FAST_IS_REG(dst) ? (dst << 1) : TMP_FREG1; + sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1; if (FAST_IS_REG(src)) FAIL_IF(push_inst(compiler, MTC1 | flags | T(src) | FS(TMP_FREG1), MOVABLE_INS)); else if (src & SLJIT_MEM) { /* Load the integer value into a VFP register. */ - FAIL_IF(emit_op_mem2(compiler, ((flags) ? DOUBLE_DATA : SINGLE_DATA) | LOAD_DATA, TMP_FREG1, src, srcw, dst, dstw)); + FAIL_IF(emit_op_mem2(compiler, ((flags) ? DOUBLE_DATA : SINGLE_DATA) | LOAD_DATA, FR(TMP_FREG1), src, srcw, dst, dstw)); } else { #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) @@ -1361,7 +1336,7 @@ static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_sw(struct sljit_comp FAIL_IF(push_inst(compiler, CVT_S_S | flags | (4 << 21) | (((op & SLJIT_F32_OP) ^ SLJIT_F32_OP) >> 8) | FS(TMP_FREG1) | FD(dst_r), MOVABLE_INS)); if (dst & SLJIT_MEM) - return emit_op_mem2(compiler, FLOAT_DATA(op), TMP_FREG1, dst, dstw, 0, 0); + return emit_op_mem2(compiler, FLOAT_DATA(op), FR(TMP_FREG1), dst, dstw, 0, 0); return SLJIT_SUCCESS; #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) @@ -1373,39 +1348,38 @@ static SLJIT_INLINE sljit_s32 sljit_emit_fop1_cmp(struct sljit_compiler *compile sljit_s32 src1, sljit_sw src1w, sljit_s32 src2, sljit_sw src2w) { + sljit_ins inst; + if (src1 & SLJIT_MEM) { - FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w, src2, src2w)); + FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG1), src1, src1w, src2, src2w)); src1 = TMP_FREG1; } - else - src1 <<= 1; if (src2 & SLJIT_MEM) { - FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src2, src2w, 0, 0)); + FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG2), src2, src2w, 0, 0)); src2 = TMP_FREG2; } - else - src2 <<= 1; - - /* src2 and src1 are swapped. */ - if (op & SLJIT_SET_E) { - FAIL_IF(push_inst(compiler, C_UEQ_S | FMT(op) | FT(src2) | FS(src1), UNMOVABLE_INS)); - FAIL_IF(push_inst(compiler, CFC1 | TA(EQUAL_FLAG) | DA(FCSR_REG), EQUAL_FLAG)); - FAIL_IF(push_inst(compiler, SRL | TA(EQUAL_FLAG) | DA(EQUAL_FLAG) | SH_IMM(23), EQUAL_FLAG)); - FAIL_IF(push_inst(compiler, ANDI | SA(EQUAL_FLAG) | TA(EQUAL_FLAG) | IMM(1), EQUAL_FLAG)); - } - if (op & SLJIT_SET_S) { - /* Mixing the instructions for the two checks. */ - FAIL_IF(push_inst(compiler, C_ULT_S | FMT(op) | FT(src2) | FS(src1), UNMOVABLE_INS)); - FAIL_IF(push_inst(compiler, CFC1 | TA(ULESS_FLAG) | DA(FCSR_REG), ULESS_FLAG)); - FAIL_IF(push_inst(compiler, C_ULT_S | FMT(op) | FT(src1) | FS(src2), UNMOVABLE_INS)); - FAIL_IF(push_inst(compiler, SRL | TA(ULESS_FLAG) | DA(ULESS_FLAG) | SH_IMM(23), ULESS_FLAG)); - FAIL_IF(push_inst(compiler, ANDI | SA(ULESS_FLAG) | TA(ULESS_FLAG) | IMM(1), ULESS_FLAG)); - FAIL_IF(push_inst(compiler, CFC1 | TA(UGREATER_FLAG) | DA(FCSR_REG), UGREATER_FLAG)); - FAIL_IF(push_inst(compiler, SRL | TA(UGREATER_FLAG) | DA(UGREATER_FLAG) | SH_IMM(23), UGREATER_FLAG)); - FAIL_IF(push_inst(compiler, ANDI | SA(UGREATER_FLAG) | TA(UGREATER_FLAG) | IMM(1), UGREATER_FLAG)); - } - return push_inst(compiler, C_UN_S | FMT(op) | FT(src2) | FS(src1), FCSR_FCC); + + switch (GET_FLAG_TYPE(op)) { + case SLJIT_EQUAL_F64: + case SLJIT_NOT_EQUAL_F64: + inst = C_UEQ_S; + break; + case SLJIT_LESS_F64: + case SLJIT_GREATER_EQUAL_F64: + inst = C_ULT_S; + break; + case SLJIT_GREATER_F64: + case SLJIT_LESS_EQUAL_F64: + inst = C_ULE_S; + break; + default: + SLJIT_ASSERT(GET_FLAG_TYPE(op) == SLJIT_UNORDERED_F64 || GET_FLAG_TYPE(op) == SLJIT_ORDERED_F64); + inst = C_UN_S; + break; + } + + return push_inst(compiler, inst | FMT(op) | FT(src2) | FS(src1), UNMOVABLE_INS); } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop1(struct sljit_compiler *compiler, sljit_s32 op, @@ -1424,14 +1398,12 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop1(struct sljit_compiler *compil if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_F32) op ^= SLJIT_F32_OP; - dst_r = FAST_IS_REG(dst) ? (dst << 1) : TMP_FREG1; + dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1; if (src & SLJIT_MEM) { - FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, dst_r, src, srcw, dst, dstw)); + FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(dst_r), src, srcw, dst, dstw)); src = dst_r; } - else - src <<= 1; switch (GET_OPCODE(op)) { case SLJIT_MOV_F64: @@ -1455,7 +1427,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop1(struct sljit_compiler *compil } if (dst & SLJIT_MEM) - return emit_op_mem2(compiler, FLOAT_DATA(op), dst_r, dst, dstw, 0, 0); + return emit_op_mem2(compiler, FLOAT_DATA(op), FR(dst_r), dst, dstw, 0, 0); return SLJIT_SUCCESS; } @@ -1475,42 +1447,38 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2(struct sljit_compiler *compil compiler->cache_arg = 0; compiler->cache_argw = 0; - dst_r = FAST_IS_REG(dst) ? (dst << 1) : TMP_FREG2; + dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG2; if (src1 & SLJIT_MEM) { - if (getput_arg_fast(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w)) { + if (getput_arg_fast(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG1), src1, src1w)) { FAIL_IF(compiler->error); src1 = TMP_FREG1; } else flags |= SLOW_SRC1; } - else - src1 <<= 1; if (src2 & SLJIT_MEM) { - if (getput_arg_fast(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src2, src2w)) { + if (getput_arg_fast(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG2), src2, src2w)) { FAIL_IF(compiler->error); src2 = TMP_FREG2; } else flags |= SLOW_SRC2; } - else - src2 <<= 1; if ((flags & (SLOW_SRC1 | SLOW_SRC2)) == (SLOW_SRC1 | SLOW_SRC2)) { if (!can_cache(src1, src1w, src2, src2w) && can_cache(src1, src1w, dst, dstw)) { - FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src2, src2w, src1, src1w)); - FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w, dst, dstw)); + FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG2), src2, src2w, src1, src1w)); + FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG1), src1, src1w, dst, dstw)); } else { - FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w, src2, src2w)); - FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src2, src2w, dst, dstw)); + FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG1), src1, src1w, src2, src2w)); + FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG2), src2, src2w, dst, dstw)); } } else if (flags & SLOW_SRC1) - FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w, dst, dstw)); + FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG1), src1, src1w, dst, dstw)); else if (flags & SLOW_SRC2) - FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src2, src2w, dst, dstw)); + FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG2), src2, src2w, dst, dstw)); if (flags & SLOW_SRC1) src1 = TMP_FREG1; @@ -1536,7 +1504,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2(struct sljit_compiler *compil } if (dst_r == TMP_FREG2) - FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op), TMP_FREG2, dst, dstw, 0, 0)); + FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op), FR(TMP_FREG2), dst, dstw, 0, 0)); return SLJIT_SUCCESS; } @@ -1551,10 +1519,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler * CHECK(check_sljit_emit_fast_enter(compiler, dst, dstw)); ADJUST_LOCAL_OFFSET(dst, dstw); - /* For UNUSED dst. Uncommon, but possible. */ - if (dst == SLJIT_UNUSED) - return SLJIT_SUCCESS; - if (FAST_IS_REG(dst)) return push_inst(compiler, ADDU_W | SA(RETURN_ADDR_REG) | TA(0) | D(dst), DR(dst)); @@ -1570,10 +1534,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_return(struct sljit_compiler if (FAST_IS_REG(src)) FAIL_IF(push_inst(compiler, ADDU_W | S(src) | TA(0) | DA(RETURN_ADDR_REG), RETURN_ADDR_REG)); - else if (src & SLJIT_MEM) + else FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, RETURN_ADDR_REG, src, srcw)); - else if (src & SLJIT_IMM) - FAIL_IF(load_immediate(compiler, RETURN_ADDR_REG, srcw)); FAIL_IF(push_inst(compiler, JR | SA(RETURN_ADDR_REG), UNMOVABLE_INS)); return push_inst(compiler, NOP, UNMOVABLE_INS); @@ -1643,55 +1605,39 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compile switch (type) { case SLJIT_EQUAL: - case SLJIT_NOT_EQUAL_F64: BR_NZ(EQUAL_FLAG); break; case SLJIT_NOT_EQUAL: - case SLJIT_EQUAL_F64: BR_Z(EQUAL_FLAG); break; case SLJIT_LESS: - case SLJIT_LESS_F64: - BR_Z(ULESS_FLAG); - break; - case SLJIT_GREATER_EQUAL: - case SLJIT_GREATER_EQUAL_F64: - BR_NZ(ULESS_FLAG); - break; case SLJIT_GREATER: - case SLJIT_GREATER_F64: - BR_Z(UGREATER_FLAG); - break; - case SLJIT_LESS_EQUAL: - case SLJIT_LESS_EQUAL_F64: - BR_NZ(UGREATER_FLAG); - break; case SLJIT_SIG_LESS: - BR_Z(LESS_FLAG); - break; - case SLJIT_SIG_GREATER_EQUAL: - BR_NZ(LESS_FLAG); - break; case SLJIT_SIG_GREATER: - BR_Z(GREATER_FLAG); - break; - case SLJIT_SIG_LESS_EQUAL: - BR_NZ(GREATER_FLAG); - break; case SLJIT_OVERFLOW: case SLJIT_MUL_OVERFLOW: - BR_Z(OVERFLOW_FLAG); + BR_Z(OTHER_FLAG); break; + case SLJIT_GREATER_EQUAL: + case SLJIT_LESS_EQUAL: + case SLJIT_SIG_GREATER_EQUAL: + case SLJIT_SIG_LESS_EQUAL: case SLJIT_NOT_OVERFLOW: case SLJIT_MUL_NOT_OVERFLOW: - BR_NZ(OVERFLOW_FLAG); - break; - case SLJIT_UNORDERED_F64: - BR_F(); + BR_NZ(OTHER_FLAG); break; + case SLJIT_NOT_EQUAL_F64: + case SLJIT_GREATER_EQUAL_F64: + case SLJIT_GREATER_F64: case SLJIT_ORDERED_F64: BR_T(); break; + case SLJIT_EQUAL_F64: + case SLJIT_LESS_F64: + case SLJIT_LESS_EQUAL_F64: + case SLJIT_UNORDERED_F64: + BR_F(); + break; default: /* Not conditional branch. */ inst = 0; @@ -1706,19 +1652,16 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compile PTR_FAIL_IF(push_inst(compiler, inst, UNMOVABLE_INS)); PTR_FAIL_IF(emit_const(compiler, TMP_REG2, 0)); - if (type <= SLJIT_JUMP) { + + if (type <= SLJIT_JUMP) PTR_FAIL_IF(push_inst(compiler, JR | S(TMP_REG2), UNMOVABLE_INS)); - jump->addr = compiler->size; - PTR_FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS)); - } else { - SLJIT_ASSERT(DR(PIC_ADDR_REG) == 25 && PIC_ADDR_REG == TMP_REG2); - /* Cannot be optimized out if type is >= CALL0. */ - jump->flags |= IS_JAL | (type >= SLJIT_CALL0 ? IS_CALL : 0); + else { + jump->flags |= IS_JAL; PTR_FAIL_IF(push_inst(compiler, JALR | S(TMP_REG2) | DA(RETURN_ADDR_REG), UNMOVABLE_INS)); - jump->addr = compiler->size; - /* A NOP if type < CALL1. */ - PTR_FAIL_IF(push_inst(compiler, ADDU_W | S(SLJIT_R0) | TA(0) | DA(4), UNMOVABLE_INS)); } + + jump->addr = compiler->size; + PTR_FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS)); return jump; } @@ -1863,86 +1806,6 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_cmp(struct sljit_compiler #undef RESOLVE_IMM1 #undef RESOLVE_IMM2 -SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_fcmp(struct sljit_compiler *compiler, sljit_s32 type, - sljit_s32 src1, sljit_sw src1w, - sljit_s32 src2, sljit_sw src2w) -{ - struct sljit_jump *jump; - sljit_ins inst; - sljit_s32 if_true; - - CHECK_ERROR_PTR(); - CHECK_PTR(check_sljit_emit_fcmp(compiler, type, src1, src1w, src2, src2w)); - - compiler->cache_arg = 0; - compiler->cache_argw = 0; - - if (src1 & SLJIT_MEM) { - PTR_FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(type) | LOAD_DATA, TMP_FREG1, src1, src1w, src2, src2w)); - src1 = TMP_FREG1; - } - else - src1 <<= 1; - - if (src2 & SLJIT_MEM) { - PTR_FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(type) | LOAD_DATA, TMP_FREG2, src2, src2w, 0, 0)); - src2 = TMP_FREG2; - } - else - src2 <<= 1; - - jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump)); - PTR_FAIL_IF(!jump); - set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP); - jump->flags |= IS_BIT16_COND; - - switch (type & 0xff) { - case SLJIT_EQUAL_F64: - inst = C_UEQ_S; - if_true = 1; - break; - case SLJIT_NOT_EQUAL_F64: - inst = C_UEQ_S; - if_true = 0; - break; - case SLJIT_LESS_F64: - inst = C_ULT_S; - if_true = 1; - break; - case SLJIT_GREATER_EQUAL_F64: - inst = C_ULT_S; - if_true = 0; - break; - case SLJIT_GREATER_F64: - inst = C_ULE_S; - if_true = 0; - break; - case SLJIT_LESS_EQUAL_F64: - inst = C_ULE_S; - if_true = 1; - break; - case SLJIT_UNORDERED_F64: - inst = C_UN_S; - if_true = 1; - break; - default: /* Make compilers happy. */ - SLJIT_ASSERT_STOP(); - case SLJIT_ORDERED_F64: - inst = C_UN_S; - if_true = 0; - break; - } - - PTR_FAIL_IF(push_inst(compiler, inst | FMT(type) | FT(src2) | FS(src1), UNMOVABLE_INS)); - /* Intentionally the other opcode. */ - PTR_FAIL_IF(push_inst(compiler, (if_true ? BC1F : BC1T) | JUMP_LENGTH, UNMOVABLE_INS)); - PTR_FAIL_IF(emit_const(compiler, TMP_REG2, 0)); - PTR_FAIL_IF(push_inst(compiler, JR | S(TMP_REG2), UNMOVABLE_INS)); - jump->addr = compiler->size; - PTR_FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS)); - return jump; -} - #undef JUMP_LENGTH #undef BR_Z #undef BR_NZ @@ -1954,41 +1817,12 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_fcmp(struct sljit_compile SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 src, sljit_sw srcw) { - sljit_s32 src_r = TMP_REG2; struct sljit_jump *jump = NULL; CHECK_ERROR(); CHECK(check_sljit_emit_ijump(compiler, type, src, srcw)); ADJUST_LOCAL_OFFSET(src, srcw); - if (FAST_IS_REG(src)) { - if (DR(src) != 4) - src_r = src; - else - FAIL_IF(push_inst(compiler, ADDU_W | S(src) | TA(0) | D(TMP_REG2), DR(TMP_REG2))); - } - - if (type >= SLJIT_CALL0) { - SLJIT_ASSERT(DR(PIC_ADDR_REG) == 25 && PIC_ADDR_REG == TMP_REG2); - if (src & (SLJIT_IMM | SLJIT_MEM)) { - if (src & SLJIT_IMM) - FAIL_IF(load_immediate(compiler, DR(PIC_ADDR_REG), srcw)); - else { - SLJIT_ASSERT(src_r == TMP_REG2 && (src & SLJIT_MEM)); - FAIL_IF(emit_op(compiler, SLJIT_MOV, WORD_DATA, TMP_REG2, 0, TMP_REG1, 0, src, srcw)); - } - FAIL_IF(push_inst(compiler, JALR | S(PIC_ADDR_REG) | DA(RETURN_ADDR_REG), UNMOVABLE_INS)); - /* We need an extra instruction in any case. */ - return push_inst(compiler, ADDU_W | S(SLJIT_R0) | TA(0) | DA(4), UNMOVABLE_INS); - } - - /* Register input. */ - if (type >= SLJIT_CALL1) - FAIL_IF(push_inst(compiler, ADDU_W | S(SLJIT_R0) | TA(0) | DA(4), 4)); - FAIL_IF(push_inst(compiler, JALR | S(src_r) | DA(RETURN_ADDR_REG), UNMOVABLE_INS)); - return push_inst(compiler, ADDU_W | S(src_r) | TA(0) | D(PIC_ADDR_REG), UNMOVABLE_INS); - } - if (src & SLJIT_IMM) { jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump)); FAIL_IF(!jump); @@ -1999,11 +1833,14 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compi jump->flags |= IS_MOVABLE; FAIL_IF(emit_const(compiler, TMP_REG2, 0)); + src = TMP_REG2; + } + else if (src & SLJIT_MEM) { + FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, DR(TMP_REG2), src, srcw)); + src = TMP_REG2; } - else if (src & SLJIT_MEM) - FAIL_IF(emit_op(compiler, SLJIT_MOV, WORD_DATA, TMP_REG2, 0, TMP_REG1, 0, src, srcw)); - FAIL_IF(push_inst(compiler, JR | S(src_r), UNMOVABLE_INS)); + FAIL_IF(push_inst(compiler, JR | S(src), UNMOVABLE_INS)); if (jump) jump->addr = compiler->size; FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS)); @@ -2012,115 +1849,160 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compi SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw dstw, - sljit_s32 src, sljit_sw srcw, sljit_s32 type) { - sljit_s32 sugg_dst_ar, dst_ar; - sljit_s32 flags = GET_ALL_FLAGS(op); + sljit_s32 src_ar, dst_ar; + sljit_s32 saved_op = op; #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) -# define mem_type WORD_DATA + sljit_s32 mem_type = WORD_DATA; #else sljit_s32 mem_type = (op & SLJIT_I32_OP) ? (INT_DATA | SIGNED_DATA) : WORD_DATA; #endif CHECK_ERROR(); - CHECK(check_sljit_emit_op_flags(compiler, op, dst, dstw, src, srcw, type)); + CHECK(check_sljit_emit_op_flags(compiler, op, dst, dstw, type)); ADJUST_LOCAL_OFFSET(dst, dstw); - if (dst == SLJIT_UNUSED) - return SLJIT_SUCCESS; - op = GET_OPCODE(op); #if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64) - if (op == SLJIT_MOV_S32 || op == SLJIT_MOV_U32) + if (op == SLJIT_MOV_S32) mem_type = INT_DATA | SIGNED_DATA; #endif - sugg_dst_ar = DR((op < SLJIT_ADD && FAST_IS_REG(dst)) ? dst : TMP_REG2); + dst_ar = DR((op < SLJIT_ADD && FAST_IS_REG(dst)) ? dst : TMP_REG2); compiler->cache_arg = 0; compiler->cache_argw = 0; - if (op >= SLJIT_ADD && (src & SLJIT_MEM)) { - ADJUST_LOCAL_OFFSET(src, srcw); - FAIL_IF(emit_op_mem2(compiler, mem_type | LOAD_DATA, DR(TMP_REG1), src, srcw, dst, dstw)); - src = TMP_REG1; - srcw = 0; - } + + if (op >= SLJIT_ADD && (dst & SLJIT_MEM)) + FAIL_IF(emit_op_mem2(compiler, mem_type | LOAD_DATA, DR(TMP_REG1), dst, dstw, dst, dstw)); switch (type & 0xff) { case SLJIT_EQUAL: case SLJIT_NOT_EQUAL: - FAIL_IF(push_inst(compiler, SLTIU | SA(EQUAL_FLAG) | TA(sugg_dst_ar) | IMM(1), sugg_dst_ar)); - dst_ar = sugg_dst_ar; - break; - case SLJIT_LESS: - case SLJIT_GREATER_EQUAL: - case SLJIT_LESS_F64: - case SLJIT_GREATER_EQUAL_F64: - dst_ar = ULESS_FLAG; - break; - case SLJIT_GREATER: - case SLJIT_LESS_EQUAL: - case SLJIT_GREATER_F64: - case SLJIT_LESS_EQUAL_F64: - dst_ar = UGREATER_FLAG; - break; - case SLJIT_SIG_LESS: - case SLJIT_SIG_GREATER_EQUAL: - dst_ar = LESS_FLAG; - break; - case SLJIT_SIG_GREATER: - case SLJIT_SIG_LESS_EQUAL: - dst_ar = GREATER_FLAG; - break; - case SLJIT_OVERFLOW: - case SLJIT_NOT_OVERFLOW: - dst_ar = OVERFLOW_FLAG; + FAIL_IF(push_inst(compiler, SLTIU | SA(EQUAL_FLAG) | TA(dst_ar) | IMM(1), dst_ar)); + src_ar = dst_ar; break; case SLJIT_MUL_OVERFLOW: case SLJIT_MUL_NOT_OVERFLOW: - FAIL_IF(push_inst(compiler, SLTIU | SA(OVERFLOW_FLAG) | TA(sugg_dst_ar) | IMM(1), sugg_dst_ar)); - dst_ar = sugg_dst_ar; + FAIL_IF(push_inst(compiler, SLTIU | SA(OTHER_FLAG) | TA(dst_ar) | IMM(1), dst_ar)); + src_ar = dst_ar; type ^= 0x1; /* Flip type bit for the XORI below. */ break; + case SLJIT_GREATER_F64: + case SLJIT_LESS_EQUAL_F64: + type ^= 0x1; /* Flip type bit for the XORI below. */ case SLJIT_EQUAL_F64: case SLJIT_NOT_EQUAL_F64: - dst_ar = EQUAL_FLAG; - break; - + case SLJIT_LESS_F64: + case SLJIT_GREATER_EQUAL_F64: case SLJIT_UNORDERED_F64: case SLJIT_ORDERED_F64: - FAIL_IF(push_inst(compiler, CFC1 | TA(sugg_dst_ar) | DA(FCSR_REG), sugg_dst_ar)); - FAIL_IF(push_inst(compiler, SRL | TA(sugg_dst_ar) | DA(sugg_dst_ar) | SH_IMM(23), sugg_dst_ar)); - FAIL_IF(push_inst(compiler, ANDI | SA(sugg_dst_ar) | TA(sugg_dst_ar) | IMM(1), sugg_dst_ar)); - dst_ar = sugg_dst_ar; + FAIL_IF(push_inst(compiler, CFC1 | TA(dst_ar) | DA(FCSR_REG), dst_ar)); + FAIL_IF(push_inst(compiler, SRL | TA(dst_ar) | DA(dst_ar) | SH_IMM(23), dst_ar)); + FAIL_IF(push_inst(compiler, ANDI | SA(dst_ar) | TA(dst_ar) | IMM(1), dst_ar)); + src_ar = dst_ar; break; default: - SLJIT_ASSERT_STOP(); - dst_ar = sugg_dst_ar; + src_ar = OTHER_FLAG; break; } if (type & 0x1) { - FAIL_IF(push_inst(compiler, XORI | SA(dst_ar) | TA(sugg_dst_ar) | IMM(1), sugg_dst_ar)); - dst_ar = sugg_dst_ar; + FAIL_IF(push_inst(compiler, XORI | SA(src_ar) | TA(dst_ar) | IMM(1), dst_ar)); + src_ar = dst_ar; } - if (op >= SLJIT_ADD) { - if (DR(TMP_REG2) != dst_ar) - FAIL_IF(push_inst(compiler, ADDU_W | SA(dst_ar) | TA(0) | D(TMP_REG2), DR(TMP_REG2))); - return emit_op(compiler, op | flags, mem_type | CUMULATIVE_OP | LOGICAL_OP | IMM_OP | ALT_KEEP_CACHE, dst, dstw, src, srcw, TMP_REG2, 0); + if (op < SLJIT_ADD) { + if (dst & SLJIT_MEM) + return emit_op_mem(compiler, mem_type, src_ar, dst, dstw); + + if (src_ar != dst_ar) + return push_inst(compiler, ADDU_W | SA(src_ar) | TA(0) | DA(dst_ar), dst_ar); + return SLJIT_SUCCESS; } + /* OTHER_FLAG cannot be specified as src2 argument at the moment. */ + if (DR(TMP_REG2) != src_ar) + FAIL_IF(push_inst(compiler, ADDU_W | SA(src_ar) | TA(0) | D(TMP_REG2), DR(TMP_REG2))); + + mem_type |= CUMULATIVE_OP | LOGICAL_OP | IMM_OP | ALT_KEEP_CACHE; + if (dst & SLJIT_MEM) - return emit_op_mem(compiler, mem_type, dst_ar, dst, dstw); + return emit_op(compiler, saved_op, mem_type, dst, dstw, TMP_REG1, 0, TMP_REG2, 0); + return emit_op(compiler, saved_op, mem_type, dst, dstw, dst, dstw, TMP_REG2, 0); +} - if (sugg_dst_ar != dst_ar) - return push_inst(compiler, ADDU_W | SA(dst_ar) | TA(0) | DA(sugg_dst_ar), sugg_dst_ar); - return SLJIT_SUCCESS; +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 dst_reg, + sljit_s32 src, sljit_sw srcw) +{ +#if (defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1) + sljit_ins ins; +#endif -#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) -# undef mem_type + CHECK_ERROR(); + CHECK(check_sljit_emit_cmov(compiler, type, dst_reg, src, srcw)); + +#if (defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1) + + if (SLJIT_UNLIKELY(src & SLJIT_IMM)) { +#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64) + if (dst_reg & SLJIT_I32_OP) + srcw = (sljit_s32)srcw; +#endif + FAIL_IF(load_immediate(compiler, DR(TMP_REG1), srcw)); + src = TMP_REG1; + srcw = 0; + } + + dst_reg &= ~SLJIT_I32_OP; + + switch (type & 0xff) { + case SLJIT_EQUAL: + ins = MOVZ | TA(EQUAL_FLAG); + break; + case SLJIT_NOT_EQUAL: + ins = MOVN | TA(EQUAL_FLAG); + break; + case SLJIT_LESS: + case SLJIT_GREATER: + case SLJIT_SIG_LESS: + case SLJIT_SIG_GREATER: + case SLJIT_OVERFLOW: + case SLJIT_MUL_OVERFLOW: + ins = MOVN | TA(OTHER_FLAG); + break; + case SLJIT_GREATER_EQUAL: + case SLJIT_LESS_EQUAL: + case SLJIT_SIG_GREATER_EQUAL: + case SLJIT_SIG_LESS_EQUAL: + case SLJIT_NOT_OVERFLOW: + case SLJIT_MUL_NOT_OVERFLOW: + ins = MOVZ | TA(OTHER_FLAG); + break; + case SLJIT_EQUAL_F64: + case SLJIT_LESS_F64: + case SLJIT_LESS_EQUAL_F64: + case SLJIT_UNORDERED_F64: + ins = MOVT; + break; + case SLJIT_NOT_EQUAL_F64: + case SLJIT_GREATER_EQUAL_F64: + case SLJIT_GREATER_F64: + case SLJIT_ORDERED_F64: + ins = MOVF; + break; + default: + ins = MOVZ | TA(OTHER_FLAG); + SLJIT_UNREACHABLE(); + break; + } + + return push_inst(compiler, ins | S(src) | D(dst_reg), DR(dst_reg)); + +#else + return sljit_emit_cmov_generic(compiler, type, dst_reg, src, srcw); #endif } @@ -2137,7 +2019,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compi PTR_FAIL_IF(!const_); set_const(const_, compiler); - reg = SLOW_IS_REG(dst) ? dst : TMP_REG2; + reg = FAST_IS_REG(dst) ? dst : TMP_REG2; PTR_FAIL_IF(emit_const(compiler, reg, init_value)); diff --git a/thirdparty/pcre2/src/sljit/sljitNativePPC_32.c b/thirdparty/pcre2/src/sljit/sljitNativePPC_32.c index f696d1b8d5..fc185f7847 100644 --- a/thirdparty/pcre2/src/sljit/sljitNativePPC_32.c +++ b/thirdparty/pcre2/src/sljit/sljitNativePPC_32.c @@ -1,7 +1,7 @@ /* * Stack-less Just-In-Time compiler * - * Copyright 2009-2012 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved. + * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are * permitted provided that the following conditions are met: @@ -88,77 +88,86 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl case SLJIT_NEG: SLJIT_ASSERT(src1 == TMP_REG1); - return push_inst(compiler, NEG | OERC(flags) | D(dst) | A(src2)); + /* Setting XER SO is not enough, CR SO is also needed. */ + return push_inst(compiler, NEG | OE((flags & ALT_FORM1) ? ALT_SET_FLAGS : 0) | RC(flags) | D(dst) | A(src2)); case SLJIT_CLZ: SLJIT_ASSERT(src1 == TMP_REG1); - return push_inst(compiler, CNTLZW | RC(flags) | S(src2) | A(dst)); + return push_inst(compiler, CNTLZW | S(src2) | A(dst)); case SLJIT_ADD: if (flags & ALT_FORM1) { - /* Flags does not set: BIN_IMM_EXTS unnecessary. */ - SLJIT_ASSERT(src2 == TMP_REG2); - return push_inst(compiler, ADDI | D(dst) | A(src1) | compiler->imm); + /* Setting XER SO is not enough, CR SO is also needed. */ + return push_inst(compiler, ADD | OE(ALT_SET_FLAGS) | RC(ALT_SET_FLAGS) | D(dst) | A(src1) | B(src2)); } + if (flags & ALT_FORM2) { /* Flags does not set: BIN_IMM_EXTS unnecessary. */ SLJIT_ASSERT(src2 == TMP_REG2); - return push_inst(compiler, ADDIS | D(dst) | A(src1) | compiler->imm); + + if (flags & ALT_FORM3) + return push_inst(compiler, ADDIS | D(dst) | A(src1) | compiler->imm); + + if (flags & ALT_FORM4) { + FAIL_IF(push_inst(compiler, ADDIS | D(dst) | A(src1) | (((compiler->imm >> 16) & 0xffff) + ((compiler->imm >> 15) & 0x1)))); + src1 = dst; + } + + return push_inst(compiler, ADDI | D(dst) | A(src1) | (compiler->imm & 0xffff)); } if (flags & ALT_FORM3) { SLJIT_ASSERT(src2 == TMP_REG2); return push_inst(compiler, ADDIC | D(dst) | A(src1) | compiler->imm); } - if (flags & ALT_FORM4) { - /* Flags does not set: BIN_IMM_EXTS unnecessary. */ - FAIL_IF(push_inst(compiler, ADDI | D(dst) | A(src1) | (compiler->imm & 0xffff))); - return push_inst(compiler, ADDIS | D(dst) | A(dst) | (((compiler->imm >> 16) & 0xffff) + ((compiler->imm >> 15) & 0x1))); - } if (!(flags & ALT_SET_FLAGS)) return push_inst(compiler, ADD | D(dst) | A(src1) | B(src2)); - return push_inst(compiler, ADDC | OERC(ALT_SET_FLAGS) | D(dst) | A(src1) | B(src2)); + if (flags & ALT_FORM4) + return push_inst(compiler, ADDC | RC(ALT_SET_FLAGS) | D(dst) | A(src1) | B(src2)); + return push_inst(compiler, ADD | RC(flags) | D(dst) | A(src1) | B(src2)); case SLJIT_ADDC: - if (flags & ALT_FORM1) { - FAIL_IF(push_inst(compiler, MFXER | D(0))); - FAIL_IF(push_inst(compiler, ADDE | D(dst) | A(src1) | B(src2))); - return push_inst(compiler, MTXER | S(0)); - } return push_inst(compiler, ADDE | D(dst) | A(src1) | B(src2)); case SLJIT_SUB: if (flags & ALT_FORM1) { + if (flags & ALT_FORM2) { + FAIL_IF(push_inst(compiler, CMPLI | CRD(0) | A(src1) | compiler->imm)); + if (!(flags & ALT_FORM3)) + return SLJIT_SUCCESS; + return push_inst(compiler, ADDI | D(dst) | A(src1) | (-compiler->imm & 0xffff)); + } + FAIL_IF(push_inst(compiler, CMPL | CRD(0) | A(src1) | B(src2))); + if (!(flags & ALT_FORM3)) + return SLJIT_SUCCESS; + return push_inst(compiler, SUBF | D(dst) | A(src2) | B(src1)); + } + + if (flags & ALT_FORM2) { + /* Setting XER SO is not enough, CR SO is also needed. */ + return push_inst(compiler, SUBF | OE(ALT_SET_FLAGS) | RC(ALT_SET_FLAGS) | D(dst) | A(src2) | B(src1)); + } + + if (flags & ALT_FORM3) { /* Flags does not set: BIN_IMM_EXTS unnecessary. */ SLJIT_ASSERT(src2 == TMP_REG2); return push_inst(compiler, SUBFIC | D(dst) | A(src1) | compiler->imm); } - if (flags & (ALT_FORM2 | ALT_FORM3)) { - SLJIT_ASSERT(src2 == TMP_REG2); - if (flags & ALT_FORM2) - FAIL_IF(push_inst(compiler, CMPI | CRD(0) | A(src1) | compiler->imm)); - if (flags & ALT_FORM3) - return push_inst(compiler, CMPLI | CRD(4) | A(src1) | compiler->imm); - return SLJIT_SUCCESS; - } - if (flags & (ALT_FORM4 | ALT_FORM5)) { - if (flags & ALT_FORM4) - FAIL_IF(push_inst(compiler, CMPL | CRD(4) | A(src1) | B(src2))); - if (flags & ALT_FORM5) - FAIL_IF(push_inst(compiler, CMP | CRD(0) | A(src1) | B(src2))); - return SLJIT_SUCCESS; + + if (flags & ALT_FORM4) { + if (flags & ALT_FORM5) { + SLJIT_ASSERT(src2 == TMP_REG2); + return push_inst(compiler, CMPI | CRD(0) | A(src1) | compiler->imm); + } + return push_inst(compiler, CMP | CRD(0) | A(src1) | B(src2)); } + if (!(flags & ALT_SET_FLAGS)) return push_inst(compiler, SUBF | D(dst) | A(src2) | B(src1)); - if (flags & ALT_FORM6) - FAIL_IF(push_inst(compiler, CMPL | CRD(4) | A(src1) | B(src2))); - return push_inst(compiler, SUBFC | OERC(ALT_SET_FLAGS) | D(dst) | A(src2) | B(src1)); + if (flags & ALT_FORM5) + return push_inst(compiler, SUBFC | RC(ALT_SET_FLAGS) | D(dst) | A(src2) | B(src1)); + return push_inst(compiler, SUBF | RC(flags) | D(dst) | A(src2) | B(src1)); case SLJIT_SUBC: - if (flags & ALT_FORM1) { - FAIL_IF(push_inst(compiler, MFXER | D(0))); - FAIL_IF(push_inst(compiler, SUBFE | D(dst) | A(src2) | B(src1))); - return push_inst(compiler, MTXER | S(0)); - } return push_inst(compiler, SUBFE | D(dst) | A(src2) | B(src1)); case SLJIT_MUL: @@ -166,7 +175,7 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl SLJIT_ASSERT(src2 == TMP_REG2); return push_inst(compiler, MULLI | D(dst) | A(src1) | compiler->imm); } - return push_inst(compiler, MULLW | OERC(flags) | D(dst) | A(src2) | B(src1)); + return push_inst(compiler, MULLW | OE(flags) | RC(flags) | D(dst) | A(src2) | B(src1)); case SLJIT_AND: if (flags & ALT_FORM1) { @@ -228,19 +237,15 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl return push_inst(compiler, SRW | RC(flags) | S(src1) | A(dst) | B(src2)); case SLJIT_ASHR: - if (flags & ALT_FORM3) - FAIL_IF(push_inst(compiler, MFXER | D(0))); if (flags & ALT_FORM1) { SLJIT_ASSERT(src2 == TMP_REG2); compiler->imm &= 0x1f; - FAIL_IF(push_inst(compiler, SRAWI | RC(flags) | S(src1) | A(dst) | (compiler->imm << 11))); + return push_inst(compiler, SRAWI | RC(flags) | S(src1) | A(dst) | (compiler->imm << 11)); } - else - FAIL_IF(push_inst(compiler, SRAW | RC(flags) | S(src1) | A(dst) | B(src2))); - return (flags & ALT_FORM3) ? push_inst(compiler, MTXER | S(0)) : SLJIT_SUCCESS; + return push_inst(compiler, SRAW | RC(flags) | S(src1) | A(dst) | B(src2)); } - SLJIT_ASSERT_STOP(); + SLJIT_UNREACHABLE(); return SLJIT_SUCCESS; } diff --git a/thirdparty/pcre2/src/sljit/sljitNativePPC_64.c b/thirdparty/pcre2/src/sljit/sljitNativePPC_64.c index 386d247dbc..706b2ba20b 100644 --- a/thirdparty/pcre2/src/sljit/sljitNativePPC_64.c +++ b/thirdparty/pcre2/src/sljit/sljitNativePPC_64.c @@ -1,7 +1,7 @@ /* * Stack-less Just-In-Time compiler * - * Copyright 2009-2012 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved. + * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are * permitted provided that the following conditions are met: @@ -204,84 +204,118 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl case SLJIT_NEG: SLJIT_ASSERT(src1 == TMP_REG1); + + if ((flags & (ALT_FORM1 | ALT_SIGN_EXT)) == (ALT_FORM1 | ALT_SIGN_EXT)) { + FAIL_IF(push_inst(compiler, RLDI(TMP_REG2, src2, 32, 31, 1))); + FAIL_IF(push_inst(compiler, NEG | OE(ALT_SET_FLAGS) | RC(ALT_SET_FLAGS) | D(dst) | A(TMP_REG2))); + return push_inst(compiler, RLDI(dst, dst, 32, 32, 0)); + } + UN_EXTS(); - return push_inst(compiler, NEG | OERC(flags) | D(dst) | A(src2)); + /* Setting XER SO is not enough, CR SO is also needed. */ + return push_inst(compiler, NEG | OE((flags & ALT_FORM1) ? ALT_SET_FLAGS : 0) | RC(flags) | D(dst) | A(src2)); case SLJIT_CLZ: SLJIT_ASSERT(src1 == TMP_REG1); if (flags & ALT_FORM1) - return push_inst(compiler, CNTLZW | RC(flags) | S(src2) | A(dst)); - return push_inst(compiler, CNTLZD | RC(flags) | S(src2) | A(dst)); + return push_inst(compiler, CNTLZW | S(src2) | A(dst)); + return push_inst(compiler, CNTLZD | S(src2) | A(dst)); case SLJIT_ADD: if (flags & ALT_FORM1) { - /* Flags does not set: BIN_IMM_EXTS unnecessary. */ - SLJIT_ASSERT(src2 == TMP_REG2); - return push_inst(compiler, ADDI | D(dst) | A(src1) | compiler->imm); + if (flags & ALT_SIGN_EXT) { + FAIL_IF(push_inst(compiler, RLDI(TMP_REG1, src1, 32, 31, 1))); + src1 = TMP_REG1; + FAIL_IF(push_inst(compiler, RLDI(TMP_REG2, src2, 32, 31, 1))); + src2 = TMP_REG2; + } + /* Setting XER SO is not enough, CR SO is also needed. */ + FAIL_IF(push_inst(compiler, ADD | OE(ALT_SET_FLAGS) | RC(ALT_SET_FLAGS) | D(dst) | A(src1) | B(src2))); + if (flags & ALT_SIGN_EXT) + return push_inst(compiler, RLDI(dst, dst, 32, 32, 0)); + return SLJIT_SUCCESS; } + if (flags & ALT_FORM2) { /* Flags does not set: BIN_IMM_EXTS unnecessary. */ SLJIT_ASSERT(src2 == TMP_REG2); - return push_inst(compiler, ADDIS | D(dst) | A(src1) | compiler->imm); + + if (flags & ALT_FORM3) + return push_inst(compiler, ADDIS | D(dst) | A(src1) | compiler->imm); + + if (flags & ALT_FORM4) { + FAIL_IF(push_inst(compiler, ADDIS | D(dst) | A(src1) | (((compiler->imm >> 16) & 0xffff) + ((compiler->imm >> 15) & 0x1)))); + src1 = dst; + } + + return push_inst(compiler, ADDI | D(dst) | A(src1) | (compiler->imm & 0xffff)); } if (flags & ALT_FORM3) { SLJIT_ASSERT(src2 == TMP_REG2); BIN_IMM_EXTS(); return push_inst(compiler, ADDIC | D(dst) | A(src1) | compiler->imm); } - if (flags & ALT_FORM4) { - /* Flags does not set: BIN_IMM_EXTS unnecessary. */ - FAIL_IF(push_inst(compiler, ADDI | D(dst) | A(src1) | (compiler->imm & 0xffff))); - return push_inst(compiler, ADDIS | D(dst) | A(dst) | (((compiler->imm >> 16) & 0xffff) + ((compiler->imm >> 15) & 0x1))); - } if (!(flags & ALT_SET_FLAGS)) return push_inst(compiler, ADD | D(dst) | A(src1) | B(src2)); BIN_EXTS(); - return push_inst(compiler, ADDC | OERC(ALT_SET_FLAGS) | D(dst) | A(src1) | B(src2)); + if (flags & ALT_FORM4) + return push_inst(compiler, ADDC | RC(ALT_SET_FLAGS) | D(dst) | A(src1) | B(src2)); + return push_inst(compiler, ADD | RC(flags) | D(dst) | A(src1) | B(src2)); case SLJIT_ADDC: - if (flags & ALT_FORM1) { - FAIL_IF(push_inst(compiler, MFXER | D(0))); - FAIL_IF(push_inst(compiler, ADDE | D(dst) | A(src1) | B(src2))); - return push_inst(compiler, MTXER | S(0)); - } BIN_EXTS(); return push_inst(compiler, ADDE | D(dst) | A(src1) | B(src2)); case SLJIT_SUB: if (flags & ALT_FORM1) { + if (flags & ALT_FORM2) { + FAIL_IF(push_inst(compiler, CMPLI | CRD(0 | ((flags & ALT_SIGN_EXT) ? 0 : 1)) | A(src1) | compiler->imm)); + if (!(flags & ALT_FORM3)) + return SLJIT_SUCCESS; + return push_inst(compiler, ADDI | D(dst) | A(src1) | (-compiler->imm & 0xffff)); + } + FAIL_IF(push_inst(compiler, CMPL | CRD(0 | ((flags & ALT_SIGN_EXT) ? 0 : 1)) | A(src1) | B(src2))); + if (!(flags & ALT_FORM3)) + return SLJIT_SUCCESS; + return push_inst(compiler, SUBF | D(dst) | A(src2) | B(src1)); + } + + if (flags & ALT_FORM2) { + if (flags & ALT_SIGN_EXT) { + FAIL_IF(push_inst(compiler, RLDI(TMP_REG1, src1, 32, 31, 1))); + src1 = TMP_REG1; + FAIL_IF(push_inst(compiler, RLDI(TMP_REG2, src2, 32, 31, 1))); + src2 = TMP_REG2; + } + /* Setting XER SO is not enough, CR SO is also needed. */ + FAIL_IF(push_inst(compiler, SUBF | OE(ALT_SET_FLAGS) | RC(ALT_SET_FLAGS) | D(dst) | A(src2) | B(src1))); + if (flags & ALT_SIGN_EXT) + return push_inst(compiler, RLDI(dst, dst, 32, 32, 0)); + return SLJIT_SUCCESS; + } + + if (flags & ALT_FORM3) { /* Flags does not set: BIN_IMM_EXTS unnecessary. */ SLJIT_ASSERT(src2 == TMP_REG2); return push_inst(compiler, SUBFIC | D(dst) | A(src1) | compiler->imm); } - if (flags & (ALT_FORM2 | ALT_FORM3)) { - SLJIT_ASSERT(src2 == TMP_REG2); - if (flags & ALT_FORM2) - FAIL_IF(push_inst(compiler, CMPI | CRD(0 | ((flags & ALT_SIGN_EXT) ? 0 : 1)) | A(src1) | compiler->imm)); - if (flags & ALT_FORM3) - return push_inst(compiler, CMPLI | CRD(4 | ((flags & ALT_SIGN_EXT) ? 0 : 1)) | A(src1) | compiler->imm); - return SLJIT_SUCCESS; - } - if (flags & (ALT_FORM4 | ALT_FORM5)) { - if (flags & ALT_FORM4) - FAIL_IF(push_inst(compiler, CMPL | CRD(4 | ((flags & ALT_SIGN_EXT) ? 0 : 1)) | A(src1) | B(src2))); - if (flags & ALT_FORM5) - return push_inst(compiler, CMP | CRD(0 | ((flags & ALT_SIGN_EXT) ? 0 : 1)) | A(src1) | B(src2)); - return SLJIT_SUCCESS; + + if (flags & ALT_FORM4) { + if (flags & ALT_FORM5) { + SLJIT_ASSERT(src2 == TMP_REG2); + return push_inst(compiler, CMPI | CRD(0 | ((flags & ALT_SIGN_EXT) ? 0 : 1)) | A(src1) | compiler->imm); + } + return push_inst(compiler, CMP | CRD(0 | ((flags & ALT_SIGN_EXT) ? 0 : 1)) | A(src1) | B(src2)); } + if (!(flags & ALT_SET_FLAGS)) return push_inst(compiler, SUBF | D(dst) | A(src2) | B(src1)); BIN_EXTS(); - if (flags & ALT_FORM6) - FAIL_IF(push_inst(compiler, CMPL | CRD(4 | ((flags & ALT_SIGN_EXT) ? 0 : 1)) | A(src1) | B(src2))); - return push_inst(compiler, SUBFC | OERC(ALT_SET_FLAGS) | D(dst) | A(src2) | B(src1)); + if (flags & ALT_FORM5) + return push_inst(compiler, SUBFC | RC(ALT_SET_FLAGS) | D(dst) | A(src2) | B(src1)); + return push_inst(compiler, SUBF | RC(flags) | D(dst) | A(src2) | B(src1)); case SLJIT_SUBC: - if (flags & ALT_FORM1) { - FAIL_IF(push_inst(compiler, MFXER | D(0))); - FAIL_IF(push_inst(compiler, SUBFE | D(dst) | A(src2) | B(src1))); - return push_inst(compiler, MTXER | S(0)); - } BIN_EXTS(); return push_inst(compiler, SUBFE | D(dst) | A(src2) | B(src1)); @@ -292,8 +326,8 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl } BIN_EXTS(); if (flags & ALT_FORM2) - return push_inst(compiler, MULLW | OERC(flags) | D(dst) | A(src2) | B(src1)); - return push_inst(compiler, MULLD | OERC(flags) | D(dst) | A(src2) | B(src1)); + return push_inst(compiler, MULLW | OE(flags) | RC(flags) | D(dst) | A(src2) | B(src1)); + return push_inst(compiler, MULLD | OE(flags) | RC(flags) | D(dst) | A(src2) | B(src1)); case SLJIT_AND: if (flags & ALT_FORM1) { @@ -345,10 +379,8 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl compiler->imm &= 0x1f; return push_inst(compiler, RLWINM | RC(flags) | S(src1) | A(dst) | (compiler->imm << 11) | ((31 - compiler->imm) << 1)); } - else { - compiler->imm &= 0x3f; - return push_inst(compiler, RLDI(dst, src1, compiler->imm, 63 - compiler->imm, 1) | RC(flags)); - } + compiler->imm &= 0x3f; + return push_inst(compiler, RLDI(dst, src1, compiler->imm, 63 - compiler->imm, 1) | RC(flags)); } return push_inst(compiler, ((flags & ALT_FORM2) ? SLW : SLD) | RC(flags) | S(src1) | A(dst) | B(src2)); @@ -359,33 +391,80 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl compiler->imm &= 0x1f; return push_inst(compiler, RLWINM | RC(flags) | S(src1) | A(dst) | (((32 - compiler->imm) & 0x1f) << 11) | (compiler->imm << 6) | (31 << 1)); } - else { - compiler->imm &= 0x3f; - return push_inst(compiler, RLDI(dst, src1, 64 - compiler->imm, compiler->imm, 0) | RC(flags)); - } + compiler->imm &= 0x3f; + return push_inst(compiler, RLDI(dst, src1, 64 - compiler->imm, compiler->imm, 0) | RC(flags)); } return push_inst(compiler, ((flags & ALT_FORM2) ? SRW : SRD) | RC(flags) | S(src1) | A(dst) | B(src2)); case SLJIT_ASHR: - if (flags & ALT_FORM3) - FAIL_IF(push_inst(compiler, MFXER | D(0))); if (flags & ALT_FORM1) { SLJIT_ASSERT(src2 == TMP_REG2); if (flags & ALT_FORM2) { compiler->imm &= 0x1f; - FAIL_IF(push_inst(compiler, SRAWI | RC(flags) | S(src1) | A(dst) | (compiler->imm << 11))); + return push_inst(compiler, SRAWI | RC(flags) | S(src1) | A(dst) | (compiler->imm << 11)); } - else { - compiler->imm &= 0x3f; - FAIL_IF(push_inst(compiler, SRADI | RC(flags) | S(src1) | A(dst) | ((compiler->imm & 0x1f) << 11) | ((compiler->imm & 0x20) >> 4))); + compiler->imm &= 0x3f; + return push_inst(compiler, SRADI | RC(flags) | S(src1) | A(dst) | ((compiler->imm & 0x1f) << 11) | ((compiler->imm & 0x20) >> 4)); + } + return push_inst(compiler, ((flags & ALT_FORM2) ? SRAW : SRAD) | RC(flags) | S(src1) | A(dst) | B(src2)); + } + + SLJIT_UNREACHABLE(); + return SLJIT_SUCCESS; +} + +static sljit_s32 call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_types, sljit_s32 *src) +{ + sljit_s32 arg_count = 0; + sljit_s32 word_arg_count = 0; + sljit_s32 types = 0; + sljit_s32 reg = 0; + + if (src) + reg = *src & REG_MASK; + + arg_types >>= SLJIT_DEF_SHIFT; + + while (arg_types) { + types = (types << SLJIT_DEF_SHIFT) | (arg_types & SLJIT_DEF_MASK); + + switch (arg_types & SLJIT_DEF_MASK) { + case SLJIT_ARG_TYPE_F32: + case SLJIT_ARG_TYPE_F64: + arg_count++; + break; + default: + arg_count++; + word_arg_count++; + + if (arg_count != word_arg_count && arg_count == reg) { + FAIL_IF(push_inst(compiler, OR | S(reg) | A(TMP_CALL_REG) | B(reg))); + *src = TMP_CALL_REG; } + break; + } + + arg_types >>= SLJIT_DEF_SHIFT; + } + + while (types) { + switch (types & SLJIT_DEF_MASK) { + case SLJIT_ARG_TYPE_F32: + case SLJIT_ARG_TYPE_F64: + arg_count--; + break; + default: + if (arg_count != word_arg_count) + FAIL_IF(push_inst(compiler, OR | S(word_arg_count) | A(arg_count) | B(word_arg_count))); + + arg_count--; + word_arg_count--; + break; } - else - FAIL_IF(push_inst(compiler, ((flags & ALT_FORM2) ? SRAW : SRAD) | RC(flags) | S(src1) | A(dst) | B(src2))); - return (flags & ALT_FORM3) ? push_inst(compiler, MTXER | S(0)) : SLJIT_SUCCESS; + + types >>= SLJIT_DEF_SHIFT; } - SLJIT_ASSERT_STOP(); return SLJIT_SUCCESS; } diff --git a/thirdparty/pcre2/src/sljit/sljitNativePPC_common.c b/thirdparty/pcre2/src/sljit/sljitNativePPC_common.c index 150c0bf9f4..5ef4ac96c4 100644 --- a/thirdparty/pcre2/src/sljit/sljitNativePPC_common.c +++ b/thirdparty/pcre2/src/sljit/sljitNativePPC_common.c @@ -1,7 +1,7 @@ /* * Stack-less Just-In-Time compiler * - * Copyright 2009-2012 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved. + * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are * permitted provided that the following conditions are met: @@ -93,20 +93,23 @@ static void ppc_cache_flush(sljit_ins *from, sljit_ins *to) #define TMP_REG1 (SLJIT_NUMBER_OF_REGISTERS + 2) #define TMP_REG2 (SLJIT_NUMBER_OF_REGISTERS + 3) -#define TMP_REG3 (SLJIT_NUMBER_OF_REGISTERS + 4) -#define TMP_ZERO (SLJIT_NUMBER_OF_REGISTERS + 5) +#define TMP_ZERO (SLJIT_NUMBER_OF_REGISTERS + 4) #if (defined SLJIT_PASS_ENTRY_ADDR_TO_CALL && SLJIT_PASS_ENTRY_ADDR_TO_CALL) -#define TMP_CALL_REG (SLJIT_NUMBER_OF_REGISTERS + 6) +#define TMP_CALL_REG (SLJIT_NUMBER_OF_REGISTERS + 5) #else #define TMP_CALL_REG TMP_REG2 #endif -#define TMP_FREG1 (0) -#define TMP_FREG2 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1) +#define TMP_FREG1 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1) +#define TMP_FREG2 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 2) static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 7] = { - 0, 3, 4, 5, 6, 7, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 1, 8, 9, 10, 31, 12 + 0, 3, 4, 5, 6, 7, 8, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 1, 9, 10, 31, 12 +}; + +static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3] = { + 0, 1, 2, 3, 4, 5, 6, 0, 7 }; /* --------------------------------------------------------------------- */ @@ -117,19 +120,19 @@ static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 7] = { #define A(a) (reg_map[a] << 16) #define B(b) (reg_map[b] << 11) #define C(c) (reg_map[c] << 6) -#define FD(fd) ((fd) << 21) -#define FS(fs) ((fs) << 21) -#define FA(fa) ((fa) << 16) -#define FB(fb) ((fb) << 11) -#define FC(fc) ((fc) << 6) +#define FD(fd) (freg_map[fd] << 21) +#define FS(fs) (freg_map[fs] << 21) +#define FA(fa) (freg_map[fa] << 16) +#define FB(fb) (freg_map[fb] << 11) +#define FC(fc) (freg_map[fc] << 6) #define IMM(imm) ((imm) & 0xffff) #define CRD(d) ((d) << 21) /* Instruction bit sections. OE and Rc flag (see ALT_SET_FLAGS). */ -#define OERC(flags) (((flags & ALT_SET_FLAGS) >> 10) | (flags & ALT_SET_FLAGS)) +#define OE(flags) ((flags) & ALT_SET_FLAGS) /* Rc flag (see ALT_SET_FLAGS). */ -#define RC(flags) ((flags & ALT_SET_FLAGS) >> 10) +#define RC(flags) (((flags) & ALT_SET_FLAGS) >> 10) #define HI(opcode) ((opcode) << 26) #define LO(opcode) ((opcode) << 1) @@ -154,6 +157,7 @@ static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 7] = { #define CMPL (HI(31) | LO(32)) #define CMPLI (HI(10)) #define CROR (HI(19) | LO(449)) +#define DCBT (HI(31) | LO(278)) #define DIVD (HI(31) | LO(489)) #define DIVDU (HI(31) | LO(457)) #define DIVW (HI(31) | LO(491)) @@ -524,6 +528,25 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil #endif } +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type) +{ + switch (feature_type) { + case SLJIT_HAS_FPU: +#ifdef SLJIT_IS_FPU_AVAILABLE + return SLJIT_IS_FPU_AVAILABLE; +#else + /* Available by default. */ + return 1; +#endif + + case SLJIT_HAS_CLZ: + return 1; + + default: + return 0; + } +} + /* --------------------------------------------------------------------- */ /* Entry, exit */ /* --------------------------------------------------------------------- */ @@ -533,47 +556,40 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil /* Creates an index in data_transfer_insts array. */ #define LOAD_DATA 0x01 #define INDEXED 0x02 -#define WRITE_BACK 0x04 +#define SIGNED_DATA 0x04 + #define WORD_DATA 0x00 #define BYTE_DATA 0x08 #define HALF_DATA 0x10 #define INT_DATA 0x18 -#define SIGNED_DATA 0x20 /* Separates integer and floating point registers */ -#define GPR_REG 0x3f -#define DOUBLE_DATA 0x40 +#define GPR_REG 0x1f +#define DOUBLE_DATA 0x20 #define MEM_MASK 0x7f /* Other inp_flags. */ -#define ARG_TEST 0x000100 /* Integer opertion and set flags -> requires exts on 64 bit systems. */ -#define ALT_SIGN_EXT 0x000200 +#define ALT_SIGN_EXT 0x000100 /* This flag affects the RC() and OERC() macros. */ #define ALT_SET_FLAGS 0x000400 -#define ALT_KEEP_CACHE 0x000800 -#define ALT_FORM1 0x010000 -#define ALT_FORM2 0x020000 -#define ALT_FORM3 0x040000 -#define ALT_FORM4 0x080000 -#define ALT_FORM5 0x100000 -#define ALT_FORM6 0x200000 +#define ALT_FORM1 0x001000 +#define ALT_FORM2 0x002000 +#define ALT_FORM3 0x004000 +#define ALT_FORM4 0x008000 +#define ALT_FORM5 0x010000 /* Source and destination is register. */ #define REG_DEST 0x000001 #define REG1_SOURCE 0x000002 #define REG2_SOURCE 0x000004 -/* getput_arg_fast returned true. */ -#define FAST_DEST 0x000008 -/* Multiple instructions are required. */ -#define SLOW_DEST 0x000010 /* -ALT_SIGN_EXT 0x000200 -ALT_SET_FLAGS 0x000400 -ALT_FORM1 0x010000 +ALT_SIGN_EXT 0x000100 +ALT_SET_FLAGS 0x000200 +ALT_FORM1 0x001000 ... -ALT_FORM6 0x200000 */ +ALT_FORM5 0x010000 */ #if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) #include "sljitNativePPC_32.c" @@ -590,14 +606,14 @@ ALT_FORM6 0x200000 */ #endif SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compiler, - sljit_s32 options, sljit_s32 args, sljit_s32 scratches, sljit_s32 saveds, + sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds, sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size) { - sljit_s32 i, tmp, offs; + sljit_s32 args, i, tmp, offs; CHECK_ERROR(); - CHECK(check_sljit_emit_enter(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size)); - set_emit_enter(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size); + CHECK(check_sljit_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size)); + set_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size); FAIL_IF(push_inst(compiler, MFLR | D(0))); offs = -(sljit_s32)(sizeof(sljit_sw)); @@ -623,6 +639,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi #endif FAIL_IF(push_inst(compiler, ADDI | D(TMP_ZERO) | A(0) | 0)); + + args = get_arg_count(arg_types); + if (args >= 1) FAIL_IF(push_inst(compiler, OR | S(SLJIT_R0) | A(SLJIT_S0) | B(SLJIT_R0))); if (args >= 2) @@ -654,12 +673,12 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *compiler, - sljit_s32 options, sljit_s32 args, sljit_s32 scratches, sljit_s32 saveds, + sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds, sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size) { CHECK_ERROR(); - CHECK(check_sljit_set_context(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size)); - set_set_context(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size); + CHECK(check_sljit_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size)); + set_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size); local_size += GET_SAVED_REGISTERS_SIZE(scratches, saveds, 1) + SLJIT_LOCALS_OFFSET; compiler->local_size = (local_size + 15) & ~0xf; @@ -718,17 +737,17 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return(struct sljit_compiler *comp /* Operators */ /* --------------------------------------------------------------------- */ -/* i/x - immediate/indexed form - n/w - no write-back / write-back (1 bit) - s/l - store/load (1 bit) +/* s/l - store/load (1 bit) + i/x - immediate/indexed form u/s - signed/unsigned (1 bit) w/b/h/i - word/byte/half/int allowed (2 bit) - It contans 32 items, but not all are different. */ + + Some opcodes are repeated (e.g. store signed / unsigned byte is the same instruction). */ /* 64 bit only: [reg+imm] must be aligned to 4 bytes. */ +#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) #define INT_ALIGNED 0x10000 -/* 64-bit only: there is no lwau instruction. */ -#define UPDATE_REQ 0x20000 +#endif #if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) #define ARCH_32_64(a, b) a @@ -737,401 +756,217 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return(struct sljit_compiler *comp #else #define ARCH_32_64(a, b) b #define INST_CODE_AND_DST(inst, flags, reg) \ - (((inst) & ~(INT_ALIGNED | UPDATE_REQ)) | (((flags) & MEM_MASK) <= GPR_REG ? D(reg) : FD(reg))) + (((inst) & ~INT_ALIGNED) | (((flags) & MEM_MASK) <= GPR_REG ? D(reg) : FD(reg))) #endif -static const sljit_ins data_transfer_insts[64 + 8] = { +static const sljit_ins data_transfer_insts[64 + 16] = { -/* -------- Unsigned -------- */ +/* -------- Integer -------- */ /* Word. */ -/* u w n i s */ ARCH_32_64(HI(36) /* stw */, HI(62) | INT_ALIGNED | 0x0 /* std */), -/* u w n i l */ ARCH_32_64(HI(32) /* lwz */, HI(58) | INT_ALIGNED | 0x0 /* ld */), -/* u w n x s */ ARCH_32_64(HI(31) | LO(151) /* stwx */, HI(31) | LO(149) /* stdx */), -/* u w n x l */ ARCH_32_64(HI(31) | LO(23) /* lwzx */, HI(31) | LO(21) /* ldx */), +/* w u i s */ ARCH_32_64(HI(36) /* stw */, HI(62) | INT_ALIGNED | 0x0 /* std */), +/* w u i l */ ARCH_32_64(HI(32) /* lwz */, HI(58) | INT_ALIGNED | 0x0 /* ld */), +/* w u x s */ ARCH_32_64(HI(31) | LO(151) /* stwx */, HI(31) | LO(149) /* stdx */), +/* w u x l */ ARCH_32_64(HI(31) | LO(23) /* lwzx */, HI(31) | LO(21) /* ldx */), -/* u w w i s */ ARCH_32_64(HI(37) /* stwu */, HI(62) | INT_ALIGNED | 0x1 /* stdu */), -/* u w w i l */ ARCH_32_64(HI(33) /* lwzu */, HI(58) | INT_ALIGNED | 0x1 /* ldu */), -/* u w w x s */ ARCH_32_64(HI(31) | LO(183) /* stwux */, HI(31) | LO(181) /* stdux */), -/* u w w x l */ ARCH_32_64(HI(31) | LO(55) /* lwzux */, HI(31) | LO(53) /* ldux */), +/* w s i s */ ARCH_32_64(HI(36) /* stw */, HI(62) | INT_ALIGNED | 0x0 /* std */), +/* w s i l */ ARCH_32_64(HI(32) /* lwz */, HI(58) | INT_ALIGNED | 0x0 /* ld */), +/* w s x s */ ARCH_32_64(HI(31) | LO(151) /* stwx */, HI(31) | LO(149) /* stdx */), +/* w s x l */ ARCH_32_64(HI(31) | LO(23) /* lwzx */, HI(31) | LO(21) /* ldx */), /* Byte. */ -/* u b n i s */ HI(38) /* stb */, -/* u b n i l */ HI(34) /* lbz */, -/* u b n x s */ HI(31) | LO(215) /* stbx */, -/* u b n x l */ HI(31) | LO(87) /* lbzx */, +/* b u i s */ HI(38) /* stb */, +/* b u i l */ HI(34) /* lbz */, +/* b u x s */ HI(31) | LO(215) /* stbx */, +/* b u x l */ HI(31) | LO(87) /* lbzx */, -/* u b w i s */ HI(39) /* stbu */, -/* u b w i l */ HI(35) /* lbzu */, -/* u b w x s */ HI(31) | LO(247) /* stbux */, -/* u b w x l */ HI(31) | LO(119) /* lbzux */, +/* b s i s */ HI(38) /* stb */, +/* b s i l */ HI(34) /* lbz */ /* EXTS_REQ */, +/* b s x s */ HI(31) | LO(215) /* stbx */, +/* b s x l */ HI(31) | LO(87) /* lbzx */ /* EXTS_REQ */, /* Half. */ -/* u h n i s */ HI(44) /* sth */, -/* u h n i l */ HI(40) /* lhz */, -/* u h n x s */ HI(31) | LO(407) /* sthx */, -/* u h n x l */ HI(31) | LO(279) /* lhzx */, +/* h u i s */ HI(44) /* sth */, +/* h u i l */ HI(40) /* lhz */, +/* h u x s */ HI(31) | LO(407) /* sthx */, +/* h u x l */ HI(31) | LO(279) /* lhzx */, -/* u h w i s */ HI(45) /* sthu */, -/* u h w i l */ HI(41) /* lhzu */, -/* u h w x s */ HI(31) | LO(439) /* sthux */, -/* u h w x l */ HI(31) | LO(311) /* lhzux */, +/* h s i s */ HI(44) /* sth */, +/* h s i l */ HI(42) /* lha */, +/* h s x s */ HI(31) | LO(407) /* sthx */, +/* h s x l */ HI(31) | LO(343) /* lhax */, /* Int. */ -/* u i n i s */ HI(36) /* stw */, -/* u i n i l */ HI(32) /* lwz */, -/* u i n x s */ HI(31) | LO(151) /* stwx */, -/* u i n x l */ HI(31) | LO(23) /* lwzx */, +/* i u i s */ HI(36) /* stw */, +/* i u i l */ HI(32) /* lwz */, +/* i u x s */ HI(31) | LO(151) /* stwx */, +/* i u x l */ HI(31) | LO(23) /* lwzx */, + +/* i s i s */ HI(36) /* stw */, +/* i s i l */ ARCH_32_64(HI(32) /* lwz */, HI(58) | INT_ALIGNED | 0x2 /* lwa */), +/* i s x s */ HI(31) | LO(151) /* stwx */, +/* i s x l */ ARCH_32_64(HI(31) | LO(23) /* lwzx */, HI(31) | LO(341) /* lwax */), -/* u i w i s */ HI(37) /* stwu */, -/* u i w i l */ HI(33) /* lwzu */, -/* u i w x s */ HI(31) | LO(183) /* stwux */, -/* u i w x l */ HI(31) | LO(55) /* lwzux */, +/* -------- Floating point -------- */ -/* -------- Signed -------- */ +/* d i s */ HI(54) /* stfd */, +/* d i l */ HI(50) /* lfd */, +/* d x s */ HI(31) | LO(727) /* stfdx */, +/* d x l */ HI(31) | LO(599) /* lfdx */, + +/* s i s */ HI(52) /* stfs */, +/* s i l */ HI(48) /* lfs */, +/* s x s */ HI(31) | LO(663) /* stfsx */, +/* s x l */ HI(31) | LO(535) /* lfsx */, +}; + +static const sljit_ins updated_data_transfer_insts[64] = { + +/* -------- Integer -------- */ /* Word. */ -/* s w n i s */ ARCH_32_64(HI(36) /* stw */, HI(62) | INT_ALIGNED | 0x0 /* std */), -/* s w n i l */ ARCH_32_64(HI(32) /* lwz */, HI(58) | INT_ALIGNED | 0x0 /* ld */), -/* s w n x s */ ARCH_32_64(HI(31) | LO(151) /* stwx */, HI(31) | LO(149) /* stdx */), -/* s w n x l */ ARCH_32_64(HI(31) | LO(23) /* lwzx */, HI(31) | LO(21) /* ldx */), +/* w u i s */ ARCH_32_64(HI(37) /* stwu */, HI(62) | INT_ALIGNED | 0x1 /* stdu */), +/* w u i l */ ARCH_32_64(HI(33) /* lwzu */, HI(58) | INT_ALIGNED | 0x1 /* ldu */), +/* w u x s */ ARCH_32_64(HI(31) | LO(183) /* stwux */, HI(31) | LO(181) /* stdux */), +/* w u x l */ ARCH_32_64(HI(31) | LO(55) /* lwzux */, HI(31) | LO(53) /* ldux */), -/* s w w i s */ ARCH_32_64(HI(37) /* stwu */, HI(62) | INT_ALIGNED | 0x1 /* stdu */), -/* s w w i l */ ARCH_32_64(HI(33) /* lwzu */, HI(58) | INT_ALIGNED | 0x1 /* ldu */), -/* s w w x s */ ARCH_32_64(HI(31) | LO(183) /* stwux */, HI(31) | LO(181) /* stdux */), -/* s w w x l */ ARCH_32_64(HI(31) | LO(55) /* lwzux */, HI(31) | LO(53) /* ldux */), +/* w s i s */ ARCH_32_64(HI(37) /* stwu */, HI(62) | INT_ALIGNED | 0x1 /* stdu */), +/* w s i l */ ARCH_32_64(HI(33) /* lwzu */, HI(58) | INT_ALIGNED | 0x1 /* ldu */), +/* w s x s */ ARCH_32_64(HI(31) | LO(183) /* stwux */, HI(31) | LO(181) /* stdux */), +/* w s x l */ ARCH_32_64(HI(31) | LO(55) /* lwzux */, HI(31) | LO(53) /* ldux */), /* Byte. */ -/* s b n i s */ HI(38) /* stb */, -/* s b n i l */ HI(34) /* lbz */ /* EXTS_REQ */, -/* s b n x s */ HI(31) | LO(215) /* stbx */, -/* s b n x l */ HI(31) | LO(87) /* lbzx */ /* EXTS_REQ */, +/* b u i s */ HI(39) /* stbu */, +/* b u i l */ HI(35) /* lbzu */, +/* b u x s */ HI(31) | LO(247) /* stbux */, +/* b u x l */ HI(31) | LO(119) /* lbzux */, -/* s b w i s */ HI(39) /* stbu */, -/* s b w i l */ HI(35) /* lbzu */ /* EXTS_REQ */, -/* s b w x s */ HI(31) | LO(247) /* stbux */, -/* s b w x l */ HI(31) | LO(119) /* lbzux */ /* EXTS_REQ */, +/* b s i s */ HI(39) /* stbu */, +/* b s i l */ 0 /* no such instruction */, +/* b s x s */ HI(31) | LO(247) /* stbux */, +/* b s x l */ 0 /* no such instruction */, /* Half. */ -/* s h n i s */ HI(44) /* sth */, -/* s h n i l */ HI(42) /* lha */, -/* s h n x s */ HI(31) | LO(407) /* sthx */, -/* s h n x l */ HI(31) | LO(343) /* lhax */, +/* h u i s */ HI(45) /* sthu */, +/* h u i l */ HI(41) /* lhzu */, +/* h u x s */ HI(31) | LO(439) /* sthux */, +/* h u x l */ HI(31) | LO(311) /* lhzux */, -/* s h w i s */ HI(45) /* sthu */, -/* s h w i l */ HI(43) /* lhau */, -/* s h w x s */ HI(31) | LO(439) /* sthux */, -/* s h w x l */ HI(31) | LO(375) /* lhaux */, +/* h s i s */ HI(45) /* sthu */, +/* h s i l */ HI(43) /* lhau */, +/* h s x s */ HI(31) | LO(439) /* sthux */, +/* h s x l */ HI(31) | LO(375) /* lhaux */, /* Int. */ -/* s i n i s */ HI(36) /* stw */, -/* s i n i l */ ARCH_32_64(HI(32) /* lwz */, HI(58) | INT_ALIGNED | 0x2 /* lwa */), -/* s i n x s */ HI(31) | LO(151) /* stwx */, -/* s i n x l */ ARCH_32_64(HI(31) | LO(23) /* lwzx */, HI(31) | LO(341) /* lwax */), +/* i u i s */ HI(37) /* stwu */, +/* i u i l */ HI(33) /* lwzu */, +/* i u x s */ HI(31) | LO(183) /* stwux */, +/* i u x l */ HI(31) | LO(55) /* lwzux */, -/* s i w i s */ HI(37) /* stwu */, -/* s i w i l */ ARCH_32_64(HI(33) /* lwzu */, HI(58) | INT_ALIGNED | UPDATE_REQ | 0x2 /* lwa */), -/* s i w x s */ HI(31) | LO(183) /* stwux */, -/* s i w x l */ ARCH_32_64(HI(31) | LO(55) /* lwzux */, HI(31) | LO(373) /* lwaux */), +/* i s i s */ HI(37) /* stwu */, +/* i s i l */ ARCH_32_64(HI(33) /* lwzu */, 0 /* no such instruction */), +/* i s x s */ HI(31) | LO(183) /* stwux */, +/* i s x l */ ARCH_32_64(HI(31) | LO(55) /* lwzux */, HI(31) | LO(373) /* lwaux */), -/* -------- Double -------- */ +/* -------- Floating point -------- */ -/* d n i s */ HI(54) /* stfd */, -/* d n i l */ HI(50) /* lfd */, -/* d n x s */ HI(31) | LO(727) /* stfdx */, -/* d n x l */ HI(31) | LO(599) /* lfdx */, - -/* s n i s */ HI(52) /* stfs */, -/* s n i l */ HI(48) /* lfs */, -/* s n x s */ HI(31) | LO(663) /* stfsx */, -/* s n x l */ HI(31) | LO(535) /* lfsx */, +/* d i s */ HI(55) /* stfdu */, +/* d i l */ HI(51) /* lfdu */, +/* d x s */ HI(31) | LO(759) /* stfdux */, +/* d x l */ HI(31) | LO(631) /* lfdux */, +/* s i s */ HI(53) /* stfsu */, +/* s i l */ HI(49) /* lfsu */, +/* s x s */ HI(31) | LO(695) /* stfsux */, +/* s x l */ HI(31) | LO(567) /* lfsux */, }; #undef ARCH_32_64 /* Simple cases, (no caching is required). */ -static sljit_s32 getput_arg_fast(struct sljit_compiler *compiler, sljit_s32 inp_flags, sljit_s32 reg, sljit_s32 arg, sljit_sw argw) +static sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 inp_flags, sljit_s32 reg, + sljit_s32 arg, sljit_sw argw, sljit_s32 tmp_reg) { sljit_ins inst; + sljit_s32 offs_reg; + sljit_sw high_short; /* Should work when (arg & REG_MASK) == 0. */ - SLJIT_COMPILE_ASSERT(A(0) == 0, a0_must_be_0); + SLJIT_ASSERT(A(0) == 0); SLJIT_ASSERT(arg & SLJIT_MEM); - if (arg & OFFS_REG_MASK) { - if (argw & 0x3) - return 0; - if (inp_flags & ARG_TEST) - return 1; - - inst = data_transfer_insts[(inp_flags | INDEXED) & MEM_MASK]; - SLJIT_ASSERT(!(inst & (INT_ALIGNED | UPDATE_REQ))); - FAIL_IF(push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | A(arg & REG_MASK) | B(OFFS_REG(arg)))); - return -1; - } - - if (SLJIT_UNLIKELY(!(arg & REG_MASK))) - inp_flags &= ~WRITE_BACK; - -#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) - inst = data_transfer_insts[inp_flags & MEM_MASK]; - SLJIT_ASSERT((arg & REG_MASK) || !(inst & UPDATE_REQ)); - - if (argw > SIMM_MAX || argw < SIMM_MIN || ((inst & INT_ALIGNED) && (argw & 0x3)) || (inst & UPDATE_REQ)) - return 0; - if (inp_flags & ARG_TEST) - return 1; -#endif + if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) { + argw &= 0x3; + offs_reg = OFFS_REG(arg); + if (argw != 0) { #if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) - if (argw > SIMM_MAX || argw < SIMM_MIN) - return 0; - if (inp_flags & ARG_TEST) - return 1; - - inst = data_transfer_insts[inp_flags & MEM_MASK]; - SLJIT_ASSERT(!(inst & (INT_ALIGNED | UPDATE_REQ))); + FAIL_IF(push_inst(compiler, RLWINM | S(OFFS_REG(arg)) | A(tmp_reg) | (argw << 11) | ((31 - argw) << 1))); +#else + FAIL_IF(push_inst(compiler, RLDI(tmp_reg, OFFS_REG(arg), argw, 63 - argw, 1))); #endif + offs_reg = tmp_reg; + } - FAIL_IF(push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | A(arg & REG_MASK) | IMM(argw))); - return -1; -} + inst = data_transfer_insts[(inp_flags | INDEXED) & MEM_MASK]; -/* See getput_arg below. - Note: can_cache is called only for binary operators. Those operator always - uses word arguments without write back. */ -static sljit_s32 can_cache(sljit_s32 arg, sljit_sw argw, sljit_s32 next_arg, sljit_sw next_argw) -{ - sljit_sw high_short, next_high_short; #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) - sljit_sw diff; + SLJIT_ASSERT(!(inst & INT_ALIGNED)); #endif - SLJIT_ASSERT((arg & SLJIT_MEM) && (next_arg & SLJIT_MEM)); - - if (arg & OFFS_REG_MASK) - return ((arg & OFFS_REG_MASK) == (next_arg & OFFS_REG_MASK) && (argw & 0x3) == (next_argw & 0x3)); - - if (next_arg & OFFS_REG_MASK) - return 0; - -#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) - high_short = (argw + ((argw & 0x8000) << 1)) & ~0xffff; - next_high_short = (next_argw + ((next_argw & 0x8000) << 1)) & ~0xffff; - return high_short == next_high_short; -#else - if (argw <= 0x7fffffffl && argw >= -0x80000000l) { - high_short = (argw + ((argw & 0x8000) << 1)) & ~0xffff; - next_high_short = (next_argw + ((next_argw & 0x8000) << 1)) & ~0xffff; - if (high_short == next_high_short) - return 1; + return push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | A(arg & REG_MASK) | B(offs_reg)); } - diff = argw - next_argw; - if (!(arg & REG_MASK)) - return diff <= SIMM_MAX && diff >= SIMM_MIN; - - if (arg == next_arg && diff <= SIMM_MAX && diff >= SIMM_MIN) - return 1; - - return 0; -#endif -} - -#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) -#define ADJUST_CACHED_IMM(imm) \ - if ((inst & INT_ALIGNED) && (imm & 0x3)) { \ - /* Adjust cached value. Fortunately this is really a rare case */ \ - compiler->cache_argw += imm & 0x3; \ - FAIL_IF(push_inst(compiler, ADDI | D(TMP_REG3) | A(TMP_REG3) | (imm & 0x3))); \ - imm &= ~0x3; \ - } -#endif + inst = data_transfer_insts[inp_flags & MEM_MASK]; + arg &= REG_MASK; -/* Emit the necessary instructions. See can_cache above. */ -static sljit_s32 getput_arg(struct sljit_compiler *compiler, sljit_s32 inp_flags, sljit_s32 reg, sljit_s32 arg, sljit_sw argw, sljit_s32 next_arg, sljit_sw next_argw) -{ - sljit_s32 tmp_r; - sljit_ins inst; - sljit_sw high_short, next_high_short; #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) - sljit_sw diff; -#endif + if ((inst & INT_ALIGNED) && (argw & 0x3) != 0) { + FAIL_IF(load_immediate(compiler, tmp_reg, argw)); - SLJIT_ASSERT(arg & SLJIT_MEM); - - tmp_r = ((inp_flags & LOAD_DATA) && ((inp_flags) & MEM_MASK) <= GPR_REG) ? reg : TMP_REG1; - /* Special case for "mov reg, [reg, ... ]". */ - if ((arg & REG_MASK) == tmp_r) - tmp_r = TMP_REG1; - - if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) { - argw &= 0x3; - /* Otherwise getput_arg_fast would capture it. */ - SLJIT_ASSERT(argw); - - if ((SLJIT_MEM | (arg & OFFS_REG_MASK)) == compiler->cache_arg && argw == compiler->cache_argw) - tmp_r = TMP_REG3; - else { - if ((arg & OFFS_REG_MASK) == (next_arg & OFFS_REG_MASK) && argw == (next_argw & 0x3)) { - compiler->cache_arg = SLJIT_MEM | (arg & OFFS_REG_MASK); - compiler->cache_argw = argw; - tmp_r = TMP_REG3; - } -#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) - FAIL_IF(push_inst(compiler, RLWINM | S(OFFS_REG(arg)) | A(tmp_r) | (argw << 11) | ((31 - argw) << 1))); -#else - FAIL_IF(push_inst(compiler, RLDI(tmp_r, OFFS_REG(arg), argw, 63 - argw, 1))); -#endif - } inst = data_transfer_insts[(inp_flags | INDEXED) & MEM_MASK]; - SLJIT_ASSERT(!(inst & (INT_ALIGNED | UPDATE_REQ))); - return push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | A(arg & REG_MASK) | B(tmp_r)); + return push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | A(arg) | B(tmp_reg)); } +#endif - if (SLJIT_UNLIKELY(!(arg & REG_MASK))) - inp_flags &= ~WRITE_BACK; - - inst = data_transfer_insts[inp_flags & MEM_MASK]; - SLJIT_ASSERT((arg & REG_MASK) || !(inst & UPDATE_REQ)); + if (argw <= SIMM_MAX && argw >= SIMM_MIN) + return push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | A(arg) | IMM(argw)); #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) - if (argw <= 0x7fff7fffl && argw >= -0x80000000l - && (!(inst & INT_ALIGNED) || !(argw & 0x3)) && !(inst & UPDATE_REQ)) { + if (argw <= 0x7fff7fffl && argw >= -0x80000000l) { #endif - arg &= REG_MASK; high_short = (sljit_s32)(argw + ((argw & 0x8000) << 1)) & ~0xffff; - /* The getput_arg_fast should handle this otherwise. */ + #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) SLJIT_ASSERT(high_short && high_short <= 0x7fffffffl && high_short >= -0x80000000l); #else - SLJIT_ASSERT(high_short && !(inst & (INT_ALIGNED | UPDATE_REQ))); + SLJIT_ASSERT(high_short); #endif - if (inp_flags & WRITE_BACK) { - if (arg == reg) { - FAIL_IF(push_inst(compiler, OR | S(reg) | A(tmp_r) | B(reg))); - reg = tmp_r; - } - tmp_r = arg; - FAIL_IF(push_inst(compiler, ADDIS | D(arg) | A(arg) | IMM(high_short >> 16))); - } - else if (compiler->cache_arg != (SLJIT_MEM | arg) || high_short != compiler->cache_argw) { - if ((next_arg & SLJIT_MEM) && !(next_arg & OFFS_REG_MASK)) { - next_high_short = (sljit_s32)(next_argw + ((next_argw & 0x8000) << 1)) & ~0xffff; - if (high_short == next_high_short) { - compiler->cache_arg = SLJIT_MEM | arg; - compiler->cache_argw = high_short; - tmp_r = TMP_REG3; - } - } - FAIL_IF(push_inst(compiler, ADDIS | D(tmp_r) | A(arg & REG_MASK) | IMM(high_short >> 16))); - } - else - tmp_r = TMP_REG3; - - return push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | A(tmp_r) | IMM(argw)); + FAIL_IF(push_inst(compiler, ADDIS | D(tmp_reg) | A(arg) | IMM(high_short >> 16))); + return push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | A(tmp_reg) | IMM(argw)); #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) } - /* Everything else is PPC-64 only. */ - if (SLJIT_UNLIKELY(!(arg & REG_MASK))) { - diff = argw - compiler->cache_argw; - if ((compiler->cache_arg & SLJIT_IMM) && diff <= SIMM_MAX && diff >= SIMM_MIN) { - ADJUST_CACHED_IMM(diff); - return push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | A(TMP_REG3) | IMM(diff)); - } - - diff = argw - next_argw; - if ((next_arg & SLJIT_MEM) && diff <= SIMM_MAX && diff >= SIMM_MIN) { - SLJIT_ASSERT(inp_flags & LOAD_DATA); - - compiler->cache_arg = SLJIT_IMM; - compiler->cache_argw = argw; - tmp_r = TMP_REG3; - } - - FAIL_IF(load_immediate(compiler, tmp_r, argw)); - return push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | A(tmp_r)); - } + /* The rest is PPC-64 only. */ - diff = argw - compiler->cache_argw; - if (compiler->cache_arg == arg && diff <= SIMM_MAX && diff >= SIMM_MIN) { - SLJIT_ASSERT(!(inp_flags & WRITE_BACK) && !(inst & UPDATE_REQ)); - ADJUST_CACHED_IMM(diff); - return push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | A(TMP_REG3) | IMM(diff)); - } - - if ((compiler->cache_arg & SLJIT_IMM) && diff <= SIMM_MAX && diff >= SIMM_MIN) { - inst = data_transfer_insts[(inp_flags | INDEXED) & MEM_MASK]; - SLJIT_ASSERT(!(inst & (INT_ALIGNED | UPDATE_REQ))); - if (compiler->cache_argw != argw) { - FAIL_IF(push_inst(compiler, ADDI | D(TMP_REG3) | A(TMP_REG3) | IMM(diff))); - compiler->cache_argw = argw; - } - return push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | A(arg & REG_MASK) | B(TMP_REG3)); - } - - if (argw == next_argw && (next_arg & SLJIT_MEM)) { - SLJIT_ASSERT(inp_flags & LOAD_DATA); - FAIL_IF(load_immediate(compiler, TMP_REG3, argw)); - - compiler->cache_arg = SLJIT_IMM; - compiler->cache_argw = argw; - - inst = data_transfer_insts[(inp_flags | INDEXED) & MEM_MASK]; - SLJIT_ASSERT(!(inst & (INT_ALIGNED | UPDATE_REQ))); - return push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | A(arg & REG_MASK) | B(TMP_REG3)); - } - - diff = argw - next_argw; - if (arg == next_arg && !(inp_flags & WRITE_BACK) && diff <= SIMM_MAX && diff >= SIMM_MIN) { - SLJIT_ASSERT(inp_flags & LOAD_DATA); - FAIL_IF(load_immediate(compiler, TMP_REG3, argw)); - FAIL_IF(push_inst(compiler, ADD | D(TMP_REG3) | A(TMP_REG3) | B(arg & REG_MASK))); - - compiler->cache_arg = arg; - compiler->cache_argw = argw; - - return push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | A(TMP_REG3)); - } + FAIL_IF(load_immediate(compiler, tmp_reg, argw)); - if ((next_arg & SLJIT_MEM) && !(next_arg & OFFS_REG_MASK) && diff <= SIMM_MAX && diff >= SIMM_MIN) { - SLJIT_ASSERT(inp_flags & LOAD_DATA); - FAIL_IF(load_immediate(compiler, TMP_REG3, argw)); - - compiler->cache_arg = SLJIT_IMM; - compiler->cache_argw = argw; - tmp_r = TMP_REG3; - } - else - FAIL_IF(load_immediate(compiler, tmp_r, argw)); - - /* Get the indexed version instead of the normal one. */ inst = data_transfer_insts[(inp_flags | INDEXED) & MEM_MASK]; - SLJIT_ASSERT(!(inst & (INT_ALIGNED | UPDATE_REQ))); - return push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | A(arg & REG_MASK) | B(tmp_r)); + return push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | A(arg) | B(tmp_reg)); #endif } -static SLJIT_INLINE sljit_s32 emit_op_mem2(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 arg1, sljit_sw arg1w, sljit_s32 arg2, sljit_sw arg2w) -{ - if (getput_arg_fast(compiler, flags, reg, arg1, arg1w)) - return compiler->error; - return getput_arg(compiler, flags, reg, arg1, arg1w, arg2, arg2w); -} - static sljit_s32 emit_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 input_flags, sljit_s32 dst, sljit_sw dstw, sljit_s32 src1, sljit_sw src1w, @@ -1139,42 +974,21 @@ static sljit_s32 emit_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s3 { /* arg1 goes to TMP_REG1 or src reg arg2 goes to TMP_REG2, imm or src reg - TMP_REG3 can be used for caching - result goes to TMP_REG2, so put result can use TMP_REG1 and TMP_REG3. */ - sljit_s32 dst_r; + result goes to TMP_REG2, so put result can use TMP_REG1. */ + sljit_s32 dst_r = TMP_REG2; sljit_s32 src1_r; sljit_s32 src2_r; sljit_s32 sugg_src2_r = TMP_REG2; - sljit_s32 flags = input_flags & (ALT_FORM1 | ALT_FORM2 | ALT_FORM3 | ALT_FORM4 | ALT_FORM5 | ALT_FORM6 | ALT_SIGN_EXT | ALT_SET_FLAGS); - - if (!(input_flags & ALT_KEEP_CACHE)) { - compiler->cache_arg = 0; - compiler->cache_argw = 0; - } + sljit_s32 flags = input_flags & (ALT_FORM1 | ALT_FORM2 | ALT_FORM3 | ALT_FORM4 | ALT_FORM5 | ALT_SIGN_EXT | ALT_SET_FLAGS); /* Destination check. */ - if (SLJIT_UNLIKELY(dst == SLJIT_UNUSED)) { - if (op >= SLJIT_MOV && op <= SLJIT_MOVU_S32 && !(src2 & SLJIT_MEM)) - return SLJIT_SUCCESS; - dst_r = TMP_REG2; - } - else if (FAST_IS_REG(dst)) { + if (SLOW_IS_REG(dst)) { dst_r = dst; flags |= REG_DEST; - if (op >= SLJIT_MOV && op <= SLJIT_MOVU_S32) + + if (op >= SLJIT_MOV && op <= SLJIT_MOV_P) sugg_src2_r = dst_r; } - else { - SLJIT_ASSERT(dst & SLJIT_MEM); - if (getput_arg_fast(compiler, input_flags | ARG_TEST, TMP_REG2, dst, dstw)) { - flags |= FAST_DEST; - dst_r = TMP_REG2; - } - else { - flags |= SLOW_DEST; - dst_r = 0; - } - } /* Source 1. */ if (FAST_IS_REG(src1)) { @@ -1185,80 +999,34 @@ static sljit_s32 emit_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s3 FAIL_IF(load_immediate(compiler, TMP_REG1, src1w)); src1_r = TMP_REG1; } - else if (getput_arg_fast(compiler, input_flags | LOAD_DATA, TMP_REG1, src1, src1w)) { - FAIL_IF(compiler->error); + else { + FAIL_IF(emit_op_mem(compiler, input_flags | LOAD_DATA, TMP_REG1, src1, src1w, TMP_REG1)); src1_r = TMP_REG1; } - else - src1_r = 0; /* Source 2. */ if (FAST_IS_REG(src2)) { src2_r = src2; flags |= REG2_SOURCE; - if (!(flags & REG_DEST) && op >= SLJIT_MOV && op <= SLJIT_MOVU_S32) + + if (!(flags & REG_DEST) && op >= SLJIT_MOV && op <= SLJIT_MOV_P) dst_r = src2_r; } else if (src2 & SLJIT_IMM) { FAIL_IF(load_immediate(compiler, sugg_src2_r, src2w)); src2_r = sugg_src2_r; } - else if (getput_arg_fast(compiler, input_flags | LOAD_DATA, sugg_src2_r, src2, src2w)) { - FAIL_IF(compiler->error); - src2_r = sugg_src2_r; - } - else - src2_r = 0; - - /* src1_r, src2_r and dst_r can be zero (=unprocessed). - All arguments are complex addressing modes, and it is a binary operator. */ - if (src1_r == 0 && src2_r == 0 && dst_r == 0) { - if (!can_cache(src1, src1w, src2, src2w) && can_cache(src1, src1w, dst, dstw)) { - FAIL_IF(getput_arg(compiler, input_flags | LOAD_DATA, TMP_REG2, src2, src2w, src1, src1w)); - FAIL_IF(getput_arg(compiler, input_flags | LOAD_DATA, TMP_REG1, src1, src1w, dst, dstw)); - } - else { - FAIL_IF(getput_arg(compiler, input_flags | LOAD_DATA, TMP_REG1, src1, src1w, src2, src2w)); - FAIL_IF(getput_arg(compiler, input_flags | LOAD_DATA, TMP_REG2, src2, src2w, dst, dstw)); - } - src1_r = TMP_REG1; - src2_r = TMP_REG2; - } - else if (src1_r == 0 && src2_r == 0) { - FAIL_IF(getput_arg(compiler, input_flags | LOAD_DATA, TMP_REG1, src1, src1w, src2, src2w)); - src1_r = TMP_REG1; - } - else if (src1_r == 0 && dst_r == 0) { - FAIL_IF(getput_arg(compiler, input_flags | LOAD_DATA, TMP_REG1, src1, src1w, dst, dstw)); - src1_r = TMP_REG1; - } - else if (src2_r == 0 && dst_r == 0) { - FAIL_IF(getput_arg(compiler, input_flags | LOAD_DATA, sugg_src2_r, src2, src2w, dst, dstw)); - src2_r = sugg_src2_r; - } - - if (dst_r == 0) - dst_r = TMP_REG2; - - if (src1_r == 0) { - FAIL_IF(getput_arg(compiler, input_flags | LOAD_DATA, TMP_REG1, src1, src1w, 0, 0)); - src1_r = TMP_REG1; - } - - if (src2_r == 0) { - FAIL_IF(getput_arg(compiler, input_flags | LOAD_DATA, sugg_src2_r, src2, src2w, 0, 0)); + else { + FAIL_IF(emit_op_mem(compiler, input_flags | LOAD_DATA, sugg_src2_r, src2, src2w, TMP_REG2)); src2_r = sugg_src2_r; } FAIL_IF(emit_single_op(compiler, op, flags, dst_r, src1_r, src2_r)); - if (flags & (FAST_DEST | SLOW_DEST)) { - if (flags & FAST_DEST) - FAIL_IF(getput_arg_fast(compiler, input_flags, dst_r, dst, dstw)); - else - FAIL_IF(getput_arg(compiler, input_flags, dst_r, dst, dstw, 0, 0)); - } - return SLJIT_SUCCESS; + if (!(dst & SLJIT_MEM)) + return SLJIT_SUCCESS; + + return emit_op_mem(compiler, input_flags, dst_r, dst, dstw, TMP_REG1); } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compiler, sljit_s32 op) @@ -1308,6 +1076,31 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compile return SLJIT_SUCCESS; } +static sljit_s32 emit_prefetch(struct sljit_compiler *compiler, + sljit_s32 src, sljit_sw srcw) +{ + if (!(src & OFFS_REG_MASK)) { + if (srcw == 0 && (src & REG_MASK) != SLJIT_UNUSED) + return push_inst(compiler, DCBT | A(0) | B(src & REG_MASK)); + + FAIL_IF(load_immediate(compiler, TMP_REG1, srcw)); + /* Works with SLJIT_MEM0() case as well. */ + return push_inst(compiler, DCBT | A(src & REG_MASK) | B(TMP_REG1)); + } + + srcw &= 0x3; + + if (srcw == 0) + return push_inst(compiler, DCBT | A(src & REG_MASK) | B(OFFS_REG(src))); + +#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) + FAIL_IF(push_inst(compiler, RLWINM | S(OFFS_REG(src)) | A(TMP_REG1) | (srcw << 11) | ((31 - srcw) << 1))); +#else + FAIL_IF(push_inst(compiler, RLDI(TMP_REG1, OFFS_REG(src), srcw, 63 - srcw, 1))); +#endif + return push_inst(compiler, DCBT | A(src & REG_MASK) | B(TMP_REG1)); +} + #define EMIT_MOV(type, type_flags, type_cast) \ emit_op(compiler, (src & SLJIT_IMM) ? SLJIT_MOV : type, flags | (type_flags), dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? type_cast srcw : srcw) @@ -1315,7 +1108,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile sljit_s32 dst, sljit_sw dstw, sljit_s32 src, sljit_sw srcw) { - sljit_s32 flags = GET_FLAGS(op) ? ALT_SET_FLAGS : 0; + sljit_s32 flags = HAS_FLAGS(op) ? ALT_SET_FLAGS : 0; sljit_s32 op_flags = GET_ALL_FLAGS(op); CHECK_ERROR(); @@ -1323,39 +1116,45 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile ADJUST_LOCAL_OFFSET(dst, dstw); ADJUST_LOCAL_OFFSET(src, srcw); + if (dst == SLJIT_UNUSED && !HAS_FLAGS(op)) { + if (op <= SLJIT_MOV_P && (src & SLJIT_MEM)) + return emit_prefetch(compiler, src, srcw); + + return SLJIT_SUCCESS; + } + op = GET_OPCODE(op); if ((src & SLJIT_IMM) && srcw == 0) src = TMP_ZERO; - if (op_flags & SLJIT_SET_O) + if (GET_FLAG_TYPE(op_flags) == SLJIT_OVERFLOW) FAIL_IF(push_inst(compiler, MTXER | S(TMP_ZERO))); + if (op < SLJIT_NOT && FAST_IS_REG(src) && src == dst) { + if (!TYPE_CAST_NEEDED(op)) + return SLJIT_SUCCESS; + } + +#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) if (op_flags & SLJIT_I32_OP) { if (op < SLJIT_NOT) { - if (FAST_IS_REG(src) && src == dst) { - if (!TYPE_CAST_NEEDED(op)) - return SLJIT_SUCCESS; + if (src & SLJIT_MEM) { + if (op == SLJIT_MOV_S32) + op = SLJIT_MOV_U32; + } + else if (src & SLJIT_IMM) { + if (op == SLJIT_MOV_U32) + op = SLJIT_MOV_S32; } -#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) - if (op == SLJIT_MOV_S32 && (src & SLJIT_MEM)) - op = SLJIT_MOV_U32; - if (op == SLJIT_MOVU_S32 && (src & SLJIT_MEM)) - op = SLJIT_MOVU_U32; - if (op == SLJIT_MOV_U32 && (src & SLJIT_IMM)) - op = SLJIT_MOV_S32; - if (op == SLJIT_MOVU_U32 && (src & SLJIT_IMM)) - op = SLJIT_MOVU_S32; -#endif } -#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) else { /* Most operations expect sign extended arguments. */ flags |= INT_DATA | SIGNED_DATA; - if (src & SLJIT_IMM) - srcw = (sljit_s32)srcw; + if (HAS_FLAGS(op_flags)) + flags |= ALT_SIGN_EXT; } -#endif } +#endif switch (op) { case SLJIT_MOV: @@ -1386,39 +1185,11 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile case SLJIT_MOV_S16: return EMIT_MOV(SLJIT_MOV_S16, HALF_DATA | SIGNED_DATA, (sljit_s16)); - case SLJIT_MOVU: - case SLJIT_MOVU_P: -#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) - case SLJIT_MOVU_U32: - case SLJIT_MOVU_S32: -#endif - return emit_op(compiler, SLJIT_MOV, flags | WORD_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, srcw); - -#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) - case SLJIT_MOVU_U32: - return EMIT_MOV(SLJIT_MOV_U32, INT_DATA | WRITE_BACK, (sljit_u32)); - - case SLJIT_MOVU_S32: - return EMIT_MOV(SLJIT_MOV_S32, INT_DATA | SIGNED_DATA | WRITE_BACK, (sljit_s32)); -#endif - - case SLJIT_MOVU_U8: - return EMIT_MOV(SLJIT_MOV_U8, BYTE_DATA | WRITE_BACK, (sljit_u8)); - - case SLJIT_MOVU_S8: - return EMIT_MOV(SLJIT_MOV_S8, BYTE_DATA | SIGNED_DATA | WRITE_BACK, (sljit_s8)); - - case SLJIT_MOVU_U16: - return EMIT_MOV(SLJIT_MOV_U16, HALF_DATA | WRITE_BACK, (sljit_u16)); - - case SLJIT_MOVU_S16: - return EMIT_MOV(SLJIT_MOV_S16, HALF_DATA | SIGNED_DATA | WRITE_BACK, (sljit_s16)); - case SLJIT_NOT: return emit_op(compiler, SLJIT_NOT, flags, dst, dstw, TMP_REG1, 0, src, srcw); case SLJIT_NEG: - return emit_op(compiler, SLJIT_NEG, flags, dst, dstw, TMP_REG1, 0, src, srcw); + return emit_op(compiler, SLJIT_NEG, flags | (GET_FLAG_TYPE(op_flags) ? ALT_FORM1 : 0), dst, dstw, TMP_REG1, 0, src, srcw); case SLJIT_CLZ: #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) @@ -1471,7 +1242,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile sljit_s32 src1, sljit_sw src1w, sljit_s32 src2, sljit_sw src2w) { - sljit_s32 flags = GET_FLAGS(op) ? ALT_SET_FLAGS : 0; + sljit_s32 flags = HAS_FLAGS(op) ? ALT_SET_FLAGS : 0; CHECK_ERROR(); CHECK(check_sljit_emit_op2(compiler, op, dst, dstw, src1, src1w, src2, src2w)); @@ -1479,6 +1250,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile ADJUST_LOCAL_OFFSET(src1, src1w); ADJUST_LOCAL_OFFSET(src2, src2w); + if (dst == SLJIT_UNUSED && !HAS_FLAGS(op)) + return SLJIT_SUCCESS; + if ((src1 & SLJIT_IMM) && src1w == 0) src1 = TMP_ZERO; if ((src2 & SLJIT_IMM) && src2w == 0) @@ -1492,45 +1266,46 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile src1w = (sljit_s32)(src1w); if (src2 & SLJIT_IMM) src2w = (sljit_s32)(src2w); - if (GET_FLAGS(op)) + if (HAS_FLAGS(op)) flags |= ALT_SIGN_EXT; } #endif - if (op & SLJIT_SET_O) + if (GET_FLAG_TYPE(op) == SLJIT_OVERFLOW) FAIL_IF(push_inst(compiler, MTXER | S(TMP_ZERO))); - if (src2 == TMP_REG2) - flags |= ALT_KEEP_CACHE; switch (GET_OPCODE(op)) { case SLJIT_ADD: - if (!GET_FLAGS(op) && ((src1 | src2) & SLJIT_IMM)) { + if (GET_FLAG_TYPE(op) == SLJIT_OVERFLOW) + return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM1, dst, dstw, src1, src1w, src2, src2w); + + if (!HAS_FLAGS(op) && ((src1 | src2) & SLJIT_IMM)) { if (TEST_SL_IMM(src2, src2w)) { compiler->imm = src2w & 0xffff; - return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM1, dst, dstw, src1, src1w, TMP_REG2, 0); + return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2, dst, dstw, src1, src1w, TMP_REG2, 0); } if (TEST_SL_IMM(src1, src1w)) { compiler->imm = src1w & 0xffff; - return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM1, dst, dstw, src2, src2w, TMP_REG2, 0); + return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2, dst, dstw, src2, src2w, TMP_REG2, 0); } if (TEST_SH_IMM(src2, src2w)) { compiler->imm = (src2w >> 16) & 0xffff; - return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2, dst, dstw, src1, src1w, TMP_REG2, 0); + return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2 | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0); } if (TEST_SH_IMM(src1, src1w)) { compiler->imm = (src1w >> 16) & 0xffff; - return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2, dst, dstw, src2, src2w, TMP_REG2, 0); + return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2 | ALT_FORM3, dst, dstw, src2, src2w, TMP_REG2, 0); } /* Range between -1 and -32768 is covered above. */ if (TEST_ADD_IMM(src2, src2w)) { compiler->imm = src2w & 0xffffffff; - return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM4, dst, dstw, src1, src1w, TMP_REG2, 0); + return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2 | ALT_FORM4, dst, dstw, src1, src1w, TMP_REG2, 0); } if (TEST_ADD_IMM(src1, src1w)) { compiler->imm = src1w & 0xffffffff; - return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM4, dst, dstw, src2, src2w, TMP_REG2, 0); + return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2 | ALT_FORM4, dst, dstw, src2, src2w, TMP_REG2, 0); } } - if (!(GET_FLAGS(op) & (SLJIT_SET_E | SLJIT_SET_O))) { + if (HAS_FLAGS(op)) { if (TEST_SL_IMM(src2, src2w)) { compiler->imm = src2w & 0xffff; return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0); @@ -1540,75 +1315,75 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM3, dst, dstw, src2, src2w, TMP_REG2, 0); } } - return emit_op(compiler, SLJIT_ADD, flags, dst, dstw, src1, src1w, src2, src2w); + return emit_op(compiler, SLJIT_ADD, flags | ((GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY)) ? ALT_FORM4 : 0), dst, dstw, src1, src1w, src2, src2w); case SLJIT_ADDC: - return emit_op(compiler, SLJIT_ADDC, flags | (!(op & SLJIT_KEEP_FLAGS) ? 0 : ALT_FORM1), dst, dstw, src1, src1w, src2, src2w); + return emit_op(compiler, SLJIT_ADDC, flags, dst, dstw, src1, src1w, src2, src2w); case SLJIT_SUB: - if (!GET_FLAGS(op) && ((src1 | src2) & SLJIT_IMM)) { + if (GET_FLAG_TYPE(op) >= SLJIT_LESS && GET_FLAG_TYPE(op) <= SLJIT_LESS_EQUAL) { + if (dst == SLJIT_UNUSED) { + if (TEST_UL_IMM(src2, src2w)) { + compiler->imm = src2w & 0xffff; + return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM1 | ALT_FORM2, dst, dstw, src1, src1w, TMP_REG2, 0); + } + return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM1, dst, dstw, src1, src1w, src2, src2w); + } + + if ((src2 & SLJIT_IMM) && src2w >= 0 && src2w <= (SIMM_MAX + 1)) { + compiler->imm = src2w; + return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM1 | ALT_FORM2 | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0); + } + return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM1 | ALT_FORM3, dst, dstw, src1, src1w, src2, src2w); + } + + if (GET_FLAG_TYPE(op) == SLJIT_OVERFLOW) + return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM2, dst, dstw, src1, src1w, src2, src2w); + + if (!HAS_FLAGS(op) && ((src1 | src2) & SLJIT_IMM)) { if (TEST_SL_IMM(src2, -src2w)) { compiler->imm = (-src2w) & 0xffff; - return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM1, dst, dstw, src1, src1w, TMP_REG2, 0); + return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2, dst, dstw, src1, src1w, TMP_REG2, 0); } if (TEST_SL_IMM(src1, src1w)) { compiler->imm = src1w & 0xffff; - return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM1, dst, dstw, src2, src2w, TMP_REG2, 0); + return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM3, dst, dstw, src2, src2w, TMP_REG2, 0); } if (TEST_SH_IMM(src2, -src2w)) { compiler->imm = ((-src2w) >> 16) & 0xffff; - return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2, dst, dstw, src1, src1w, TMP_REG2, 0); + return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2 | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0); } /* Range between -1 and -32768 is covered above. */ if (TEST_ADD_IMM(src2, -src2w)) { compiler->imm = -src2w & 0xffffffff; - return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM4, dst, dstw, src1, src1w, TMP_REG2, 0); + return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2 | ALT_FORM4, dst, dstw, src1, src1w, TMP_REG2, 0); } } - if (dst == SLJIT_UNUSED && (op & (SLJIT_SET_E | SLJIT_SET_U | SLJIT_SET_S)) && !(op & (SLJIT_SET_O | SLJIT_SET_C))) { - if (!(op & SLJIT_SET_U)) { - /* We know ALT_SIGN_EXT is set if it is an SLJIT_I32_OP on 64 bit systems. */ - if (TEST_SL_IMM(src2, src2w)) { - compiler->imm = src2w & 0xffff; - return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM2, dst, dstw, src1, src1w, TMP_REG2, 0); - } - if (GET_FLAGS(op) == SLJIT_SET_E && TEST_SL_IMM(src1, src1w)) { - compiler->imm = src1w & 0xffff; - return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM2, dst, dstw, src2, src2w, TMP_REG2, 0); - } - } - if (!(op & (SLJIT_SET_E | SLJIT_SET_S))) { - /* We know ALT_SIGN_EXT is set if it is an SLJIT_I32_OP on 64 bit systems. */ - if (TEST_UL_IMM(src2, src2w)) { - compiler->imm = src2w & 0xffff; - return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0); - } - return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM4, dst, dstw, src1, src1w, src2, src2w); - } - if ((src2 & SLJIT_IMM) && src2w >= 0 && src2w <= 0x7fff) { - compiler->imm = src2w; - return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM2 | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0); + + if (dst == SLJIT_UNUSED && GET_FLAG_TYPE(op) != GET_FLAG_TYPE(SLJIT_SET_CARRY)) { + if (TEST_SL_IMM(src2, src2w)) { + compiler->imm = src2w & 0xffff; + return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM4 | ALT_FORM5, dst, dstw, src1, src1w, TMP_REG2, 0); } - return emit_op(compiler, SLJIT_SUB, flags | ((op & SLJIT_SET_U) ? ALT_FORM4 : 0) | ((op & (SLJIT_SET_E | SLJIT_SET_S)) ? ALT_FORM5 : 0), dst, dstw, src1, src1w, src2, src2w); + return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM4, dst, dstw, src1, src1w, src2, src2w); } - if (!(op & (SLJIT_SET_E | SLJIT_SET_U | SLJIT_SET_S | SLJIT_SET_O))) { - if (TEST_SL_IMM(src2, -src2w)) { - compiler->imm = (-src2w) & 0xffff; - return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0); - } + + if (TEST_SL_IMM(src2, -src2w)) { + compiler->imm = (-src2w) & 0xffff; + return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0); } /* We know ALT_SIGN_EXT is set if it is an SLJIT_I32_OP on 64 bit systems. */ - return emit_op(compiler, SLJIT_SUB, flags | (!(op & SLJIT_SET_U) ? 0 : ALT_FORM6), dst, dstw, src1, src1w, src2, src2w); + return emit_op(compiler, SLJIT_SUB, flags | ((GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY)) ? ALT_FORM5 : 0), dst, dstw, src1, src1w, src2, src2w); case SLJIT_SUBC: - return emit_op(compiler, SLJIT_SUBC, flags | (!(op & SLJIT_KEEP_FLAGS) ? 0 : ALT_FORM1), dst, dstw, src1, src1w, src2, src2w); + return emit_op(compiler, SLJIT_SUBC, flags, dst, dstw, src1, src1w, src2, src2w); case SLJIT_MUL: #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) if (op & SLJIT_I32_OP) flags |= ALT_FORM2; #endif - if (!GET_FLAGS(op)) { + if (!HAS_FLAGS(op)) { if (TEST_SL_IMM(src2, src2w)) { compiler->imm = src2w & 0xffff; return emit_op(compiler, SLJIT_MUL, flags | ALT_FORM1, dst, dstw, src1, src1w, TMP_REG2, 0); @@ -1618,13 +1393,15 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile return emit_op(compiler, SLJIT_MUL, flags | ALT_FORM1, dst, dstw, src2, src2w, TMP_REG2, 0); } } + else + FAIL_IF(push_inst(compiler, MTXER | S(TMP_ZERO))); return emit_op(compiler, SLJIT_MUL, flags, dst, dstw, src1, src1w, src2, src2w); case SLJIT_AND: case SLJIT_OR: case SLJIT_XOR: /* Commutative unsigned operations. */ - if (!GET_FLAGS(op) || GET_OPCODE(op) == SLJIT_AND) { + if (!HAS_FLAGS(op) || GET_OPCODE(op) == SLJIT_AND) { if (TEST_UL_IMM(src2, src2w)) { compiler->imm = src2w; return emit_op(compiler, GET_OPCODE(op), flags | ALT_FORM1, dst, dstw, src1, src1w, TMP_REG2, 0); @@ -1642,7 +1419,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile return emit_op(compiler, GET_OPCODE(op), flags | ALT_FORM2, dst, dstw, src2, src2w, TMP_REG2, 0); } } - if (!GET_FLAGS(op) && GET_OPCODE(op) != SLJIT_AND) { + if (GET_OPCODE(op) != SLJIT_AND && GET_OPCODE(op) != SLJIT_AND) { + /* Unlike or and xor, and resets unwanted bits as well. */ if (TEST_UI_IMM(src2, src2w)) { compiler->imm = src2w; return emit_op(compiler, GET_OPCODE(op), flags | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0); @@ -1654,12 +1432,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile } return emit_op(compiler, GET_OPCODE(op), flags, dst, dstw, src1, src1w, src2, src2w); - case SLJIT_ASHR: - if (op & SLJIT_KEEP_FLAGS) - flags |= ALT_FORM3; - /* Fall through. */ case SLJIT_SHL: case SLJIT_LSHR: + case SLJIT_ASHR: #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) if (op & SLJIT_I32_OP) flags |= ALT_FORM2; @@ -1683,7 +1458,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 reg) SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_float_register_index(sljit_s32 reg) { CHECK_REG_INDEX(check_sljit_get_float_register_index(reg)); - return reg; + return freg_map[reg]; } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *compiler, @@ -1699,16 +1474,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *c /* Floating point operators */ /* --------------------------------------------------------------------- */ -SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_is_fpu_available(void) -{ -#ifdef SLJIT_IS_FPU_AVAILABLE - return SLJIT_IS_FPU_AVAILABLE; -#else - /* Available by default. */ - return 1; -#endif -} - #define FLOAT_DATA(op) (DOUBLE_DATA | ((op & SLJIT_F32_OP) >> 6)) #define SELECT_FOP(op, single, double) ((op & SLJIT_F32_OP) ? single : double) @@ -1733,7 +1498,7 @@ static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_sw_from_f64(struct sljit_comp { if (src & SLJIT_MEM) { /* We can ignore the temporary data store on the stack from caching point of view. */ - FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src, srcw, dst, dstw)); + FAIL_IF(emit_op_mem(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src, srcw, TMP_REG1)); src = TMP_FREG1; } @@ -1741,28 +1506,21 @@ static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_sw_from_f64(struct sljit_comp op = GET_OPCODE(op); FAIL_IF(push_inst(compiler, (op == SLJIT_CONV_S32_FROM_F64 ? FCTIWZ : FCTIDZ) | FD(TMP_FREG1) | FB(src))); - if (dst == SLJIT_UNUSED) - return SLJIT_SUCCESS; - if (op == SLJIT_CONV_SW_FROM_F64) { if (FAST_IS_REG(dst)) { - FAIL_IF(emit_op_mem2(compiler, DOUBLE_DATA, TMP_FREG1, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET, 0, 0)); - return emit_op_mem2(compiler, WORD_DATA | LOAD_DATA, dst, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET, 0, 0); + FAIL_IF(emit_op_mem(compiler, DOUBLE_DATA, TMP_FREG1, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET, TMP_REG1)); + return emit_op_mem(compiler, WORD_DATA | LOAD_DATA, dst, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET, TMP_REG1); } - return emit_op_mem2(compiler, DOUBLE_DATA, TMP_FREG1, dst, dstw, 0, 0); + return emit_op_mem(compiler, DOUBLE_DATA, TMP_FREG1, dst, dstw, TMP_REG1); } - #else FAIL_IF(push_inst(compiler, FCTIWZ | FD(TMP_FREG1) | FB(src))); - - if (dst == SLJIT_UNUSED) - return SLJIT_SUCCESS; #endif if (FAST_IS_REG(dst)) { FAIL_IF(load_immediate(compiler, TMP_REG1, FLOAT_TMP_MEM_OFFSET)); FAIL_IF(push_inst(compiler, STFIWX | FS(TMP_FREG1) | A(SLJIT_SP) | B(TMP_REG1))); - return emit_op_mem2(compiler, INT_DATA | LOAD_DATA, dst, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET, 0, 0); + return emit_op_mem(compiler, INT_DATA | LOAD_DATA, dst, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET, TMP_REG1); } SLJIT_ASSERT(dst & SLJIT_MEM); @@ -1813,21 +1571,21 @@ static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_sw(struct sljit_comp if (FAST_IS_REG(src)) FAIL_IF(push_inst(compiler, EXTSW | S(src) | A(TMP_REG1))); else - FAIL_IF(emit_op_mem2(compiler, INT_DATA | SIGNED_DATA | LOAD_DATA, TMP_REG1, src, srcw, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET)); + FAIL_IF(emit_op_mem(compiler, INT_DATA | SIGNED_DATA | LOAD_DATA, TMP_REG1, src, srcw, TMP_REG1)); src = TMP_REG1; } if (FAST_IS_REG(src)) { - FAIL_IF(emit_op_mem2(compiler, WORD_DATA, src, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET)); - FAIL_IF(emit_op_mem2(compiler, DOUBLE_DATA | LOAD_DATA, TMP_FREG1, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET, dst, dstw)); + FAIL_IF(emit_op_mem(compiler, WORD_DATA, src, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET, TMP_REG1)); + FAIL_IF(emit_op_mem(compiler, DOUBLE_DATA | LOAD_DATA, TMP_FREG1, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET, TMP_REG1)); } else - FAIL_IF(emit_op_mem2(compiler, DOUBLE_DATA | LOAD_DATA, TMP_FREG1, src, srcw, dst, dstw)); + FAIL_IF(emit_op_mem(compiler, DOUBLE_DATA | LOAD_DATA, TMP_FREG1, src, srcw, TMP_REG1)); FAIL_IF(push_inst(compiler, FCFID | FD(dst_r) | FB(TMP_FREG1))); if (dst & SLJIT_MEM) - return emit_op_mem2(compiler, FLOAT_DATA(op), TMP_FREG1, dst, dstw, 0, 0); + return emit_op_mem(compiler, FLOAT_DATA(op), TMP_FREG1, dst, dstw, TMP_REG1); if (op & SLJIT_F32_OP) return push_inst(compiler, FRSP | FD(dst_r) | FB(dst_r)); return SLJIT_SUCCESS; @@ -1843,7 +1601,7 @@ static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_sw(struct sljit_comp invert_sign = 0; } else if (!FAST_IS_REG(src)) { - FAIL_IF(emit_op_mem2(compiler, WORD_DATA | SIGNED_DATA | LOAD_DATA, TMP_REG1, src, srcw, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET_LOW)); + FAIL_IF(emit_op_mem(compiler, WORD_DATA | SIGNED_DATA | LOAD_DATA, TMP_REG1, src, srcw, TMP_REG1)); src = TMP_REG1; } @@ -1855,17 +1613,17 @@ static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_sw(struct sljit_comp FAIL_IF(push_inst(compiler, ADDIS | D(TMP_REG2) | A(0) | 0x4330)); if (invert_sign) FAIL_IF(push_inst(compiler, XORIS | S(src) | A(TMP_REG1) | 0x8000)); - FAIL_IF(emit_op_mem2(compiler, WORD_DATA, TMP_REG2, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET_HI, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET)); - FAIL_IF(emit_op_mem2(compiler, WORD_DATA, TMP_REG1, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET_LOW, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET_HI)); + FAIL_IF(emit_op_mem(compiler, WORD_DATA, TMP_REG2, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET_HI, TMP_REG1)); + FAIL_IF(emit_op_mem(compiler, WORD_DATA, TMP_REG1, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET_LOW, TMP_REG2)); FAIL_IF(push_inst(compiler, ADDIS | D(TMP_REG1) | A(0) | 0x8000)); - FAIL_IF(emit_op_mem2(compiler, DOUBLE_DATA | LOAD_DATA, TMP_FREG1, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET_LOW)); - FAIL_IF(emit_op_mem2(compiler, WORD_DATA, TMP_REG1, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET_LOW, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET)); - FAIL_IF(emit_op_mem2(compiler, DOUBLE_DATA | LOAD_DATA, TMP_FREG2, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET_LOW)); + FAIL_IF(emit_op_mem(compiler, DOUBLE_DATA | LOAD_DATA, TMP_FREG1, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET, TMP_REG1)); + FAIL_IF(emit_op_mem(compiler, WORD_DATA, TMP_REG1, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET_LOW, TMP_REG2)); + FAIL_IF(emit_op_mem(compiler, DOUBLE_DATA | LOAD_DATA, TMP_FREG2, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET, TMP_REG1)); FAIL_IF(push_inst(compiler, FSUB | FD(dst_r) | FA(TMP_FREG1) | FB(TMP_FREG2))); if (dst & SLJIT_MEM) - return emit_op_mem2(compiler, FLOAT_DATA(op), TMP_FREG1, dst, dstw, 0, 0); + return emit_op_mem(compiler, FLOAT_DATA(op), TMP_FREG1, dst, dstw, TMP_REG1); if (op & SLJIT_F32_OP) return push_inst(compiler, FRSP | FD(dst_r) | FB(dst_r)); return SLJIT_SUCCESS; @@ -1878,12 +1636,12 @@ static SLJIT_INLINE sljit_s32 sljit_emit_fop1_cmp(struct sljit_compiler *compile sljit_s32 src2, sljit_sw src2w) { if (src1 & SLJIT_MEM) { - FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w, src2, src2w)); + FAIL_IF(emit_op_mem(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w, TMP_REG1)); src1 = TMP_FREG1; } if (src2 & SLJIT_MEM) { - FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src2, src2w, 0, 0)); + FAIL_IF(emit_op_mem(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src2, src2w, TMP_REG2)); src2 = TMP_FREG2; } @@ -1897,8 +1655,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop1(struct sljit_compiler *compil sljit_s32 dst_r; CHECK_ERROR(); - compiler->cache_arg = 0; - compiler->cache_argw = 0; SLJIT_COMPILE_ASSERT((SLJIT_F32_OP == 0x100) && !(DOUBLE_DATA & 0x4), float_transfer_bit_error); SELECT_FOP1_OPERATION_WITH_CHECKS(compiler, op, dst, dstw, src, srcw); @@ -1909,7 +1665,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop1(struct sljit_compiler *compil dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1; if (src & SLJIT_MEM) { - FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, dst_r, src, srcw, dst, dstw)); + FAIL_IF(emit_op_mem(compiler, FLOAT_DATA(op) | LOAD_DATA, dst_r, src, srcw, TMP_REG1)); src = dst_r; } @@ -1938,7 +1694,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop1(struct sljit_compiler *compil } if (dst & SLJIT_MEM) - FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op), dst_r, dst, dstw, 0, 0)); + FAIL_IF(emit_op_mem(compiler, FLOAT_DATA(op), dst_r, dst, dstw, TMP_REG1)); return SLJIT_SUCCESS; } @@ -1947,7 +1703,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2(struct sljit_compiler *compil sljit_s32 src1, sljit_sw src1w, sljit_s32 src2, sljit_sw src2w) { - sljit_s32 dst_r, flags = 0; + sljit_s32 dst_r; CHECK_ERROR(); CHECK(check_sljit_emit_fop2(compiler, op, dst, dstw, src1, src1w, src2, src2w)); @@ -1955,46 +1711,17 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2(struct sljit_compiler *compil ADJUST_LOCAL_OFFSET(src1, src1w); ADJUST_LOCAL_OFFSET(src2, src2w); - compiler->cache_arg = 0; - compiler->cache_argw = 0; - dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG2; if (src1 & SLJIT_MEM) { - if (getput_arg_fast(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w)) { - FAIL_IF(compiler->error); - src1 = TMP_FREG1; - } else - flags |= ALT_FORM1; + FAIL_IF(emit_op_mem(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w, TMP_REG1)); + src1 = TMP_FREG1; } if (src2 & SLJIT_MEM) { - if (getput_arg_fast(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src2, src2w)) { - FAIL_IF(compiler->error); - src2 = TMP_FREG2; - } else - flags |= ALT_FORM2; - } - - if ((flags & (ALT_FORM1 | ALT_FORM2)) == (ALT_FORM1 | ALT_FORM2)) { - if (!can_cache(src1, src1w, src2, src2w) && can_cache(src1, src1w, dst, dstw)) { - FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src2, src2w, src1, src1w)); - FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w, dst, dstw)); - } - else { - FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w, src2, src2w)); - FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src2, src2w, dst, dstw)); - } - } - else if (flags & ALT_FORM1) - FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w, dst, dstw)); - else if (flags & ALT_FORM2) - FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src2, src2w, dst, dstw)); - - if (flags & ALT_FORM1) - src1 = TMP_FREG1; - if (flags & ALT_FORM2) + FAIL_IF(emit_op_mem(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src2, src2w, TMP_REG2)); src2 = TMP_FREG2; + } switch (GET_OPCODE(op)) { case SLJIT_ADD_F64: @@ -2014,13 +1741,12 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2(struct sljit_compiler *compil break; } - if (dst_r == TMP_FREG2) - FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op), TMP_FREG2, dst, dstw, 0, 0)); + if (dst & SLJIT_MEM) + FAIL_IF(emit_op_mem(compiler, FLOAT_DATA(op), TMP_FREG2, dst, dstw, TMP_REG1)); return SLJIT_SUCCESS; } -#undef FLOAT_DATA #undef SELECT_FOP /* --------------------------------------------------------------------- */ @@ -2033,10 +1759,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler * CHECK(check_sljit_emit_fast_enter(compiler, dst, dstw)); ADJUST_LOCAL_OFFSET(dst, dstw); - /* For UNUSED dst. Uncommon, but possible. */ - if (dst == SLJIT_UNUSED) - return SLJIT_SUCCESS; - if (FAST_IS_REG(dst)) return push_inst(compiler, MFLR | D(dst)); @@ -2054,12 +1776,10 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_return(struct sljit_compiler if (FAST_IS_REG(src)) FAIL_IF(push_inst(compiler, MTLR | S(src))); else { - if (src & SLJIT_MEM) - FAIL_IF(emit_op(compiler, SLJIT_MOV, WORD_DATA, TMP_REG2, 0, TMP_REG1, 0, src, srcw)); - else if (src & SLJIT_IMM) - FAIL_IF(load_immediate(compiler, TMP_REG2, srcw)); + FAIL_IF(emit_op(compiler, SLJIT_MOV, WORD_DATA, TMP_REG2, 0, TMP_REG1, 0, src, srcw)); FAIL_IF(push_inst(compiler, MTLR | S(TMP_REG2))); } + return push_inst(compiler, BLR); } @@ -2093,33 +1813,33 @@ static sljit_ins get_bo_bi_flags(sljit_s32 type) return (4 << 21) | (2 << 16); case SLJIT_LESS: - case SLJIT_LESS_F64: - return (12 << 21) | ((4 + 0) << 16); - - case SLJIT_GREATER_EQUAL: - case SLJIT_GREATER_EQUAL_F64: - return (4 << 21) | ((4 + 0) << 16); - - case SLJIT_GREATER: - case SLJIT_GREATER_F64: - return (12 << 21) | ((4 + 1) << 16); - - case SLJIT_LESS_EQUAL: - case SLJIT_LESS_EQUAL_F64: - return (4 << 21) | ((4 + 1) << 16); - case SLJIT_SIG_LESS: return (12 << 21) | (0 << 16); + case SLJIT_GREATER_EQUAL: case SLJIT_SIG_GREATER_EQUAL: return (4 << 21) | (0 << 16); + case SLJIT_GREATER: case SLJIT_SIG_GREATER: return (12 << 21) | (1 << 16); + case SLJIT_LESS_EQUAL: case SLJIT_SIG_LESS_EQUAL: return (4 << 21) | (1 << 16); + case SLJIT_LESS_F64: + return (12 << 21) | ((4 + 0) << 16); + + case SLJIT_GREATER_EQUAL_F64: + return (4 << 21) | ((4 + 0) << 16); + + case SLJIT_GREATER_F64: + return (12 << 21) | ((4 + 1) << 16); + + case SLJIT_LESS_EQUAL_F64: + return (4 << 21) | ((4 + 1) << 16); + case SLJIT_OVERFLOW: case SLJIT_MUL_OVERFLOW: return (12 << 21) | (3 << 16); @@ -2141,7 +1861,7 @@ static sljit_ins get_bo_bi_flags(sljit_s32 type) return (4 << 21) | ((4 + 3) << 16); default: - SLJIT_ASSERT(type >= SLJIT_JUMP && type <= SLJIT_CALL3); + SLJIT_ASSERT(type >= SLJIT_JUMP && type <= SLJIT_CALL_CDECL); return (20 << 21); } } @@ -2167,7 +1887,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compile if (type < SLJIT_JUMP) jump->flags |= IS_COND; #if (defined SLJIT_PASS_ENTRY_ADDR_TO_CALL && SLJIT_PASS_ENTRY_ADDR_TO_CALL) - if (type >= SLJIT_CALL0) + if (type >= SLJIT_CALL) jump->flags |= IS_CALL; #endif @@ -2178,6 +1898,24 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compile return jump; } +SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 arg_types) +{ + CHECK_ERROR_PTR(); + CHECK_PTR(check_sljit_emit_call(compiler, type, arg_types)); + +#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) + PTR_FAIL_IF(call_with_args(compiler, arg_types, NULL)); +#endif + +#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \ + || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) + compiler->skip_checks = 1; +#endif + + return sljit_emit_jump(compiler, type); +} + SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 src, sljit_sw srcw) { struct sljit_jump *jump = NULL; @@ -2189,7 +1927,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compi if (FAST_IS_REG(src)) { #if (defined SLJIT_PASS_ENTRY_ADDR_TO_CALL && SLJIT_PASS_ENTRY_ADDR_TO_CALL) - if (type >= SLJIT_CALL0) { + if (type >= SLJIT_CALL) { FAIL_IF(push_inst(compiler, OR | S(src) | A(TMP_CALL_REG) | B(src))); src_r = TMP_CALL_REG; } @@ -2199,12 +1937,13 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compi src_r = src; #endif } else if (src & SLJIT_IMM) { + /* These jumps are converted to jump/call instructions when possible. */ jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump)); FAIL_IF(!jump); set_jump(jump, compiler, JUMP_ADDR); jump->u.target = srcw; #if (defined SLJIT_PASS_ENTRY_ADDR_TO_CALL && SLJIT_PASS_ENTRY_ADDR_TO_CALL) - if (type >= SLJIT_CALL0) + if (type >= SLJIT_CALL) jump->flags |= IS_CALL; #endif FAIL_IF(emit_const(compiler, TMP_CALL_REG, 0)); @@ -2221,153 +1960,302 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compi return push_inst(compiler, BCCTR | (20 << 21) | (type >= SLJIT_FAST_CALL ? 1 : 0)); } -/* Get a bit from CR, all other bits are zeroed. */ -#define GET_CR_BIT(bit, dst) \ - FAIL_IF(push_inst(compiler, MFCR | D(dst))); \ - FAIL_IF(push_inst(compiler, RLWINM | S(dst) | A(dst) | ((1 + (bit)) << 11) | (31 << 6) | (31 << 1))); +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 arg_types, + sljit_s32 src, sljit_sw srcw) +{ + CHECK_ERROR(); + CHECK(check_sljit_emit_icall(compiler, type, arg_types, src, srcw)); + +#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) + if (src & SLJIT_MEM) { + ADJUST_LOCAL_OFFSET(src, srcw); + FAIL_IF(emit_op(compiler, SLJIT_MOV, WORD_DATA, TMP_CALL_REG, 0, TMP_REG1, 0, src, srcw)); + src = TMP_CALL_REG; + } + + FAIL_IF(call_with_args(compiler, arg_types, &src)); +#endif + +#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \ + || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) + compiler->skip_checks = 1; +#endif -#define INVERT_BIT(dst) \ - FAIL_IF(push_inst(compiler, XORI | S(dst) | A(dst) | 0x1)); + return sljit_emit_ijump(compiler, type, src, srcw); +} SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw dstw, - sljit_s32 src, sljit_sw srcw, sljit_s32 type) { - sljit_s32 reg, input_flags; - sljit_s32 flags = GET_ALL_FLAGS(op); - sljit_sw original_dstw = dstw; + sljit_s32 reg, input_flags, cr_bit, invert; + sljit_s32 saved_op = op; + sljit_sw saved_dstw = dstw; CHECK_ERROR(); - CHECK(check_sljit_emit_op_flags(compiler, op, dst, dstw, src, srcw, type)); + CHECK(check_sljit_emit_op_flags(compiler, op, dst, dstw, type)); ADJUST_LOCAL_OFFSET(dst, dstw); - if (dst == SLJIT_UNUSED) - return SLJIT_SUCCESS; - - op = GET_OPCODE(op); - reg = (op < SLJIT_ADD && FAST_IS_REG(dst)) ? dst : TMP_REG2; - - compiler->cache_arg = 0; - compiler->cache_argw = 0; - if (op >= SLJIT_ADD && (src & SLJIT_MEM)) { - ADJUST_LOCAL_OFFSET(src, srcw); #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) - input_flags = (flags & SLJIT_I32_OP) ? INT_DATA : WORD_DATA; + input_flags = (op & SLJIT_I32_OP) ? INT_DATA : WORD_DATA; #else - input_flags = WORD_DATA; + input_flags = WORD_DATA; #endif - FAIL_IF(emit_op_mem2(compiler, input_flags | LOAD_DATA, TMP_REG1, src, srcw, dst, dstw)); - src = TMP_REG1; - srcw = 0; - } - switch (type & 0xff) { - case SLJIT_EQUAL: - GET_CR_BIT(2, reg); - break; + op = GET_OPCODE(op); + reg = (op < SLJIT_ADD && FAST_IS_REG(dst)) ? dst : TMP_REG2; - case SLJIT_NOT_EQUAL: - GET_CR_BIT(2, reg); - INVERT_BIT(reg); - break; + if (op >= SLJIT_ADD && (dst & SLJIT_MEM)) + FAIL_IF(emit_op_mem(compiler, input_flags | LOAD_DATA, TMP_REG1, dst, dstw, TMP_REG1)); + + invert = 0; + cr_bit = 0; + switch (type & 0xff) { case SLJIT_LESS: - case SLJIT_LESS_F64: - GET_CR_BIT(4 + 0, reg); + case SLJIT_SIG_LESS: break; case SLJIT_GREATER_EQUAL: - case SLJIT_GREATER_EQUAL_F64: - GET_CR_BIT(4 + 0, reg); - INVERT_BIT(reg); + case SLJIT_SIG_GREATER_EQUAL: + invert = 1; break; case SLJIT_GREATER: - case SLJIT_GREATER_F64: - GET_CR_BIT(4 + 1, reg); + case SLJIT_SIG_GREATER: + cr_bit = 1; break; case SLJIT_LESS_EQUAL: - case SLJIT_LESS_EQUAL_F64: - GET_CR_BIT(4 + 1, reg); - INVERT_BIT(reg); - break; - - case SLJIT_SIG_LESS: - GET_CR_BIT(0, reg); - break; - - case SLJIT_SIG_GREATER_EQUAL: - GET_CR_BIT(0, reg); - INVERT_BIT(reg); + case SLJIT_SIG_LESS_EQUAL: + cr_bit = 1; + invert = 1; break; - case SLJIT_SIG_GREATER: - GET_CR_BIT(1, reg); + case SLJIT_EQUAL: + cr_bit = 2; break; - case SLJIT_SIG_LESS_EQUAL: - GET_CR_BIT(1, reg); - INVERT_BIT(reg); + case SLJIT_NOT_EQUAL: + cr_bit = 2; + invert = 1; break; case SLJIT_OVERFLOW: case SLJIT_MUL_OVERFLOW: - GET_CR_BIT(3, reg); + cr_bit = 3; break; case SLJIT_NOT_OVERFLOW: case SLJIT_MUL_NOT_OVERFLOW: - GET_CR_BIT(3, reg); - INVERT_BIT(reg); + cr_bit = 3; + invert = 1; + break; + + case SLJIT_LESS_F64: + cr_bit = 4 + 0; + break; + + case SLJIT_GREATER_EQUAL_F64: + cr_bit = 4 + 0; + invert = 1; + break; + + case SLJIT_GREATER_F64: + cr_bit = 4 + 1; + break; + + case SLJIT_LESS_EQUAL_F64: + cr_bit = 4 + 1; + invert = 1; break; case SLJIT_EQUAL_F64: - GET_CR_BIT(4 + 2, reg); + cr_bit = 4 + 2; break; case SLJIT_NOT_EQUAL_F64: - GET_CR_BIT(4 + 2, reg); - INVERT_BIT(reg); + cr_bit = 4 + 2; + invert = 1; break; case SLJIT_UNORDERED_F64: - GET_CR_BIT(4 + 3, reg); + cr_bit = 4 + 3; break; case SLJIT_ORDERED_F64: - GET_CR_BIT(4 + 3, reg); - INVERT_BIT(reg); + cr_bit = 4 + 3; + invert = 1; break; default: - SLJIT_ASSERT_STOP(); + SLJIT_UNREACHABLE(); break; } + FAIL_IF(push_inst(compiler, MFCR | D(reg))); + FAIL_IF(push_inst(compiler, RLWINM | S(reg) | A(reg) | ((1 + (cr_bit)) << 11) | (31 << 6) | (31 << 1))); + + if (invert) + FAIL_IF(push_inst(compiler, XORI | S(reg) | A(reg) | 0x1)); + if (op < SLJIT_ADD) { -#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) - if (op == SLJIT_MOV) - input_flags = WORD_DATA; - else { - op = SLJIT_MOV_U32; - input_flags = INT_DATA; - } -#else - op = SLJIT_MOV; - input_flags = WORD_DATA; -#endif - if (reg != TMP_REG2) + if (!(dst & SLJIT_MEM)) return SLJIT_SUCCESS; - return emit_op(compiler, op, input_flags, dst, dstw, TMP_REG1, 0, TMP_REG2, 0); + return emit_op_mem(compiler, input_flags, reg, dst, dstw, TMP_REG1); } #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \ || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) compiler->skip_checks = 1; #endif - return sljit_emit_op2(compiler, op | flags, dst, original_dstw, src, srcw, TMP_REG2, 0); + if (dst & SLJIT_MEM) + return sljit_emit_op2(compiler, saved_op, dst, saved_dstw, TMP_REG1, 0, TMP_REG2, 0); + return sljit_emit_op2(compiler, saved_op, dst, 0, dst, 0, TMP_REG2, 0); +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 dst_reg, + sljit_s32 src, sljit_sw srcw) +{ + CHECK_ERROR(); + CHECK(check_sljit_emit_cmov(compiler, type, dst_reg, src, srcw)); + + return sljit_emit_cmov_generic(compiler, type, dst_reg, src, srcw);; +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 reg, + sljit_s32 mem, sljit_sw memw) +{ + sljit_s32 mem_flags; + sljit_ins inst; + + CHECK_ERROR(); + CHECK(check_sljit_emit_mem(compiler, type, reg, mem, memw)); + + if (type & SLJIT_MEM_POST) + return SLJIT_ERR_UNSUPPORTED; + + switch (type & 0xff) { + case SLJIT_MOV: + case SLJIT_MOV_P: +#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) + case SLJIT_MOV_U32: + case SLJIT_MOV_S32: +#endif + mem_flags = WORD_DATA; + break; + +#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) + case SLJIT_MOV_U32: + mem_flags = INT_DATA; + break; + + case SLJIT_MOV_S32: + mem_flags = INT_DATA; + + if (!(type & SLJIT_MEM_STORE) && !(type & SLJIT_I32_OP)) { + if (mem & OFFS_REG_MASK) + mem_flags |= SIGNED_DATA; + else + return SLJIT_ERR_UNSUPPORTED; + } + break; +#endif + + case SLJIT_MOV_U8: + case SLJIT_MOV_S8: + mem_flags = BYTE_DATA; + break; + + case SLJIT_MOV_U16: + mem_flags = HALF_DATA; + break; + + case SLJIT_MOV_S16: + mem_flags = HALF_DATA | SIGNED_DATA; + break; + + default: + SLJIT_UNREACHABLE(); + mem_flags = WORD_DATA; + break; + } + + if (!(type & SLJIT_MEM_STORE)) + mem_flags |= LOAD_DATA; + + if (SLJIT_UNLIKELY(mem & OFFS_REG_MASK)) { + if (memw != 0) + return SLJIT_ERR_UNSUPPORTED; + + if (type & SLJIT_MEM_SUPP) + return SLJIT_SUCCESS; + + inst = updated_data_transfer_insts[mem_flags | INDEXED]; + FAIL_IF(push_inst(compiler, INST_CODE_AND_DST(inst, 0, reg) | A(mem & REG_MASK) | B(OFFS_REG(mem)))); + } + else { + if (memw > SIMM_MAX || memw < SIMM_MIN) + return SLJIT_ERR_UNSUPPORTED; + + inst = updated_data_transfer_insts[mem_flags]; + +#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) + if ((inst & INT_ALIGNED) && (memw & 0x3) != 0) + return SLJIT_ERR_UNSUPPORTED; +#endif + + if (type & SLJIT_MEM_SUPP) + return SLJIT_SUCCESS; + + FAIL_IF(push_inst(compiler, INST_CODE_AND_DST(inst, 0, reg) | A(mem & REG_MASK) | IMM(memw))); + } + + if ((mem_flags & LOAD_DATA) && (type & 0xff) == SLJIT_MOV_S8) + return push_inst(compiler, EXTSB | S(reg) | A(reg)); + return SLJIT_SUCCESS; +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 freg, + sljit_s32 mem, sljit_sw memw) +{ + sljit_s32 mem_flags; + sljit_ins inst; + + CHECK_ERROR(); + CHECK(check_sljit_emit_fmem(compiler, type, freg, mem, memw)); + + if (type & SLJIT_MEM_POST) + return SLJIT_ERR_UNSUPPORTED; + + if (SLJIT_UNLIKELY(mem & OFFS_REG_MASK)) { + if (memw != 0) + return SLJIT_ERR_UNSUPPORTED; + } + else { + if (memw > SIMM_MAX || memw < SIMM_MIN) + return SLJIT_ERR_UNSUPPORTED; + } + + if (type & SLJIT_MEM_SUPP) + return SLJIT_SUCCESS; + + mem_flags = FLOAT_DATA(type); + + if (!(type & SLJIT_MEM_STORE)) + mem_flags |= LOAD_DATA; + + if (SLJIT_UNLIKELY(mem & OFFS_REG_MASK)) { + inst = updated_data_transfer_insts[mem_flags | INDEXED]; + return push_inst(compiler, INST_CODE_AND_DST(inst, DOUBLE_DATA, freg) | A(mem & REG_MASK) | B(OFFS_REG(mem))); + } + + inst = updated_data_transfer_insts[mem_flags]; + return push_inst(compiler, INST_CODE_AND_DST(inst, DOUBLE_DATA, freg) | A(mem & REG_MASK) | IMM(memw)); } SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw init_value) @@ -2383,7 +2271,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compi PTR_FAIL_IF(!const_); set_const(const_, compiler); - reg = SLOW_IS_REG(dst) ? dst : TMP_REG2; + reg = FAST_IS_REG(dst) ? dst : TMP_REG2; PTR_FAIL_IF(emit_const(compiler, reg, init_value)); diff --git a/thirdparty/pcre2/src/sljit/sljitNativeSPARC_32.c b/thirdparty/pcre2/src/sljit/sljitNativeSPARC_32.c index 4a206f11d0..0671b130cc 100644 --- a/thirdparty/pcre2/src/sljit/sljitNativeSPARC_32.c +++ b/thirdparty/pcre2/src/sljit/sljitNativeSPARC_32.c @@ -1,7 +1,7 @@ /* * Stack-less Just-In-Time compiler * - * Copyright 2009-2012 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved. + * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are * permitted provided that the following conditions are met: @@ -60,7 +60,7 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl return push_inst(compiler, SRA | D(dst) | S1(dst) | IMM(24), DR(dst)); } else if (dst != src2) - SLJIT_ASSERT_STOP(); + SLJIT_UNREACHABLE(); return SLJIT_SUCCESS; case SLJIT_MOV_U16: @@ -71,7 +71,7 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl return push_inst(compiler, (op == SLJIT_MOV_S16 ? SRA : SRL) | D(dst) | S1(dst) | IMM(16), DR(dst)); } else if (dst != src2) - SLJIT_ASSERT_STOP(); + SLJIT_UNREACHABLE(); return SLJIT_SUCCESS; case SLJIT_NOT: @@ -80,18 +80,17 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl case SLJIT_CLZ: SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM)); - /* sparc 32 does not support SLJIT_KEEP_FLAGS. Not sure I can fix this. */ FAIL_IF(push_inst(compiler, SUB | SET_FLAGS | D(0) | S1(src2) | S2(0), SET_FLAGS)); FAIL_IF(push_inst(compiler, OR | D(TMP_REG1) | S1(0) | S2(src2), DR(TMP_REG1))); FAIL_IF(push_inst(compiler, BICC | DA(0x1) | (7 & DISP_MASK), UNMOVABLE_INS)); - FAIL_IF(push_inst(compiler, OR | (flags & SET_FLAGS) | D(dst) | S1(0) | IMM(32), UNMOVABLE_INS | (flags & SET_FLAGS))); + FAIL_IF(push_inst(compiler, OR | D(dst) | S1(0) | IMM(32), UNMOVABLE_INS)); FAIL_IF(push_inst(compiler, OR | D(dst) | S1(0) | IMM(-1), DR(dst))); /* Loop. */ FAIL_IF(push_inst(compiler, SUB | SET_FLAGS | D(0) | S1(TMP_REG1) | S2(0), SET_FLAGS)); FAIL_IF(push_inst(compiler, SLL | D(TMP_REG1) | S1(TMP_REG1) | IMM(1), DR(TMP_REG1))); FAIL_IF(push_inst(compiler, BICC | DA(0xe) | (-2 & DISP_MASK), UNMOVABLE_INS)); - return push_inst(compiler, ADD | (flags & SET_FLAGS) | D(dst) | S1(dst) | IMM(1), UNMOVABLE_INS | (flags & SET_FLAGS)); + return push_inst(compiler, ADD | D(dst) | S1(dst) | IMM(1), UNMOVABLE_INS); case SLJIT_ADD: return push_inst(compiler, ADD | (flags & SET_FLAGS) | D(dst) | S1(src1) | ARG2(flags, src2), DR(dst) | (flags & SET_FLAGS)); @@ -135,7 +134,126 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl return !(flags & SET_FLAGS) ? SLJIT_SUCCESS : push_inst(compiler, SUB | SET_FLAGS | D(0) | S1(dst) | S2(0), SET_FLAGS); } - SLJIT_ASSERT_STOP(); + SLJIT_UNREACHABLE(); + return SLJIT_SUCCESS; +} + +static sljit_s32 call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_types, sljit_s32 *src) +{ + sljit_s32 reg_index = 8; + sljit_s32 word_reg_index = 8; + sljit_s32 float_arg_index = 1; + sljit_s32 double_arg_count = 0; + sljit_s32 float_offset = (16 + 6) * sizeof(sljit_sw); + sljit_s32 types = 0; + sljit_s32 reg = 0; + sljit_s32 move_to_tmp2 = 0; + + if (src) + reg = reg_map[*src & REG_MASK]; + + arg_types >>= SLJIT_DEF_SHIFT; + + while (arg_types) { + types = (types << SLJIT_DEF_SHIFT) | (arg_types & SLJIT_DEF_MASK); + + switch (arg_types & SLJIT_DEF_MASK) { + case SLJIT_ARG_TYPE_F32: + float_arg_index++; + if (reg_index == reg) + move_to_tmp2 = 1; + reg_index++; + break; + case SLJIT_ARG_TYPE_F64: + float_arg_index++; + double_arg_count++; + if (reg_index == reg || reg_index + 1 == reg) + move_to_tmp2 = 1; + reg_index += 2; + break; + default: + if (reg_index != word_reg_index && reg_index < 14 && reg_index == reg) + move_to_tmp2 = 1; + reg_index++; + word_reg_index++; + break; + } + + if (move_to_tmp2) { + move_to_tmp2 = 0; + if (reg < 14) + FAIL_IF(push_inst(compiler, OR | D(TMP_REG1) | S1(0) | S2A(reg), DR(TMP_REG1))); + *src = TMP_REG1; + } + + arg_types >>= SLJIT_DEF_SHIFT; + } + + arg_types = types; + + while (arg_types) { + switch (arg_types & SLJIT_DEF_MASK) { + case SLJIT_ARG_TYPE_F32: + float_arg_index--; + FAIL_IF(push_inst(compiler, STF | FD(float_arg_index) | S1(SLJIT_SP) | IMM(float_offset), MOVABLE_INS)); + float_offset -= sizeof(sljit_f64); + break; + case SLJIT_ARG_TYPE_F64: + float_arg_index--; + if (float_arg_index == 4 && double_arg_count == 4) { + FAIL_IF(push_inst(compiler, STF | FD(float_arg_index) | S1(SLJIT_SP) | IMM((16 + 7) * sizeof(sljit_sw)), MOVABLE_INS)); + FAIL_IF(push_inst(compiler, STF | FD(float_arg_index) | (1 << 25) | S1(SLJIT_SP) | IMM((16 + 8) * sizeof(sljit_sw)), MOVABLE_INS)); + } + else + FAIL_IF(push_inst(compiler, STDF | FD(float_arg_index) | S1(SLJIT_SP) | IMM(float_offset), MOVABLE_INS)); + float_offset -= sizeof(sljit_f64); + break; + default: + break; + } + + arg_types >>= SLJIT_DEF_SHIFT; + } + + float_offset = (16 + 6) * sizeof(sljit_sw); + + while (types) { + switch (types & SLJIT_DEF_MASK) { + case SLJIT_ARG_TYPE_F32: + reg_index--; + if (reg_index < 14) + FAIL_IF(push_inst(compiler, LDUW | DA(reg_index) | S1(SLJIT_SP) | IMM(float_offset), reg_index)); + float_offset -= sizeof(sljit_f64); + break; + case SLJIT_ARG_TYPE_F64: + reg_index -= 2; + if (reg_index < 14) { + if ((reg_index & 0x1) != 0) { + FAIL_IF(push_inst(compiler, LDUW | DA(reg_index) | S1(SLJIT_SP) | IMM(float_offset), reg_index)); + if (reg_index < 13) + FAIL_IF(push_inst(compiler, LDUW | DA(reg_index + 1) | S1(SLJIT_SP) | IMM(float_offset + sizeof(sljit_sw)), reg_index + 1)); + } + else + FAIL_IF(push_inst(compiler, LDD | DA(reg_index) | S1(SLJIT_SP) | IMM(float_offset), reg_index)); + } + float_offset -= sizeof(sljit_f64); + break; + default: + reg_index--; + word_reg_index--; + + if (reg_index != word_reg_index) { + if (reg_index < 14) + FAIL_IF(push_inst(compiler, OR | DA(reg_index) | S1(0) | S2A(word_reg_index), reg_index)); + else + FAIL_IF(push_inst(compiler, STW | DA(word_reg_index) | S1(SLJIT_SP) | IMM(92), word_reg_index)); + } + break; + } + + types >>= SLJIT_DEF_SHIFT; + } + return SLJIT_SUCCESS; } diff --git a/thirdparty/pcre2/src/sljit/sljitNativeSPARC_common.c b/thirdparty/pcre2/src/sljit/sljitNativeSPARC_common.c index 7445fc4723..669ecd8152 100644 --- a/thirdparty/pcre2/src/sljit/sljitNativeSPARC_common.c +++ b/thirdparty/pcre2/src/sljit/sljitNativeSPARC_common.c @@ -1,7 +1,7 @@ /* * Stack-less Just-In-Time compiler * - * Copyright 2009-2012 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved. + * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are * permitted provided that the following conditions are met: @@ -90,13 +90,19 @@ static void sparc_cache_flush(sljit_ins *from, sljit_ins *to) #define TMP_REG1 (SLJIT_NUMBER_OF_REGISTERS + 2) #define TMP_REG2 (SLJIT_NUMBER_OF_REGISTERS + 3) #define TMP_REG3 (SLJIT_NUMBER_OF_REGISTERS + 4) +/* This register is modified by calls, which affects the instruction + in the delay slot if it is used as a source register. */ #define TMP_LINK (SLJIT_NUMBER_OF_REGISTERS + 5) -#define TMP_FREG1 (0) -#define TMP_FREG2 ((SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1) << 1) +#define TMP_FREG1 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1) +#define TMP_FREG2 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 2) static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 6] = { - 0, 8, 9, 10, 13, 29, 28, 27, 23, 22, 21, 20, 19, 18, 17, 16, 26, 25, 24, 14, 1, 11, 12, 15 + 0, 8, 9, 10, 11, 29, 28, 27, 23, 22, 21, 20, 19, 18, 17, 16, 26, 25, 24, 14, 1, 12, 13, 15 +}; + +static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3] = { + 0, 0, 2, 4, 6, 8, 10, 12, 14 }; /* --------------------------------------------------------------------- */ @@ -104,10 +110,15 @@ static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 6] = { /* --------------------------------------------------------------------- */ #define D(d) (reg_map[d] << 25) +#define FD(d) (freg_map[d] << 25) +#define FDN(d) ((freg_map[d] | 0x1) << 25) #define DA(d) ((d) << 25) #define S1(s1) (reg_map[s1] << 14) -#define S2(s2) (reg_map[s2]) +#define FS1(s1) (freg_map[s1] << 14) #define S1A(s1) ((s1) << 14) +#define S2(s2) (reg_map[s2]) +#define FS2(s2) (freg_map[s2]) +#define FS2N(s2) (freg_map[s2] | 0x1) #define S2A(s2) (s2) #define IMM_ARG 0x2000 #define DOP(op) ((op) << 5) @@ -144,6 +155,8 @@ static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 6] = { #define FSUBD (OPC1(0x2) | OPC3(0x34) | DOP(0x46)) #define FSUBS (OPC1(0x2) | OPC3(0x34) | DOP(0x45)) #define JMPL (OPC1(0x2) | OPC3(0x38)) +#define LDD (OPC1(0x3) | OPC3(0x03)) +#define LDUW (OPC1(0x3) | OPC3(0x00)) #define NOP (OPC1(0x0) | OPC2(0x04)) #define OR (OPC1(0x2) | OPC3(0x02)) #define ORN (OPC1(0x2) | OPC3(0x06)) @@ -157,6 +170,9 @@ static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 6] = { #define SRAX (OPC1(0x2) | OPC3(0x27) | (1 << 12)) #define SRL (OPC1(0x2) | OPC3(0x26)) #define SRLX (OPC1(0x2) | OPC3(0x26) | (1 << 12)) +#define STDF (OPC1(0x3) | OPC3(0x27)) +#define STF (OPC1(0x3) | OPC3(0x24)) +#define STW (OPC1(0x3) | OPC3(0x04)) #define SUB (OPC1(0x2) | OPC3(0x04)) #define SUBC (OPC1(0x2) | OPC3(0x0c)) #define TA (OPC1(0x2) | OPC3(0x3a) | (8 << 25)) @@ -394,6 +410,27 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil return code; } +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type) +{ + switch (feature_type) { + case SLJIT_HAS_FPU: +#ifdef SLJIT_IS_FPU_AVAILABLE + return SLJIT_IS_FPU_AVAILABLE; +#else + /* Available by default. */ + return 1; +#endif + +#if (defined SLJIT_CONFIG_SPARC_64 && SLJIT_CONFIG_SPARC_64) + case SLJIT_HAS_CMOV: + return 1; +#endif + + default: + return 0; + } +} + /* --------------------------------------------------------------------- */ /* Entry, exit */ /* --------------------------------------------------------------------- */ @@ -412,18 +449,17 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil #define MEM_MASK 0x1f -#define WRITE_BACK 0x00020 -#define ARG_TEST 0x00040 -#define ALT_KEEP_CACHE 0x00080 -#define CUMULATIVE_OP 0x00100 -#define IMM_OP 0x00200 -#define SRC2_IMM 0x00400 +#define ARG_TEST 0x00020 +#define ALT_KEEP_CACHE 0x00040 +#define CUMULATIVE_OP 0x00080 +#define IMM_OP 0x00100 +#define SRC2_IMM 0x00200 -#define REG_DEST 0x00800 -#define REG2_SOURCE 0x01000 -#define SLOW_SRC1 0x02000 -#define SLOW_SRC2 0x04000 -#define SLOW_DEST 0x08000 +#define REG_DEST 0x00400 +#define REG2_SOURCE 0x00800 +#define SLOW_SRC1 0x01000 +#define SLOW_SRC2 0x02000 +#define SLOW_DEST 0x04000 /* SET_FLAGS (0x10 << 19) also belong here! */ @@ -434,12 +470,12 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil #endif SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compiler, - sljit_s32 options, sljit_s32 args, sljit_s32 scratches, sljit_s32 saveds, + sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds, sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size) { CHECK_ERROR(); - CHECK(check_sljit_emit_enter(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size)); - set_emit_enter(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size); + CHECK(check_sljit_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size)); + set_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size); local_size = (local_size + SLJIT_LOCALS_OFFSET + 7) & ~0x7; compiler->local_size = local_size; @@ -458,12 +494,12 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *compiler, - sljit_s32 options, sljit_s32 args, sljit_s32 scratches, sljit_s32 saveds, + sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds, sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size) { CHECK_ERROR(); - CHECK(check_sljit_set_context(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size)); - set_set_context(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size); + CHECK(check_sljit_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size)); + set_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size); compiler->local_size = (local_size + SLJIT_LOCALS_OFFSET + 7) & ~0x7; return SLJIT_SUCCESS; @@ -525,18 +561,16 @@ static sljit_s32 getput_arg_fast(struct sljit_compiler *compiler, sljit_s32 flag { SLJIT_ASSERT(arg & SLJIT_MEM); - if (!(flags & WRITE_BACK) || !(arg & REG_MASK)) { - if ((!(arg & OFFS_REG_MASK) && argw <= SIMM_MAX && argw >= SIMM_MIN) - || ((arg & OFFS_REG_MASK) && (argw & 0x3) == 0)) { - /* Works for both absoulte and relative addresses (immediate case). */ - if (SLJIT_UNLIKELY(flags & ARG_TEST)) - return 1; - FAIL_IF(push_inst(compiler, data_transfer_insts[flags & MEM_MASK] - | ((flags & MEM_MASK) <= GPR_REG ? D(reg) : DA(reg)) - | S1(arg & REG_MASK) | ((arg & OFFS_REG_MASK) ? S2(OFFS_REG(arg)) : IMM(argw)), - ((flags & MEM_MASK) <= GPR_REG && (flags & LOAD_DATA)) ? DR(reg) : MOVABLE_INS)); - return -1; - } + if ((!(arg & OFFS_REG_MASK) && argw <= SIMM_MAX && argw >= SIMM_MIN) + || ((arg & OFFS_REG_MASK) && (argw & 0x3) == 0)) { + /* Works for both absoulte and relative addresses (immediate case). */ + if (SLJIT_UNLIKELY(flags & ARG_TEST)) + return 1; + FAIL_IF(push_inst(compiler, data_transfer_insts[flags & MEM_MASK] + | ((flags & MEM_MASK) <= GPR_REG ? D(reg) : FD(reg)) + | S1(arg & REG_MASK) | ((arg & OFFS_REG_MASK) ? S2(OFFS_REG(arg)) : IMM(argw)), + ((flags & MEM_MASK) <= GPR_REG && (flags & LOAD_DATA)) ? DR(reg) : MOVABLE_INS)); + return -1; } return 0; } @@ -578,7 +612,6 @@ static sljit_s32 getput_arg(struct sljit_compiler *compiler, sljit_s32 flags, sl base = arg & REG_MASK; if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) { argw &= 0x3; - SLJIT_ASSERT(argw != 0); /* Using the cache. */ if (((SLJIT_MEM | (arg & OFFS_REG_MASK)) == compiler->cache_arg) && (argw == compiler->cache_argw)) @@ -618,14 +651,11 @@ static sljit_s32 getput_arg(struct sljit_compiler *compiler, sljit_s32 flags, sl } } - dest = ((flags & MEM_MASK) <= GPR_REG ? D(reg) : DA(reg)); + dest = ((flags & MEM_MASK) <= GPR_REG ? D(reg) : FD(reg)); delay_slot = ((flags & MEM_MASK) <= GPR_REG && (flags & LOAD_DATA)) ? DR(reg) : MOVABLE_INS; if (!base) return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | dest | S1(arg2) | IMM(0), delay_slot); - if (!(flags & WRITE_BACK)) - return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | dest | S1(base) | S2(arg2), delay_slot); - FAIL_IF(push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | dest | S1(base) | S2(arg2), delay_slot)); - return push_inst(compiler, ADD | D(base) | S1(base) | S2(arg2), DR(base)); + return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | dest | S1(base) | S2(arg2), delay_slot); } static SLJIT_INLINE sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 arg, sljit_sw argw) @@ -663,18 +693,16 @@ static sljit_s32 emit_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s3 compiler->cache_argw = 0; } - if (SLJIT_UNLIKELY(dst == SLJIT_UNUSED)) { - if (op >= SLJIT_MOV && op <= SLJIT_MOVU_S32 && !(src2 & SLJIT_MEM)) - return SLJIT_SUCCESS; - } - else if (FAST_IS_REG(dst)) { - dst_r = dst; - flags |= REG_DEST; - if (op >= SLJIT_MOV && op <= SLJIT_MOVU_S32) - sugg_src2_r = dst_r; + if (dst != SLJIT_UNUSED) { + if (FAST_IS_REG(dst)) { + dst_r = dst; + flags |= REG_DEST; + if (op >= SLJIT_MOV && op <= SLJIT_MOV_P) + sugg_src2_r = dst_r; + } + else if ((dst & SLJIT_MEM) && !getput_arg_fast(compiler, flags | ARG_TEST, TMP_REG1, dst, dstw)) + flags |= SLOW_DEST; } - else if ((dst & SLJIT_MEM) && !getput_arg_fast(compiler, flags | ARG_TEST, TMP_REG1, dst, dstw)) - flags |= SLOW_DEST; if (flags & IMM_OP) { if ((src2 & SLJIT_IMM) && src2w) { @@ -720,7 +748,7 @@ static sljit_s32 emit_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s3 if (FAST_IS_REG(src2)) { src2_r = src2; flags |= REG2_SOURCE; - if (!(flags & REG_DEST) && op >= SLJIT_MOV && op <= SLJIT_MOVU_S32) + if (!(flags & REG_DEST) && op >= SLJIT_MOV && op <= SLJIT_MOV_P) dst_r = src2_r; } else if (src2 & SLJIT_IMM) { @@ -731,7 +759,7 @@ static sljit_s32 emit_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s3 } else { src2_r = 0; - if ((op >= SLJIT_MOV && op <= SLJIT_MOVU_S32) && (dst & SLJIT_MEM)) + if ((op >= SLJIT_MOV && op <= SLJIT_MOV_P) && (dst & SLJIT_MEM)) dst_r = 0; } } @@ -823,13 +851,16 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile sljit_s32 dst, sljit_sw dstw, sljit_s32 src, sljit_sw srcw) { - sljit_s32 flags = GET_FLAGS(op) ? SET_FLAGS : 0; + sljit_s32 flags = HAS_FLAGS(op) ? SET_FLAGS : 0; CHECK_ERROR(); CHECK(check_sljit_emit_op1(compiler, op, dst, dstw, src, srcw)); ADJUST_LOCAL_OFFSET(dst, dstw); ADJUST_LOCAL_OFFSET(src, srcw); + if (dst == SLJIT_UNUSED && !HAS_FLAGS(op)) + return SLJIT_SUCCESS; + op = GET_OPCODE(op); switch (op) { case SLJIT_MOV: @@ -854,28 +885,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile case SLJIT_MOV_S16: return emit_op(compiler, SLJIT_MOV_S16, flags | HALF_DATA | SIGNED_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_s16)srcw : srcw); - case SLJIT_MOVU: - case SLJIT_MOVU_P: - return emit_op(compiler, SLJIT_MOV, flags | WORD_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, srcw); - - case SLJIT_MOVU_U32: - return emit_op(compiler, SLJIT_MOV_U32, flags | INT_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, srcw); - - case SLJIT_MOVU_S32: - return emit_op(compiler, SLJIT_MOV_S32, flags | INT_DATA | SIGNED_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, srcw); - - case SLJIT_MOVU_U8: - return emit_op(compiler, SLJIT_MOV_U8, flags | BYTE_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_u8)srcw : srcw); - - case SLJIT_MOVU_S8: - return emit_op(compiler, SLJIT_MOV_S8, flags | BYTE_DATA | SIGNED_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_s8)srcw : srcw); - - case SLJIT_MOVU_U16: - return emit_op(compiler, SLJIT_MOV_U16, flags | HALF_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_u16)srcw : srcw); - - case SLJIT_MOVU_S16: - return emit_op(compiler, SLJIT_MOV_S16, flags | HALF_DATA | SIGNED_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_s16)srcw : srcw); - case SLJIT_NOT: case SLJIT_CLZ: return emit_op(compiler, op, flags, dst, dstw, TMP_REG1, 0, src, srcw); @@ -892,7 +901,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile sljit_s32 src1, sljit_sw src1w, sljit_s32 src2, sljit_sw src2w) { - sljit_s32 flags = GET_FLAGS(op) ? SET_FLAGS : 0; + sljit_s32 flags = HAS_FLAGS(op) ? SET_FLAGS : 0; CHECK_ERROR(); CHECK(check_sljit_emit_op2(compiler, op, dst, dstw, src1, src1w, src2, src2w)); @@ -900,6 +909,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile ADJUST_LOCAL_OFFSET(src1, src1w); ADJUST_LOCAL_OFFSET(src2, src2w); + if (dst == SLJIT_UNUSED && !HAS_FLAGS(op)) + return SLJIT_SUCCESS; + op = GET_OPCODE(op); switch (op) { case SLJIT_ADD: @@ -921,7 +933,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile if (src2 & SLJIT_IMM) src2w &= 0x1f; #else - SLJIT_ASSERT_STOP(); + SLJIT_UNREACHABLE(); #endif return emit_op(compiler, op, flags | IMM_OP, dst, dstw, src1, src1w, src2, src2w); } @@ -938,7 +950,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 reg) SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_float_register_index(sljit_s32 reg) { CHECK_REG_INDEX(check_sljit_get_float_register_index(reg)); - return reg << 1; + return freg_map[reg]; } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *compiler, @@ -954,16 +966,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *c /* Floating point operators */ /* --------------------------------------------------------------------- */ -SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_is_fpu_available(void) -{ -#ifdef SLJIT_IS_FPU_AVAILABLE - return SLJIT_IS_FPU_AVAILABLE; -#else - /* Available by default. */ - return 1; -#endif -} - #define FLOAT_DATA(op) (DOUBLE_DATA | ((op & SLJIT_F32_OP) >> 7)) #define SELECT_FOP(op, single, double) ((op & SLJIT_F32_OP) ? single : double) #define FLOAT_TMP_MEM_OFFSET (22 * sizeof(sljit_sw)) @@ -976,13 +978,8 @@ static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_sw_from_f64(struct sljit_comp FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src, srcw, dst, dstw)); src = TMP_FREG1; } - else - src <<= 1; - - FAIL_IF(push_inst(compiler, SELECT_FOP(op, FSTOI, FDTOI) | DA(TMP_FREG1) | S2A(src), MOVABLE_INS)); - if (dst == SLJIT_UNUSED) - return SLJIT_SUCCESS; + FAIL_IF(push_inst(compiler, SELECT_FOP(op, FSTOI, FDTOI) | FD(TMP_FREG1) | FS2(src), MOVABLE_INS)); if (FAST_IS_REG(dst)) { FAIL_IF(emit_op_mem2(compiler, SINGLE_DATA, TMP_FREG1, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET)); @@ -997,7 +994,7 @@ static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_sw(struct sljit_comp sljit_s32 dst, sljit_sw dstw, sljit_s32 src, sljit_sw srcw) { - sljit_s32 dst_r = FAST_IS_REG(dst) ? (dst << 1) : TMP_FREG1; + sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1; if (src & SLJIT_IMM) { #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) @@ -1016,7 +1013,7 @@ static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_sw(struct sljit_comp } FAIL_IF(emit_op_mem2(compiler, SINGLE_DATA | LOAD_DATA, TMP_FREG1, src, srcw, dst, dstw)); - FAIL_IF(push_inst(compiler, SELECT_FOP(op, FITOS, FITOD) | DA(dst_r) | S2A(TMP_FREG1), MOVABLE_INS)); + FAIL_IF(push_inst(compiler, SELECT_FOP(op, FITOS, FITOD) | FD(dst_r) | FS2(TMP_FREG1), MOVABLE_INS)); if (dst & SLJIT_MEM) return emit_op_mem2(compiler, FLOAT_DATA(op), TMP_FREG1, dst, dstw, 0, 0); @@ -1031,17 +1028,13 @@ static SLJIT_INLINE sljit_s32 sljit_emit_fop1_cmp(struct sljit_compiler *compile FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w, src2, src2w)); src1 = TMP_FREG1; } - else - src1 <<= 1; if (src2 & SLJIT_MEM) { FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src2, src2w, 0, 0)); src2 = TMP_FREG2; } - else - src2 <<= 1; - return push_inst(compiler, SELECT_FOP(op, FCMPS, FCMPD) | S1A(src1) | S2A(src2), FCC_IS_SET | MOVABLE_INS); + return push_inst(compiler, SELECT_FOP(op, FCMPS, FCMPD) | FS1(src1) | FS2(src2), FCC_IS_SET | MOVABLE_INS); } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop1(struct sljit_compiler *compiler, sljit_s32 op, @@ -1060,39 +1053,37 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop1(struct sljit_compiler *compil if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_F32) op ^= SLJIT_F32_OP; - dst_r = FAST_IS_REG(dst) ? (dst << 1) : TMP_FREG1; + dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1; if (src & SLJIT_MEM) { FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, dst_r, src, srcw, dst, dstw)); src = dst_r; } - else - src <<= 1; switch (GET_OPCODE(op)) { case SLJIT_MOV_F64: if (src != dst_r) { if (dst_r != TMP_FREG1) { - FAIL_IF(push_inst(compiler, FMOVS | DA(dst_r) | S2A(src), MOVABLE_INS)); + FAIL_IF(push_inst(compiler, FMOVS | FD(dst_r) | FS2(src), MOVABLE_INS)); if (!(op & SLJIT_F32_OP)) - FAIL_IF(push_inst(compiler, FMOVS | DA(dst_r | 1) | S2A(src | 1), MOVABLE_INS)); + FAIL_IF(push_inst(compiler, FMOVS | FDN(dst_r) | FS2N(src), MOVABLE_INS)); } else dst_r = src; } break; case SLJIT_NEG_F64: - FAIL_IF(push_inst(compiler, FNEGS | DA(dst_r) | S2A(src), MOVABLE_INS)); + FAIL_IF(push_inst(compiler, FNEGS | FD(dst_r) | FS2(src), MOVABLE_INS)); if (dst_r != src && !(op & SLJIT_F32_OP)) - FAIL_IF(push_inst(compiler, FMOVS | DA(dst_r | 1) | S2A(src | 1), MOVABLE_INS)); + FAIL_IF(push_inst(compiler, FMOVS | FDN(dst_r) | FS2N(src), MOVABLE_INS)); break; case SLJIT_ABS_F64: - FAIL_IF(push_inst(compiler, FABSS | DA(dst_r) | S2A(src), MOVABLE_INS)); + FAIL_IF(push_inst(compiler, FABSS | FD(dst_r) | FS2(src), MOVABLE_INS)); if (dst_r != src && !(op & SLJIT_F32_OP)) - FAIL_IF(push_inst(compiler, FMOVS | DA(dst_r | 1) | S2A(src | 1), MOVABLE_INS)); + FAIL_IF(push_inst(compiler, FMOVS | FDN(dst_r) | FS2N(src), MOVABLE_INS)); break; case SLJIT_CONV_F64_FROM_F32: - FAIL_IF(push_inst(compiler, SELECT_FOP(op, FSTOD, FDTOS) | DA(dst_r) | S2A(src), MOVABLE_INS)); + FAIL_IF(push_inst(compiler, SELECT_FOP(op, FSTOD, FDTOS) | FD(dst_r) | FS2(src), MOVABLE_INS)); op ^= SLJIT_F32_OP; break; } @@ -1118,7 +1109,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2(struct sljit_compiler *compil compiler->cache_arg = 0; compiler->cache_argw = 0; - dst_r = FAST_IS_REG(dst) ? (dst << 1) : TMP_FREG2; + dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG2; if (src1 & SLJIT_MEM) { if (getput_arg_fast(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w)) { @@ -1127,8 +1118,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2(struct sljit_compiler *compil } else flags |= SLOW_SRC1; } - else - src1 <<= 1; if (src2 & SLJIT_MEM) { if (getput_arg_fast(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src2, src2w)) { @@ -1137,8 +1126,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2(struct sljit_compiler *compil } else flags |= SLOW_SRC2; } - else - src2 <<= 1; if ((flags & (SLOW_SRC1 | SLOW_SRC2)) == (SLOW_SRC1 | SLOW_SRC2)) { if (!can_cache(src1, src1w, src2, src2w) && can_cache(src1, src1w, dst, dstw)) { @@ -1162,19 +1149,19 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2(struct sljit_compiler *compil switch (GET_OPCODE(op)) { case SLJIT_ADD_F64: - FAIL_IF(push_inst(compiler, SELECT_FOP(op, FADDS, FADDD) | DA(dst_r) | S1A(src1) | S2A(src2), MOVABLE_INS)); + FAIL_IF(push_inst(compiler, SELECT_FOP(op, FADDS, FADDD) | FD(dst_r) | FS1(src1) | FS2(src2), MOVABLE_INS)); break; case SLJIT_SUB_F64: - FAIL_IF(push_inst(compiler, SELECT_FOP(op, FSUBS, FSUBD) | DA(dst_r) | S1A(src1) | S2A(src2), MOVABLE_INS)); + FAIL_IF(push_inst(compiler, SELECT_FOP(op, FSUBS, FSUBD) | FD(dst_r) | FS1(src1) | FS2(src2), MOVABLE_INS)); break; case SLJIT_MUL_F64: - FAIL_IF(push_inst(compiler, SELECT_FOP(op, FMULS, FMULD) | DA(dst_r) | S1A(src1) | S2A(src2), MOVABLE_INS)); + FAIL_IF(push_inst(compiler, SELECT_FOP(op, FMULS, FMULD) | FD(dst_r) | FS1(src1) | FS2(src2), MOVABLE_INS)); break; case SLJIT_DIV_F64: - FAIL_IF(push_inst(compiler, SELECT_FOP(op, FDIVS, FDIVD) | DA(dst_r) | S1A(src1) | S2A(src2), MOVABLE_INS)); + FAIL_IF(push_inst(compiler, SELECT_FOP(op, FDIVS, FDIVD) | FD(dst_r) | FS1(src1) | FS2(src2), MOVABLE_INS)); break; } @@ -1197,10 +1184,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler * CHECK(check_sljit_emit_fast_enter(compiler, dst, dstw)); ADJUST_LOCAL_OFFSET(dst, dstw); - /* For UNUSED dst. Uncommon, but possible. */ - if (dst == SLJIT_UNUSED) - return SLJIT_SUCCESS; - if (FAST_IS_REG(dst)) return push_inst(compiler, OR | D(dst) | S1(0) | S2(TMP_LINK), DR(dst)); @@ -1216,10 +1199,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_return(struct sljit_compiler if (FAST_IS_REG(src)) FAIL_IF(push_inst(compiler, OR | D(TMP_LINK) | S1(0) | S2(src), DR(TMP_LINK))); - else if (src & SLJIT_MEM) + else FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, TMP_LINK, src, srcw)); - else if (src & SLJIT_IMM) - FAIL_IF(load_immediate(compiler, TMP_LINK, srcw)); FAIL_IF(push_inst(compiler, JMPL | D(0) | S1(TMP_LINK) | IMM(8), UNMOVABLE_INS)); return push_inst(compiler, NOP, UNMOVABLE_INS); @@ -1296,7 +1277,7 @@ static sljit_ins get_cc(sljit_s32 type) return DA(0xf); default: - SLJIT_ASSERT_STOP(); + SLJIT_UNREACHABLE(); return DA(0x8); } } @@ -1332,21 +1313,38 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compile #else #error "Implementation required" #endif - } else { + } + else { if ((compiler->delay_slot & DST_INS_MASK) != UNMOVABLE_INS) jump->flags |= IS_MOVABLE; if (type >= SLJIT_FAST_CALL) jump->flags |= IS_CALL; } - PTR_FAIL_IF(emit_const(compiler, TMP_REG2, 0)); - PTR_FAIL_IF(push_inst(compiler, JMPL | D(type >= SLJIT_FAST_CALL ? TMP_LINK : 0) | S1(TMP_REG2) | IMM(0), UNMOVABLE_INS)); + PTR_FAIL_IF(emit_const(compiler, TMP_REG1, 0)); + PTR_FAIL_IF(push_inst(compiler, JMPL | D(type >= SLJIT_FAST_CALL ? TMP_LINK : 0) | S1(TMP_REG1) | IMM(0), UNMOVABLE_INS)); jump->addr = compiler->size; PTR_FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS)); return jump; } +SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 arg_types) +{ + CHECK_ERROR_PTR(); + CHECK_PTR(check_sljit_emit_call(compiler, type, arg_types)); + + PTR_FAIL_IF(call_with_args(compiler, arg_types, NULL)); + +#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \ + || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) + compiler->skip_checks = 1; +#endif + + return sljit_emit_jump(compiler, type); +} + SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 src, sljit_sw srcw) { struct sljit_jump *jump = NULL; @@ -1363,17 +1361,18 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compi FAIL_IF(!jump); set_jump(jump, compiler, JUMP_ADDR); jump->u.target = srcw; + if ((compiler->delay_slot & DST_INS_MASK) != UNMOVABLE_INS) jump->flags |= IS_MOVABLE; if (type >= SLJIT_FAST_CALL) jump->flags |= IS_CALL; - FAIL_IF(emit_const(compiler, TMP_REG2, 0)); - src_r = TMP_REG2; + FAIL_IF(emit_const(compiler, TMP_REG1, 0)); + src_r = TMP_REG1; } else { - FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, TMP_REG2, src, srcw)); - src_r = TMP_REG2; + FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, TMP_REG1, src, srcw)); + src_r = TMP_REG1; } FAIL_IF(push_inst(compiler, JMPL | D(type >= SLJIT_FAST_CALL ? TMP_LINK : 0) | S1(src_r) | IMM(0), UNMOVABLE_INS)); @@ -1382,32 +1381,48 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compi return push_inst(compiler, NOP, UNMOVABLE_INS); } +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 arg_types, + sljit_s32 src, sljit_sw srcw) +{ + CHECK_ERROR(); + CHECK(check_sljit_emit_icall(compiler, type, arg_types, src, srcw)); + + if (src & SLJIT_MEM) { + ADJUST_LOCAL_OFFSET(src, srcw); + FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, TMP_REG1, src, srcw)); + src = TMP_REG1; + } + + FAIL_IF(call_with_args(compiler, arg_types, &src)); + +#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \ + || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) + compiler->skip_checks = 1; +#endif + + return sljit_emit_ijump(compiler, type, src, srcw); +} + SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw dstw, - sljit_s32 src, sljit_sw srcw, sljit_s32 type) { - sljit_s32 reg, flags = (GET_FLAGS(op) ? SET_FLAGS : 0); + sljit_s32 reg, flags = HAS_FLAGS(op) ? SET_FLAGS : 0; CHECK_ERROR(); - CHECK(check_sljit_emit_op_flags(compiler, op, dst, dstw, src, srcw, type)); + CHECK(check_sljit_emit_op_flags(compiler, op, dst, dstw, type)); ADJUST_LOCAL_OFFSET(dst, dstw); - if (dst == SLJIT_UNUSED) - return SLJIT_SUCCESS; - #if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32) op = GET_OPCODE(op); reg = (op < SLJIT_ADD && FAST_IS_REG(dst)) ? dst : TMP_REG2; compiler->cache_arg = 0; compiler->cache_argw = 0; - if (op >= SLJIT_ADD && (src & SLJIT_MEM)) { - ADJUST_LOCAL_OFFSET(src, srcw); - FAIL_IF(emit_op_mem2(compiler, WORD_DATA | LOAD_DATA, TMP_REG1, src, srcw, dst, dstw)); - src = TMP_REG1; - srcw = 0; - } + + if (op >= SLJIT_ADD && (dst & SLJIT_MEM)) + FAIL_IF(emit_op_mem2(compiler, WORD_DATA | LOAD_DATA, TMP_REG1, dst, dstw, dst, dstw)); type &= 0xff; if (type < SLJIT_EQUAL_F64) @@ -1418,10 +1433,31 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *co FAIL_IF(push_inst(compiler, OR | D(reg) | S1(0) | IMM(1), UNMOVABLE_INS)); FAIL_IF(push_inst(compiler, OR | D(reg) | S1(0) | IMM(0), UNMOVABLE_INS)); - if (op >= SLJIT_ADD) - return emit_op(compiler, op, flags | CUMULATIVE_OP | IMM_OP | ALT_KEEP_CACHE, dst, dstw, src, srcw, TMP_REG2, 0); + if (op >= SLJIT_ADD) { + flags |= CUMULATIVE_OP | IMM_OP | ALT_KEEP_CACHE; + if (dst & SLJIT_MEM) + return emit_op(compiler, op, flags, dst, dstw, TMP_REG1, 0, TMP_REG2, 0); + return emit_op(compiler, op, flags, dst, 0, dst, 0, TMP_REG2, 0); + } + + if (!(dst & SLJIT_MEM)) + return SLJIT_SUCCESS; + + return emit_op_mem(compiler, WORD_DATA, TMP_REG2, dst, dstw); +#else +#error "Implementation required" +#endif +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 dst_reg, + sljit_s32 src, sljit_sw srcw) +{ + CHECK_ERROR(); + CHECK(check_sljit_emit_cmov(compiler, type, dst_reg, src, srcw)); - return (reg == TMP_REG2) ? emit_op_mem(compiler, WORD_DATA, TMP_REG2, dst, dstw) : SLJIT_SUCCESS; +#if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32) + return sljit_emit_cmov_generic(compiler, type, dst_reg, src, srcw);; #else #error "Implementation required" #endif @@ -1440,7 +1476,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compi PTR_FAIL_IF(!const_); set_const(const_, compiler); - reg = SLOW_IS_REG(dst) ? dst : TMP_REG2; + reg = FAST_IS_REG(dst) ? dst : TMP_REG2; PTR_FAIL_IF(emit_const(compiler, reg, init_value)); diff --git a/thirdparty/pcre2/src/sljit/sljitNativeTILEGX-encoder.c b/thirdparty/pcre2/src/sljit/sljitNativeTILEGX-encoder.c index 719632908c..dd82ebae6a 100644 --- a/thirdparty/pcre2/src/sljit/sljitNativeTILEGX-encoder.c +++ b/thirdparty/pcre2/src/sljit/sljitNativeTILEGX-encoder.c @@ -2,7 +2,7 @@ * Stack-less Just-In-Time compiler * * Copyright 2013-2013 Tilera Corporation(jiwang@tilera.com). All rights reserved. - * Copyright 2009-2012 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved. + * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are * permitted provided that the following conditions are met: diff --git a/thirdparty/pcre2/src/sljit/sljitNativeTILEGX_64.c b/thirdparty/pcre2/src/sljit/sljitNativeTILEGX_64.c index 177a65b006..003f43a790 100644 --- a/thirdparty/pcre2/src/sljit/sljitNativeTILEGX_64.c +++ b/thirdparty/pcre2/src/sljit/sljitNativeTILEGX_64.c @@ -2,7 +2,7 @@ * Stack-less Just-In-Time compiler * * Copyright 2013-2013 Tilera Corporation(jiwang@tilera.com). All rights reserved. - * Copyright 2009-2012 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved. + * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are * permitted provided that the following conditions are met: @@ -687,7 +687,7 @@ static sljit_s32 update_buffer(struct sljit_compiler *compiler) inst_buf[0] = inst1; inst_buf_index = 1; } else - SLJIT_ASSERT_STOP(); + SLJIT_UNREACHABLE(); #ifdef TILEGX_JIT_DEBUG return push_inst_nodebug(compiler, bits); @@ -727,10 +727,10 @@ static sljit_s32 update_buffer(struct sljit_compiler *compiler) return push_inst(compiler, bits); #endif } else - SLJIT_ASSERT_STOP(); + SLJIT_UNREACHABLE(); } - SLJIT_ASSERT_STOP(); + SLJIT_UNREACHABLE(); } static sljit_s32 flush_buffer(struct sljit_compiler *compiler) @@ -814,7 +814,7 @@ static sljit_s32 push_3_buffer(struct sljit_compiler *compiler, tilegx_mnemonic break; default: printf("unrecoginzed opc: %s\n", opcode->name); - SLJIT_ASSERT_STOP(); + SLJIT_UNREACHABLE(); } inst_buf_index++; @@ -859,7 +859,7 @@ static sljit_s32 push_2_buffer(struct sljit_compiler *compiler, tilegx_mnemonic break; default: printf("unrecoginzed opc: %s\n", opcode->name); - SLJIT_ASSERT_STOP(); + SLJIT_UNREACHABLE(); } inst_buf_index++; @@ -1952,7 +1952,7 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl return SLJIT_SUCCESS; } - SLJIT_ASSERT_STOP(); + SLJIT_UNREACHABLE(); return SLJIT_SUCCESS; } @@ -2092,9 +2092,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *co CHECK(check_sljit_emit_op_flags(compiler, op, dst, dstw, src, srcw, type)); ADJUST_LOCAL_OFFSET(dst, dstw); - if (dst == SLJIT_UNUSED) - return SLJIT_SUCCESS; - op = GET_OPCODE(op); if (op == SLJIT_MOV_S32 || op == SLJIT_MOV_U32) mem_type = INT_DATA | SIGNED_DATA; @@ -2143,7 +2140,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *co break; default: - SLJIT_ASSERT_STOP(); + SLJIT_UNREACHABLE(); dst_ar = sugg_dst_ar; break; } @@ -2186,7 +2183,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compile case SLJIT_DIVMOD_SW: case SLJIT_DIV_UW: case SLJIT_DIV_SW: - SLJIT_ASSERT_STOP(); + SLJIT_UNREACHABLE(); } return SLJIT_SUCCESS; @@ -2487,19 +2484,14 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump * sljit_emit_jump(struct sljit_compil return jump; } -SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_is_fpu_available(void) -{ - return 0; -} - SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop1(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw dstw, sljit_s32 src, sljit_sw srcw) { - SLJIT_ASSERT_STOP(); + SLJIT_UNREACHABLE(); } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw dstw, sljit_s32 src1, sljit_sw src1w, sljit_s32 src2, sljit_sw src2w) { - SLJIT_ASSERT_STOP(); + SLJIT_UNREACHABLE(); } SLJIT_API_FUNC_ATTRIBUTE struct sljit_const * sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw init_value) diff --git a/thirdparty/pcre2/src/sljit/sljitNativeX86_32.c b/thirdparty/pcre2/src/sljit/sljitNativeX86_32.c index 00333f6b33..8a83e273a4 100644 --- a/thirdparty/pcre2/src/sljit/sljitNativeX86_32.c +++ b/thirdparty/pcre2/src/sljit/sljitNativeX86_32.c @@ -1,7 +1,7 @@ /* * Stack-less Just-In-Time compiler * - * Copyright 2009-2012 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved. + * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are * permitted provided that the following conditions are met: @@ -64,20 +64,40 @@ static sljit_u8* generate_far_jump_code(struct sljit_jump *jump, sljit_u8 *code_ } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compiler, - sljit_s32 options, sljit_s32 args, sljit_s32 scratches, sljit_s32 saveds, + sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds, sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size) { - sljit_s32 size; + sljit_s32 args, size; sljit_u8 *inst; CHECK_ERROR(); - CHECK(check_sljit_emit_enter(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size)); - set_emit_enter(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size); + CHECK(check_sljit_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size)); + set_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size); + args = get_arg_count(arg_types); compiler->args = args; - compiler->flags_saved = 0; - size = 1 + (scratches > 7 ? (scratches - 7) : 0) + (saveds <= 3 ? saveds : 3); + /* [esp+0] for saving temporaries and function calls. */ + compiler->stack_tmp_size = 2 * sizeof(sljit_sw); + +#if !(defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL) + if (scratches > 3) + compiler->stack_tmp_size = 3 * sizeof(sljit_sw); +#endif + + compiler->saveds_offset = compiler->stack_tmp_size; + if (scratches > 3) + compiler->saveds_offset += ((scratches > (3 + 6)) ? 6 : (scratches - 3)) * sizeof(sljit_sw); + + compiler->locals_offset = compiler->saveds_offset; + + if (saveds > 3) + compiler->locals_offset += (saveds - 3) * sizeof(sljit_sw); + + if (options & SLJIT_F64_ALIGNMENT) + compiler->locals_offset = (compiler->locals_offset + sizeof(sljit_f64) - 1) & ~(sizeof(sljit_f64) - 1); + + size = 1 + (scratches > 9 ? (scratches - 9) : 0) + (saveds <= 3 ? saveds : 3); #if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL) size += (args > 0 ? (args * 2) : 0) + (args > 2 ? 2 : 0); #else @@ -94,11 +114,11 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi *inst++ = MOD_REG | (reg_map[TMP_REG1] << 3) | 0x4 /* esp */; } #endif - if (saveds > 2 || scratches > 7) + if (saveds > 2 || scratches > 9) PUSH_REG(reg_map[SLJIT_S2]); - if (saveds > 1 || scratches > 8) + if (saveds > 1 || scratches > 10) PUSH_REG(reg_map[SLJIT_S1]); - if (saveds > 0 || scratches > 9) + if (saveds > 0 || scratches > 11) PUSH_REG(reg_map[SLJIT_S0]); #if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL) @@ -134,73 +154,106 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi } #endif - SLJIT_COMPILE_ASSERT(SLJIT_LOCALS_OFFSET >= (2 + 4) * sizeof(sljit_uw), require_at_least_two_words); + SLJIT_ASSERT(SLJIT_LOCALS_OFFSET > 0); + #if defined(__APPLE__) /* Ignore pushed registers and SLJIT_LOCALS_OFFSET when computing the aligned local size. */ - saveds = (2 + (scratches > 7 ? (scratches - 7) : 0) + (saveds <= 3 ? saveds : 3)) * sizeof(sljit_uw); + saveds = (2 + (scratches > 9 ? (scratches - 9) : 0) + (saveds <= 3 ? saveds : 3)) * sizeof(sljit_uw); local_size = ((SLJIT_LOCALS_OFFSET + saveds + local_size + 15) & ~15) - saveds; #else - if (options & SLJIT_DOUBLE_ALIGNMENT) { - local_size = SLJIT_LOCALS_OFFSET + ((local_size + 7) & ~7); - - inst = (sljit_u8*)ensure_buf(compiler, 1 + 17); - FAIL_IF(!inst); - - INC_SIZE(17); - inst[0] = MOV_r_rm; - inst[1] = MOD_REG | (reg_map[TMP_REG1] << 3) | reg_map[SLJIT_SP]; - inst[2] = GROUP_F7; - inst[3] = MOD_REG | (0 << 3) | reg_map[SLJIT_SP]; - sljit_unaligned_store_sw(inst + 4, 0x4); - inst[8] = JNE_i8; - inst[9] = 6; - inst[10] = GROUP_BINARY_81; - inst[11] = MOD_REG | (5 << 3) | reg_map[SLJIT_SP]; - sljit_unaligned_store_sw(inst + 12, 0x4); - inst[16] = PUSH_r + reg_map[TMP_REG1]; - } + if (options & SLJIT_F64_ALIGNMENT) + local_size = SLJIT_LOCALS_OFFSET + ((local_size + sizeof(sljit_f64) - 1) & ~(sizeof(sljit_f64) - 1)); else - local_size = SLJIT_LOCALS_OFFSET + ((local_size + 3) & ~3); + local_size = SLJIT_LOCALS_OFFSET + ((local_size + sizeof(sljit_sw) - 1) & ~(sizeof(sljit_sw) - 1)); #endif compiler->local_size = local_size; + #ifdef _WIN32 if (local_size > 1024) { #if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL) FAIL_IF(emit_do_imm(compiler, MOV_r_i32 + reg_map[SLJIT_R0], local_size)); #else - local_size -= SLJIT_LOCALS_OFFSET; + /* Space for a single argument. This amount is excluded when the stack is allocated below. */ + local_size -= sizeof(sljit_sw); FAIL_IF(emit_do_imm(compiler, MOV_r_i32 + reg_map[SLJIT_R0], local_size)); - FAIL_IF(emit_non_cum_binary(compiler, SUB_r_rm, SUB_rm_r, SUB, SUB_EAX_i32, - SLJIT_SP, 0, SLJIT_SP, 0, SLJIT_IMM, SLJIT_LOCALS_OFFSET)); + FAIL_IF(emit_non_cum_binary(compiler, BINARY_OPCODE(SUB), + SLJIT_SP, 0, SLJIT_SP, 0, SLJIT_IMM, sizeof(sljit_sw))); #endif - FAIL_IF(sljit_emit_ijump(compiler, SLJIT_CALL1, SLJIT_IMM, SLJIT_FUNC_OFFSET(sljit_grow_stack))); + FAIL_IF(sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARG1(SW), SLJIT_IMM, SLJIT_FUNC_OFFSET(sljit_grow_stack))); } #endif SLJIT_ASSERT(local_size > 0); - return emit_non_cum_binary(compiler, SUB_r_rm, SUB_rm_r, SUB, SUB_EAX_i32, + +#if !defined(__APPLE__) + if (options & SLJIT_F64_ALIGNMENT) { + EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_SP, 0); + + /* Some space might allocated during sljit_grow_stack() above on WIN32. */ + FAIL_IF(emit_non_cum_binary(compiler, BINARY_OPCODE(SUB), + SLJIT_SP, 0, SLJIT_SP, 0, SLJIT_IMM, local_size + sizeof(sljit_sw))); + +#if defined _WIN32 && !(defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL) + if (compiler->local_size > 1024) + FAIL_IF(emit_cum_binary(compiler, BINARY_OPCODE(ADD), + TMP_REG1, 0, TMP_REG1, 0, SLJIT_IMM, sizeof(sljit_sw))); +#endif + + inst = (sljit_u8*)ensure_buf(compiler, 1 + 6); + FAIL_IF(!inst); + + INC_SIZE(6); + inst[0] = GROUP_BINARY_81; + inst[1] = MOD_REG | AND | reg_map[SLJIT_SP]; + sljit_unaligned_store_sw(inst + 2, ~(sizeof(sljit_f64) - 1)); + + /* The real local size must be used. */ + return emit_mov(compiler, SLJIT_MEM1(SLJIT_SP), compiler->local_size, TMP_REG1, 0); + } +#endif + return emit_non_cum_binary(compiler, BINARY_OPCODE(SUB), SLJIT_SP, 0, SLJIT_SP, 0, SLJIT_IMM, local_size); } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *compiler, - sljit_s32 options, sljit_s32 args, sljit_s32 scratches, sljit_s32 saveds, + sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds, sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size) { CHECK_ERROR(); - CHECK(check_sljit_set_context(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size)); - set_set_context(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size); + CHECK(check_sljit_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size)); + set_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size); - compiler->args = args; + compiler->args = get_arg_count(arg_types); + + /* [esp+0] for saving temporaries and function calls. */ + compiler->stack_tmp_size = 2 * sizeof(sljit_sw); + +#if !(defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL) + if (scratches > 3) + compiler->stack_tmp_size = 3 * sizeof(sljit_sw); +#endif + + compiler->saveds_offset = compiler->stack_tmp_size; + if (scratches > 3) + compiler->saveds_offset += ((scratches > (3 + 6)) ? 6 : (scratches - 3)) * sizeof(sljit_sw); + + compiler->locals_offset = compiler->saveds_offset; + + if (saveds > 3) + compiler->locals_offset += (saveds - 3) * sizeof(sljit_sw); + + if (options & SLJIT_F64_ALIGNMENT) + compiler->locals_offset = (compiler->locals_offset + sizeof(sljit_f64) - 1) & ~(sizeof(sljit_f64) - 1); #if defined(__APPLE__) - saveds = (2 + (scratches > 7 ? (scratches - 7) : 0) + (saveds <= 3 ? saveds : 3)) * sizeof(sljit_uw); + saveds = (2 + (scratches > 9 ? (scratches - 9) : 0) + (saveds <= 3 ? saveds : 3)) * sizeof(sljit_uw); compiler->local_size = ((SLJIT_LOCALS_OFFSET + saveds + local_size + 15) & ~15) - saveds; #else - if (options & SLJIT_DOUBLE_ALIGNMENT) - compiler->local_size = SLJIT_LOCALS_OFFSET + ((local_size + 7) & ~7); + if (options & SLJIT_F64_ALIGNMENT) + compiler->local_size = SLJIT_LOCALS_OFFSET + ((local_size + sizeof(sljit_f64) - 1) & ~(sizeof(sljit_f64) - 1)); else - compiler->local_size = SLJIT_LOCALS_OFFSET + ((local_size + 3) & ~3); + compiler->local_size = SLJIT_LOCALS_OFFSET + ((local_size + sizeof(sljit_sw) - 1) & ~(sizeof(sljit_sw) - 1)); #endif return SLJIT_SUCCESS; } @@ -214,23 +267,19 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return(struct sljit_compiler *comp CHECK(check_sljit_emit_return(compiler, op, src, srcw)); SLJIT_ASSERT(compiler->args >= 0); - compiler->flags_saved = 0; FAIL_IF(emit_mov_before_return(compiler, op, src, srcw)); SLJIT_ASSERT(compiler->local_size > 0); - FAIL_IF(emit_cum_binary(compiler, ADD_r_rm, ADD_rm_r, ADD, ADD_EAX_i32, - SLJIT_SP, 0, SLJIT_SP, 0, SLJIT_IMM, compiler->local_size)); #if !defined(__APPLE__) - if (compiler->options & SLJIT_DOUBLE_ALIGNMENT) { - inst = (sljit_u8*)ensure_buf(compiler, 1 + 3); - FAIL_IF(!inst); - - INC_SIZE(3); - inst[0] = MOV_r_rm; - inst[1] = (reg_map[SLJIT_SP] << 3) | 0x4 /* SIB */; - inst[2] = (4 << 3) | reg_map[SLJIT_SP]; - } + if (compiler->options & SLJIT_F64_ALIGNMENT) + EMIT_MOV(compiler, SLJIT_SP, 0, SLJIT_MEM1(SLJIT_SP), compiler->local_size) + else + FAIL_IF(emit_cum_binary(compiler, BINARY_OPCODE(ADD), + SLJIT_SP, 0, SLJIT_SP, 0, SLJIT_IMM, compiler->local_size)); +#else + FAIL_IF(emit_cum_binary(compiler, BINARY_OPCODE(ADD), + SLJIT_SP, 0, SLJIT_SP, 0, SLJIT_IMM, compiler->local_size)); #endif size = 2 + (compiler->scratches > 7 ? (compiler->scratches - 7) : 0) + @@ -247,11 +296,11 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return(struct sljit_compiler *comp INC_SIZE(size); - if (compiler->saveds > 0 || compiler->scratches > 9) + if (compiler->saveds > 0 || compiler->scratches > 11) POP_REG(reg_map[SLJIT_S0]); - if (compiler->saveds > 1 || compiler->scratches > 8) + if (compiler->saveds > 1 || compiler->scratches > 10) POP_REG(reg_map[SLJIT_S1]); - if (compiler->saveds > 2 || compiler->scratches > 7) + if (compiler->saveds > 2 || compiler->scratches > 9) POP_REG(reg_map[SLJIT_S2]); POP_REG(reg_map[TMP_REG1]); #if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL) @@ -366,7 +415,7 @@ static sljit_u8* emit_x86_instruction(struct sljit_compiler *compiler, sljit_s32 if ((flags & EX86_BIN_INS) && (a & SLJIT_IMM)) *inst = (flags & EX86_BYTE_ARG) ? GROUP_BINARY_83 : GROUP_BINARY_81; - if ((a & SLJIT_IMM) || (a == 0)) + if (a & SLJIT_IMM) *buf_ptr = 0; else if (!(flags & EX86_SSE2_OP1)) *buf_ptr = reg_map[a] << 3; @@ -438,42 +487,324 @@ static sljit_u8* emit_x86_instruction(struct sljit_compiler *compiler, sljit_s32 /* Call / return instructions */ /* --------------------------------------------------------------------- */ -static SLJIT_INLINE sljit_s32 call_with_args(struct sljit_compiler *compiler, sljit_s32 type) +#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL) + +static sljit_s32 c_fast_call_get_stack_size(sljit_s32 arg_types, sljit_s32 *word_arg_count_ptr) { - sljit_u8 *inst; + sljit_s32 stack_size = 0; + sljit_s32 word_arg_count = 0; + + arg_types >>= SLJIT_DEF_SHIFT; + + while (arg_types) { + switch (arg_types & SLJIT_DEF_MASK) { + case SLJIT_ARG_TYPE_F32: + stack_size += sizeof(sljit_f32); + break; + case SLJIT_ARG_TYPE_F64: + stack_size += sizeof(sljit_f64); + break; + default: + word_arg_count++; + if (word_arg_count > 2) + stack_size += sizeof(sljit_sw); + break; + } -#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL) - inst = (sljit_u8*)ensure_buf(compiler, type >= SLJIT_CALL3 ? 1 + 2 + 1 : 1 + 2); - FAIL_IF(!inst); - INC_SIZE(type >= SLJIT_CALL3 ? 2 + 1 : 2); + arg_types >>= SLJIT_DEF_SHIFT; + } + + if (word_arg_count_ptr) + *word_arg_count_ptr = word_arg_count; - if (type >= SLJIT_CALL3) + return stack_size; +} + +static sljit_s32 c_fast_call_with_args(struct sljit_compiler *compiler, + sljit_s32 arg_types, sljit_s32 stack_size, sljit_s32 word_arg_count, sljit_s32 swap_args) +{ + sljit_u8 *inst; + sljit_s32 float_arg_count; + + if (stack_size == sizeof(sljit_sw) && word_arg_count == 3) { + inst = (sljit_u8*)ensure_buf(compiler, 1 + 1); + FAIL_IF(!inst); + INC_SIZE(1); PUSH_REG(reg_map[SLJIT_R2]); - *inst++ = MOV_r_rm; - *inst++ = MOD_REG | (reg_map[SLJIT_R2] << 3) | reg_map[SLJIT_R0]; + } + else if (stack_size > 0) { + if (word_arg_count >= 4) + EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_MEM1(SLJIT_SP), compiler->saveds_offset - sizeof(sljit_sw)); + + FAIL_IF(emit_non_cum_binary(compiler, BINARY_OPCODE(SUB), + SLJIT_SP, 0, SLJIT_SP, 0, SLJIT_IMM, stack_size)); + + stack_size = 0; + arg_types >>= SLJIT_DEF_SHIFT; + word_arg_count = 0; + float_arg_count = 0; + while (arg_types) { + switch (arg_types & SLJIT_DEF_MASK) { + case SLJIT_ARG_TYPE_F32: + float_arg_count++; + FAIL_IF(emit_sse2_store(compiler, 1, SLJIT_MEM1(SLJIT_SP), stack_size, float_arg_count)); + stack_size += sizeof(sljit_f32); + break; + case SLJIT_ARG_TYPE_F64: + float_arg_count++; + FAIL_IF(emit_sse2_store(compiler, 0, SLJIT_MEM1(SLJIT_SP), stack_size, float_arg_count)); + stack_size += sizeof(sljit_f64); + break; + default: + word_arg_count++; + if (word_arg_count == 3) { + EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), stack_size, SLJIT_R2, 0); + stack_size += sizeof(sljit_sw); + } + else if (word_arg_count == 4) { + EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), stack_size, TMP_REG1, 0); + stack_size += sizeof(sljit_sw); + } + break; + } + + arg_types >>= SLJIT_DEF_SHIFT; + } + } + + if (word_arg_count > 0) { + if (swap_args) { + inst = (sljit_u8*)ensure_buf(compiler, 1 + 1); + FAIL_IF(!inst); + INC_SIZE(1); + + *inst++ = XCHG_EAX_r | reg_map[SLJIT_R2]; + } + else { + inst = (sljit_u8*)ensure_buf(compiler, 1 + 2); + FAIL_IF(!inst); + INC_SIZE(2); + + *inst++ = MOV_r_rm; + *inst++ = MOD_REG | (reg_map[SLJIT_R2] << 3) | reg_map[SLJIT_R0]; + } + } + + return SLJIT_SUCCESS; +} + +#endif + +static sljit_s32 cdecl_call_get_stack_size(struct sljit_compiler *compiler, sljit_s32 arg_types, sljit_s32 *word_arg_count_ptr) +{ + sljit_s32 stack_size = 0; + sljit_s32 word_arg_count = 0; + + arg_types >>= SLJIT_DEF_SHIFT; + + while (arg_types) { + switch (arg_types & SLJIT_DEF_MASK) { + case SLJIT_ARG_TYPE_F32: + stack_size += sizeof(sljit_f32); + break; + case SLJIT_ARG_TYPE_F64: + stack_size += sizeof(sljit_f64); + break; + default: + word_arg_count++; + stack_size += sizeof(sljit_sw); + break; + } + + arg_types >>= SLJIT_DEF_SHIFT; + } + + if (word_arg_count_ptr) + *word_arg_count_ptr = word_arg_count; + + if (stack_size <= compiler->stack_tmp_size) + return 0; + +#if defined(__APPLE__) + return ((stack_size - compiler->stack_tmp_size + 15) & ~15); #else - inst = (sljit_u8*)ensure_buf(compiler, 1 + 4 * (type - SLJIT_CALL0)); + return stack_size - compiler->stack_tmp_size; +#endif +} + +static sljit_s32 cdecl_call_with_args(struct sljit_compiler *compiler, + sljit_s32 arg_types, sljit_s32 stack_size, sljit_s32 word_arg_count) +{ + sljit_s32 float_arg_count = 0; + + if (word_arg_count >= 4) + EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_MEM1(SLJIT_SP), compiler->saveds_offset - sizeof(sljit_sw)); + + if (stack_size > 0) + FAIL_IF(emit_non_cum_binary(compiler, BINARY_OPCODE(SUB), + SLJIT_SP, 0, SLJIT_SP, 0, SLJIT_IMM, stack_size)); + + stack_size = 0; + word_arg_count = 0; + arg_types >>= SLJIT_DEF_SHIFT; + + while (arg_types) { + switch (arg_types & SLJIT_DEF_MASK) { + case SLJIT_ARG_TYPE_F32: + float_arg_count++; + FAIL_IF(emit_sse2_store(compiler, 1, SLJIT_MEM1(SLJIT_SP), stack_size, float_arg_count)); + stack_size += sizeof(sljit_f32); + break; + case SLJIT_ARG_TYPE_F64: + float_arg_count++; + FAIL_IF(emit_sse2_store(compiler, 0, SLJIT_MEM1(SLJIT_SP), stack_size, float_arg_count)); + stack_size += sizeof(sljit_f64); + break; + default: + word_arg_count++; + EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), stack_size, (word_arg_count >= 4) ? TMP_REG1 : word_arg_count, 0); + stack_size += sizeof(sljit_sw); + break; + } + + arg_types >>= SLJIT_DEF_SHIFT; + } + + return SLJIT_SUCCESS; +} + +static sljit_s32 post_call_with_args(struct sljit_compiler *compiler, + sljit_s32 arg_types, sljit_s32 stack_size) +{ + sljit_u8 *inst; + sljit_s32 single; + + if (stack_size > 0) + FAIL_IF(emit_cum_binary(compiler, BINARY_OPCODE(ADD), + SLJIT_SP, 0, SLJIT_SP, 0, SLJIT_IMM, stack_size)); + + if ((arg_types & SLJIT_DEF_MASK) < SLJIT_ARG_TYPE_F32) + return SLJIT_SUCCESS; + + single = ((arg_types & SLJIT_DEF_MASK) == SLJIT_ARG_TYPE_F32); + + inst = (sljit_u8*)ensure_buf(compiler, 1 + 3); FAIL_IF(!inst); - INC_SIZE(4 * (type - SLJIT_CALL0)); - - *inst++ = MOV_rm_r; - *inst++ = MOD_DISP8 | (reg_map[SLJIT_R0] << 3) | 0x4 /* SIB */; - *inst++ = (0x4 /* none*/ << 3) | reg_map[SLJIT_SP]; - *inst++ = 0; - if (type >= SLJIT_CALL2) { - *inst++ = MOV_rm_r; - *inst++ = MOD_DISP8 | (reg_map[SLJIT_R1] << 3) | 0x4 /* SIB */; - *inst++ = (0x4 /* none*/ << 3) | reg_map[SLJIT_SP]; - *inst++ = sizeof(sljit_sw); + INC_SIZE(3); + inst[0] = single ? FSTPS : FSTPD; + inst[1] = (0x03 << 3) | 0x04; + inst[2] = (0x04 << 3) | reg_map[SLJIT_SP]; + + return emit_sse2_load(compiler, single, SLJIT_FR0, SLJIT_MEM1(SLJIT_SP), 0); +} + +SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 arg_types) +{ + struct sljit_jump *jump; + sljit_s32 stack_size = 0; + sljit_s32 word_arg_count; + + CHECK_ERROR_PTR(); + CHECK_PTR(check_sljit_emit_call(compiler, type, arg_types)); + +#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL) + if ((type & 0xff) == SLJIT_CALL) { + stack_size = c_fast_call_get_stack_size(arg_types, &word_arg_count); + PTR_FAIL_IF(c_fast_call_with_args(compiler, arg_types, stack_size, word_arg_count, 0)); + +#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \ + || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) + compiler->skip_checks = 1; +#endif + + jump = sljit_emit_jump(compiler, type); + PTR_FAIL_IF(jump == NULL); + + PTR_FAIL_IF(post_call_with_args(compiler, arg_types, 0)); + return jump; } - if (type >= SLJIT_CALL3) { - *inst++ = MOV_rm_r; - *inst++ = MOD_DISP8 | (reg_map[SLJIT_R2] << 3) | 0x4 /* SIB */; - *inst++ = (0x4 /* none*/ << 3) | reg_map[SLJIT_SP]; - *inst++ = 2 * sizeof(sljit_sw); +#endif + + stack_size = cdecl_call_get_stack_size(compiler, arg_types, &word_arg_count); + PTR_FAIL_IF(cdecl_call_with_args(compiler, arg_types, stack_size, word_arg_count)); + +#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \ + || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) + compiler->skip_checks = 1; +#endif + + jump = sljit_emit_jump(compiler, type); + PTR_FAIL_IF(jump == NULL); + + PTR_FAIL_IF(post_call_with_args(compiler, arg_types, stack_size)); + return jump; +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 arg_types, + sljit_s32 src, sljit_sw srcw) +{ + sljit_s32 stack_size = 0; + sljit_s32 word_arg_count; +#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL) + sljit_s32 swap_args; +#endif + + CHECK_ERROR(); + CHECK(check_sljit_emit_icall(compiler, type, arg_types, src, srcw)); + +#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL) + SLJIT_ASSERT(reg_map[SLJIT_R0] == 0 && reg_map[SLJIT_R2] == 1 && SLJIT_R0 == 1 && SLJIT_R2 == 3); + + if ((type & 0xff) == SLJIT_CALL) { + stack_size = c_fast_call_get_stack_size(arg_types, &word_arg_count); + swap_args = 0; + + if (word_arg_count > 0) { + if ((src & REG_MASK) == SLJIT_R2 || OFFS_REG(src) == SLJIT_R2) { + swap_args = 1; + if (((src & REG_MASK) | 0x2) == SLJIT_R2) + src ^= 0x2; + if ((OFFS_REG(src) | 0x2) == SLJIT_R2) + src ^= TO_OFFS_REG(0x2); + } + } + + FAIL_IF(c_fast_call_with_args(compiler, arg_types, stack_size, word_arg_count, swap_args)); + + compiler->saveds_offset += stack_size; + compiler->locals_offset += stack_size; + +#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \ + || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) + compiler->skip_checks = 1; +#endif + FAIL_IF(sljit_emit_ijump(compiler, type, src, srcw)); + + compiler->saveds_offset -= stack_size; + compiler->locals_offset -= stack_size; + + return post_call_with_args(compiler, arg_types, 0); } #endif - return SLJIT_SUCCESS; + + stack_size = cdecl_call_get_stack_size(compiler, arg_types, &word_arg_count); + FAIL_IF(cdecl_call_with_args(compiler, arg_types, stack_size, word_arg_count)); + + compiler->saveds_offset += stack_size; + compiler->locals_offset += stack_size; + +#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \ + || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) + compiler->skip_checks = 1; +#endif + FAIL_IF(sljit_emit_ijump(compiler, type, src, srcw)); + + compiler->saveds_offset -= stack_size; + compiler->locals_offset -= stack_size; + + return post_call_with_args(compiler, arg_types, stack_size); } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw) @@ -524,7 +855,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_return(struct sljit_compiler INC_SIZE(1 + 1); PUSH_REG(reg_map[src]); } - else if (src & SLJIT_MEM) { + else { inst = emit_x86_instruction(compiler, 1, 0, 0, src, srcw); FAIL_IF(!inst); *inst++ = GROUP_FF; @@ -534,16 +865,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_return(struct sljit_compiler FAIL_IF(!inst); INC_SIZE(1); } - else { - /* SLJIT_IMM. */ - inst = (sljit_u8*)ensure_buf(compiler, 1 + 5 + 1); - FAIL_IF(!inst); - - INC_SIZE(5 + 1); - *inst++ = PUSH_i32; - sljit_unaligned_store_sw(inst, srcw); - inst += sizeof(sljit_sw); - } RET(); return SLJIT_SUCCESS; diff --git a/thirdparty/pcre2/src/sljit/sljitNativeX86_64.c b/thirdparty/pcre2/src/sljit/sljitNativeX86_64.c index bc92d45680..635ebd087c 100644 --- a/thirdparty/pcre2/src/sljit/sljitNativeX86_64.c +++ b/thirdparty/pcre2/src/sljit/sljitNativeX86_64.c @@ -1,7 +1,7 @@ /* * Stack-less Just-In-Time compiler * - * Copyright 2009-2012 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved. + * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are * permitted provided that the following conditions are met: @@ -41,42 +41,55 @@ static sljit_s32 emit_load_imm64(struct sljit_compiler *compiler, sljit_s32 reg, static sljit_u8* generate_far_jump_code(struct sljit_jump *jump, sljit_u8 *code_ptr, sljit_s32 type) { + int short_addr = !(jump->flags & SLJIT_REWRITABLE_JUMP) && !(jump->flags & JUMP_LABEL) && (jump->u.target <= 0xffffffff); + + /* The relative jump below specialized for this case. */ + SLJIT_ASSERT(reg_map[TMP_REG2] >= 8); + if (type < SLJIT_JUMP) { /* Invert type. */ *code_ptr++ = get_jump_code(type ^ 0x1) - 0x10; - *code_ptr++ = 10 + 3; + *code_ptr++ = short_addr ? (6 + 3) : (10 + 3); } - SLJIT_COMPILE_ASSERT(reg_map[TMP_REG3] == 9, tmp3_is_9_first); - *code_ptr++ = REX_W | REX_B; - *code_ptr++ = MOV_r_i32 + 1; + *code_ptr++ = short_addr ? REX_B : (REX_W | REX_B); + *code_ptr++ = MOV_r_i32 | reg_lmap[TMP_REG2]; jump->addr = (sljit_uw)code_ptr; if (jump->flags & JUMP_LABEL) jump->flags |= PATCH_MD; + else if (short_addr) + sljit_unaligned_store_s32(code_ptr, (sljit_s32)jump->u.target); else sljit_unaligned_store_sw(code_ptr, jump->u.target); - code_ptr += sizeof(sljit_sw); + code_ptr += short_addr ? sizeof(sljit_s32) : sizeof(sljit_sw); + *code_ptr++ = REX_B; *code_ptr++ = GROUP_FF; - *code_ptr++ = (type >= SLJIT_FAST_CALL) ? (MOD_REG | CALL_rm | 1) : (MOD_REG | JMP_rm | 1); + *code_ptr++ = MOD_REG | (type >= SLJIT_FAST_CALL ? CALL_rm : JMP_rm) | reg_lmap[TMP_REG2]; return code_ptr; } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compiler, - sljit_s32 options, sljit_s32 args, sljit_s32 scratches, sljit_s32 saveds, + sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds, sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size) { - sljit_s32 i, tmp, size, saved_register_size; + sljit_s32 args, i, tmp, size, saved_register_size; sljit_u8 *inst; CHECK_ERROR(); - CHECK(check_sljit_emit_enter(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size)); - set_emit_enter(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size); + CHECK(check_sljit_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size)); + set_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size); - compiler->flags_saved = 0; +#ifdef _WIN64 + /* Two/four register slots for parameters plus space for xmm6 register if needed. */ + if (fscratches >= 6 || fsaveds >= 1) + compiler->locals_offset = 6 * sizeof(sljit_sw); + else + compiler->locals_offset = ((scratches > 2) ? 4 : 2) * sizeof(sljit_sw); +#endif /* Including the return address saved by the call instruction. */ saved_register_size = GET_SAVED_REGISTERS_SIZE(scratches, saveds, 1); @@ -102,6 +115,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi PUSH_REG(reg_lmap[i]); } + args = get_arg_count(arg_types); + if (args > 0) { size = args * 3; inst = (sljit_u8*)ensure_buf(compiler, 1 + size); @@ -155,7 +170,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi INC_SIZE(4 + (3 + sizeof(sljit_s32))); *inst++ = REX_W; *inst++ = GROUP_BINARY_83; - *inst++ = MOD_REG | SUB | 4; + *inst++ = MOD_REG | SUB | reg_map[SLJIT_SP]; /* Allocated size for registers must be divisible by 8. */ SLJIT_ASSERT(!(saved_register_size & 0x7)); /* Aligned to 16 byte. */ @@ -167,7 +182,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi local_size -= 4 * sizeof(sljit_sw); } /* Second instruction */ - SLJIT_COMPILE_ASSERT(reg_map[SLJIT_R0] < 8, temporary_reg1_is_loreg); + SLJIT_ASSERT(reg_map[SLJIT_R0] < 8); *inst++ = REX_W; *inst++ = MOV_rm_i32; *inst++ = MOD_REG | reg_lmap[SLJIT_R0]; @@ -176,29 +191,30 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) compiler->skip_checks = 1; #endif - FAIL_IF(sljit_emit_ijump(compiler, SLJIT_CALL1, SLJIT_IMM, SLJIT_FUNC_OFFSET(sljit_grow_stack))); + FAIL_IF(sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARG1(SW), SLJIT_IMM, SLJIT_FUNC_OFFSET(sljit_grow_stack))); } #endif - SLJIT_ASSERT(local_size > 0); - if (local_size <= 127) { - inst = (sljit_u8*)ensure_buf(compiler, 1 + 4); - FAIL_IF(!inst); - INC_SIZE(4); - *inst++ = REX_W; - *inst++ = GROUP_BINARY_83; - *inst++ = MOD_REG | SUB | 4; - *inst++ = local_size; - } - else { - inst = (sljit_u8*)ensure_buf(compiler, 1 + 7); - FAIL_IF(!inst); - INC_SIZE(7); - *inst++ = REX_W; - *inst++ = GROUP_BINARY_81; - *inst++ = MOD_REG | SUB | 4; - sljit_unaligned_store_s32(inst, local_size); - inst += sizeof(sljit_s32); + if (local_size > 0) { + if (local_size <= 127) { + inst = (sljit_u8*)ensure_buf(compiler, 1 + 4); + FAIL_IF(!inst); + INC_SIZE(4); + *inst++ = REX_W; + *inst++ = GROUP_BINARY_83; + *inst++ = MOD_REG | SUB | reg_map[SLJIT_SP]; + *inst++ = local_size; + } + else { + inst = (sljit_u8*)ensure_buf(compiler, 1 + 7); + FAIL_IF(!inst); + INC_SIZE(7); + *inst++ = REX_W; + *inst++ = GROUP_BINARY_81; + *inst++ = MOD_REG | SUB | reg_map[SLJIT_SP]; + sljit_unaligned_store_s32(inst, local_size); + inst += sizeof(sljit_s32); + } } #ifdef _WIN64 @@ -216,14 +232,22 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *compiler, - sljit_s32 options, sljit_s32 args, sljit_s32 scratches, sljit_s32 saveds, + sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds, sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size) { sljit_s32 saved_register_size; CHECK_ERROR(); - CHECK(check_sljit_set_context(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size)); - set_set_context(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size); + CHECK(check_sljit_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size)); + set_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size); + +#ifdef _WIN64 + /* Two/four register slots for parameters plus space for xmm6 register if needed. */ + if (fscratches >= 6 || fsaveds >= 1) + compiler->locals_offset = 6 * sizeof(sljit_sw); + else + compiler->locals_offset = ((scratches > 2) ? 4 : 2) * sizeof(sljit_sw); +#endif /* Including the return address saved by the call instruction. */ saved_register_size = GET_SAVED_REGISTERS_SIZE(scratches, saveds, 1); @@ -239,7 +263,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return(struct sljit_compiler *comp CHECK_ERROR(); CHECK(check_sljit_emit_return(compiler, op, src, srcw)); - compiler->flags_saved = 0; FAIL_IF(emit_mov_before_return(compiler, op, src, srcw)); #ifdef _WIN64 @@ -253,24 +276,25 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return(struct sljit_compiler *comp } #endif - SLJIT_ASSERT(compiler->local_size > 0); - if (compiler->local_size <= 127) { - inst = (sljit_u8*)ensure_buf(compiler, 1 + 4); - FAIL_IF(!inst); - INC_SIZE(4); - *inst++ = REX_W; - *inst++ = GROUP_BINARY_83; - *inst++ = MOD_REG | ADD | 4; - *inst = compiler->local_size; - } - else { - inst = (sljit_u8*)ensure_buf(compiler, 1 + 7); - FAIL_IF(!inst); - INC_SIZE(7); - *inst++ = REX_W; - *inst++ = GROUP_BINARY_81; - *inst++ = MOD_REG | ADD | 4; - sljit_unaligned_store_s32(inst, compiler->local_size); + if (compiler->local_size > 0) { + if (compiler->local_size <= 127) { + inst = (sljit_u8*)ensure_buf(compiler, 1 + 4); + FAIL_IF(!inst); + INC_SIZE(4); + *inst++ = REX_W; + *inst++ = GROUP_BINARY_83; + *inst++ = MOD_REG | ADD | 4; + *inst = compiler->local_size; + } + else { + inst = (sljit_u8*)ensure_buf(compiler, 1 + 7); + FAIL_IF(!inst); + INC_SIZE(7); + *inst++ = REX_W; + *inst++ = GROUP_BINARY_81; + *inst++ = MOD_REG | ADD | 4; + sljit_unaligned_store_s32(inst, compiler->local_size); + } } tmp = compiler->scratches; @@ -365,13 +389,12 @@ static sljit_u8* emit_x86_instruction(struct sljit_compiler *compiler, sljit_s32 if (b & SLJIT_MEM) { if (!(b & OFFS_REG_MASK)) { if (NOT_HALFWORD(immb)) { - if (emit_load_imm64(compiler, TMP_REG3, immb)) - return NULL; + PTR_FAIL_IF(emit_load_imm64(compiler, TMP_REG2, immb)); immb = 0; if (b & REG_MASK) - b |= TO_OFFS_REG(TMP_REG3); + b |= TO_OFFS_REG(TMP_REG2); else - b |= TMP_REG3; + b |= TMP_REG2; } else if (reg_lmap[b & REG_MASK] == 4) b |= TO_OFFS_REG(SLJIT_SP); @@ -400,7 +423,11 @@ static sljit_u8* emit_x86_instruction(struct sljit_compiler *compiler, sljit_s32 } } } - else if (!(flags & EX86_SSE2_OP2) && reg_map[b] >= 8) + else if (!(flags & EX86_SSE2_OP2)) { + if (reg_map[b] >= 8) + rex |= REX_B; + } + else if (freg_map[b] >= 8) rex |= REX_B; if (a & SLJIT_IMM) { @@ -427,7 +454,11 @@ static sljit_u8* emit_x86_instruction(struct sljit_compiler *compiler, sljit_s32 else { SLJIT_ASSERT(!(flags & EX86_SHIFT_INS) || a == SLJIT_PREF_SHIFT_REG); /* reg_map[SLJIT_PREF_SHIFT_REG] is less than 8. */ - if (!(flags & EX86_SSE2_OP1) && reg_map[a] >= 8) + if (!(flags & EX86_SSE2_OP1)) { + if (reg_map[a] >= 8) + rex |= REX_R; + } + else if (freg_map[a] >= 8) rex |= REX_R; } @@ -454,12 +485,12 @@ static sljit_u8* emit_x86_instruction(struct sljit_compiler *compiler, sljit_s32 if ((flags & EX86_BIN_INS) && (a & SLJIT_IMM)) *inst = (flags & EX86_BYTE_ARG) ? GROUP_BINARY_83 : GROUP_BINARY_81; - if ((a & SLJIT_IMM) || (a == 0)) + if (a & SLJIT_IMM) *buf_ptr = 0; else if (!(flags & EX86_SSE2_OP1)) *buf_ptr = reg_lmap[a] << 3; else - *buf_ptr = a << 3; + *buf_ptr = freg_lmap[a] << 3; } else { if (a & SLJIT_IMM) { @@ -473,7 +504,7 @@ static sljit_u8* emit_x86_instruction(struct sljit_compiler *compiler, sljit_s32 } if (!(b & SLJIT_MEM)) - *buf_ptr++ |= MOD_REG + ((!(flags & EX86_SSE2_OP2)) ? reg_lmap[b] : b); + *buf_ptr++ |= MOD_REG + ((!(flags & EX86_SSE2_OP2)) ? reg_lmap[b] : freg_lmap[b]); else if ((b & REG_MASK) != SLJIT_UNUSED) { if ((b & OFFS_REG_MASK) == SLJIT_UNUSED || (b & OFFS_REG_MASK) == TO_OFFS_REG(SLJIT_SP)) { if (immb != 0 || reg_lmap[b & REG_MASK] == 5) { @@ -531,42 +562,161 @@ static sljit_u8* emit_x86_instruction(struct sljit_compiler *compiler, sljit_s32 /* Call / return instructions */ /* --------------------------------------------------------------------- */ -static SLJIT_INLINE sljit_s32 call_with_args(struct sljit_compiler *compiler, sljit_s32 type) +#ifndef _WIN64 + +static sljit_s32 call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_types, sljit_s32 *src_ptr, sljit_sw srcw) { - sljit_u8 *inst; + sljit_s32 src = src_ptr ? (*src_ptr) : 0; + sljit_s32 word_arg_count = 0; -#ifndef _WIN64 - SLJIT_COMPILE_ASSERT(reg_map[SLJIT_R1] == 6 && reg_map[SLJIT_R0] < 8 && reg_map[SLJIT_R2] < 8, args_registers); + SLJIT_ASSERT(reg_map[SLJIT_R1] == 6 && reg_map[SLJIT_R3] == 1 && reg_map[TMP_REG1] == 2); - inst = (sljit_u8*)ensure_buf(compiler, 1 + ((type < SLJIT_CALL3) ? 3 : 6)); - FAIL_IF(!inst); - INC_SIZE((type < SLJIT_CALL3) ? 3 : 6); - if (type >= SLJIT_CALL3) { - *inst++ = REX_W; - *inst++ = MOV_r_rm; - *inst++ = MOD_REG | (0x2 /* rdx */ << 3) | reg_lmap[SLJIT_R2]; + compiler->mode32 = 0; + + /* Remove return value. */ + arg_types >>= SLJIT_DEF_SHIFT; + + while (arg_types) { + if ((arg_types & SLJIT_DEF_MASK) < SLJIT_ARG_TYPE_F32) + word_arg_count++; + arg_types >>= SLJIT_DEF_SHIFT; } - *inst++ = REX_W; - *inst++ = MOV_r_rm; - *inst++ = MOD_REG | (0x7 /* rdi */ << 3) | reg_lmap[SLJIT_R0]; + + if (word_arg_count == 0) + return SLJIT_SUCCESS; + + if (src & SLJIT_MEM) { + ADJUST_LOCAL_OFFSET(src, srcw); + EMIT_MOV(compiler, TMP_REG2, 0, src, srcw); + *src_ptr = TMP_REG2; + } + else if (src == SLJIT_R2 && word_arg_count >= SLJIT_R2) + *src_ptr = TMP_REG1; + + if (word_arg_count >= 3) + EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_R2, 0); + return emit_mov(compiler, SLJIT_R2, 0, SLJIT_R0, 0); +} + #else - SLJIT_COMPILE_ASSERT(reg_map[SLJIT_R1] == 2 && reg_map[SLJIT_R0] < 8 && reg_map[SLJIT_R2] < 8, args_registers); - inst = (sljit_u8*)ensure_buf(compiler, 1 + ((type < SLJIT_CALL3) ? 3 : 6)); - FAIL_IF(!inst); - INC_SIZE((type < SLJIT_CALL3) ? 3 : 6); - if (type >= SLJIT_CALL3) { - *inst++ = REX_W | REX_R; - *inst++ = MOV_r_rm; - *inst++ = MOD_REG | (0x0 /* r8 */ << 3) | reg_lmap[SLJIT_R2]; +static sljit_s32 call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_types, sljit_s32 *src_ptr, sljit_sw srcw) +{ + sljit_s32 src = src_ptr ? (*src_ptr) : 0; + sljit_s32 arg_count = 0; + sljit_s32 word_arg_count = 0; + sljit_s32 float_arg_count = 0; + sljit_s32 types = 0; + sljit_s32 data_trandfer = 0; + static sljit_u8 word_arg_regs[5] = { 0, SLJIT_R3, SLJIT_R1, SLJIT_R2, TMP_REG1 }; + + SLJIT_ASSERT(reg_map[SLJIT_R3] == 1 && reg_map[SLJIT_R1] == 2 && reg_map[SLJIT_R2] == 8 && reg_map[TMP_REG1] == 9); + + compiler->mode32 = 0; + arg_types >>= SLJIT_DEF_SHIFT; + + while (arg_types) { + types = (types << SLJIT_DEF_SHIFT) | (arg_types & SLJIT_DEF_MASK); + + switch (arg_types & SLJIT_DEF_MASK) { + case SLJIT_ARG_TYPE_F32: + case SLJIT_ARG_TYPE_F64: + arg_count++; + float_arg_count++; + + if (arg_count != float_arg_count) + data_trandfer = 1; + break; + default: + arg_count++; + word_arg_count++; + + if (arg_count != word_arg_count || arg_count != word_arg_regs[arg_count]) { + data_trandfer = 1; + + if (src == word_arg_regs[arg_count]) { + EMIT_MOV(compiler, TMP_REG2, 0, src, 0); + *src_ptr = TMP_REG2; + } + } + break; + } + + arg_types >>= SLJIT_DEF_SHIFT; } - *inst++ = REX_W; - *inst++ = MOV_r_rm; - *inst++ = MOD_REG | (0x1 /* rcx */ << 3) | reg_lmap[SLJIT_R0]; -#endif + + if (!data_trandfer) + return SLJIT_SUCCESS; + + if (src & SLJIT_MEM) { + ADJUST_LOCAL_OFFSET(src, srcw); + EMIT_MOV(compiler, TMP_REG2, 0, src, srcw); + *src_ptr = TMP_REG2; + } + + while (types) { + switch (types & SLJIT_DEF_MASK) { + case SLJIT_ARG_TYPE_F32: + if (arg_count != float_arg_count) + FAIL_IF(emit_sse2_load(compiler, 1, arg_count, float_arg_count, 0)); + arg_count--; + float_arg_count--; + break; + case SLJIT_ARG_TYPE_F64: + if (arg_count != float_arg_count) + FAIL_IF(emit_sse2_load(compiler, 0, arg_count, float_arg_count, 0)); + arg_count--; + float_arg_count--; + break; + default: + if (arg_count != word_arg_count || arg_count != word_arg_regs[arg_count]) + EMIT_MOV(compiler, word_arg_regs[arg_count], 0, word_arg_count, 0); + arg_count--; + word_arg_count--; + break; + } + + types >>= SLJIT_DEF_SHIFT; + } + return SLJIT_SUCCESS; } +#endif + +SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 arg_types) +{ + CHECK_ERROR_PTR(); + CHECK_PTR(check_sljit_emit_call(compiler, type, arg_types)); + + PTR_FAIL_IF(call_with_args(compiler, arg_types, NULL, 0)); + +#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \ + || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) + compiler->skip_checks = 1; +#endif + + return sljit_emit_jump(compiler, type); +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 arg_types, + sljit_s32 src, sljit_sw srcw) +{ + CHECK_ERROR(); + CHECK(check_sljit_emit_icall(compiler, type, arg_types, src, srcw)); + + FAIL_IF(call_with_args(compiler, arg_types, &src, srcw)); + +#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \ + || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) + compiler->skip_checks = 1; +#endif + + return sljit_emit_ijump(compiler, type, src, srcw); +} + SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw) { sljit_u8 *inst; @@ -612,11 +762,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_return(struct sljit_compiler CHECK(check_sljit_emit_fast_return(compiler, src, srcw)); ADJUST_LOCAL_OFFSET(src, srcw); - if ((src & SLJIT_IMM) && NOT_HALFWORD(srcw)) { - FAIL_IF(emit_load_imm64(compiler, TMP_REG1, srcw)); - src = TMP_REG1; - } - if (FAST_IS_REG(src)) { if (reg_map[src] < 8) { inst = (sljit_u8*)ensure_buf(compiler, 1 + 1 + 1); @@ -634,7 +779,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_return(struct sljit_compiler PUSH_REG(reg_lmap[src]); } } - else if (src & SLJIT_MEM) { + else { /* REX_W is not necessary (src is not immediate). */ compiler->mode32 = 1; inst = emit_x86_instruction(compiler, 1, 0, 0, src, srcw); @@ -646,23 +791,11 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_return(struct sljit_compiler FAIL_IF(!inst); INC_SIZE(1); } - else { - SLJIT_ASSERT(IS_HALFWORD(srcw)); - /* SLJIT_IMM. */ - inst = (sljit_u8*)ensure_buf(compiler, 1 + 5 + 1); - FAIL_IF(!inst); - - INC_SIZE(5 + 1); - *inst++ = PUSH_i32; - sljit_unaligned_store_s32(inst, srcw); - inst += sizeof(sljit_s32); - } RET(); return SLJIT_SUCCESS; } - /* --------------------------------------------------------------------- */ /* Extend input */ /* --------------------------------------------------------------------- */ diff --git a/thirdparty/pcre2/src/sljit/sljitNativeX86_common.c b/thirdparty/pcre2/src/sljit/sljitNativeX86_common.c index 12a0e272af..ab7b36adb2 100644 --- a/thirdparty/pcre2/src/sljit/sljitNativeX86_common.c +++ b/thirdparty/pcre2/src/sljit/sljitNativeX86_common.c @@ -1,7 +1,7 @@ /* * Stack-less Just-In-Time compiler * - * Copyright 2009-2012 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved. + * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are * permitted provided that the following conditions are met: @@ -26,7 +26,11 @@ SLJIT_API_FUNC_ATTRIBUTE const char* sljit_get_platform_name(void) { +#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL) + return "x86" SLJIT_CPUINFO " ABI:fastcall"; +#else return "x86" SLJIT_CPUINFO; +#endif } /* @@ -35,7 +39,7 @@ SLJIT_API_FUNC_ATTRIBUTE const char* sljit_get_platform_name(void) 1 - ECX 2 - EDX 3 - EBX - 4 - none + 4 - ESP 5 - EBP 6 - ESI 7 - EDI @@ -47,7 +51,7 @@ SLJIT_API_FUNC_ATTRIBUTE const char* sljit_get_platform_name(void) 1 - RCX 2 - RDX 3 - RBX - 4 - none + 4 - RSP 5 - RBP 6 - RSI 7 - RDI @@ -67,12 +71,15 @@ SLJIT_API_FUNC_ATTRIBUTE const char* sljit_get_platform_name(void) #define TMP_REG1 (SLJIT_NUMBER_OF_REGISTERS + 2) static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 3] = { - 0, 0, 2, 1, 0, 0, 0, 0, 7, 6, 3, 4, 5 + 0, 0, 2, 1, 0, 0, 0, 0, 0, 0, 7, 6, 3, 4, 5 }; #define CHECK_EXTRA_REGS(p, w, do) \ - if (p >= SLJIT_R3 && p <= SLJIT_R6) { \ - w = SLJIT_LOCALS_OFFSET + ((p) - (SLJIT_R3 + 4)) * sizeof(sljit_sw); \ + if (p >= SLJIT_R3 && p <= SLJIT_S3) { \ + if (p <= compiler->scratches) \ + w = compiler->saveds_offset - ((p) - SLJIT_R2) * (sljit_sw)sizeof(sljit_sw); \ + else \ + w = compiler->locals_offset + ((p) - SLJIT_S2) * (sljit_sw)sizeof(sljit_sw); \ p = SLJIT_MEM1(SLJIT_SP); \ do; \ } @@ -82,31 +89,39 @@ static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 3] = { /* Last register + 1. */ #define TMP_REG1 (SLJIT_NUMBER_OF_REGISTERS + 2) #define TMP_REG2 (SLJIT_NUMBER_OF_REGISTERS + 3) -#define TMP_REG3 (SLJIT_NUMBER_OF_REGISTERS + 4) /* Note: r12 & 0x7 == 0b100, which decoded as SIB byte present Note: avoid to use r12 and r13 for memory addessing - therefore r12 is better for SAVED_EREG than SAVED_REG. */ + therefore r12 is better to be a higher saved register. */ #ifndef _WIN64 -/* 1st passed in rdi, 2nd argument passed in rsi, 3rd in rdx. */ -static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 5] = { - 0, 0, 6, 1, 8, 11, 10, 12, 5, 13, 14, 15, 3, 4, 2, 7, 9 +/* Args: rdi(=7), rsi(=6), rdx(=2), rcx(=1), r8, r9. Scratches: rax(=0), r10, r11 */ +static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 4] = { + 0, 0, 6, 7, 1, 8, 11, 10, 12, 5, 13, 14, 15, 3, 4, 2, 9 }; /* low-map. reg_map & 0x7. */ -static const sljit_u8 reg_lmap[SLJIT_NUMBER_OF_REGISTERS + 5] = { - 0, 0, 6, 1, 0, 3, 2, 4, 5, 5, 6, 7, 3, 4, 2, 7, 1 +static const sljit_u8 reg_lmap[SLJIT_NUMBER_OF_REGISTERS + 4] = { + 0, 0, 6, 7, 1, 0, 3, 2, 4, 5, 5, 6, 7, 3, 4, 2, 1 }; #else -/* 1st passed in rcx, 2nd argument passed in rdx, 3rd in r8. */ -static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 5] = { - 0, 0, 2, 1, 11, 12, 5, 13, 14, 15, 7, 6, 3, 4, 10, 8, 9 +/* Args: rcx(=1), rdx(=2), r8, r9. Scratches: rax(=0), r10, r11 */ +static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 4] = { + 0, 0, 2, 8, 1, 11, 12, 5, 13, 14, 15, 7, 6, 3, 4, 9, 10 }; /* low-map. reg_map & 0x7. */ -static const sljit_u8 reg_lmap[SLJIT_NUMBER_OF_REGISTERS + 5] = { - 0, 0, 2, 1, 3, 4, 5, 5, 6, 7, 7, 6, 3, 4, 2, 0, 1 +static const sljit_u8 reg_lmap[SLJIT_NUMBER_OF_REGISTERS + 4] = { + 0, 0, 2, 0, 1, 3, 4, 5, 5, 6, 7, 7, 6, 3, 4, 1, 2 }; #endif +/* Args: xmm0-xmm3 */ +static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1] = { + 4, 0, 1, 2, 3, 5, 6 +}; +/* low-map. freg_map & 0x7. */ +static const sljit_u8 freg_lmap[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1] = { + 4, 0, 1, 2, 3, 5, 6 +}; + #define REX_W 0x48 #define REX_R 0x44 #define REX_X 0x42 @@ -166,7 +181,7 @@ static const sljit_u8 reg_lmap[SLJIT_NUMBER_OF_REGISTERS + 5] = { #define CALL_i32 0xe8 #define CALL_rm (/* GROUP_FF */ 2 << 3) #define CDQ 0x99 -#define CMOVNE_r_rm (/* GROUP_0F */ 0x45) +#define CMOVE_r_rm (/* GROUP_0F */ 0x44) #define CMP (/* BINARY */ 7 << 3) #define CMP_EAX_i32 0x3d #define CMP_r_rm 0x3b @@ -176,6 +191,8 @@ static const sljit_u8 reg_lmap[SLJIT_NUMBER_OF_REGISTERS + 5] = { #define CVTTSD2SI_r_xm 0x2c #define DIV (/* GROUP_F7 */ 6 << 3) #define DIVSD_x_xm 0x5e +#define FSTPS 0xd9 +#define FSTPD 0xdd #define INT3 0xcc #define IDIV (/* GROUP_F7 */ 7 << 3) #define IMUL (/* GROUP_F7 */ 5 << 3) @@ -214,6 +231,7 @@ static const sljit_u8 reg_lmap[SLJIT_NUMBER_OF_REGISTERS + 5] = { #define POP_r 0x58 #define POP_rm 0x8f #define POPF 0x9d +#define PREFETCH 0x18 #define PUSH_i32 0x68 #define PUSH_r 0x50 #define PUSH_rm (/* GROUP_FF */ 6 << 3) @@ -459,11 +477,7 @@ static sljit_u8* generate_near_jump_code(struct sljit_jump *jump, sljit_u8 *code code_ptr += sizeof(sljit_s8); } else { jump->flags |= PATCH_MW; -#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) - code_ptr += sizeof(sljit_sw); -#else code_ptr += sizeof(sljit_s32); -#endif } return code_ptr; @@ -585,18 +599,59 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil return (void*)(code + executable_offset); } +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type) +{ + switch (feature_type) { + case SLJIT_HAS_FPU: +#ifdef SLJIT_IS_FPU_AVAILABLE + return SLJIT_IS_FPU_AVAILABLE; +#elif (defined SLJIT_DETECT_SSE2 && SLJIT_DETECT_SSE2) + if (cpu_has_sse2 == -1) + get_cpu_features(); + return cpu_has_sse2; +#else /* SLJIT_DETECT_SSE2 */ + return 1; +#endif /* SLJIT_DETECT_SSE2 */ + +#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) + case SLJIT_HAS_VIRTUAL_REGISTERS: + return 1; +#endif + + case SLJIT_HAS_CLZ: + case SLJIT_HAS_CMOV: + if (cpu_has_cmov == -1) + get_cpu_features(); + return cpu_has_cmov; + + case SLJIT_HAS_SSE2: +#if (defined SLJIT_DETECT_SSE2 && SLJIT_DETECT_SSE2) + if (cpu_has_sse2 == -1) + get_cpu_features(); + return cpu_has_sse2; +#else + return 1; +#endif + + default: + return 0; + } +} + /* --------------------------------------------------------------------- */ /* Operators */ /* --------------------------------------------------------------------- */ +#define BINARY_OPCODE(opcode) (((opcode ## _EAX_i32) << 24) | ((opcode ## _r_rm) << 16) | ((opcode ## _rm_r) << 8) | (opcode)) + static sljit_s32 emit_cum_binary(struct sljit_compiler *compiler, - sljit_u8 op_rm, sljit_u8 op_mr, sljit_u8 op_imm, sljit_u8 op_eax_imm, + sljit_u32 op_types, sljit_s32 dst, sljit_sw dstw, sljit_s32 src1, sljit_sw src1w, sljit_s32 src2, sljit_sw src2w); static sljit_s32 emit_non_cum_binary(struct sljit_compiler *compiler, - sljit_u8 op_rm, sljit_u8 op_mr, sljit_u8 op_imm, sljit_u8 op_eax_imm, + sljit_u32 op_types, sljit_s32 dst, sljit_sw dstw, sljit_s32 src1, sljit_sw src1w, sljit_s32 src2, sljit_sw src2w); @@ -605,57 +660,19 @@ static sljit_s32 emit_mov(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_s32 src, sljit_sw srcw); -static SLJIT_INLINE sljit_s32 emit_save_flags(struct sljit_compiler *compiler) -{ - sljit_u8 *inst; - -#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) - inst = (sljit_u8*)ensure_buf(compiler, 1 + 5); - FAIL_IF(!inst); - INC_SIZE(5); -#else - inst = (sljit_u8*)ensure_buf(compiler, 1 + 6); - FAIL_IF(!inst); - INC_SIZE(6); - *inst++ = REX_W; -#endif - *inst++ = LEA_r_m; /* lea esp/rsp, [esp/rsp + sizeof(sljit_sw)] */ - *inst++ = 0x64; - *inst++ = 0x24; - *inst++ = (sljit_u8)sizeof(sljit_sw); - *inst++ = PUSHF; - compiler->flags_saved = 1; - return SLJIT_SUCCESS; -} +#define EMIT_MOV(compiler, dst, dstw, src, srcw) \ + FAIL_IF(emit_mov(compiler, dst, dstw, src, srcw)); -static SLJIT_INLINE sljit_s32 emit_restore_flags(struct sljit_compiler *compiler, sljit_s32 keep_flags) -{ - sljit_u8 *inst; +static SLJIT_INLINE sljit_s32 emit_sse2_store(struct sljit_compiler *compiler, + sljit_s32 single, sljit_s32 dst, sljit_sw dstw, sljit_s32 src); -#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) - inst = (sljit_u8*)ensure_buf(compiler, 1 + 5); - FAIL_IF(!inst); - INC_SIZE(5); - *inst++ = POPF; -#else - inst = (sljit_u8*)ensure_buf(compiler, 1 + 6); - FAIL_IF(!inst); - INC_SIZE(6); - *inst++ = POPF; - *inst++ = REX_W; -#endif - *inst++ = LEA_r_m; /* lea esp/rsp, [esp/rsp - sizeof(sljit_sw)] */ - *inst++ = 0x64; - *inst++ = 0x24; - *inst++ = (sljit_u8)(-(sljit_s8)sizeof(sljit_sw)); - compiler->flags_saved = keep_flags; - return SLJIT_SUCCESS; -} +static SLJIT_INLINE sljit_s32 emit_sse2_load(struct sljit_compiler *compiler, + sljit_s32 single, sljit_s32 dst, sljit_s32 src, sljit_sw srcw); #ifdef _WIN32 #include <malloc.h> -static void SLJIT_CALL sljit_grow_stack(sljit_sw local_size) +static void SLJIT_FUNC sljit_grow_stack(sljit_sw local_size) { /* Workaround for calling the internal _chkstk() function on Windows. This function touches all 4k pages belongs to the requested stack space, @@ -681,15 +698,8 @@ static sljit_s32 emit_mov(struct sljit_compiler *compiler, { sljit_u8* inst; - if (dst == SLJIT_UNUSED) { - /* No destination, doesn't need to setup flags. */ - if (src & SLJIT_MEM) { - inst = emit_x86_instruction(compiler, 1, TMP_REG1, 0, src, srcw); - FAIL_IF(!inst); - *inst = MOV_r_rm; - } - return SLJIT_SUCCESS; - } + SLJIT_ASSERT(dst != SLJIT_UNUSED); + if (FAST_IS_REG(src)) { inst = emit_x86_instruction(compiler, 1, src, 0, dst, dstw); FAIL_IF(!inst); @@ -711,8 +721,10 @@ static sljit_s32 emit_mov(struct sljit_compiler *compiler, } #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) if (!compiler->mode32 && NOT_HALFWORD(srcw)) { - FAIL_IF(emit_load_imm64(compiler, TMP_REG2, srcw)); - inst = emit_x86_instruction(compiler, 1, TMP_REG2, 0, dst, dstw); + /* Immediate to memory move. Only SLJIT_MOV operation copies + an immediate directly into memory so TMP_REG1 can be used. */ + FAIL_IF(emit_load_imm64(compiler, TMP_REG1, srcw)); + inst = emit_x86_instruction(compiler, 1, TMP_REG1, 0, dst, dstw); FAIL_IF(!inst); *inst = MOV_rm_r; return SLJIT_SUCCESS; @@ -730,7 +742,8 @@ static sljit_s32 emit_mov(struct sljit_compiler *compiler, return SLJIT_SUCCESS; } - /* Memory to memory move. Requires two instruction. */ + /* Memory to memory move. Only SLJIT_MOV operation copies + data from memory to memory so TMP_REG1 can be used. */ inst = emit_x86_instruction(compiler, 1, TMP_REG1, 0, src, srcw); FAIL_IF(!inst); *inst = MOV_r_rm; @@ -740,9 +753,6 @@ static sljit_s32 emit_mov(struct sljit_compiler *compiler, return SLJIT_SUCCESS; } -#define EMIT_MOV(compiler, dst, dstw, src, srcw) \ - FAIL_IF(emit_mov(compiler, dst, dstw, src, srcw)); - SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compiler, sljit_s32 op) { sljit_u8 *inst; @@ -772,20 +782,17 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compile case SLJIT_DIVMOD_SW: case SLJIT_DIV_UW: case SLJIT_DIV_SW: - compiler->flags_saved = 0; #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) #ifdef _WIN64 - SLJIT_COMPILE_ASSERT( + SLJIT_ASSERT( reg_map[SLJIT_R0] == 0 && reg_map[SLJIT_R1] == 2 - && reg_map[TMP_REG1] > 7, - invalid_register_assignment_for_div_mul); + && reg_map[TMP_REG1] > 7); #else - SLJIT_COMPILE_ASSERT( + SLJIT_ASSERT( reg_map[SLJIT_R0] == 0 && reg_map[SLJIT_R1] < 7 - && reg_map[TMP_REG1] == 2, - invalid_register_assignment_for_div_mul); + && reg_map[TMP_REG1] == 2); #endif compiler->mode32 = op & SLJIT_I32_OP; #endif @@ -909,9 +916,6 @@ static sljit_s32 emit_mov_byte(struct sljit_compiler *compiler, sljit_s32 sign, compiler->mode32 = 0; #endif - if (dst == SLJIT_UNUSED && !(src & SLJIT_MEM)) - return SLJIT_SUCCESS; /* Empty instruction. */ - if (src & SLJIT_IMM) { if (FAST_IS_REG(dst)) { #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) @@ -1040,6 +1044,30 @@ static sljit_s32 emit_mov_byte(struct sljit_compiler *compiler, sljit_s32 sign, return SLJIT_SUCCESS; } +static sljit_s32 emit_prefetch(struct sljit_compiler *compiler, sljit_s32 op, + sljit_s32 src, sljit_sw srcw) +{ + sljit_u8* inst; + +#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) + compiler->mode32 = 1; +#endif + + inst = emit_x86_instruction(compiler, 2, 0, 0, src, srcw); + FAIL_IF(!inst); + *inst++ = GROUP_0F; + *inst++ = PREFETCH; + + if (op >= SLJIT_MOV_U8 && op <= SLJIT_MOV_S8) + *inst |= (3 << 3); + else if (op >= SLJIT_MOV_U16 && op <= SLJIT_MOV_S16) + *inst |= (2 << 3); + else + *inst |= (1 << 3); + + return SLJIT_SUCCESS; +} + static sljit_s32 emit_mov_half(struct sljit_compiler *compiler, sljit_s32 sign, sljit_s32 dst, sljit_sw dstw, sljit_s32 src, sljit_sw srcw) @@ -1051,9 +1079,6 @@ static sljit_s32 emit_mov_half(struct sljit_compiler *compiler, sljit_s32 sign, compiler->mode32 = 0; #endif - if (dst == SLJIT_UNUSED && !(src & SLJIT_MEM)) - return SLJIT_SUCCESS; /* Empty instruction. */ - if (src & SLJIT_IMM) { if (FAST_IS_REG(dst)) { #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) @@ -1097,14 +1122,6 @@ static sljit_s32 emit_unary(struct sljit_compiler *compiler, sljit_u8 opcode, { sljit_u8* inst; - if (dst == SLJIT_UNUSED) { - EMIT_MOV(compiler, TMP_REG1, 0, src, srcw); - inst = emit_x86_instruction(compiler, 1, 0, 0, TMP_REG1, 0); - FAIL_IF(!inst); - *inst++ = GROUP_F7; - *inst |= opcode; - return SLJIT_SUCCESS; - } if (dst == src && dstw == srcw) { /* Same input and output */ inst = emit_x86_instruction(compiler, 1, 0, 0, dst, dstw); @@ -1113,14 +1130,19 @@ static sljit_s32 emit_unary(struct sljit_compiler *compiler, sljit_u8 opcode, *inst |= opcode; return SLJIT_SUCCESS; } + + if (SLJIT_UNLIKELY(dst == SLJIT_UNUSED)) + dst = TMP_REG1; + if (FAST_IS_REG(dst)) { EMIT_MOV(compiler, dst, 0, src, srcw); - inst = emit_x86_instruction(compiler, 1, 0, 0, dst, dstw); + inst = emit_x86_instruction(compiler, 1, 0, 0, dst, 0); FAIL_IF(!inst); *inst++ = GROUP_F7; *inst |= opcode; return SLJIT_SUCCESS; } + EMIT_MOV(compiler, TMP_REG1, 0, src, srcw); inst = emit_x86_instruction(compiler, 1, 0, 0, TMP_REG1, 0); FAIL_IF(!inst); @@ -1136,20 +1158,12 @@ static sljit_s32 emit_not_with_flags(struct sljit_compiler *compiler, { sljit_u8* inst; - if (dst == SLJIT_UNUSED) { - EMIT_MOV(compiler, TMP_REG1, 0, src, srcw); - inst = emit_x86_instruction(compiler, 1, 0, 0, TMP_REG1, 0); - FAIL_IF(!inst); - *inst++ = GROUP_F7; - *inst |= NOT_rm; - inst = emit_x86_instruction(compiler, 1, TMP_REG1, 0, TMP_REG1, 0); - FAIL_IF(!inst); - *inst = OR_r_rm; - return SLJIT_SUCCESS; - } + if (dst == SLJIT_UNUSED) + dst = TMP_REG1; + if (FAST_IS_REG(dst)) { EMIT_MOV(compiler, dst, 0, src, srcw); - inst = emit_x86_instruction(compiler, 1, 0, 0, dst, dstw); + inst = emit_x86_instruction(compiler, 1, 0, 0, dst, 0); FAIL_IF(!inst); *inst++ = GROUP_F7; *inst |= NOT_rm; @@ -1158,6 +1172,7 @@ static sljit_s32 emit_not_with_flags(struct sljit_compiler *compiler, *inst = OR_r_rm; return SLJIT_SUCCESS; } + EMIT_MOV(compiler, TMP_REG1, 0, src, srcw); inst = emit_x86_instruction(compiler, 1, 0, 0, TMP_REG1, 0); FAIL_IF(!inst); @@ -1170,6 +1185,10 @@ static sljit_s32 emit_not_with_flags(struct sljit_compiler *compiler, return SLJIT_SUCCESS; } +#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) +static const sljit_sw emit_clz_arg = 32 + 31; +#endif + static sljit_s32 emit_clz(struct sljit_compiler *compiler, sljit_s32 op_flags, sljit_s32 dst, sljit_sw dstw, sljit_s32 src, sljit_sw srcw) @@ -1178,104 +1197,54 @@ static sljit_s32 emit_clz(struct sljit_compiler *compiler, sljit_s32 op_flags, sljit_s32 dst_r; SLJIT_UNUSED_ARG(op_flags); - if (SLJIT_UNLIKELY(dst == SLJIT_UNUSED)) { - /* Just set the zero flag. */ - EMIT_MOV(compiler, TMP_REG1, 0, src, srcw); - inst = emit_x86_instruction(compiler, 1, 0, 0, TMP_REG1, 0); - FAIL_IF(!inst); - *inst++ = GROUP_F7; - *inst |= NOT_rm; -#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) - inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, SLJIT_IMM, 31, TMP_REG1, 0); -#else - inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, SLJIT_IMM, !(op_flags & SLJIT_I32_OP) ? 63 : 31, TMP_REG1, 0); -#endif - FAIL_IF(!inst); - *inst |= SHR; - return SLJIT_SUCCESS; - } - if (SLJIT_UNLIKELY(src & SLJIT_IMM)) { - EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_IMM, srcw); - src = TMP_REG1; - srcw = 0; - } + if (cpu_has_cmov == -1) + get_cpu_features(); - inst = emit_x86_instruction(compiler, 2, TMP_REG1, 0, src, srcw); + dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1; + + inst = emit_x86_instruction(compiler, 2, dst_r, 0, src, srcw); FAIL_IF(!inst); *inst++ = GROUP_0F; *inst = BSR_r_rm; #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) - if (FAST_IS_REG(dst)) - dst_r = dst; - else { - /* Find an unused temporary register. */ - if ((dst & REG_MASK) != SLJIT_R0 && (dst & OFFS_REG_MASK) != TO_OFFS_REG(SLJIT_R0)) - dst_r = SLJIT_R0; - else if ((dst & REG_MASK) != SLJIT_R1 && (dst & OFFS_REG_MASK) != TO_OFFS_REG(SLJIT_R1)) - dst_r = SLJIT_R1; + if (cpu_has_cmov) { + if (dst_r != TMP_REG1) { + EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_IMM, 32 + 31); + inst = emit_x86_instruction(compiler, 2, dst_r, 0, TMP_REG1, 0); + } else - dst_r = SLJIT_R2; - EMIT_MOV(compiler, dst, dstw, dst_r, 0); - } - EMIT_MOV(compiler, dst_r, 0, SLJIT_IMM, 32 + 31); -#else - dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2; - compiler->mode32 = 0; - EMIT_MOV(compiler, dst_r, 0, SLJIT_IMM, !(op_flags & SLJIT_I32_OP) ? 64 + 63 : 32 + 31); - compiler->mode32 = op_flags & SLJIT_I32_OP; -#endif + inst = emit_x86_instruction(compiler, 2, dst_r, 0, SLJIT_MEM0(), (sljit_sw)&emit_clz_arg); - if (cpu_has_cmov == -1) - get_cpu_features(); - - if (cpu_has_cmov) { - inst = emit_x86_instruction(compiler, 2, dst_r, 0, TMP_REG1, 0); FAIL_IF(!inst); *inst++ = GROUP_0F; - *inst = CMOVNE_r_rm; - } else { -#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) - inst = (sljit_u8*)ensure_buf(compiler, 1 + 4); - FAIL_IF(!inst); - INC_SIZE(4); + *inst = CMOVE_r_rm; + } + else + FAIL_IF(sljit_emit_cmov_generic(compiler, SLJIT_EQUAL, dst_r, SLJIT_IMM, 32 + 31)); - *inst++ = JE_i8; - *inst++ = 2; - *inst++ = MOV_r_rm; - *inst++ = MOD_REG | (reg_map[dst_r] << 3) | reg_map[TMP_REG1]; + inst = emit_x86_instruction(compiler, 1 | EX86_BIN_INS, SLJIT_IMM, 31, dst_r, 0); #else - inst = (sljit_u8*)ensure_buf(compiler, 1 + 5); - FAIL_IF(!inst); - INC_SIZE(5); + if (cpu_has_cmov) { + EMIT_MOV(compiler, TMP_REG2, 0, SLJIT_IMM, !(op_flags & SLJIT_I32_OP) ? (64 + 63) : (32 + 31)); - *inst++ = JE_i8; - *inst++ = 3; - *inst++ = REX_W | (reg_map[dst_r] >= 8 ? REX_R : 0) | (reg_map[TMP_REG1] >= 8 ? REX_B : 0); - *inst++ = MOV_r_rm; - *inst++ = MOD_REG | (reg_lmap[dst_r] << 3) | reg_lmap[TMP_REG1]; -#endif + inst = emit_x86_instruction(compiler, 2, dst_r, 0, TMP_REG2, 0); + FAIL_IF(!inst); + *inst++ = GROUP_0F; + *inst = CMOVE_r_rm; } + else + FAIL_IF(sljit_emit_cmov_generic(compiler, SLJIT_EQUAL, dst_r, SLJIT_IMM, !(op_flags & SLJIT_I32_OP) ? (64 + 63) : (32 + 31))); -#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) - inst = emit_x86_instruction(compiler, 1 | EX86_BIN_INS, SLJIT_IMM, 31, dst_r, 0); -#else inst = emit_x86_instruction(compiler, 1 | EX86_BIN_INS, SLJIT_IMM, !(op_flags & SLJIT_I32_OP) ? 63 : 31, dst_r, 0); #endif + FAIL_IF(!inst); *(inst + 1) |= XOR; -#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) - if (dst & SLJIT_MEM) { - inst = emit_x86_instruction(compiler, 1, dst_r, 0, dst, dstw); - FAIL_IF(!inst); - *inst = XCHG_r_rm; - } -#else if (dst & SLJIT_MEM) - EMIT_MOV(compiler, dst, dstw, TMP_REG2, 0); -#endif + EMIT_MOV(compiler, dst, dstw, TMP_REG1, 0); return SLJIT_SUCCESS; } @@ -1283,14 +1252,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile sljit_s32 dst, sljit_sw dstw, sljit_s32 src, sljit_sw srcw) { - sljit_u8* inst; - sljit_s32 update = 0; sljit_s32 op_flags = GET_ALL_FLAGS(op); #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) sljit_s32 dst_is_ereg = 0; - sljit_s32 src_is_ereg = 0; -#else -# define src_is_ereg 0 #endif CHECK_ERROR(); @@ -1299,40 +1263,42 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile ADJUST_LOCAL_OFFSET(src, srcw); CHECK_EXTRA_REGS(dst, dstw, dst_is_ereg = 1); - CHECK_EXTRA_REGS(src, srcw, src_is_ereg = 1); + CHECK_EXTRA_REGS(src, srcw, (void)0); #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) compiler->mode32 = op_flags & SLJIT_I32_OP; #endif + if (dst == SLJIT_UNUSED && !HAS_FLAGS(op)) { + if (op <= SLJIT_MOV_P && (src & SLJIT_MEM)) + return emit_prefetch(compiler, op, src, srcw); + return SLJIT_SUCCESS; + } + op = GET_OPCODE(op); - if (op >= SLJIT_MOV && op <= SLJIT_MOVU_P) { + + if (op >= SLJIT_MOV && op <= SLJIT_MOV_P) { #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) compiler->mode32 = 0; #endif + if (FAST_IS_REG(src) && src == dst) { + if (!TYPE_CAST_NEEDED(op)) + return SLJIT_SUCCESS; + } + if (op_flags & SLJIT_I32_OP) { - if (FAST_IS_REG(src) && src == dst) { - if (!TYPE_CAST_NEEDED(op)) - return SLJIT_SUCCESS; - } #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) - if (op == SLJIT_MOV_S32 && (src & SLJIT_MEM)) - op = SLJIT_MOV_U32; - if (op == SLJIT_MOVU_S32 && (src & SLJIT_MEM)) - op = SLJIT_MOVU_U32; - if (op == SLJIT_MOV_U32 && (src & SLJIT_IMM)) - op = SLJIT_MOV_S32; - if (op == SLJIT_MOVU_U32 && (src & SLJIT_IMM)) - op = SLJIT_MOVU_S32; + if (src & SLJIT_MEM) { + if (op == SLJIT_MOV_S32) + op = SLJIT_MOV_U32; + } + else if (src & SLJIT_IMM) { + if (op == SLJIT_MOV_U32) + op = SLJIT_MOV_S32; + } #endif } - SLJIT_COMPILE_ASSERT(SLJIT_MOV + 8 == SLJIT_MOVU, movu_offset); - if (op >= SLJIT_MOVU) { - update = 1; - op -= 8; - } - if (src & SLJIT_IMM) { switch (op) { case SLJIT_MOV_U8: @@ -1362,14 +1328,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile #endif } - if (SLJIT_UNLIKELY(update) && (src & SLJIT_MEM) && !src_is_ereg && (src & REG_MASK) && (srcw != 0 || (src & OFFS_REG_MASK) != 0)) { - inst = emit_x86_instruction(compiler, 1, src & REG_MASK, 0, src, srcw); - FAIL_IF(!inst); - *inst = LEA_r_m; - src &= SLJIT_MEM | 0xf; - srcw = 0; - } - #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) if (SLJIT_UNLIKELY(dst_is_ereg) && (!(op == SLJIT_MOV || op == SLJIT_MOV_U32 || op == SLJIT_MOV_S32 || op == SLJIT_MOV_P) || (src & SLJIT_MEM))) { SLJIT_ASSERT(dst == SLJIT_MEM1(SLJIT_SP)); @@ -1412,40 +1370,23 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile if (SLJIT_UNLIKELY(dst_is_ereg) && dst == TMP_REG1) return emit_mov(compiler, SLJIT_MEM1(SLJIT_SP), dstw, TMP_REG1, 0); #endif - - if (SLJIT_UNLIKELY(update) && (dst & SLJIT_MEM) && (dst & REG_MASK) && (dstw != 0 || (dst & OFFS_REG_MASK) != 0)) { - inst = emit_x86_instruction(compiler, 1, dst & REG_MASK, 0, dst, dstw); - FAIL_IF(!inst); - *inst = LEA_r_m; - } return SLJIT_SUCCESS; } - if (SLJIT_UNLIKELY(GET_FLAGS(op_flags))) - compiler->flags_saved = 0; - switch (op) { case SLJIT_NOT: - if (SLJIT_UNLIKELY(op_flags & SLJIT_SET_E)) + if (SLJIT_UNLIKELY(op_flags & SLJIT_SET_Z)) return emit_not_with_flags(compiler, dst, dstw, src, srcw); return emit_unary(compiler, NOT_rm, dst, dstw, src, srcw); case SLJIT_NEG: - if (SLJIT_UNLIKELY(op_flags & SLJIT_KEEP_FLAGS) && !compiler->flags_saved) - FAIL_IF(emit_save_flags(compiler)); return emit_unary(compiler, NEG_rm, dst, dstw, src, srcw); case SLJIT_CLZ: - if (SLJIT_UNLIKELY(op_flags & SLJIT_KEEP_FLAGS) && !compiler->flags_saved) - FAIL_IF(emit_save_flags(compiler)); return emit_clz(compiler, op_flags, dst, dstw, src, srcw); } return SLJIT_SUCCESS; - -#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) -# undef src_is_ereg -#endif } #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) @@ -1457,8 +1398,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile *(inst + 1) |= (op_imm); \ } \ else { \ - FAIL_IF(emit_load_imm64(compiler, TMP_REG2, immw)); \ - inst = emit_x86_instruction(compiler, 1, TMP_REG2, 0, arg, argw); \ + FAIL_IF(emit_load_imm64(compiler, (arg == TMP_REG1) ? TMP_REG2 : TMP_REG1, immw)); \ + inst = emit_x86_instruction(compiler, 1, (arg == TMP_REG1) ? TMP_REG2 : TMP_REG1, 0, arg, argw); \ FAIL_IF(!inst); \ *inst = (op_mr); \ } @@ -1479,12 +1420,16 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile #endif static sljit_s32 emit_cum_binary(struct sljit_compiler *compiler, - sljit_u8 op_rm, sljit_u8 op_mr, sljit_u8 op_imm, sljit_u8 op_eax_imm, + sljit_u32 op_types, sljit_s32 dst, sljit_sw dstw, sljit_s32 src1, sljit_sw src1w, sljit_s32 src2, sljit_sw src2w) { sljit_u8* inst; + sljit_u8 op_eax_imm = (op_types >> 24); + sljit_u8 op_rm = (op_types >> 16) & 0xff; + sljit_u8 op_mr = (op_types >> 8) & 0xff; + sljit_u8 op_imm = op_types & 0xff; if (dst == SLJIT_UNUSED) { EMIT_MOV(compiler, TMP_REG1, 0, src1, src1w); @@ -1595,12 +1540,16 @@ static sljit_s32 emit_cum_binary(struct sljit_compiler *compiler, } static sljit_s32 emit_non_cum_binary(struct sljit_compiler *compiler, - sljit_u8 op_rm, sljit_u8 op_mr, sljit_u8 op_imm, sljit_u8 op_eax_imm, + sljit_u32 op_types, sljit_s32 dst, sljit_sw dstw, sljit_s32 src1, sljit_sw src1w, sljit_s32 src2, sljit_sw src2w) { sljit_u8* inst; + sljit_u8 op_eax_imm = (op_types >> 24); + sljit_u8 op_rm = (op_types >> 16) & 0xff; + sljit_u8 op_mr = (op_types >> 8) & 0xff; + sljit_u8 op_imm = op_types & 0xff; if (dst == SLJIT_UNUSED) { EMIT_MOV(compiler, TMP_REG1, 0, src1, src1w); @@ -1684,7 +1633,7 @@ static sljit_s32 emit_mul(struct sljit_compiler *compiler, sljit_u8* inst; sljit_s32 dst_r; - dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1; + dst_r = SLOW_IS_REG(dst) ? dst : TMP_REG1; /* Register destination. */ if (dst_r == src1 && !(src2 & SLJIT_IMM)) { @@ -1736,9 +1685,9 @@ static sljit_s32 emit_mul(struct sljit_compiler *compiler, sljit_unaligned_store_s32(inst, (sljit_s32)src1w); } else { - EMIT_MOV(compiler, TMP_REG2, 0, SLJIT_IMM, src1w); if (dst_r != src2) EMIT_MOV(compiler, dst_r, 0, src2, src2w); + FAIL_IF(emit_load_imm64(compiler, TMP_REG2, src1w)); inst = emit_x86_instruction(compiler, 2, dst_r, 0, TMP_REG2, 0); FAIL_IF(!inst); *inst++ = GROUP_0F; @@ -1779,9 +1728,9 @@ static sljit_s32 emit_mul(struct sljit_compiler *compiler, sljit_unaligned_store_s32(inst, (sljit_s32)src2w); } else { - EMIT_MOV(compiler, TMP_REG2, 0, SLJIT_IMM, src2w); if (dst_r != src1) EMIT_MOV(compiler, dst_r, 0, src1, src1w); + FAIL_IF(emit_load_imm64(compiler, TMP_REG2, src2w)); inst = emit_x86_instruction(compiler, 2, dst_r, 0, TMP_REG2, 0); FAIL_IF(!inst); *inst++ = GROUP_0F; @@ -1800,13 +1749,13 @@ static sljit_s32 emit_mul(struct sljit_compiler *compiler, *inst = IMUL_r_rm; } - if (dst_r == TMP_REG1) + if (dst & SLJIT_MEM) EMIT_MOV(compiler, dst, dstw, TMP_REG1, 0); return SLJIT_SUCCESS; } -static sljit_s32 emit_lea_binary(struct sljit_compiler *compiler, sljit_s32 keep_flags, +static sljit_s32 emit_lea_binary(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_s32 src1, sljit_sw src1w, sljit_s32 src2, sljit_sw src2w) @@ -1815,12 +1764,10 @@ static sljit_s32 emit_lea_binary(struct sljit_compiler *compiler, sljit_s32 keep sljit_s32 dst_r, done = 0; /* These cases better be left to handled by normal way. */ - if (!keep_flags) { - if (dst == src1 && dstw == src1w) - return SLJIT_ERR_UNSUPPORTED; - if (dst == src2 && dstw == src2w) - return SLJIT_ERR_UNSUPPORTED; - } + if (dst == src1 && dstw == src1w) + return SLJIT_ERR_UNSUPPORTED; + if (dst == src2 && dstw == src2w) + return SLJIT_ERR_UNSUPPORTED; dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1; @@ -1932,7 +1879,7 @@ static sljit_s32 emit_test_binary(struct sljit_compiler *compiler, } #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) - if (src2 == SLJIT_R0 && (src2 & SLJIT_IMM) && (src1w > 127 || src1w < -128) && (compiler->mode32 || IS_HALFWORD(src1w))) { + if (src2 == SLJIT_R0 && (src1 & SLJIT_IMM) && (src1w > 127 || src1w < -128) && (compiler->mode32 || IS_HALFWORD(src1w))) { #else if (src2 == SLJIT_R0 && (src1 & SLJIT_IMM) && (src1w > 127 || src1w < -128)) { #endif @@ -1949,8 +1896,8 @@ static sljit_s32 emit_test_binary(struct sljit_compiler *compiler, *inst = GROUP_F7; } else { - FAIL_IF(emit_load_imm64(compiler, TMP_REG2, src2w)); - inst = emit_x86_instruction(compiler, 1, TMP_REG2, 0, src1, src1w); + FAIL_IF(emit_load_imm64(compiler, TMP_REG1, src2w)); + inst = emit_x86_instruction(compiler, 1, TMP_REG1, 0, src1, src1w); FAIL_IF(!inst); *inst = TEST_rm_r; } @@ -1978,8 +1925,8 @@ static sljit_s32 emit_test_binary(struct sljit_compiler *compiler, *inst = GROUP_F7; } else { - FAIL_IF(emit_load_imm64(compiler, TMP_REG2, src1w)); - inst = emit_x86_instruction(compiler, 1, TMP_REG2, 0, src2, src2w); + FAIL_IF(emit_load_imm64(compiler, TMP_REG1, src1w)); + inst = emit_x86_instruction(compiler, 1, TMP_REG1, 0, src2, src2w); FAIL_IF(!inst); *inst = TEST_rm_r; } @@ -2080,7 +2027,7 @@ static sljit_s32 emit_shift(struct sljit_compiler *compiler, *inst |= mode; EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, TMP_REG1, 0); } - else if (FAST_IS_REG(dst) && dst != src2 && !ADDRESSING_DEPENDS_ON(src2, dst)) { + else if (SLOW_IS_REG(dst) && dst != src2 && !ADDRESSING_DEPENDS_ON(src2, dst)) { if (src1 != dst) EMIT_MOV(compiler, dst, 0, src1, src1w); EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_PREF_SHIFT_REG, 0); @@ -2091,25 +2038,26 @@ static sljit_s32 emit_shift(struct sljit_compiler *compiler, EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, TMP_REG1, 0); } else { - /* This case is really difficult, since ecx itself may used for - addressing, and we must ensure to work even in that case. */ + /* This case is complex since ecx itself may be used for + addressing, and this case must be supported as well. */ EMIT_MOV(compiler, TMP_REG1, 0, src1, src1w); -#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) - EMIT_MOV(compiler, TMP_REG2, 0, SLJIT_PREF_SHIFT_REG, 0); +#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) + EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), 0, SLJIT_PREF_SHIFT_REG, 0); + EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, src2, src2w); + inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, SLJIT_PREF_SHIFT_REG, 0, TMP_REG1, 0); + FAIL_IF(!inst); + *inst |= mode; + EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, SLJIT_MEM1(SLJIT_SP), 0); #else - /* [esp+0] contains the flags. */ - EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), sizeof(sljit_sw), SLJIT_PREF_SHIFT_REG, 0); -#endif + EMIT_MOV(compiler, TMP_REG2, 0, SLJIT_PREF_SHIFT_REG, 0); EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, src2, src2w); inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, SLJIT_PREF_SHIFT_REG, 0, TMP_REG1, 0); FAIL_IF(!inst); *inst |= mode; -#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, TMP_REG2, 0); -#else - EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, SLJIT_MEM1(SLJIT_SP), sizeof(sljit_sw)); #endif - EMIT_MOV(compiler, dst, dstw, TMP_REG1, 0); + if (dst != SLJIT_UNUSED) + return emit_mov(compiler, dst, dstw, TMP_REG1, 0); } return SLJIT_SUCCESS; @@ -2133,7 +2081,7 @@ static sljit_s32 emit_shift_with_flags(struct sljit_compiler *compiler, if (!set_flags) return emit_mov(compiler, dst, dstw, src1, src1w); /* OR dst, src, 0 */ - return emit_cum_binary(compiler, OR_r_rm, OR_rm_r, OR, OR_EAX_i32, + return emit_cum_binary(compiler, BINARY_OPCODE(OR), dst, dstw, src1, src1w, SLJIT_IMM, 0); } @@ -2143,10 +2091,10 @@ static sljit_s32 emit_shift_with_flags(struct sljit_compiler *compiler, if (!FAST_IS_REG(dst)) FAIL_IF(emit_cmp_binary(compiler, src1, src1w, SLJIT_IMM, 0)); - FAIL_IF(emit_shift(compiler,mode, dst, dstw, src1, src1w, src2, src2w)); + FAIL_IF(emit_shift(compiler, mode, dst, dstw, src1, src1w, src2, src2w)); if (FAST_IS_REG(dst)) - return emit_cmp_binary(compiler, dst, dstw, SLJIT_IMM, 0); + return emit_cmp_binary(compiler, (dst == SLJIT_UNUSED) ? TMP_REG1 : dst, dstw, SLJIT_IMM, 0); return SLJIT_SUCCESS; } @@ -2168,77 +2116,54 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile compiler->mode32 = op & SLJIT_I32_OP; #endif - if (GET_OPCODE(op) >= SLJIT_MUL) { - if (SLJIT_UNLIKELY(GET_FLAGS(op))) - compiler->flags_saved = 0; - else if (SLJIT_UNLIKELY(op & SLJIT_KEEP_FLAGS) && !compiler->flags_saved) - FAIL_IF(emit_save_flags(compiler)); - } + if (dst == SLJIT_UNUSED && !HAS_FLAGS(op)) + return SLJIT_SUCCESS; switch (GET_OPCODE(op)) { case SLJIT_ADD: - if (!GET_FLAGS(op)) { - if (emit_lea_binary(compiler, op & SLJIT_KEEP_FLAGS, dst, dstw, src1, src1w, src2, src2w) != SLJIT_ERR_UNSUPPORTED) + if (!HAS_FLAGS(op)) { + if (emit_lea_binary(compiler, dst, dstw, src1, src1w, src2, src2w) != SLJIT_ERR_UNSUPPORTED) return compiler->error; } - else - compiler->flags_saved = 0; - if (SLJIT_UNLIKELY(op & SLJIT_KEEP_FLAGS) && !compiler->flags_saved) - FAIL_IF(emit_save_flags(compiler)); - return emit_cum_binary(compiler, ADD_r_rm, ADD_rm_r, ADD, ADD_EAX_i32, + return emit_cum_binary(compiler, BINARY_OPCODE(ADD), dst, dstw, src1, src1w, src2, src2w); case SLJIT_ADDC: - if (SLJIT_UNLIKELY(compiler->flags_saved)) /* C flag must be restored. */ - FAIL_IF(emit_restore_flags(compiler, 1)); - else if (SLJIT_UNLIKELY(op & SLJIT_KEEP_FLAGS)) - FAIL_IF(emit_save_flags(compiler)); - if (SLJIT_UNLIKELY(GET_FLAGS(op))) - compiler->flags_saved = 0; - return emit_cum_binary(compiler, ADC_r_rm, ADC_rm_r, ADC, ADC_EAX_i32, + return emit_cum_binary(compiler, BINARY_OPCODE(ADC), dst, dstw, src1, src1w, src2, src2w); case SLJIT_SUB: - if (!GET_FLAGS(op)) { - if ((src2 & SLJIT_IMM) && emit_lea_binary(compiler, op & SLJIT_KEEP_FLAGS, dst, dstw, src1, src1w, SLJIT_IMM, -src2w) != SLJIT_ERR_UNSUPPORTED) + if (!HAS_FLAGS(op)) { + if ((src2 & SLJIT_IMM) && emit_lea_binary(compiler, dst, dstw, src1, src1w, SLJIT_IMM, -src2w) != SLJIT_ERR_UNSUPPORTED) return compiler->error; } - else - compiler->flags_saved = 0; - if (SLJIT_UNLIKELY(op & SLJIT_KEEP_FLAGS) && !compiler->flags_saved) - FAIL_IF(emit_save_flags(compiler)); + if (dst == SLJIT_UNUSED) return emit_cmp_binary(compiler, src1, src1w, src2, src2w); - return emit_non_cum_binary(compiler, SUB_r_rm, SUB_rm_r, SUB, SUB_EAX_i32, + return emit_non_cum_binary(compiler, BINARY_OPCODE(SUB), dst, dstw, src1, src1w, src2, src2w); case SLJIT_SUBC: - if (SLJIT_UNLIKELY(compiler->flags_saved)) /* C flag must be restored. */ - FAIL_IF(emit_restore_flags(compiler, 1)); - else if (SLJIT_UNLIKELY(op & SLJIT_KEEP_FLAGS)) - FAIL_IF(emit_save_flags(compiler)); - if (SLJIT_UNLIKELY(GET_FLAGS(op))) - compiler->flags_saved = 0; - return emit_non_cum_binary(compiler, SBB_r_rm, SBB_rm_r, SBB, SBB_EAX_i32, + return emit_non_cum_binary(compiler, BINARY_OPCODE(SBB), dst, dstw, src1, src1w, src2, src2w); case SLJIT_MUL: return emit_mul(compiler, dst, dstw, src1, src1w, src2, src2w); case SLJIT_AND: if (dst == SLJIT_UNUSED) return emit_test_binary(compiler, src1, src1w, src2, src2w); - return emit_cum_binary(compiler, AND_r_rm, AND_rm_r, AND, AND_EAX_i32, + return emit_cum_binary(compiler, BINARY_OPCODE(AND), dst, dstw, src1, src1w, src2, src2w); case SLJIT_OR: - return emit_cum_binary(compiler, OR_r_rm, OR_rm_r, OR, OR_EAX_i32, + return emit_cum_binary(compiler, BINARY_OPCODE(OR), dst, dstw, src1, src1w, src2, src2w); case SLJIT_XOR: - return emit_cum_binary(compiler, XOR_r_rm, XOR_rm_r, XOR, XOR_EAX_i32, + return emit_cum_binary(compiler, BINARY_OPCODE(XOR), dst, dstw, src1, src1w, src2, src2w); case SLJIT_SHL: - return emit_shift_with_flags(compiler, SHL, GET_FLAGS(op), + return emit_shift_with_flags(compiler, SHL, HAS_FLAGS(op), dst, dstw, src1, src1w, src2, src2w); case SLJIT_LSHR: - return emit_shift_with_flags(compiler, SHR, GET_FLAGS(op), + return emit_shift_with_flags(compiler, SHR, HAS_FLAGS(op), dst, dstw, src1, src1w, src2, src2w); case SLJIT_ASHR: - return emit_shift_with_flags(compiler, SAR, GET_FLAGS(op), + return emit_shift_with_flags(compiler, SAR, HAS_FLAGS(op), dst, dstw, src1, src1w, src2, src2w); } @@ -2249,7 +2174,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 reg) { CHECK_REG_INDEX(check_sljit_get_register_index(reg)); #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) - if (reg >= SLJIT_R3 && reg <= SLJIT_R6) + if (reg >= SLJIT_R3 && reg <= SLJIT_R8) return -1; #endif return reg_map[reg]; @@ -2258,7 +2183,11 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 reg) SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_float_register_index(sljit_s32 reg) { CHECK_REG_INDEX(check_sljit_get_float_register_index(reg)); +#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) return reg; +#else + return freg_map[reg]; +#endif } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *compiler, @@ -2280,36 +2209,25 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *c /* Floating point operators */ /* --------------------------------------------------------------------- */ -/* Alignment + 2 * 16 bytes. */ -static sljit_s32 sse2_data[3 + (4 + 4) * 2]; +/* Alignment(3) + 4 * 16 bytes. */ +static sljit_s32 sse2_data[3 + (4 * 4)]; static sljit_s32 *sse2_buffer; static void init_compiler(void) { + /* Align to 16 bytes. */ sse2_buffer = (sljit_s32*)(((sljit_uw)sse2_data + 15) & ~0xf); - /* Single precision constants. */ + + /* Single precision constants (each constant is 16 byte long). */ sse2_buffer[0] = 0x80000000; sse2_buffer[4] = 0x7fffffff; - /* Double precision constants. */ + /* Double precision constants (each constant is 16 byte long). */ sse2_buffer[8] = 0; sse2_buffer[9] = 0x80000000; sse2_buffer[12] = 0xffffffff; sse2_buffer[13] = 0x7fffffff; } -SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_is_fpu_available(void) -{ -#ifdef SLJIT_IS_FPU_AVAILABLE - return SLJIT_IS_FPU_AVAILABLE; -#elif (defined SLJIT_DETECT_SSE2 && SLJIT_DETECT_SSE2) - if (cpu_has_sse2 == -1) - get_cpu_features(); - return cpu_has_sse2; -#else /* SLJIT_DETECT_SSE2 */ - return 1; -#endif /* SLJIT_DETECT_SSE2 */ -} - static sljit_s32 emit_sse2(struct sljit_compiler *compiler, sljit_u8 opcode, sljit_s32 single, sljit_s32 xmm1, sljit_s32 xmm2, sljit_sw xmm2w) { @@ -2350,7 +2268,7 @@ static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_sw_from_f64(struct sljit_comp sljit_s32 dst, sljit_sw dstw, sljit_s32 src, sljit_sw srcw) { - sljit_s32 dst_r = SLOW_IS_REG(dst) ? dst : TMP_REG1; + sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1; sljit_u8 *inst; #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) @@ -2363,7 +2281,7 @@ static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_sw_from_f64(struct sljit_comp *inst++ = GROUP_0F; *inst = CVTTSD2SI_r_xm; - if (dst_r == TMP_REG1 && dst != SLJIT_UNUSED) + if (dst & SLJIT_MEM) return emit_mov(compiler, dst, dstw, TMP_REG1, 0); return SLJIT_SUCCESS; } @@ -2407,11 +2325,11 @@ static SLJIT_INLINE sljit_s32 sljit_emit_fop1_cmp(struct sljit_compiler *compile sljit_s32 src1, sljit_sw src1w, sljit_s32 src2, sljit_sw src2w) { - compiler->flags_saved = 0; if (!FAST_IS_REG(src1)) { FAIL_IF(emit_sse2_load(compiler, op & SLJIT_F32_OP, TMP_FREG, src1, src1w)); src1 = TMP_FREG; } + return emit_sse2_logic(compiler, UCOMISD_x_xm, !(op & SLJIT_F32_OP), src1, src2, src2w); } @@ -2456,7 +2374,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop1(struct sljit_compiler *compil return SLJIT_SUCCESS; } - if (SLOW_IS_REG(dst)) { + if (FAST_IS_REG(dst)) { dst_r = dst; if (dst != src) FAIL_IF(emit_sse2_load(compiler, op & SLJIT_F32_OP, dst_r, src, srcw)); @@ -2554,11 +2472,6 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compi CHECK_ERROR_PTR(); CHECK_PTR(check_sljit_emit_label(compiler)); - /* We should restore the flags before the label, - since other taken jumps has their own flags as well. */ - if (SLJIT_UNLIKELY(compiler->flags_saved)) - PTR_FAIL_IF(emit_restore_flags(compiler, 0)); - if (compiler->last_label && compiler->last_label->size == compiler->size) return compiler->last_label; @@ -2583,20 +2496,11 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compile CHECK_ERROR_PTR(); CHECK_PTR(check_sljit_emit_jump(compiler, type)); - if (SLJIT_UNLIKELY(compiler->flags_saved)) { - if ((type & 0xff) <= SLJIT_JUMP) - PTR_FAIL_IF(emit_restore_flags(compiler, 0)); - compiler->flags_saved = 0; - } - jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump)); PTR_FAIL_IF_NULL(jump); set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP); type &= 0xff; - if (type >= SLJIT_CALL1) - PTR_FAIL_IF(call_with_args(compiler, type)); - /* Worst case size. */ #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) compiler->size += (type >= SLJIT_JUMP) ? 5 : 6; @@ -2623,32 +2527,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compi CHECK_EXTRA_REGS(src, srcw, (void)0); - if (SLJIT_UNLIKELY(compiler->flags_saved)) { - if (type <= SLJIT_JUMP) - FAIL_IF(emit_restore_flags(compiler, 0)); - compiler->flags_saved = 0; - } - - if (type >= SLJIT_CALL1) { -#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) -#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL) - if (src == SLJIT_R2) { - EMIT_MOV(compiler, TMP_REG1, 0, src, 0); - src = TMP_REG1; - } - if (src == SLJIT_MEM1(SLJIT_SP) && type >= SLJIT_CALL3) - srcw += sizeof(sljit_sw); -#endif -#endif -#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) && defined(_WIN64) - if (src == SLJIT_R2) { - EMIT_MOV(compiler, TMP_REG1, 0, src, 0); - src = TMP_REG1; - } -#endif - FAIL_IF(call_with_args(compiler, type)); - } - if (src == SLJIT_IMM) { jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump)); FAIL_IF_NULL(jump); @@ -2683,37 +2561,29 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compi SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw dstw, - sljit_s32 src, sljit_sw srcw, sljit_s32 type) { sljit_u8 *inst; sljit_u8 cond_set = 0; #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) sljit_s32 reg; -#else - /* CHECK_EXTRA_REGS migh overwrite these values. */ +#endif + /* ADJUST_LOCAL_OFFSET and CHECK_EXTRA_REGS might overwrite these values. */ sljit_s32 dst_save = dst; sljit_sw dstw_save = dstw; -#endif CHECK_ERROR(); - CHECK(check_sljit_emit_op_flags(compiler, op, dst, dstw, src, srcw, type)); - SLJIT_UNUSED_ARG(srcw); - - if (dst == SLJIT_UNUSED) - return SLJIT_SUCCESS; + CHECK(check_sljit_emit_op_flags(compiler, op, dst, dstw, type)); ADJUST_LOCAL_OFFSET(dst, dstw); CHECK_EXTRA_REGS(dst, dstw, (void)0); - if (SLJIT_UNLIKELY(compiler->flags_saved)) - FAIL_IF(emit_restore_flags(compiler, op & SLJIT_KEEP_FLAGS)); type &= 0xff; /* setcc = jcc + 0x10. */ cond_set = get_jump_code(type) + 0x10; #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) - if (GET_OPCODE(op) == SLJIT_OR && !GET_ALL_FLAGS(op) && FAST_IS_REG(dst) && dst == src) { + if (GET_OPCODE(op) == SLJIT_OR && !GET_ALL_FLAGS(op) && FAST_IS_REG(dst)) { inst = (sljit_u8*)ensure_buf(compiler, 1 + 4 + 3); FAIL_IF(!inst); INC_SIZE(4 + 3); @@ -2728,7 +2598,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *co return SLJIT_SUCCESS; } - reg = (op == SLJIT_MOV && FAST_IS_REG(dst)) ? dst : TMP_REG1; + reg = (GET_OPCODE(op) < SLJIT_ADD && FAST_IS_REG(dst)) ? dst : TMP_REG1; inst = (sljit_u8*)ensure_buf(compiler, 1 + 4 + 4); FAIL_IF(!inst); @@ -2739,6 +2609,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *co *inst++ = cond_set; *inst++ = MOD_REG | reg_lmap[reg]; *inst++ = REX_W | (reg_map[reg] <= 7 ? 0 : (REX_B | REX_R)); + /* The movzx instruction does not affect flags. */ *inst++ = GROUP_0F; *inst++ = MOVZX_r_rm8; *inst = MOD_REG | (reg_lmap[reg] << 3) | reg_lmap[reg]; @@ -2750,12 +2621,15 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *co compiler->mode32 = GET_OPCODE(op) != SLJIT_MOV; return emit_mov(compiler, dst, dstw, TMP_REG1, 0); } + #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \ || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) compiler->skip_checks = 1; #endif - return sljit_emit_op2(compiler, op, dst, dstw, dst, dstw, TMP_REG1, 0); -#else /* SLJIT_CONFIG_X86_64 */ + return sljit_emit_op2(compiler, op, dst_save, dstw_save, dst_save, dstw_save, TMP_REG1, 0); + +#else + /* The SLJIT_CONFIG_X86_32 code path starts here. */ if (GET_OPCODE(op) < SLJIT_ADD && FAST_IS_REG(dst)) { if (reg_map[dst] <= 4) { /* Low byte is accessible. */ @@ -2809,8 +2683,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *co return SLJIT_SUCCESS; } - if (GET_OPCODE(op) == SLJIT_OR && !GET_ALL_FLAGS(op) && FAST_IS_REG(dst) && dst == src && reg_map[dst] <= 4) { - SLJIT_COMPILE_ASSERT(reg_map[SLJIT_R0] == 0, scratch_reg1_must_be_eax); + if (GET_OPCODE(op) == SLJIT_OR && !GET_ALL_FLAGS(op) && FAST_IS_REG(dst) && reg_map[dst] <= 4) { + SLJIT_ASSERT(reg_map[SLJIT_R0] == 0); + if (dst != SLJIT_R0) { inst = (sljit_u8*)ensure_buf(compiler, 1 + 1 + 3 + 2 + 1); FAIL_IF(!inst); @@ -2869,6 +2744,46 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *co #endif /* SLJIT_CONFIG_X86_64 */ } +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 dst_reg, + sljit_s32 src, sljit_sw srcw) +{ + sljit_u8* inst; + + CHECK_ERROR(); + CHECK(check_sljit_emit_cmov(compiler, type, dst_reg, src, srcw)); + +#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) + dst_reg &= ~SLJIT_I32_OP; + + if (!sljit_has_cpu_feature(SLJIT_HAS_CMOV) || (dst_reg >= SLJIT_R3 && dst_reg <= SLJIT_S3)) + return sljit_emit_cmov_generic(compiler, type, dst_reg, src, srcw); +#else + if (!sljit_has_cpu_feature(SLJIT_HAS_CMOV)) + return sljit_emit_cmov_generic(compiler, type, dst_reg, src, srcw); +#endif + + /* ADJUST_LOCAL_OFFSET is not needed. */ + CHECK_EXTRA_REGS(src, srcw, (void)0); + +#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) + compiler->mode32 = dst_reg & SLJIT_I32_OP; + dst_reg &= ~SLJIT_I32_OP; +#endif + + if (SLJIT_UNLIKELY(src & SLJIT_IMM)) { + EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_IMM, srcw); + src = TMP_REG1; + srcw = 0; + } + + inst = emit_x86_instruction(compiler, 2, dst_reg, 0, src, srcw); + FAIL_IF(!inst); + *inst++ = GROUP_0F; + *inst = get_jump_code(type & 0xff) - 0x40; + return SLJIT_SUCCESS; +} + SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_local_base(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw offset) { CHECK_ERROR(); @@ -2887,16 +2802,16 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_local_base(struct sljit_compiler *c if (NOT_HALFWORD(offset)) { FAIL_IF(emit_load_imm64(compiler, TMP_REG1, offset)); #if (defined SLJIT_DEBUG && SLJIT_DEBUG) - SLJIT_ASSERT(emit_lea_binary(compiler, SLJIT_KEEP_FLAGS, dst, dstw, SLJIT_SP, 0, TMP_REG1, 0) != SLJIT_ERR_UNSUPPORTED); + SLJIT_ASSERT(emit_lea_binary(compiler, dst, dstw, SLJIT_SP, 0, TMP_REG1, 0) != SLJIT_ERR_UNSUPPORTED); return compiler->error; #else - return emit_lea_binary(compiler, SLJIT_KEEP_FLAGS, dst, dstw, SLJIT_SP, 0, TMP_REG1, 0); + return emit_lea_binary(compiler, dst, dstw, SLJIT_SP, 0, TMP_REG1, 0); #endif } #endif if (offset != 0) - return emit_lea_binary(compiler, SLJIT_KEEP_FLAGS, dst, dstw, SLJIT_SP, 0, SLJIT_IMM, offset); + return emit_lea_binary(compiler, dst, dstw, SLJIT_SP, 0, SLJIT_IMM, offset); return emit_mov(compiler, dst, dstw, SLJIT_SP, 0); } @@ -2920,14 +2835,11 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compi #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) compiler->mode32 = 0; - reg = SLOW_IS_REG(dst) ? dst : TMP_REG1; + reg = FAST_IS_REG(dst) ? dst : TMP_REG1; if (emit_load_imm64(compiler, reg, init_value)) return NULL; #else - if (dst == SLJIT_UNUSED) - dst = TMP_REG1; - if (emit_mov(compiler, dst, dstw, SLJIT_IMM, init_value)) return NULL; #endif @@ -2962,69 +2874,3 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_consta SLJIT_UNUSED_ARG(executable_offset); sljit_unaligned_store_sw((void*)addr, new_constant); } - -SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_x86_is_sse2_available(void) -{ -#if (defined SLJIT_DETECT_SSE2 && SLJIT_DETECT_SSE2) - if (cpu_has_sse2 == -1) - get_cpu_features(); - return cpu_has_sse2; -#else - return 1; -#endif -} - -SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_x86_is_cmov_available(void) -{ - if (cpu_has_cmov == -1) - get_cpu_features(); - return cpu_has_cmov; -} - -SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_x86_emit_cmov(struct sljit_compiler *compiler, - sljit_s32 type, - sljit_s32 dst_reg, - sljit_s32 src, sljit_sw srcw) -{ - sljit_u8* inst; - - CHECK_ERROR(); -#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) - CHECK_ARGUMENT(sljit_x86_is_cmov_available()); - CHECK_ARGUMENT(!(type & ~(0xff | SLJIT_I32_OP))); - CHECK_ARGUMENT((type & 0xff) >= SLJIT_EQUAL && (type & 0xff) <= SLJIT_ORDERED_F64); - CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(dst_reg & ~SLJIT_I32_OP)); - FUNCTION_CHECK_SRC(src, srcw); -#endif -#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) - if (SLJIT_UNLIKELY(!!compiler->verbose)) { - fprintf(compiler->verbose, " x86_cmov%s %s%s, ", - !(dst_reg & SLJIT_I32_OP) ? "" : ".i", - jump_names[type & 0xff], JUMP_POSTFIX(type)); - sljit_verbose_reg(compiler, dst_reg & ~SLJIT_I32_OP); - fprintf(compiler->verbose, ", "); - sljit_verbose_param(compiler, src, srcw); - fprintf(compiler->verbose, "\n"); - } -#endif - - ADJUST_LOCAL_OFFSET(src, srcw); - CHECK_EXTRA_REGS(src, srcw, (void)0); - -#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) - compiler->mode32 = dst_reg & SLJIT_I32_OP; -#endif - dst_reg &= ~SLJIT_I32_OP; - - if (SLJIT_UNLIKELY(src & SLJIT_IMM)) { - EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_IMM, srcw); - src = TMP_REG1; - srcw = 0; - } - - inst = emit_x86_instruction(compiler, 2, dst_reg, 0, src, srcw); - FAIL_IF(!inst); - *inst++ = GROUP_0F; - *inst = get_jump_code(type & 0xff) - 0x40; - return SLJIT_SUCCESS; -} diff --git a/thirdparty/pcre2/src/sljit/sljitProtExecAllocator.c b/thirdparty/pcre2/src/sljit/sljitProtExecAllocator.c new file mode 100644 index 0000000000..8a5b2b3cfe --- /dev/null +++ b/thirdparty/pcre2/src/sljit/sljitProtExecAllocator.c @@ -0,0 +1,421 @@ +/* + * Stack-less Just-In-Time compiler + * + * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + This file contains a simple executable memory allocator + + It is assumed, that executable code blocks are usually medium (or sometimes + large) memory blocks, and the allocator is not too frequently called (less + optimized than other allocators). Thus, using it as a generic allocator is + not suggested. + + How does it work: + Memory is allocated in continuous memory areas called chunks by alloc_chunk() + Chunk format: + [ block ][ block ] ... [ block ][ block terminator ] + + All blocks and the block terminator is started with block_header. The block + header contains the size of the previous and the next block. These sizes + can also contain special values. + Block size: + 0 - The block is a free_block, with a different size member. + 1 - The block is a block terminator. + n - The block is used at the moment, and the value contains its size. + Previous block size: + 0 - This is the first block of the memory chunk. + n - The size of the previous block. + + Using these size values we can go forward or backward on the block chain. + The unused blocks are stored in a chain list pointed by free_blocks. This + list is useful if we need to find a suitable memory area when the allocator + is called. + + When a block is freed, the new free block is connected to its adjacent free + blocks if possible. + + [ free block ][ used block ][ free block ] + and "used block" is freed, the three blocks are connected together: + [ one big free block ] +*/ + +/* --------------------------------------------------------------------- */ +/* System (OS) functions */ +/* --------------------------------------------------------------------- */ + +/* 64 KByte. */ +#define CHUNK_SIZE 0x10000 + +struct chunk_header { + void *executable; + int fd; +}; + +/* + alloc_chunk / free_chunk : + * allocate executable system memory chunks + * the size is always divisible by CHUNK_SIZE + allocator_grab_lock / allocator_release_lock : + * make the allocator thread safe + * can be empty if the OS (or the application) does not support threading + * only the allocator requires this lock, sljit is fully thread safe + as it only uses local variables +*/ + +#include <fcntl.h> + +#ifndef O_NOATIME +#define O_NOATIME 0 +#endif + +#ifdef __O_TMPFILE +#ifndef O_TMPFILE +#define O_TMPFILE (__O_TMPFILE | O_DIRECTORY) +#endif +#endif + +int mkostemp(char *template, int flags); +char *secure_getenv(const char *name); + +static SLJIT_INLINE int create_tempfile(void) +{ + int fd; + + char tmp_name[256]; + size_t tmp_name_len; + char *dir; + size_t len; + +#ifdef P_tmpdir + len = (P_tmpdir != NULL) ? strlen(P_tmpdir) : 0; + + if (len > 0 && len < sizeof(tmp_name)) { + strcpy(tmp_name, P_tmpdir); + tmp_name_len = len; + } + else { + strcpy(tmp_name, "/tmp"); + tmp_name_len = 4; + } +#else + strcpy(tmp_name, "/tmp"); + tmp_name_len = 4; +#endif + + dir = secure_getenv("TMPDIR"); + if (dir) { + len = strlen(dir); + if (len > 0 && len < sizeof(tmp_name)) { + strcpy(tmp_name, dir); + tmp_name_len = len; + } + } + + SLJIT_ASSERT(tmp_name_len > 0 && tmp_name_len < sizeof(tmp_name)); + + while (tmp_name_len > 0 && tmp_name[tmp_name_len - 1] == '/') { + tmp_name_len--; + tmp_name[tmp_name_len] = '\0'; + } + +#ifdef O_TMPFILE + fd = open(tmp_name, O_TMPFILE | O_EXCL | O_RDWR | O_NOATIME | O_CLOEXEC, S_IRUSR | S_IWUSR); + if (fd != -1) + return fd; +#endif + + if (tmp_name_len + 7 >= sizeof(tmp_name)) + { + return -1; + } + + strcpy(tmp_name + tmp_name_len, "/XXXXXX"); + fd = mkostemp(tmp_name, O_CLOEXEC | O_NOATIME); + + if (fd == -1) + return fd; + + if (unlink(tmp_name)) { + close(fd); + return -1; + } + + return fd; +} + +static SLJIT_INLINE struct chunk_header* alloc_chunk(sljit_uw size) +{ + struct chunk_header *retval; + int fd; + + fd = create_tempfile(); + if (fd == -1) + return NULL; + + if (ftruncate(fd, size)) { + close(fd); + return NULL; + } + + retval = (struct chunk_header *)mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + + if (retval == MAP_FAILED) { + close(fd); + return NULL; + } + + retval->executable = mmap(NULL, size, PROT_READ | PROT_EXEC, MAP_SHARED, fd, 0); + + if (retval->executable == MAP_FAILED) { + munmap(retval, size); + close(fd); + return NULL; + } + + retval->fd = fd; + return retval; +} + +static SLJIT_INLINE void free_chunk(void *chunk, sljit_uw size) +{ + struct chunk_header *header = ((struct chunk_header *)chunk) - 1; + + int fd = header->fd; + munmap(header->executable, size); + munmap(header, size); + close(fd); +} + +/* --------------------------------------------------------------------- */ +/* Common functions */ +/* --------------------------------------------------------------------- */ + +#define CHUNK_MASK (~(CHUNK_SIZE - 1)) + +struct block_header { + sljit_uw size; + sljit_uw prev_size; + sljit_sw executable_offset; +}; + +struct free_block { + struct block_header header; + struct free_block *next; + struct free_block *prev; + sljit_uw size; +}; + +#define AS_BLOCK_HEADER(base, offset) \ + ((struct block_header*)(((sljit_u8*)base) + offset)) +#define AS_FREE_BLOCK(base, offset) \ + ((struct free_block*)(((sljit_u8*)base) + offset)) +#define MEM_START(base) ((void*)((base) + 1)) +#define ALIGN_SIZE(size) (((size) + sizeof(struct block_header) + 7) & ~7) + +static struct free_block* free_blocks; +static sljit_uw allocated_size; +static sljit_uw total_size; + +static SLJIT_INLINE void sljit_insert_free_block(struct free_block *free_block, sljit_uw size) +{ + free_block->header.size = 0; + free_block->size = size; + + free_block->next = free_blocks; + free_block->prev = NULL; + if (free_blocks) + free_blocks->prev = free_block; + free_blocks = free_block; +} + +static SLJIT_INLINE void sljit_remove_free_block(struct free_block *free_block) +{ + if (free_block->next) + free_block->next->prev = free_block->prev; + + if (free_block->prev) + free_block->prev->next = free_block->next; + else { + SLJIT_ASSERT(free_blocks == free_block); + free_blocks = free_block->next; + } +} + +SLJIT_API_FUNC_ATTRIBUTE void* sljit_malloc_exec(sljit_uw size) +{ + struct chunk_header *chunk_header; + struct block_header *header; + struct block_header *next_header; + struct free_block *free_block; + sljit_uw chunk_size; + sljit_sw executable_offset; + + allocator_grab_lock(); + if (size < (64 - sizeof(struct block_header))) + size = (64 - sizeof(struct block_header)); + size = ALIGN_SIZE(size); + + free_block = free_blocks; + while (free_block) { + if (free_block->size >= size) { + chunk_size = free_block->size; + if (chunk_size > size + 64) { + /* We just cut a block from the end of the free block. */ + chunk_size -= size; + free_block->size = chunk_size; + header = AS_BLOCK_HEADER(free_block, chunk_size); + header->prev_size = chunk_size; + header->executable_offset = free_block->header.executable_offset; + AS_BLOCK_HEADER(header, size)->prev_size = size; + } + else { + sljit_remove_free_block(free_block); + header = (struct block_header*)free_block; + size = chunk_size; + } + allocated_size += size; + header->size = size; + allocator_release_lock(); + return MEM_START(header); + } + free_block = free_block->next; + } + + chunk_size = sizeof(struct chunk_header) + sizeof(struct block_header); + chunk_size = (chunk_size + size + CHUNK_SIZE - 1) & CHUNK_MASK; + + chunk_header = alloc_chunk(chunk_size); + if (!chunk_header) { + allocator_release_lock(); + return NULL; + } + + executable_offset = (sljit_sw)((sljit_u8*)chunk_header->executable - (sljit_u8*)chunk_header); + + chunk_size -= sizeof(struct chunk_header) + sizeof(struct block_header); + total_size += chunk_size; + + header = (struct block_header *)(chunk_header + 1); + + header->prev_size = 0; + header->executable_offset = executable_offset; + if (chunk_size > size + 64) { + /* Cut the allocated space into a free and a used block. */ + allocated_size += size; + header->size = size; + chunk_size -= size; + + free_block = AS_FREE_BLOCK(header, size); + free_block->header.prev_size = size; + free_block->header.executable_offset = executable_offset; + sljit_insert_free_block(free_block, chunk_size); + next_header = AS_BLOCK_HEADER(free_block, chunk_size); + } + else { + /* All space belongs to this allocation. */ + allocated_size += chunk_size; + header->size = chunk_size; + next_header = AS_BLOCK_HEADER(header, chunk_size); + } + next_header->size = 1; + next_header->prev_size = chunk_size; + next_header->executable_offset = executable_offset; + allocator_release_lock(); + return MEM_START(header); +} + +SLJIT_API_FUNC_ATTRIBUTE void sljit_free_exec(void* ptr) +{ + struct block_header *header; + struct free_block* free_block; + + allocator_grab_lock(); + header = AS_BLOCK_HEADER(ptr, -(sljit_sw)sizeof(struct block_header)); + header = AS_BLOCK_HEADER(header, -header->executable_offset); + allocated_size -= header->size; + + /* Connecting free blocks together if possible. */ + + /* If header->prev_size == 0, free_block will equal to header. + In this case, free_block->header.size will be > 0. */ + free_block = AS_FREE_BLOCK(header, -(sljit_sw)header->prev_size); + if (SLJIT_UNLIKELY(!free_block->header.size)) { + free_block->size += header->size; + header = AS_BLOCK_HEADER(free_block, free_block->size); + header->prev_size = free_block->size; + } + else { + free_block = (struct free_block*)header; + sljit_insert_free_block(free_block, header->size); + } + + header = AS_BLOCK_HEADER(free_block, free_block->size); + if (SLJIT_UNLIKELY(!header->size)) { + free_block->size += ((struct free_block*)header)->size; + sljit_remove_free_block((struct free_block*)header); + header = AS_BLOCK_HEADER(free_block, free_block->size); + header->prev_size = free_block->size; + } + + /* The whole chunk is free. */ + if (SLJIT_UNLIKELY(!free_block->header.prev_size && header->size == 1)) { + /* If this block is freed, we still have (allocated_size / 2) free space. */ + if (total_size - free_block->size > (allocated_size * 3 / 2)) { + total_size -= free_block->size; + sljit_remove_free_block(free_block); + free_chunk(free_block, free_block->size + sizeof(struct block_header)); + } + } + + allocator_release_lock(); +} + +SLJIT_API_FUNC_ATTRIBUTE void sljit_free_unused_memory_exec(void) +{ + struct free_block* free_block; + struct free_block* next_free_block; + + allocator_grab_lock(); + + free_block = free_blocks; + while (free_block) { + next_free_block = free_block->next; + if (!free_block->header.prev_size && + AS_BLOCK_HEADER(free_block, free_block->size)->size == 1) { + total_size -= free_block->size; + sljit_remove_free_block(free_block); + free_chunk(free_block, free_block->size + sizeof(struct block_header)); + } + free_block = next_free_block; + } + + SLJIT_ASSERT((total_size && free_blocks) || (!total_size && !free_blocks)); + allocator_release_lock(); +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_sw sljit_exec_offset(void* ptr) +{ + return ((struct block_header *)(ptr))[-1].executable_offset; +} diff --git a/thirdparty/pcre2/src/sljit/sljitUtils.c b/thirdparty/pcre2/src/sljit/sljitUtils.c index ec5c321194..5c2a838932 100644 --- a/thirdparty/pcre2/src/sljit/sljitUtils.c +++ b/thirdparty/pcre2/src/sljit/sljitUtils.c @@ -1,7 +1,7 @@ /* * Stack-less Just-In-Time compiler * - * Copyright 2009-2012 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved. + * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are * permitted provided that the following conditions are met: @@ -48,12 +48,12 @@ static SLJIT_INLINE void allocator_release_lock(void) #if (defined SLJIT_UTIL_GLOBAL_LOCK && SLJIT_UTIL_GLOBAL_LOCK) -SLJIT_API_FUNC_ATTRIBUTE void SLJIT_CALL sljit_grab_lock(void) +SLJIT_API_FUNC_ATTRIBUTE void SLJIT_FUNC sljit_grab_lock(void) { /* Always successful. */ } -SLJIT_API_FUNC_ATTRIBUTE void SLJIT_CALL sljit_release_lock(void) +SLJIT_API_FUNC_ATTRIBUTE void SLJIT_FUNC sljit_release_lock(void) { /* Always successful. */ } @@ -88,7 +88,7 @@ static SLJIT_INLINE void allocator_release_lock(void) static HANDLE global_mutex = 0; -SLJIT_API_FUNC_ATTRIBUTE void SLJIT_CALL sljit_grab_lock(void) +SLJIT_API_FUNC_ATTRIBUTE void SLJIT_FUNC sljit_grab_lock(void) { /* No idea what to do if an error occures. Static mutexes should never fail... */ if (!global_mutex) @@ -97,7 +97,7 @@ SLJIT_API_FUNC_ATTRIBUTE void SLJIT_CALL sljit_grab_lock(void) WaitForSingleObject(global_mutex, INFINITE); } -SLJIT_API_FUNC_ATTRIBUTE void SLJIT_CALL sljit_release_lock(void) +SLJIT_API_FUNC_ATTRIBUTE void SLJIT_FUNC sljit_release_lock(void) { ReleaseMutex(global_mutex); } @@ -130,12 +130,12 @@ static SLJIT_INLINE void allocator_release_lock(void) static pthread_mutex_t global_mutex = PTHREAD_MUTEX_INITIALIZER; -SLJIT_API_FUNC_ATTRIBUTE void SLJIT_CALL sljit_grab_lock(void) +SLJIT_API_FUNC_ATTRIBUTE void SLJIT_FUNC sljit_grab_lock(void) { pthread_mutex_lock(&global_mutex); } -SLJIT_API_FUNC_ATTRIBUTE void SLJIT_CALL sljit_release_lock(void) +SLJIT_API_FUNC_ATTRIBUTE void SLJIT_FUNC sljit_release_lock(void) { pthread_mutex_unlock(&global_mutex); } @@ -203,19 +203,16 @@ static SLJIT_INLINE sljit_s32 open_dev_zero(void) /* Planning to make it even more clever in the future. */ static sljit_sw sljit_page_align = 0; -SLJIT_API_FUNC_ATTRIBUTE struct sljit_stack* SLJIT_CALL sljit_allocate_stack(sljit_uw limit, sljit_uw max_limit, void *allocator_data) +SLJIT_API_FUNC_ATTRIBUTE struct sljit_stack* SLJIT_FUNC sljit_allocate_stack(sljit_uw start_size, sljit_uw max_size, void *allocator_data) { struct sljit_stack *stack; - union { - void *ptr; - sljit_uw uw; - } base; + void *ptr; #ifdef _WIN32 SYSTEM_INFO si; #endif SLJIT_UNUSED_ARG(allocator_data); - if (limit > max_limit || limit < 1) + if (start_size > max_size || start_size < 1) return NULL; #ifdef _WIN32 @@ -233,29 +230,31 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_stack* SLJIT_CALL sljit_allocate_stack(slj } #endif - /* Align limit and max_limit. */ - max_limit = (max_limit + sljit_page_align) & ~sljit_page_align; - stack = (struct sljit_stack*)SLJIT_MALLOC(sizeof(struct sljit_stack), allocator_data); if (!stack) return NULL; + /* Align max_size. */ + max_size = (max_size + sljit_page_align) & ~sljit_page_align; + #ifdef _WIN32 - base.ptr = VirtualAlloc(NULL, max_limit, MEM_RESERVE, PAGE_READWRITE); - if (!base.ptr) { + ptr = VirtualAlloc(NULL, max_size, MEM_RESERVE, PAGE_READWRITE); + if (!ptr) { SLJIT_FREE(stack, allocator_data); return NULL; } - stack->base = base.uw; - stack->limit = stack->base; - stack->max_limit = stack->base + max_limit; - if (sljit_stack_resize(stack, stack->base + limit)) { + + stack->min_start = (sljit_u8 *)ptr; + stack->end = stack->min_start + max_size; + stack->start = stack->end; + + if (sljit_stack_resize(stack, stack->end - start_size) == NULL) { sljit_free_stack(stack, allocator_data); return NULL; } #else #ifdef MAP_ANON - base.ptr = mmap(NULL, max_limit, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0); + ptr = mmap(NULL, max_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0); #else if (dev_zero < 0) { if (open_dev_zero()) { @@ -263,73 +262,70 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_stack* SLJIT_CALL sljit_allocate_stack(slj return NULL; } } - base.ptr = mmap(NULL, max_limit, PROT_READ | PROT_WRITE, MAP_PRIVATE, dev_zero, 0); + ptr = mmap(NULL, max_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, dev_zero, 0); #endif - if (base.ptr == MAP_FAILED) { + if (ptr == MAP_FAILED) { SLJIT_FREE(stack, allocator_data); return NULL; } - stack->base = base.uw; - stack->limit = stack->base + limit; - stack->max_limit = stack->base + max_limit; + stack->min_start = (sljit_u8 *)ptr; + stack->end = stack->min_start + max_size; + stack->start = stack->end - start_size; #endif - stack->top = stack->base; + stack->top = stack->end; return stack; } #undef PAGE_ALIGN -SLJIT_API_FUNC_ATTRIBUTE void SLJIT_CALL sljit_free_stack(struct sljit_stack* stack, void *allocator_data) +SLJIT_API_FUNC_ATTRIBUTE void SLJIT_FUNC sljit_free_stack(struct sljit_stack *stack, void *allocator_data) { SLJIT_UNUSED_ARG(allocator_data); #ifdef _WIN32 - VirtualFree((void*)stack->base, 0, MEM_RELEASE); + VirtualFree((void*)stack->min_start, 0, MEM_RELEASE); #else - munmap((void*)stack->base, stack->max_limit - stack->base); + munmap((void*)stack->min_start, stack->end - stack->min_start); #endif SLJIT_FREE(stack, allocator_data); } -SLJIT_API_FUNC_ATTRIBUTE sljit_sw SLJIT_CALL sljit_stack_resize(struct sljit_stack* stack, sljit_uw new_limit) +SLJIT_API_FUNC_ATTRIBUTE sljit_u8 *SLJIT_FUNC sljit_stack_resize(struct sljit_stack *stack, sljit_u8 *new_start) { - sljit_uw aligned_old_limit; - sljit_uw aligned_new_limit; + sljit_uw aligned_old_start; + sljit_uw aligned_new_start; + + if ((new_start < stack->min_start) || (new_start >= stack->end)) + return NULL; - if ((new_limit > stack->max_limit) || (new_limit < stack->base)) - return -1; #ifdef _WIN32 - aligned_new_limit = (new_limit + sljit_page_align) & ~sljit_page_align; - aligned_old_limit = (stack->limit + sljit_page_align) & ~sljit_page_align; - if (aligned_new_limit != aligned_old_limit) { - if (aligned_new_limit > aligned_old_limit) { - if (!VirtualAlloc((void*)aligned_old_limit, aligned_new_limit - aligned_old_limit, MEM_COMMIT, PAGE_READWRITE)) - return -1; + aligned_new_start = (sljit_uw)new_start & ~sljit_page_align; + aligned_old_start = ((sljit_uw)stack->start) & ~sljit_page_align; + if (aligned_new_start != aligned_old_start) { + if (aligned_new_start < aligned_old_start) { + if (!VirtualAlloc((void*)aligned_new_start, aligned_old_start - aligned_new_start, MEM_COMMIT, PAGE_READWRITE)) + return NULL; } else { - if (!VirtualFree((void*)aligned_new_limit, aligned_old_limit - aligned_new_limit, MEM_DECOMMIT)) - return -1; + if (!VirtualFree((void*)aligned_old_start, aligned_new_start - aligned_old_start, MEM_DECOMMIT)) + return NULL; } } - stack->limit = new_limit; - return 0; #else - if (new_limit >= stack->limit) { - stack->limit = new_limit; - return 0; - } - aligned_new_limit = (new_limit + sljit_page_align) & ~sljit_page_align; - aligned_old_limit = (stack->limit + sljit_page_align) & ~sljit_page_align; - /* If madvise is available, we release the unnecessary space. */ + if (stack->start < new_start) { + aligned_new_start = (sljit_uw)new_start & ~sljit_page_align; + aligned_old_start = ((sljit_uw)stack->start) & ~sljit_page_align; + /* If madvise is available, we release the unnecessary space. */ #if defined(MADV_DONTNEED) - if (aligned_new_limit < aligned_old_limit) - madvise((void*)aligned_new_limit, aligned_old_limit - aligned_new_limit, MADV_DONTNEED); + if (aligned_new_start > aligned_old_start) + madvise((void*)aligned_old_start, aligned_new_start - aligned_old_start, MADV_DONTNEED); #elif defined(POSIX_MADV_DONTNEED) - if (aligned_new_limit < aligned_old_limit) - posix_madvise((void*)aligned_new_limit, aligned_old_limit - aligned_new_limit, POSIX_MADV_DONTNEED); + if (aligned_new_start > aligned_old_start) + posix_madvise((void*)aligned_old_start, aligned_new_start - aligned_old_start, POSIX_MADV_DONTNEED); #endif - stack->limit = new_limit; - return 0; + } #endif + stack->start = new_start; + return new_start; } #endif /* SLJIT_UTIL_STACK */ diff --git a/thirdparty/squish/config.h b/thirdparty/squish/config.h index 92edefe966..05f8d72598 100644 --- a/thirdparty/squish/config.h +++ b/thirdparty/squish/config.h @@ -32,6 +32,26 @@ #endif // Set to 1 or 2 when building squish to use SSE or SSE2 instructions. +// -- GODOT start -- +#ifdef _MSC_VER + #if defined(_M_IX86_FP) + #if _M_IX86_FP >= 2 + #define SQUISH_USE_SSE 2 + #elif _M_IX86_FP >= 1 + #define SQUISH_USE_SSE 1 + #endif + #elif defined(_M_X64) + #define SQUISH_USE_SSE 2 + #endif +#else + #if defined(__SSE2__) + #define SQUISH_USE_SSE 2 + #elif defined(__SSE__) + #define SQUISH_USE_SSE 1 + #endif +#endif +// -- GODOT end -- + #ifndef SQUISH_USE_SSE #define SQUISH_USE_SSE 0 #endif diff --git a/thirdparty/thekla_atlas/nvcore/nvcore.h b/thirdparty/thekla_atlas/nvcore/nvcore.h index a3deb66be2..5ef69668d9 100644 --- a/thirdparty/thekla_atlas/nvcore/nvcore.h +++ b/thirdparty/thekla_atlas/nvcore/nvcore.h @@ -44,6 +44,9 @@ #elif defined POSH_OS_FREEBSD # define NV_OS_FREEBSD 1 # define NV_OS_UNIX 1 +#elif defined POSH_OS_HAIKU +# define NV_OS_HAIKU 1 +# define NV_OS_UNIX 1 #elif defined POSH_OS_OPENBSD # define NV_OS_OPENBSD 1 # define NV_OS_UNIX 1 @@ -341,7 +344,7 @@ template <typename T, size_t N> char (&ArraySizeHelper(T (&array)[N]))[N]; #elif NV_CC_GNUC # if NV_OS_LINUX # include "DefsGnucLinux.h" -# elif NV_OS_DARWIN || NV_OS_FREEBSD || NV_OS_OPENBSD +# elif NV_OS_DARWIN || NV_OS_FREEBSD || NV_OS_OPENBSD || NV_OS_HAIKU # include "DefsGnucDarwin.h" # elif NV_OS_ORBIS # include "DefsOrbis.h" diff --git a/thirdparty/thekla_atlas/nvmath/nvmath.h b/thirdparty/thekla_atlas/nvmath/nvmath.h index f2b69426e1..a697f9293d 100644 --- a/thirdparty/thekla_atlas/nvmath/nvmath.h +++ b/thirdparty/thekla_atlas/nvmath/nvmath.h @@ -181,10 +181,8 @@ namespace nv { #if NV_OS_WIN32 || NV_OS_XBOX || NV_OS_DURANGO return _finite(f) != 0; -#elif NV_OS_DARWIN || NV_OS_FREEBSD || NV_OS_OPENBSD || NV_OS_ORBIS +#elif NV_OS_DARWIN || NV_OS_FREEBSD || NV_OS_OPENBSD || NV_OS_ORBIS || NV_OS_LINUX return isfinite(f); -#elif NV_OS_LINUX - return finitef(f); #else # error "isFinite not supported" #endif @@ -196,10 +194,8 @@ namespace nv { #if NV_OS_WIN32 || NV_OS_XBOX || NV_OS_DURANGO return _isnan(f) != 0; -#elif NV_OS_DARWIN || NV_OS_FREEBSD || NV_OS_OPENBSD || NV_OS_ORBIS +#elif NV_OS_DARWIN || NV_OS_FREEBSD || NV_OS_OPENBSD || NV_OS_ORBIS || NV_OS_LINUX return isnan(f); -#elif NV_OS_LINUX - return isnanf(f); #else # error "isNan not supported" #endif diff --git a/thirdparty/thekla_atlas/poshlib/posh.h b/thirdparty/thekla_atlas/poshlib/posh.h index 3038297b39..72acd20ce0 100644 --- a/thirdparty/thekla_atlas/poshlib/posh.h +++ b/thirdparty/thekla_atlas/poshlib/posh.h @@ -298,6 +298,11 @@ Metrowerks: # define POSH_OS_STRING "Linux" #endif +#if defined __HAIKU__ +# define POSH_OS_HAIKU 1 +# define POSH_OS_STRING "Haiku" +#endif + #if defined __FreeBSD__ # define POSH_OS_FREEBSD 1 # define POSH_OS_STRING "FreeBSD" diff --git a/thirdparty/tinyexr/tinyexr.h b/thirdparty/tinyexr/tinyexr.h index 107c22ffb3..990c8ee142 100644 --- a/thirdparty/tinyexr/tinyexr.h +++ b/thirdparty/tinyexr/tinyexr.h @@ -1,5 +1,5 @@ /* -Copyright (c) 2014 - 2017, Syoyo Fujita +Copyright (c) 2014 - 2018, Syoyo Fujita and many contributors. All rights reserved. Redistribution and use in source and binary forms, with or without @@ -115,6 +115,7 @@ extern "C" { #define TINYEXR_ERROR_CANT_OPEN_FILE (-6) #define TINYEXR_ERROR_UNSUPPORTED_FORMAT (-7) #define TINYEXR_ERROR_INVALID_HEADER (-8) +#define TINYEXR_ERROR_UNSUPPORTED_FEATURE (-9) // @note { OpenEXR file format: http://www.openexr.com/openexrfilelayout.pdf } @@ -123,7 +124,8 @@ extern "C" { #define TINYEXR_PIXELTYPE_HALF (1) #define TINYEXR_PIXELTYPE_FLOAT (2) -#define TINYEXR_MAX_ATTRIBUTES (128) +#define TINYEXR_MAX_HEADER_ATTRIBUTES (1024) +#define TINYEXR_MAX_CUSTOM_ATTRIBUTES (128) #define TINYEXR_COMPRESSIONTYPE_NONE (0) #define TINYEXR_COMPRESSIONTYPE_RLE (1) @@ -205,7 +207,8 @@ typedef struct _EXRHeader { // Custom attributes(exludes required attributes(e.g. `channels`, // `compression`, etc) int num_custom_attributes; - EXRAttribute custom_attributes[TINYEXR_MAX_ATTRIBUTES]; + EXRAttribute *custom_attributes; // array of EXRAttribute. size = + // `num_custom_attributes`. EXRChannelInfo *channels; // [num_channels] @@ -292,6 +295,9 @@ extern int FreeEXRHeader(EXRHeader *exr_header); // Free's internal data of EXRImage struct extern int FreeEXRImage(EXRImage *exr_image); +// Free's error message +extern void FreeEXRErrorMessage(const char *msg); + // Parse EXR version header of a file. extern int ParseEXRVersionFromFile(EXRVersion *version, const char *filename); @@ -300,10 +306,14 @@ extern int ParseEXRVersionFromMemory(EXRVersion *version, const unsigned char *memory, size_t size); // Parse single-part OpenEXR header from a file and initialize `EXRHeader`. +// When there was an error message, Application must free `err` with +// FreeEXRErrorMessage() extern int ParseEXRHeaderFromFile(EXRHeader *header, const EXRVersion *version, const char *filename, const char **err); // Parse single-part OpenEXR header from a memory and initialize `EXRHeader`. +// When there was an error message, Application must free `err` with +// FreeEXRErrorMessage() extern int ParseEXRHeaderFromMemory(EXRHeader *header, const EXRVersion *version, const unsigned char *memory, size_t size, @@ -311,6 +321,8 @@ extern int ParseEXRHeaderFromMemory(EXRHeader *header, // Parse multi-part OpenEXR headers from a file and initialize `EXRHeader*` // array. +// When there was an error message, Application must free `err` with +// FreeEXRErrorMessage() extern int ParseEXRMultipartHeaderFromFile(EXRHeader ***headers, int *num_headers, const EXRVersion *version, @@ -319,6 +331,8 @@ extern int ParseEXRMultipartHeaderFromFile(EXRHeader ***headers, // Parse multi-part OpenEXR headers from a memory and initialize `EXRHeader*` // array +// When there was an error message, Application must free `err` with +// FreeEXRErrorMessage() extern int ParseEXRMultipartHeaderFromMemory(EXRHeader ***headers, int *num_headers, const EXRVersion *version, @@ -330,6 +344,8 @@ extern int ParseEXRMultipartHeaderFromMemory(EXRHeader ***headers, // Application can free EXRImage using `FreeEXRImage` // Returns negative value and may set error string in `err` when there's an // error +// When there was an error message, Application must free `err` with +// FreeEXRErrorMessage() extern int LoadEXRImageFromFile(EXRImage *image, const EXRHeader *header, const char *filename, const char **err); @@ -339,6 +355,8 @@ extern int LoadEXRImageFromFile(EXRImage *image, const EXRHeader *header, // Application can free EXRImage using `FreeEXRImage` // Returns negative value and may set error string in `err` when there's an // error +// When there was an error message, Application must free `err` with +// FreeEXRErrorMessage() extern int LoadEXRImageFromMemory(EXRImage *image, const EXRHeader *header, const unsigned char *memory, const size_t size, const char **err); @@ -349,6 +367,8 @@ extern int LoadEXRImageFromMemory(EXRImage *image, const EXRHeader *header, // Application can free EXRImage using `FreeEXRImage` // Returns negative value and may set error string in `err` when there's an // error +// When there was an error message, Application must free `err` with +// FreeEXRErrorMessage() extern int LoadEXRMultipartImageFromFile(EXRImage *images, const EXRHeader **headers, unsigned int num_parts, @@ -361,6 +381,8 @@ extern int LoadEXRMultipartImageFromFile(EXRImage *images, // Application can free EXRImage using `FreeEXRImage` // Returns negative value and may set error string in `err` when there's an // error +// When there was an error message, Application must free `err` with +// FreeEXRErrorMessage() extern int LoadEXRMultipartImageFromMemory(EXRImage *images, const EXRHeader **headers, unsigned int num_parts, @@ -370,6 +392,8 @@ extern int LoadEXRMultipartImageFromMemory(EXRImage *images, // Saves multi-channel, single-frame OpenEXR image to a file. // Returns negative value and may set error string in `err` when there's an // error +// When there was an error message, Application must free `err` with +// FreeEXRErrorMessage() extern int SaveEXRImageToFile(const EXRImage *image, const EXRHeader *exr_header, const char *filename, const char **err); @@ -379,6 +403,8 @@ extern int SaveEXRImageToFile(const EXRImage *image, // Return the number of bytes if succes. // Returns negative value and may set error string in `err` when there's an // error +// When there was an error message, Application must free `err` with +// FreeEXRErrorMessage() extern size_t SaveEXRImageToMemory(const EXRImage *image, const EXRHeader *exr_header, unsigned char **memory, const char **err); @@ -387,6 +413,8 @@ extern size_t SaveEXRImageToMemory(const EXRImage *image, // Application must free memory of variables in DeepImage(image, offset_table) // Returns negative value and may set error string in `err` when there's an // error +// When there was an error message, Application must free `err` with +// FreeEXRErrorMessage() extern int LoadDeepEXR(DeepImage *out_image, const char *filename, const char **err); @@ -409,6 +437,8 @@ extern int LoadDeepEXR(DeepImage *out_image, const char *filename, // RGB(A) channels. // Returns negative value and may set error string in `err` when there's an // error +// When there was an error message, Application must free `err` with +// FreeEXRErrorMessage() extern int LoadEXRFromMemory(float **out_rgba, int *width, int *height, const unsigned char *memory, size_t size, const char **err); @@ -428,8 +458,10 @@ extern int LoadEXRFromMemory(float **out_rgba, int *width, int *height, #include <cstdio> #include <cstdlib> #include <cstring> +#include <iostream> #include <sstream> +#include <limits> #include <string> #include <vector> @@ -486,6 +518,9 @@ namespace miniz { #pragma clang diagnostic ignored "-Wc++11-extensions" #pragma clang diagnostic ignored "-Wconversion" #pragma clang diagnostic ignored "-Wunused-function" +#pragma clang diagnostic ignored "-Wc++98-compat-pedantic" +#pragma clang diagnostic ignored "-Wundef" + #if __has_warning("-Wcomma") #pragma clang diagnostic ignored "-Wcomma" #endif @@ -495,6 +530,9 @@ namespace miniz { #if __has_warning("-Wcast-qual") #pragma clang diagnostic ignored "-Wcast-qual" #endif +#if __has_warning("-Wzero-as-null-pointer-constant") +#pragma clang diagnostic ignored "-Wzero-as-null-pointer-constant" +#endif #endif /* miniz.c v1.15 - public domain deflate/inflate, zlib-subset, ZIP @@ -2480,10 +2518,10 @@ tinfl_status tinfl_decompress(tinfl_decompressor *r, tinfl_status status = TINFL_STATUS_FAILED; mz_uint32 num_bits, dist, counter, num_extra; tinfl_bit_buf_t bit_buf; - const mz_uint8 *pIn_buf_cur = pIn_buf_next, - *const pIn_buf_end = pIn_buf_next + *pIn_buf_size; - mz_uint8 *pOut_buf_cur = pOut_buf_next, - *const pOut_buf_end = pOut_buf_next + *pOut_buf_size; + const mz_uint8 *pIn_buf_cur = pIn_buf_next, *const pIn_buf_end = + pIn_buf_next + *pIn_buf_size; + mz_uint8 *pOut_buf_cur = pOut_buf_next, *const pOut_buf_end = + pOut_buf_next + *pOut_buf_size; size_t out_buf_size_mask = (decomp_flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF) ? (size_t)-1 @@ -2955,9 +2993,8 @@ int tinfl_decompress_mem_to_callback(const void *pIn_buf, size_t *pIn_buf_size, tinfl_status status = tinfl_decompress(&decomp, (const mz_uint8 *)pIn_buf + in_buf_ofs, &in_buf_size, pDict, pDict + dict_ofs, &dst_buf_size, - (flags & - ~(TINFL_FLAG_HAS_MORE_INPUT | - TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF))); + (flags & ~(TINFL_FLAG_HAS_MORE_INPUT | + TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF))); in_buf_ofs += in_buf_size; if ((dst_buf_size) && (!(*pPut_buf_func)(pDict + dict_ofs, (int)dst_buf_size, pPut_buf_user))) @@ -3082,7 +3119,9 @@ static const mz_uint8 s_tdefl_large_dist_extra[128] = { // Radix sorts tdefl_sym_freq[] array by 16-bit key m_key. Returns ptr to sorted // values. -typedef struct { mz_uint16 m_key, m_sym_index; } tdefl_sym_freq; +typedef struct { + mz_uint16 m_key, m_sym_index; +} tdefl_sym_freq; static tdefl_sym_freq *tdefl_radix_sort_syms(mz_uint num_syms, tdefl_sym_freq *pSyms0, tdefl_sym_freq *pSyms1) { @@ -3549,10 +3588,9 @@ static int tdefl_flush_block(tdefl_compressor *d, int flush) { mz_uint saved_bit_buf, saved_bits_in; mz_uint8 *pSaved_output_buf; mz_bool comp_block_succeeded = MZ_FALSE; - int n, - use_raw_block = - ((d->m_flags & TDEFL_FORCE_ALL_RAW_BLOCKS) != 0) && - (d->m_lookahead_pos - d->m_lz_code_buf_dict_pos) <= d->m_dict_size; + int n, use_raw_block = + ((d->m_flags & TDEFL_FORCE_ALL_RAW_BLOCKS) != 0) && + (d->m_lookahead_pos - d->m_lz_code_buf_dict_pos) <= d->m_dict_size; mz_uint8 *pOutput_buf_start = ((d->m_pPut_buf_func == NULL) && ((*d->m_pOut_buf_size - d->m_out_buf_ofs) >= TDEFL_OUT_BUF_SIZE)) @@ -3582,9 +3620,8 @@ static int tdefl_flush_block(tdefl_compressor *d, int flush) { if (!use_raw_block) comp_block_succeeded = - tdefl_compress_block(d, - (d->m_flags & TDEFL_FORCE_ALL_STATIC_BLOCKS) || - (d->m_total_lz_bytes < 48)); + tdefl_compress_block(d, (d->m_flags & TDEFL_FORCE_ALL_STATIC_BLOCKS) || + (d->m_total_lz_bytes < 48)); // If the block gets expanded, forget the current contents of the output // buffer and send a raw block instead. @@ -4388,9 +4425,8 @@ mz_uint tdefl_create_comp_flags_from_zip_params(int level, int window_bits, // C and C99, so no big deal) #pragma warning(disable : 4244) // 'initializing': conversion from '__int64' to // 'int', possible loss of data -#pragma warning( \ - disable : 4267) // 'argument': conversion from '__int64' to 'int', - // possible loss of data +#pragma warning(disable : 4267) // 'argument': conversion from '__int64' to + // 'int', possible loss of data #pragma warning(disable : 4996) // 'strdup': The POSIX name for this item is // deprecated. Instead, use the ISO C and C++ // conformant name: _strdup. @@ -6894,7 +6930,7 @@ void *mz_zip_extract_archive_file_to_heap(const char *pZip_filename, #ifdef _MSC_VER #pragma warning(pop) #endif -} +} // namespace miniz #else // Reuse MINIZ_LITTE_ENDIAN macro @@ -6919,8 +6955,26 @@ void *mz_zip_extract_archive_file_to_heap(const char *pZip_filename, // return bint.c[0] == 1; //} +static void SetErrorMessage(const std::string &msg, const char **err) { + if (err) { +#ifdef _WIN32 + (*err) = _strdup(msg.c_str()); +#else + (*err) = strdup(msg.c_str()); +#endif + } +} + static const int kEXRVersionSize = 8; +static void cpy2(unsigned short *dst_val, const unsigned short *src_val) { + unsigned char *dst = reinterpret_cast<unsigned char *>(dst_val); + const unsigned char *src = reinterpret_cast<const unsigned char *>(src_val); + + dst[0] = src[0]; + dst[1] = src[1]; +} + static void swap2(unsigned short *val) { #ifdef MINIZ_LITTLE_ENDIAN (void)val; @@ -6934,6 +6988,36 @@ static void swap2(unsigned short *val) { #endif } +static void cpy4(int *dst_val, const int *src_val) { + unsigned char *dst = reinterpret_cast<unsigned char *>(dst_val); + const unsigned char *src = reinterpret_cast<const unsigned char *>(src_val); + + dst[0] = src[0]; + dst[1] = src[1]; + dst[2] = src[2]; + dst[3] = src[3]; +} + +static void cpy4(unsigned int *dst_val, const unsigned int *src_val) { + unsigned char *dst = reinterpret_cast<unsigned char *>(dst_val); + const unsigned char *src = reinterpret_cast<const unsigned char *>(src_val); + + dst[0] = src[0]; + dst[1] = src[1]; + dst[2] = src[2]; + dst[3] = src[3]; +} + +static void cpy4(float *dst_val, const float *src_val) { + unsigned char *dst = reinterpret_cast<unsigned char *>(dst_val); + const unsigned char *src = reinterpret_cast<const unsigned char *>(src_val); + + dst[0] = src[0]; + dst[1] = src[1]; + dst[2] = src[2]; + dst[3] = src[3]; +} + static void swap4(unsigned int *val) { #ifdef MINIZ_LITTLE_ENDIAN (void)val; @@ -6949,6 +7033,22 @@ static void swap4(unsigned int *val) { #endif } +#if 0 +static void cpy8(tinyexr::tinyexr_uint64 *dst_val, const tinyexr::tinyexr_uint64 *src_val) { + unsigned char *dst = reinterpret_cast<unsigned char *>(dst_val); + const unsigned char *src = reinterpret_cast<const unsigned char *>(src_val); + + dst[0] = src[0]; + dst[1] = src[1]; + dst[2] = src[2]; + dst[3] = src[3]; + dst[4] = src[4]; + dst[5] = src[5]; + dst[6] = src[6]; + dst[7] = src[7]; +} +#endif + static void swap8(tinyexr::tinyexr_uint64 *val) { #ifdef MINIZ_LITTLE_ENDIAN (void)val; @@ -7084,6 +7184,15 @@ static FP16 float_to_half_full(FP32 f) { // #define IMF_B44_COMPRESSION 6 // #define IMF_B44A_COMPRESSION 7 +#ifdef __clang__ +#pragma clang diagnostic push + +#if __has_warning("-Wzero-as-null-pointer-constant") +#pragma clang diagnostic ignored "-Wzero-as-null-pointer-constant" +#endif + +#endif + static const char *ReadString(std::string *s, const char *ptr, size_t len) { // Read untile NULL(\0). const char *p = ptr; @@ -7133,7 +7242,21 @@ static bool ReadAttribute(std::string *name, std::string *type, tinyexr::swap4(reinterpret_cast<unsigned int *>(&data_len)); if (data_len == 0) { - return false; + if ((*type).compare("string") == 0) { + // Accept empty string attribute. + + marker += sizeof(uint32_t); + size -= sizeof(uint32_t); + + *marker_size = name_len + 1 + type_len + 1 + sizeof(uint32_t); + + data->resize(1); + (*data)[0] = '\0'; + + return true; + } else { + return false; + } } marker += sizeof(uint32_t); @@ -7236,18 +7359,24 @@ static bool ReadChannelInfo(std::vector<ChannelInfo> &channels, } ChannelInfo info; - tinyexr_int64 data_len = static_cast<tinyexr_int64>(data.size()) - (p - reinterpret_cast<const char *>(data.data())); + tinyexr_int64 data_len = static_cast<tinyexr_int64>(data.size()) - + (p - reinterpret_cast<const char *>(data.data())); if (data_len < 0) { return false; } - p = ReadString( - &info.name, p, size_t(data_len)); + p = ReadString(&info.name, p, size_t(data_len)); if ((p == NULL) && (info.name.empty())) { // Buffer overrun. Issue #51. return false; } + const unsigned char *data_end = + reinterpret_cast<const unsigned char *>(p) + 16; + if (data_end >= (data.data() + data.size())) { + return false; + } + memcpy(&info.pixel_type, p, sizeof(int)); p += 4; info.p_linear = static_cast<unsigned char>(p[0]); // uchar @@ -7468,9 +7597,8 @@ static bool DecompressZip(unsigned char *dst, // C and C99, so no big deal) #pragma warning(disable : 4244) // 'initializing': conversion from '__int64' to // 'int', possible loss of data -#pragma warning( \ - disable : 4267) // 'argument': conversion from '__int64' to 'int', - // possible loss of data +#pragma warning(disable : 4267) // 'argument': conversion from '__int64' to + // 'int', possible loss of data #pragma warning(disable : 4996) // 'strdup': The POSIX name for this item is // deprecated. Instead, use the ISO C and C++ // conformant name: _strdup. @@ -7705,6 +7833,7 @@ static void DecompressRle(unsigned char *dst, #pragma clang diagnostic ignored "-Wsign-conversion" #pragma clang diagnostic ignored "-Wc++11-extensions" #pragma clang diagnostic ignored "-Wconversion" +#pragma clang diagnostic ignored "-Wc++98-compat-pedantic" #if __has_warning("-Wcast-qual") #pragma clang diagnostic ignored "-Wcast-qual" @@ -8187,8 +8316,8 @@ static void hufBuildEncTable( // for all array entries. // - int hlink[HUF_ENCSIZE]; - long long *fHeap[HUF_ENCSIZE]; + std::vector<int> hlink(HUF_ENCSIZE); + std::vector<long long *> fHeap(HUF_ENCSIZE); *im = 0; @@ -8247,8 +8376,8 @@ static void hufBuildEncTable( std::make_heap(&fHeap[0], &fHeap[nf], FHeapCompare()); - long long scode[HUF_ENCSIZE]; - memset(scode, 0, sizeof(long long) * HUF_ENCSIZE); + std::vector<long long> scode(HUF_ENCSIZE); + memset(scode.data(), 0, sizeof(long long) * HUF_ENCSIZE); while (nf > 1) { // @@ -8320,8 +8449,8 @@ static void hufBuildEncTable( // code table from scode into frq. // - hufCanonicalCodeTable(scode); - memcpy(frq, scode, sizeof(long long) * HUF_ENCSIZE); + hufCanonicalCodeTable(scode.data()); + memcpy(frq, scode.data(), sizeof(long long) * HUF_ENCSIZE); } // @@ -8657,26 +8786,62 @@ static int hufEncode // return: output size (in bits) lc += 8; \ } -#define getCode(po, rlc, c, lc, in, out, oe) \ - { \ - if (po == rlc) { \ - if (lc < 8) getChar(c, lc, in); \ - \ - lc -= 8; \ - \ - unsigned char cs = (c >> lc); \ - \ - if (out + cs > oe) return false; \ - \ - unsigned short s = out[-1]; \ - \ - while (cs-- > 0) *out++ = s; \ - } else if (out < oe) { \ - *out++ = po; \ - } else { \ - return false; \ - } \ +#if 0 +#define getCode(po, rlc, c, lc, in, out, ob, oe) \ + { \ + if (po == rlc) { \ + if (lc < 8) getChar(c, lc, in); \ + \ + lc -= 8; \ + \ + unsigned char cs = (c >> lc); \ + \ + if (out + cs > oe) return false; \ + \ + /* TinyEXR issue 78 */ \ + unsigned short s = out[-1]; \ + \ + while (cs-- > 0) *out++ = s; \ + } else if (out < oe) { \ + *out++ = po; \ + } else { \ + return false; \ + } \ + } +#else +static bool getCode(int po, int rlc, long long &c, int &lc, const char *&in, + const char *in_end, unsigned short *&out, + const unsigned short *ob, const unsigned short *oe) { + (void)ob; + if (po == rlc) { + if (lc < 8) { + /* TinyEXR issue 78 */ + if ((in + 1) >= in_end) { + return false; + } + + getChar(c, lc, in); + } + + lc -= 8; + + unsigned char cs = (c >> lc); + + if (out + cs > oe) return false; + + // Bounds check for safety + if ((out - 1) <= ob) return false; + unsigned short s = out[-1]; + + while (cs-- > 0) *out++ = s; + } else if (out < oe) { + *out++ = po; + } else { + return false; } + return true; +} +#endif // // Decode (uncompress) ni bits based on encoding & decoding tables: @@ -8692,8 +8857,8 @@ static bool hufDecode(const long long *hcode, // i : encoding table { long long c = 0; int lc = 0; - unsigned short *outb = out; - unsigned short *oe = out + no; + unsigned short *outb = out; // begin + unsigned short *oe = out + no; // end const char *ie = in + (ni + 7) / 8; // input byte size // @@ -8716,7 +8881,16 @@ static bool hufDecode(const long long *hcode, // i : encoding table // lc -= pl.len; - getCode(pl.lit, rlc, c, lc, in, out, oe); + // std::cout << "lit = " << pl.lit << std::endl; + // std::cout << "rlc = " << rlc << std::endl; + // std::cout << "c = " << c << std::endl; + // std::cout << "lc = " << lc << std::endl; + // std::cout << "in = " << in << std::endl; + // std::cout << "out = " << out << std::endl; + // std::cout << "oe = " << oe << std::endl; + if (!getCode(pl.lit, rlc, c, lc, in, ie, out, outb, oe)) { + return false; + } } else { if (!pl.p) { return false; @@ -8743,7 +8917,9 @@ static bool hufDecode(const long long *hcode, // i : encoding table // lc -= l; - getCode(pl.p[j], rlc, c, lc, in, out, oe); + if (!getCode(pl.p[j], rlc, c, lc, in, ie, out, outb, oe)) { + return false; + } break; } } @@ -8770,7 +8946,9 @@ static bool hufDecode(const long long *hcode, // i : encoding table if (pl.len) { lc -= pl.len; - getCode(pl.lit, rlc, c, lc, in, out, oe); + if (!getCode(pl.lit, rlc, c, lc, in, ie, out, outb, oe)) { + return false; + } } else { return false; // invalidCode(); // wrong (long) code @@ -8785,7 +8963,7 @@ static bool hufDecode(const long long *hcode, // i : encoding table return true; } -static void countFrequencies(long long freq[HUF_ENCSIZE], +static void countFrequencies(std::vector<long long> &freq, const unsigned short data[/*n*/], int n) { for (int i = 0; i < HUF_ENCSIZE; ++i) freq[i] = 0; @@ -8816,21 +8994,21 @@ static int hufCompress(const unsigned short raw[], int nRaw, char compressed[]) { if (nRaw == 0) return 0; - long long freq[HUF_ENCSIZE]; + std::vector<long long> freq(HUF_ENCSIZE); countFrequencies(freq, raw, nRaw); int im = 0; int iM = 0; - hufBuildEncTable(freq, &im, &iM); + hufBuildEncTable(freq.data(), &im, &iM); char *tableStart = compressed + 20; char *tableEnd = tableStart; - hufPackEncTable(freq, im, iM, &tableEnd); + hufPackEncTable(freq.data(), im, iM, &tableEnd); int tableLength = tableEnd - tableStart; char *dataStart = tableEnd; - int nBits = hufEncode(freq, raw, nRaw, iM, dataStart); + int nBits = hufEncode(freq.data(), raw, nRaw, iM, dataStart); int data_length = (nBits + 7) / 8; writeUInt(compressed, im); @@ -8843,9 +9021,9 @@ static int hufCompress(const unsigned short raw[], int nRaw, } static bool hufUncompress(const char compressed[], int nCompressed, - unsigned short raw[], int nRaw) { + std::vector<unsigned short> *raw) { if (nCompressed == 0) { - if (nRaw != 0) return false; + if (raw->size() != 0) return false; return false; } @@ -8886,7 +9064,8 @@ static bool hufUncompress(const char compressed[], int nCompressed, } hufBuildDecTable(&freq.at(0), im, iM, &hdec.at(0)); - hufDecode(&freq.at(0), &hdec.at(0), ptr, nBits, iM, nRaw, raw); + hufDecode(&freq.at(0), &hdec.at(0), ptr, nBits, iM, raw->size(), + raw->data()); } // catch (...) //{ @@ -8975,7 +9154,7 @@ static bool CompressPiz(unsigned char *outPtr, unsigned int *outSize, const unsigned char *inPtr, size_t inSize, const std::vector<ChannelInfo> &channelInfo, int data_width, int num_lines) { - unsigned char bitmap[BITMAP_SIZE]; + std::vector<unsigned char> bitmap(BITMAP_SIZE); unsigned short minNonZero; unsigned short maxNonZero; @@ -9026,12 +9205,12 @@ static bool CompressPiz(unsigned char *outPtr, unsigned int *outSize, } } - bitmapFromData(&tmpBuffer.at(0), static_cast<int>(tmpBuffer.size()), bitmap, - minNonZero, maxNonZero); + bitmapFromData(&tmpBuffer.at(0), static_cast<int>(tmpBuffer.size()), + bitmap.data(), minNonZero, maxNonZero); - unsigned short lut[USHORT_RANGE]; - unsigned short maxValue = forwardLutFromBitmap(bitmap, lut); - applyLut(lut, &tmpBuffer.at(0), static_cast<int>(tmpBuffer.size())); + std::vector<unsigned short> lut(USHORT_RANGE); + unsigned short maxValue = forwardLutFromBitmap(bitmap.data(), lut.data()); + applyLut(lut.data(), &tmpBuffer.at(0), static_cast<int>(tmpBuffer.size())); // // Store range compression info in _outBuffer @@ -9101,7 +9280,7 @@ static bool DecompressPiz(unsigned char *outPtr, const unsigned char *inPtr, return true; } - unsigned char bitmap[BITMAP_SIZE]; + std::vector<unsigned char> bitmap(BITMAP_SIZE); unsigned short minNonZero; unsigned short maxNonZero; @@ -9111,11 +9290,13 @@ static bool DecompressPiz(unsigned char *outPtr, const unsigned char *inPtr, return false; #endif - memset(bitmap, 0, BITMAP_SIZE); + memset(bitmap.data(), 0, BITMAP_SIZE); const unsigned char *ptr = inPtr; - minNonZero = *(reinterpret_cast<const unsigned short *>(ptr)); - maxNonZero = *(reinterpret_cast<const unsigned short *>(ptr + 2)); + // minNonZero = *(reinterpret_cast<const unsigned short *>(ptr)); + tinyexr::cpy2(&minNonZero, reinterpret_cast<const unsigned short *>(ptr)); + // maxNonZero = *(reinterpret_cast<const unsigned short *>(ptr + 2)); + tinyexr::cpy2(&maxNonZero, reinterpret_cast<const unsigned short *>(ptr + 2)); ptr += 4; if (maxNonZero >= BITMAP_SIZE) { @@ -9128,9 +9309,9 @@ static bool DecompressPiz(unsigned char *outPtr, const unsigned char *inPtr, ptr += maxNonZero - minNonZero + 1; } - unsigned short lut[USHORT_RANGE]; - memset(lut, 0, sizeof(unsigned short) * USHORT_RANGE); - unsigned short maxValue = reverseLutFromBitmap(bitmap, lut); + std::vector<unsigned short> lut(USHORT_RANGE); + memset(lut.data(), 0, sizeof(unsigned short) * USHORT_RANGE); + unsigned short maxValue = reverseLutFromBitmap(bitmap.data(), lut.data()); // // Huffman decoding @@ -9138,12 +9319,12 @@ static bool DecompressPiz(unsigned char *outPtr, const unsigned char *inPtr, int length; - length = *(reinterpret_cast<const int *>(ptr)); + // length = *(reinterpret_cast<const int *>(ptr)); + tinyexr::cpy4(&length, reinterpret_cast<const int *>(ptr)); ptr += sizeof(int); std::vector<unsigned short> tmpBuffer(tmpBufSize); - hufUncompress(reinterpret_cast<const char *>(ptr), length, &tmpBuffer.at(0), - static_cast<int>(tmpBufSize)); + hufUncompress(reinterpret_cast<const char *>(ptr), length, &tmpBuffer); // // Wavelet decoding @@ -9184,7 +9365,7 @@ static bool DecompressPiz(unsigned char *outPtr, const unsigned char *inPtr, // Expand the pixel data to their original range // - applyLut(lut, &tmpBuffer.at(0), static_cast<int>(tmpBufSize)); + applyLut(lut.data(), &tmpBuffer.at(0), static_cast<int>(tmpBufSize)); for (int y = 0; y < num_lines; y++) { for (size_t i = 0; i < channelData.size(); ++i) { @@ -9409,6 +9590,7 @@ bool CompressZfp(std::vector<unsigned char> *outBuf, unsigned int *outSize, // ----------------------------------------------------------------- // +// TODO(syoyo): Refactor function arguments. static bool DecodePixelData(/* out */ unsigned char **out_images, const int *requested_pixel_types, const unsigned char *data_ptr, size_t data_len, @@ -9421,6 +9603,11 @@ static bool DecodePixelData(/* out */ unsigned char **out_images, const std::vector<size_t> &channel_offset_list) { if (compression_type == TINYEXR_COMPRESSIONTYPE_PIZ) { // PIZ #if TINYEXR_USE_PIZ + if ((width == 0) || (num_lines == 0) || (pixel_data_size == 0)) { + // Invalid input #90 + return false; + } + // Allocate original data size. std::vector<unsigned char> outBuf(static_cast<size_t>( static_cast<size_t>(width * num_lines) * pixel_data_size)); @@ -9452,7 +9639,10 @@ static bool DecodePixelData(/* out */ unsigned char **out_images, for (size_t u = 0; u < static_cast<size_t>(width); u++) { FP16 hf; - hf.u = line_ptr[u]; + // hf.u = line_ptr[u]; + // use `cpy` to avoid unaligned memory access when compiler's + // optimization is on. + tinyexr::cpy2(&(hf.u), line_ptr + u); tinyexr::swap2(reinterpret_cast<unsigned short *>(&hf.u)); @@ -9495,7 +9685,9 @@ static bool DecodePixelData(/* out */ unsigned char **out_images, &outBuf.at(v * pixel_data_size * static_cast<size_t>(width) + channel_offset_list[c] * static_cast<size_t>(width))); for (size_t u = 0; u < static_cast<size_t>(width); u++) { - unsigned int val = line_ptr[u]; + unsigned int val; + // val = line_ptr[u]; + tinyexr::cpy4(&val, line_ptr + u); tinyexr::swap4(&val); @@ -9521,7 +9713,9 @@ static bool DecodePixelData(/* out */ unsigned char **out_images, v * pixel_data_size * static_cast<size_t>(x_stride) + channel_offset_list[c] * static_cast<size_t>(x_stride))); for (size_t u = 0; u < static_cast<size_t>(width); u++) { - float val = line_ptr[u]; + float val; + // val = line_ptr[u]; + tinyexr::cpy4(&val, line_ptr + u); tinyexr::swap4(reinterpret_cast<unsigned int *>(&val)); @@ -9557,9 +9751,9 @@ static bool DecodePixelData(/* out */ unsigned char **out_images, unsigned long dstLen = static_cast<unsigned long>(outBuf.size()); assert(dstLen > 0); - if (!tinyexr::DecompressZip(reinterpret_cast<unsigned char *>(&outBuf.at(0)), - &dstLen, data_ptr, - static_cast<unsigned long>(data_len))) { + if (!tinyexr::DecompressZip( + reinterpret_cast<unsigned char *>(&outBuf.at(0)), &dstLen, data_ptr, + static_cast<unsigned long>(data_len))) { return false; } @@ -9583,7 +9777,8 @@ static bool DecodePixelData(/* out */ unsigned char **out_images, for (size_t u = 0; u < static_cast<size_t>(width); u++) { tinyexr::FP16 hf; - hf.u = line_ptr[u]; + // hf.u = line_ptr[u]; + tinyexr::cpy2(&(hf.u), line_ptr + u); tinyexr::swap2(reinterpret_cast<unsigned short *>(&hf.u)); @@ -9626,7 +9821,9 @@ static bool DecodePixelData(/* out */ unsigned char **out_images, &outBuf.at(v * pixel_data_size * static_cast<size_t>(width) + channel_offset_list[c] * static_cast<size_t>(width))); for (size_t u = 0; u < static_cast<size_t>(width); u++) { - unsigned int val = line_ptr[u]; + unsigned int val; + // val = line_ptr[u]; + tinyexr::cpy4(&val, line_ptr + u); tinyexr::swap4(&val); @@ -9652,7 +9849,9 @@ static bool DecodePixelData(/* out */ unsigned char **out_images, &outBuf.at(v * pixel_data_size * static_cast<size_t>(width) + channel_offset_list[c] * static_cast<size_t>(width))); for (size_t u = 0; u < static_cast<size_t>(width); u++) { - float val = line_ptr[u]; + float val; + // val = line_ptr[u]; + tinyexr::cpy4(&val, line_ptr + u); tinyexr::swap4(reinterpret_cast<unsigned int *>(&val)); @@ -9707,7 +9906,8 @@ static bool DecodePixelData(/* out */ unsigned char **out_images, for (size_t u = 0; u < static_cast<size_t>(width); u++) { tinyexr::FP16 hf; - hf.u = line_ptr[u]; + // hf.u = line_ptr[u]; + tinyexr::cpy2(&(hf.u), line_ptr + u); tinyexr::swap2(reinterpret_cast<unsigned short *>(&hf.u)); @@ -9750,7 +9950,9 @@ static bool DecodePixelData(/* out */ unsigned char **out_images, &outBuf.at(v * pixel_data_size * static_cast<size_t>(width) + channel_offset_list[c] * static_cast<size_t>(width))); for (size_t u = 0; u < static_cast<size_t>(width); u++) { - unsigned int val = line_ptr[u]; + unsigned int val; + // val = line_ptr[u]; + tinyexr::cpy4(&val, line_ptr + u); tinyexr::swap4(&val); @@ -9776,7 +9978,9 @@ static bool DecodePixelData(/* out */ unsigned char **out_images, &outBuf.at(v * pixel_data_size * static_cast<size_t>(width) + channel_offset_list[c] * static_cast<size_t>(width))); for (size_t u = 0; u < static_cast<size_t>(width); u++) { - float val = line_ptr[u]; + float val; + // val = line_ptr[u]; + tinyexr::cpy4(&val, line_ptr + u); tinyexr::swap4(reinterpret_cast<unsigned int *>(&val)); @@ -9839,7 +10043,8 @@ static bool DecodePixelData(/* out */ unsigned char **out_images, &outBuf.at(v * pixel_data_size * static_cast<size_t>(width) + channel_offset_list[c] * static_cast<size_t>(width))); for (size_t u = 0; u < static_cast<size_t>(width); u++) { - float val = line_ptr[u]; + float val; + tinyexr::cpy4(&val, line_ptr + u); tinyexr::swap4(reinterpret_cast<unsigned int *>(&val)); @@ -9871,88 +10076,116 @@ static bool DecodePixelData(/* out */ unsigned char **out_images, #endif } else if (compression_type == TINYEXR_COMPRESSIONTYPE_NONE) { for (size_t c = 0; c < num_channels; c++) { - if (channels[c].pixel_type == TINYEXR_PIXELTYPE_HALF) { - const unsigned short *line_ptr = - reinterpret_cast<const unsigned short *>( - data_ptr + - c * static_cast<size_t>(width) * sizeof(unsigned short)); - - if (requested_pixel_types[c] == TINYEXR_PIXELTYPE_HALF) { - unsigned short *outLine = - reinterpret_cast<unsigned short *>(out_images[c]); - if (line_order == 0) { - outLine += y * x_stride; - } else { - outLine += (height - 1 - y) * x_stride; - } + for (size_t v = 0; v < static_cast<size_t>(num_lines); v++) { + if (channels[c].pixel_type == TINYEXR_PIXELTYPE_HALF) { + const unsigned short *line_ptr = + reinterpret_cast<const unsigned short *>( + data_ptr + v * pixel_data_size * size_t(width) + + channel_offset_list[c] * static_cast<size_t>(width)); + + if (requested_pixel_types[c] == TINYEXR_PIXELTYPE_HALF) { + unsigned short *outLine = + reinterpret_cast<unsigned short *>(out_images[c]); + if (line_order == 0) { + outLine += (y + v) * x_stride; + } else { + outLine += (height - 1 - (y + v)) * x_stride; + } - for (int u = 0; u < width; u++) { - tinyexr::FP16 hf; + for (int u = 0; u < width; u++) { + tinyexr::FP16 hf; - hf.u = line_ptr[u]; + // hf.u = line_ptr[u]; + tinyexr::cpy2(&(hf.u), line_ptr + u); - tinyexr::swap2(reinterpret_cast<unsigned short *>(&hf.u)); + tinyexr::swap2(reinterpret_cast<unsigned short *>(&hf.u)); + + outLine[u] = hf.u; + } + } else if (requested_pixel_types[c] == TINYEXR_PIXELTYPE_FLOAT) { + float *outLine = reinterpret_cast<float *>(out_images[c]); + if (line_order == 0) { + outLine += (y + v) * x_stride; + } else { + outLine += (height - 1 - (y + v)) * x_stride; + } - outLine[u] = hf.u; + if (reinterpret_cast<const unsigned char *>(line_ptr + width) > + (data_ptr + data_len)) { + // Insufficient data size + return false; + } + + for (int u = 0; u < width; u++) { + tinyexr::FP16 hf; + + // address may not be aliged. use byte-wise copy for safety.#76 + // hf.u = line_ptr[u]; + tinyexr::cpy2(&(hf.u), line_ptr + u); + + tinyexr::swap2(reinterpret_cast<unsigned short *>(&hf.u)); + + tinyexr::FP32 f32 = half_to_float(hf); + + outLine[u] = f32.f; + } + } else { + assert(0); + return false; } - } else if (requested_pixel_types[c] == TINYEXR_PIXELTYPE_FLOAT) { + } else if (channels[c].pixel_type == TINYEXR_PIXELTYPE_FLOAT) { + const float *line_ptr = reinterpret_cast<const float *>( + data_ptr + v * pixel_data_size * size_t(width) + + channel_offset_list[c] * static_cast<size_t>(width)); + float *outLine = reinterpret_cast<float *>(out_images[c]); if (line_order == 0) { - outLine += y * x_stride; + outLine += (y + v) * x_stride; } else { - outLine += (height - 1 - y) * x_stride; + outLine += (height - 1 - (y + v)) * x_stride; } - for (int u = 0; u < width; u++) { - tinyexr::FP16 hf; - - hf.u = line_ptr[u]; - - tinyexr::swap2(reinterpret_cast<unsigned short *>(&hf.u)); - - tinyexr::FP32 f32 = half_to_float(hf); - - outLine[u] = f32.f; + if (reinterpret_cast<const unsigned char *>(line_ptr + width) > + (data_ptr + data_len)) { + // Insufficient data size + return false; } - } else { - assert(0); - return false; - } - } else if (channels[c].pixel_type == TINYEXR_PIXELTYPE_FLOAT) { - const float *line_ptr = reinterpret_cast<const float *>( - data_ptr + c * static_cast<size_t>(width) * sizeof(float)); - float *outLine = reinterpret_cast<float *>(out_images[c]); - if (line_order == 0) { - outLine += y * x_stride; - } else { - outLine += (height - 1 - y) * x_stride; - } + for (int u = 0; u < width; u++) { + float val; + tinyexr::cpy4(&val, line_ptr + u); - for (int u = 0; u < width; u++) { - float val = line_ptr[u]; + tinyexr::swap4(reinterpret_cast<unsigned int *>(&val)); - tinyexr::swap4(reinterpret_cast<unsigned int *>(&val)); + outLine[u] = val; + } + } else if (channels[c].pixel_type == TINYEXR_PIXELTYPE_UINT) { + const unsigned int *line_ptr = reinterpret_cast<const unsigned int *>( + data_ptr + v * pixel_data_size * size_t(width) + + channel_offset_list[c] * static_cast<size_t>(width)); - outLine[u] = val; - } - } else if (channels[c].pixel_type == TINYEXR_PIXELTYPE_UINT) { - const unsigned int *line_ptr = reinterpret_cast<const unsigned int *>( - data_ptr + c * static_cast<size_t>(width) * sizeof(unsigned int)); + unsigned int *outLine = + reinterpret_cast<unsigned int *>(out_images[c]); + if (line_order == 0) { + outLine += (y + v) * x_stride; + } else { + outLine += (height - 1 - (y + v)) * x_stride; + } - unsigned int *outLine = reinterpret_cast<unsigned int *>(out_images[c]); - if (line_order == 0) { - outLine += y * x_stride; - } else { - outLine += (height - 1 - y) * x_stride; - } + for (int u = 0; u < width; u++) { + if (reinterpret_cast<const unsigned char *>(line_ptr + u) >= + (data_ptr + data_len)) { + // Corrupsed data? + return false; + } - for (int u = 0; u < width; u++) { - unsigned int val = line_ptr[u]; + unsigned int val; + tinyexr::cpy4(&val, line_ptr + u); - tinyexr::swap4(reinterpret_cast<unsigned int *>(&val)); + tinyexr::swap4(reinterpret_cast<unsigned int *>(&val)); - outLine[u] = val; + outLine[u] = val; + } } } } @@ -9994,7 +10227,7 @@ static void DecodeTiledPixelData( num_channels, channels, channel_offset_list); } -static void ComputeChannelLayout(std::vector<size_t> *channel_offset_list, +static bool ComputeChannelLayout(std::vector<size_t> *channel_offset_list, int *pixel_data_size, size_t *channel_offset, int num_channels, const EXRChannelInfo *channels) { @@ -10015,9 +10248,11 @@ static void ComputeChannelLayout(std::vector<size_t> *channel_offset_list, (*pixel_data_size) += sizeof(unsigned int); (*channel_offset) += sizeof(unsigned int); } else { - assert(0); + // ??? + return false; } } + return true; } static unsigned char **AllocateImage(int num_channels, @@ -10125,8 +10360,11 @@ static int ParseEXRHeader(HeaderInfo *info, bool *empty_header, // Read attributes size_t orig_size = size; - for (;;) { + for (size_t nattr = 0; nattr < TINYEXR_MAX_HEADER_ATTRIBUTES; nattr++) { if (0 == size) { + if (err) { + (*err) += "Insufficient data size for attributes.\n"; + } return TINYEXR_ERROR_INVALID_DATA; } else if (marker[0] == '\0') { size--; @@ -10139,6 +10377,9 @@ static int ParseEXRHeader(HeaderInfo *info, bool *empty_header, size_t marker_size; if (!tinyexr::ReadAttribute(&attr_name, &attr_type, &data, &marker_size, marker, size)) { + if (err) { + (*err) += "Failed to read attribute.\n"; + } return TINYEXR_ERROR_INVALID_DATA; } marker += marker_size; @@ -10209,14 +10450,14 @@ static int ParseEXRHeader(HeaderInfo *info, bool *empty_header, if (!ReadChannelInfo(info->channels, data)) { if (err) { - (*err) = "Failed to parse channel info."; + (*err) += "Failed to parse channel info.\n"; } return TINYEXR_ERROR_INVALID_DATA; } if (info->channels.size() < 1) { if (err) { - (*err) = "# of channels is zero."; + (*err) += "# of channels is zero.\n"; } return TINYEXR_ERROR_INVALID_DATA; } @@ -10224,9 +10465,7 @@ static int ParseEXRHeader(HeaderInfo *info, bool *empty_header, has_channels = true; } else if (attr_name.compare("dataWindow") == 0) { - if (data.size() < 16) { - // Corrupsed file(Issue #50). - } else { + if (data.size() >= 16) { memcpy(&info->data_window[0], &data.at(0), sizeof(int)); memcpy(&info->data_window[1], &data.at(4), sizeof(int)); memcpy(&info->data_window[2], &data.at(8), sizeof(int)); @@ -10238,48 +10477,60 @@ static int ParseEXRHeader(HeaderInfo *info, bool *empty_header, has_data_window = true; } } else if (attr_name.compare("displayWindow") == 0) { - memcpy(&info->display_window[0], &data.at(0), sizeof(int)); - memcpy(&info->display_window[1], &data.at(4), sizeof(int)); - memcpy(&info->display_window[2], &data.at(8), sizeof(int)); - memcpy(&info->display_window[3], &data.at(12), sizeof(int)); - tinyexr::swap4( - reinterpret_cast<unsigned int *>(&info->display_window[0])); - tinyexr::swap4( - reinterpret_cast<unsigned int *>(&info->display_window[1])); - tinyexr::swap4( - reinterpret_cast<unsigned int *>(&info->display_window[2])); - tinyexr::swap4( - reinterpret_cast<unsigned int *>(&info->display_window[3])); - - has_display_window = true; + if (data.size() >= 16) { + memcpy(&info->display_window[0], &data.at(0), sizeof(int)); + memcpy(&info->display_window[1], &data.at(4), sizeof(int)); + memcpy(&info->display_window[2], &data.at(8), sizeof(int)); + memcpy(&info->display_window[3], &data.at(12), sizeof(int)); + tinyexr::swap4( + reinterpret_cast<unsigned int *>(&info->display_window[0])); + tinyexr::swap4( + reinterpret_cast<unsigned int *>(&info->display_window[1])); + tinyexr::swap4( + reinterpret_cast<unsigned int *>(&info->display_window[2])); + tinyexr::swap4( + reinterpret_cast<unsigned int *>(&info->display_window[3])); + + has_display_window = true; + } } else if (attr_name.compare("lineOrder") == 0) { - info->line_order = static_cast<int>(data[0]); - has_line_order = true; + if (data.size() >= 1) { + info->line_order = static_cast<int>(data[0]); + has_line_order = true; + } } else if (attr_name.compare("pixelAspectRatio") == 0) { - memcpy(&info->pixel_aspect_ratio, &data.at(0), sizeof(float)); - tinyexr::swap4( - reinterpret_cast<unsigned int *>(&info->pixel_aspect_ratio)); - has_pixel_aspect_ratio = true; + if (data.size() >= sizeof(float)) { + memcpy(&info->pixel_aspect_ratio, &data.at(0), sizeof(float)); + tinyexr::swap4( + reinterpret_cast<unsigned int *>(&info->pixel_aspect_ratio)); + has_pixel_aspect_ratio = true; + } } else if (attr_name.compare("screenWindowCenter") == 0) { - memcpy(&info->screen_window_center[0], &data.at(0), sizeof(float)); - memcpy(&info->screen_window_center[1], &data.at(4), sizeof(float)); - tinyexr::swap4( - reinterpret_cast<unsigned int *>(&info->screen_window_center[0])); - tinyexr::swap4( - reinterpret_cast<unsigned int *>(&info->screen_window_center[1])); - has_screen_window_center = true; + if (data.size() >= 8) { + memcpy(&info->screen_window_center[0], &data.at(0), sizeof(float)); + memcpy(&info->screen_window_center[1], &data.at(4), sizeof(float)); + tinyexr::swap4( + reinterpret_cast<unsigned int *>(&info->screen_window_center[0])); + tinyexr::swap4( + reinterpret_cast<unsigned int *>(&info->screen_window_center[1])); + has_screen_window_center = true; + } } else if (attr_name.compare("screenWindowWidth") == 0) { - memcpy(&info->screen_window_width, &data.at(0), sizeof(float)); - tinyexr::swap4( - reinterpret_cast<unsigned int *>(&info->screen_window_width)); + if (data.size() >= sizeof(float)) { + memcpy(&info->screen_window_width, &data.at(0), sizeof(float)); + tinyexr::swap4( + reinterpret_cast<unsigned int *>(&info->screen_window_width)); - has_screen_window_width = true; + has_screen_window_width = true; + } } else if (attr_name.compare("chunkCount") == 0) { - memcpy(&info->chunk_count, &data.at(0), sizeof(int)); - tinyexr::swap4(reinterpret_cast<unsigned int *>(&info->chunk_count)); + if (data.size() >= sizeof(int)) { + memcpy(&info->chunk_count, &data.at(0), sizeof(int)); + tinyexr::swap4(reinterpret_cast<unsigned int *>(&info->chunk_count)); + } } else { - // Custom attribute(up to TINYEXR_MAX_ATTRIBUTES) - if (info->attributes.size() < TINYEXR_MAX_ATTRIBUTES) { + // Custom attribute(up to TINYEXR_MAX_CUSTOM_ATTRIBUTES) + if (info->attributes.size() < TINYEXR_MAX_CUSTOM_ATTRIBUTES) { EXRAttribute attrib; #ifdef _MSC_VER strncpy_s(attrib.name, attr_name.c_str(), 255); @@ -10409,15 +10660,30 @@ static void ConvertHeader(EXRHeader *exr_header, const HeaderInfo &info) { exr_header->requested_pixel_types[c] = info.channels[c].pixel_type; } - assert(info.attributes.size() < TINYEXR_MAX_ATTRIBUTES); exr_header->num_custom_attributes = static_cast<int>(info.attributes.size()); - for (size_t i = 0; i < info.attributes.size(); i++) { - memcpy(exr_header->custom_attributes[i].name, info.attributes[i].name, 256); - memcpy(exr_header->custom_attributes[i].type, info.attributes[i].type, 256); - exr_header->custom_attributes[i].size = info.attributes[i].size; - // Just copy poiner - exr_header->custom_attributes[i].value = info.attributes[i].value; + if (exr_header->num_custom_attributes > 0) { + // TODO(syoyo): Report warning when # of attributes exceeds + // `TINYEXR_MAX_CUSTOM_ATTRIBUTES` + if (exr_header->num_custom_attributes > TINYEXR_MAX_CUSTOM_ATTRIBUTES) { + exr_header->num_custom_attributes = TINYEXR_MAX_CUSTOM_ATTRIBUTES; + } + + exr_header->custom_attributes = static_cast<EXRAttribute *>(malloc( + sizeof(EXRAttribute) * size_t(exr_header->num_custom_attributes))); + + for (size_t i = 0; i < info.attributes.size(); i++) { + memcpy(exr_header->custom_attributes[i].name, info.attributes[i].name, + 256); + memcpy(exr_header->custom_attributes[i].type, info.attributes[i].type, + 256); + exr_header->custom_attributes[i].size = info.attributes[i].size; + // Just copy poiner + exr_header->custom_attributes[i].value = info.attributes[i].value; + } + + } else { + exr_header->custom_attributes = NULL; } exr_header->header_len = info.header_len; @@ -10425,7 +10691,8 @@ static void ConvertHeader(EXRHeader *exr_header, const HeaderInfo &info) { static int DecodeChunk(EXRImage *exr_image, const EXRHeader *exr_header, const std::vector<tinyexr::tinyexr_uint64> &offsets, - const unsigned char *head, const size_t size) { + const unsigned char *head, const size_t size, + std::string *err) { int num_channels = exr_header->num_channels; int num_scanline_blocks = 1; @@ -10445,32 +10712,40 @@ static int DecodeChunk(EXRImage *exr_image, const EXRHeader *exr_header, std::vector<size_t> channel_offset_list; int pixel_data_size = 0; size_t channel_offset = 0; - tinyexr::ComputeChannelLayout(&channel_offset_list, &pixel_data_size, - &channel_offset, num_channels, - exr_header->channels); + if (!tinyexr::ComputeChannelLayout(&channel_offset_list, &pixel_data_size, + &channel_offset, num_channels, + exr_header->channels)) { + if (err) { + (*err) += "Failed to compute channel layout.\n"; + } + return TINYEXR_ERROR_INVALID_DATA; + } - bool invalid_data = false; + bool invalid_data = false; // TODO(LTE): Use atomic lock for MT safety. if (exr_header->tiled) { size_t num_tiles = offsets.size(); // = # of blocks exr_image->tiles = static_cast<EXRTile *>( - malloc(sizeof(EXRTile) * static_cast<size_t>(num_tiles))); + calloc(sizeof(EXRTile), static_cast<size_t>(num_tiles))); for (size_t tile_idx = 0; tile_idx < num_tiles; tile_idx++) { // Allocate memory for each tile. exr_image->tiles[tile_idx].images = tinyexr::AllocateImage( num_channels, exr_header->channels, exr_header->requested_pixel_types, - data_width, data_height); + exr_header->tile_size_x, exr_header->tile_size_y); // 16 byte: tile coordinates // 4 byte : data size // ~ : data(uncompressed or compressed) if (offsets[tile_idx] + sizeof(int) * 5 > size) { + if (err) { + (*err) += "Insufficient data size.\n"; + } return TINYEXR_ERROR_INVALID_DATA; } - size_t data_size = size - (offsets[tile_idx] + sizeof(int) * 5); + size_t data_size = size_t(size - (offsets[tile_idx] + sizeof(int) * 5)); const unsigned char *data_ptr = reinterpret_cast<const unsigned char *>(head + offsets[tile_idx]); @@ -10482,8 +10757,12 @@ static int DecodeChunk(EXRImage *exr_image, const EXRHeader *exr_header, tinyexr::swap4(reinterpret_cast<unsigned int *>(&tile_coordinates[3])); // @todo{ LoD } - assert(tile_coordinates[2] == 0); - assert(tile_coordinates[3] == 0); + if (tile_coordinates[2] != 0) { + return TINYEXR_ERROR_UNSUPPORTED_FEATURE; + } + if (tile_coordinates[3] != 0) { + return TINYEXR_ERROR_UNSUPPORTED_FEATURE; + } int data_len; memcpy(&data_len, data_ptr + 16, @@ -10491,6 +10770,9 @@ static int DecodeChunk(EXRImage *exr_image, const EXRHeader *exr_header, tinyexr::swap4(reinterpret_cast<unsigned int *>(&data_len)); if (data_len < 4 || size_t(data_len) > data_size) { + if (err) { + (*err) += "Insufficient data length.\n"; + } return TINYEXR_ERROR_INVALID_DATA; } @@ -10531,56 +10813,56 @@ static int DecodeChunk(EXRImage *exr_image, const EXRHeader *exr_header, size_t y_idx = static_cast<size_t>(y); if (offsets[y_idx] + sizeof(int) * 2 > size) { - return TINYEXR_ERROR_INVALID_DATA; - } - - // 4 byte: scan line - // 4 byte: data size - // ~ : pixel data(uncompressed or compressed) - size_t data_size = size - (offsets[y_idx] + sizeof(int) * 2); - const unsigned char *data_ptr = - reinterpret_cast<const unsigned char *>(head + offsets[y_idx]); - - int line_no; - memcpy(&line_no, data_ptr, sizeof(int)); - int data_len; - memcpy(&data_len, data_ptr + 4, sizeof(int)); - tinyexr::swap4(reinterpret_cast<unsigned int *>(&line_no)); - tinyexr::swap4(reinterpret_cast<unsigned int *>(&data_len)); - - if (size_t(data_len) > data_size) { - return TINYEXR_ERROR_INVALID_DATA; - } - - int end_line_no = (std::min)(line_no + num_scanline_blocks, - (exr_header->data_window[3] + 1)); - - int num_lines = end_line_no - line_no; - //assert(num_lines > 0); - - if (num_lines <= 0) { invalid_data = true; } else { - - // Move to data addr: 8 = 4 + 4; - data_ptr += 8; - - // Adjust line_no with data_window.bmin.y - line_no -= exr_header->data_window[1]; - - if (line_no < 0) { + // 4 byte: scan line + // 4 byte: data size + // ~ : pixel data(uncompressed or compressed) + size_t data_size = size_t(size - (offsets[y_idx] + sizeof(int) * 2)); + const unsigned char *data_ptr = + reinterpret_cast<const unsigned char *>(head + offsets[y_idx]); + + int line_no; + memcpy(&line_no, data_ptr, sizeof(int)); + int data_len; + memcpy(&data_len, data_ptr + 4, sizeof(int)); + tinyexr::swap4(reinterpret_cast<unsigned int *>(&line_no)); + tinyexr::swap4(reinterpret_cast<unsigned int *>(&data_len)); + + if (size_t(data_len) > data_size) { invalid_data = true; } else { - if (!tinyexr::DecodePixelData( - exr_image->images, exr_header->requested_pixel_types, data_ptr, - static_cast<size_t>(data_len), exr_header->compression_type, - exr_header->line_order, data_width, data_height, data_width, y, - line_no, num_lines, static_cast<size_t>(pixel_data_size), - static_cast<size_t>(exr_header->num_custom_attributes), - exr_header->custom_attributes, - static_cast<size_t>(exr_header->num_channels), exr_header->channels, - channel_offset_list)) { + int end_line_no = (std::min)(line_no + num_scanline_blocks, + (exr_header->data_window[3] + 1)); + + int num_lines = end_line_no - line_no; + // assert(num_lines > 0); + + if (num_lines <= 0) { invalid_data = true; + } else { + // Move to data addr: 8 = 4 + 4; + data_ptr += 8; + + // Adjust line_no with data_window.bmin.y + line_no -= exr_header->data_window[1]; + + if (line_no < 0) { + invalid_data = true; + } else { + if (!tinyexr::DecodePixelData( + exr_image->images, exr_header->requested_pixel_types, + data_ptr, static_cast<size_t>(data_len), + exr_header->compression_type, exr_header->line_order, + data_width, data_height, data_width, y, line_no, + num_lines, static_cast<size_t>(pixel_data_size), + static_cast<size_t>(exr_header->num_custom_attributes), + exr_header->custom_attributes, + static_cast<size_t>(exr_header->num_channels), + exr_header->channels, channel_offset_list)) { + invalid_data = true; + } + } } } } @@ -10648,9 +10930,7 @@ static int DecodeEXRImage(EXRImage *exr_image, const EXRHeader *exr_header, const char **err) { if (exr_image == NULL || exr_header == NULL || head == NULL || marker == NULL || (size <= tinyexr::kEXRVersionSize)) { - if (err) { - (*err) = "Invalid argument."; - } + tinyexr::SetErrorMessage("Invalid argument for DecodeEXRImage().", err); return TINYEXR_ERROR_INVALID_ARGUMENT; } @@ -10663,13 +10943,23 @@ static int DecodeEXRImage(EXRImage *exr_image, const EXRHeader *exr_header, num_scanline_blocks = 16; } - int data_width = exr_header->data_window[2] - exr_header->data_window[0] + 1; - int data_height = exr_header->data_window[3] - exr_header->data_window[1] + 1; + int data_width = exr_header->data_window[2] - exr_header->data_window[0]; + if (data_width >= std::numeric_limits<int>::max()) { + // Issue 63 + tinyexr::SetErrorMessage("Invalid data window value", err); + return TINYEXR_ERROR_INVALID_DATA; + } + data_width++; + + int data_height = exr_header->data_window[3] - exr_header->data_window[1]; + if (data_height >= std::numeric_limits<int>::max()) { + tinyexr::SetErrorMessage("Invalid data height value", err); + return TINYEXR_ERROR_INVALID_DATA; + } + data_height++; if ((data_width < 0) || (data_height < 0)) { - if (err) { - (*err) = "Invalid data window value."; - } + tinyexr::SetErrorMessage("data window or data height is negative.", err); return TINYEXR_ERROR_INVALID_DATA; } @@ -10708,12 +10998,16 @@ static int DecodeEXRImage(EXRImage *exr_image, const EXRHeader *exr_header, for (size_t y = 0; y < num_blocks; y++) { tinyexr::tinyexr_uint64 offset; + // Issue #81 + if ((marker + sizeof(tinyexr_uint64)) >= (head + size)) { + tinyexr::SetErrorMessage("Insufficient data size in offset table.", err); + return TINYEXR_ERROR_INVALID_DATA; + } + memcpy(&offset, marker, sizeof(tinyexr::tinyexr_uint64)); tinyexr::swap8(&offset); if (offset >= size) { - if (err) { - (*err) = "Invalid offset value."; - } + tinyexr::SetErrorMessage("Invalid offset value in DecodeEXRImage.", err); return TINYEXR_ERROR_INVALID_DATA; } marker += sizeof(tinyexr::tinyexr_uint64); // = 8 @@ -10736,15 +11030,37 @@ static int DecodeEXRImage(EXRImage *exr_image, const EXRHeader *exr_header, // OK break; } else { - if (err) { - (*err) = "Cannot reconstruct lineOffset table."; - } + tinyexr::SetErrorMessage( + "Cannot reconstruct lineOffset table in DecodeEXRImage.", err); return TINYEXR_ERROR_INVALID_DATA; } } } - return DecodeChunk(exr_image, exr_header, offsets, head, size); + { + std::string e; + int ret = DecodeChunk(exr_image, exr_header, offsets, head, size, &e); + + if (ret != TINYEXR_SUCCESS) { + if (!e.empty()) { + tinyexr::SetErrorMessage(e, err); + } + + // release memory(if exists) + if ((exr_header->num_channels > 0) && exr_image && exr_image->images) { + for (size_t c = 0; c < size_t(exr_header->num_channels); c++) { + if (exr_image->images[c]) { + free(exr_image->images[c]); + exr_image->images[c] = NULL; + } + } + free(exr_image->images); + exr_image->images = NULL; + } + } + + return ret; + } } } // namespace tinyexr @@ -10752,9 +11068,7 @@ static int DecodeEXRImage(EXRImage *exr_image, const EXRHeader *exr_header, int LoadEXR(float **out_rgba, int *width, int *height, const char *filename, const char **err) { if (out_rgba == NULL) { - if (err) { - (*err) = "Invalid argument.\n"; - } + tinyexr::SetErrorMessage("Invalid argument for LoadEXR()", err); return TINYEXR_ERROR_INVALID_ARGUMENT; } @@ -10767,13 +11081,14 @@ int LoadEXR(float **out_rgba, int *width, int *height, const char *filename, { int ret = ParseEXRVersionFromFile(&exr_version, filename); if (ret != TINYEXR_SUCCESS) { + tinyexr::SetErrorMessage("Invalid EXR header.", err); return ret; } if (exr_version.multipart || exr_version.non_image) { - if (err) { - (*err) = "Loading multipart or DeepImage is not supported yet.\n"; - } + tinyexr::SetErrorMessage( + "Loading multipart or DeepImage is not supported in LoadEXR() API", + err); return TINYEXR_ERROR_INVALID_DATA; // @fixme. } } @@ -10781,6 +11096,7 @@ int LoadEXR(float **out_rgba, int *width, int *height, const char *filename, { int ret = ParseEXRHeaderFromFile(&exr_header, &exr_version, filename, err); if (ret != TINYEXR_SUCCESS) { + FreeEXRHeader(&exr_header); return ret; } } @@ -10795,6 +11111,7 @@ int LoadEXR(float **out_rgba, int *width, int *height, const char *filename, { int ret = LoadEXRImageFromFile(&exr_image, &exr_header, filename, err); if (ret != TINYEXR_SUCCESS) { + FreeEXRHeader(&exr_header); return ret; } } @@ -10819,6 +11136,9 @@ int LoadEXR(float **out_rgba, int *width, int *height, const char *filename, if ((idxA == 0) && (idxR == -1) && (idxG == -1) && (idxB == -1)) { // Alpha channel only. + if (exr_header.tiled) { + // todo.implement this + } (*out_rgba) = reinterpret_cast<float *>( malloc(4 * sizeof(float) * static_cast<size_t>(exr_image.width) * static_cast<size_t>(exr_image.height))); @@ -10833,45 +11153,77 @@ int LoadEXR(float **out_rgba, int *width, int *height, const char *filename, // Assume RGB(A) if (idxR == -1) { - if (err) { - (*err) = "R channel not found\n"; - } + tinyexr::SetErrorMessage("R channel not found", err); // @todo { free exr_image } + FreeEXRHeader(&exr_header); return TINYEXR_ERROR_INVALID_DATA; } if (idxG == -1) { - if (err) { - (*err) = "G channel not found\n"; - } + tinyexr::SetErrorMessage("G channel not found", err); // @todo { free exr_image } + FreeEXRHeader(&exr_header); return TINYEXR_ERROR_INVALID_DATA; } if (idxB == -1) { - if (err) { - (*err) = "B channel not found\n"; - } + tinyexr::SetErrorMessage("B channel not found", err); // @todo { free exr_image } + FreeEXRHeader(&exr_header); return TINYEXR_ERROR_INVALID_DATA; } (*out_rgba) = reinterpret_cast<float *>( malloc(4 * sizeof(float) * static_cast<size_t>(exr_image.width) * static_cast<size_t>(exr_image.height))); - for (int i = 0; i < exr_image.width * exr_image.height; i++) { - (*out_rgba)[4 * i + 0] = - reinterpret_cast<float **>(exr_image.images)[idxR][i]; - (*out_rgba)[4 * i + 1] = - reinterpret_cast<float **>(exr_image.images)[idxG][i]; - (*out_rgba)[4 * i + 2] = - reinterpret_cast<float **>(exr_image.images)[idxB][i]; - if (idxA != -1) { - (*out_rgba)[4 * i + 3] = - reinterpret_cast<float **>(exr_image.images)[idxA][i]; - } else { - (*out_rgba)[4 * i + 3] = 1.0; + if (exr_header.tiled) { + for (int it = 0; it < exr_image.num_tiles; it++) { + for (int j = 0; j < exr_header.tile_size_y; j++) + for (int i = 0; i < exr_header.tile_size_x; i++) { + const int ii = + exr_image.tiles[it].offset_x * exr_header.tile_size_x + i; + const int jj = + exr_image.tiles[it].offset_y * exr_header.tile_size_y + j; + const int idx = ii + jj * exr_image.width; + + // out of region check. + if (ii >= exr_image.width) { + continue; + } + if (jj >= exr_image.height) { + continue; + } + const int srcIdx = i + j * exr_header.tile_size_x; + unsigned char **src = exr_image.tiles[it].images; + (*out_rgba)[4 * idx + 0] = + reinterpret_cast<float **>(src)[idxR][srcIdx]; + (*out_rgba)[4 * idx + 1] = + reinterpret_cast<float **>(src)[idxG][srcIdx]; + (*out_rgba)[4 * idx + 2] = + reinterpret_cast<float **>(src)[idxB][srcIdx]; + if (idxA != -1) { + (*out_rgba)[4 * idx + 3] = + reinterpret_cast<float **>(src)[idxA][srcIdx]; + } else { + (*out_rgba)[4 * idx + 3] = 1.0; + } + } + } + } else { + for (int i = 0; i < exr_image.width * exr_image.height; i++) { + (*out_rgba)[4 * i + 0] = + reinterpret_cast<float **>(exr_image.images)[idxR][i]; + (*out_rgba)[4 * i + 1] = + reinterpret_cast<float **>(exr_image.images)[idxG][i]; + (*out_rgba)[4 * i + 2] = + reinterpret_cast<float **>(exr_image.images)[idxB][i]; + if (idxA != -1) { + (*out_rgba)[4 * i + 3] = + reinterpret_cast<float **>(exr_image.images)[idxA][i]; + } else { + (*out_rgba)[4 * i + 3] = 1.0; + } } } } @@ -10889,15 +11241,17 @@ int ParseEXRHeaderFromMemory(EXRHeader *exr_header, const EXRVersion *version, const unsigned char *memory, size_t size, const char **err) { if (memory == NULL || exr_header == NULL) { - if (err) { - (*err) = "Invalid argument.\n"; - } + tinyexr::SetErrorMessage( + "Invalid argument. `memory` or `exr_header` argument is null in " + "ParseEXRHeaderFromMemory()", + err); // Invalid argument return TINYEXR_ERROR_INVALID_ARGUMENT; } if (size < tinyexr::kEXRVersionSize) { + tinyexr::SetErrorMessage("Insufficient header/data size.\n", err); return TINYEXR_ERROR_INVALID_DATA; } @@ -10912,11 +11266,7 @@ int ParseEXRHeaderFromMemory(EXRHeader *exr_header, const EXRVersion *version, if (ret != TINYEXR_SUCCESS) { if (err && !err_str.empty()) { -#ifdef _WIN32 - (*err) = _strdup(err_str.c_str()); // May leak -#else - (*err) = strdup(err_str.c_str()); // May leak -#endif + tinyexr::SetErrorMessage(err_str, err); } } @@ -10932,9 +11282,7 @@ int LoadEXRFromMemory(float **out_rgba, int *width, int *height, const unsigned char *memory, size_t size, const char **err) { if (out_rgba == NULL || memory == NULL) { - if (err) { - (*err) = "Invalid argument.\n"; - } + tinyexr::SetErrorMessage("Invalid argument for LoadEXRFromMemory", err); return TINYEXR_ERROR_INVALID_ARGUMENT; } @@ -10946,6 +11294,7 @@ int LoadEXRFromMemory(float **out_rgba, int *width, int *height, int ret = ParseEXRVersionFromMemory(&exr_version, memory, size); if (ret != TINYEXR_SUCCESS) { + tinyexr::SetErrorMessage("Failed to parse EXR version", err); return ret; } @@ -10985,26 +11334,20 @@ int LoadEXRFromMemory(float **out_rgba, int *width, int *height, } if (idxR == -1) { - if (err) { - (*err) = "R channel not found\n"; - } + tinyexr::SetErrorMessage("R channel not found", err); // @todo { free exr_image } return TINYEXR_ERROR_INVALID_DATA; } if (idxG == -1) { - if (err) { - (*err) = "G channel not found\n"; - } + tinyexr::SetErrorMessage("G channel not found", err); // @todo { free exr_image } return TINYEXR_ERROR_INVALID_DATA; } if (idxB == -1) { - if (err) { - (*err) = "B channel not found\n"; - } + tinyexr::SetErrorMessage("B channel not found", err); // @todo { free exr_image } return TINYEXR_ERROR_INVALID_DATA; } @@ -11040,9 +11383,7 @@ int LoadEXRFromMemory(float **out_rgba, int *width, int *height, int LoadEXRImageFromFile(EXRImage *exr_image, const EXRHeader *exr_header, const char *filename, const char **err) { if (exr_image == NULL) { - if (err) { - (*err) = "Invalid argument."; - } + tinyexr::SetErrorMessage("Invalid argument for LoadEXRImageFromFile", err); return TINYEXR_ERROR_INVALID_ARGUMENT; } @@ -11053,9 +11394,7 @@ int LoadEXRImageFromFile(EXRImage *exr_image, const EXRHeader *exr_header, FILE *fp = fopen(filename, "rb"); #endif if (!fp) { - if (err) { - (*err) = "Cannot read file."; - } + tinyexr::SetErrorMessage("Cannot read file " + std::string(filename), err); return TINYEXR_ERROR_CANT_OPEN_FILE; } @@ -11065,6 +11404,12 @@ int LoadEXRImageFromFile(EXRImage *exr_image, const EXRHeader *exr_header, filesize = static_cast<size_t>(ftell(fp)); fseek(fp, 0, SEEK_SET); + if (filesize < 16) { + tinyexr::SetErrorMessage("File size too short " + std::string(filename), + err); + return TINYEXR_ERROR_INVALID_FILE; + } + std::vector<unsigned char> buf(filesize); // @todo { use mmap } { size_t ret; @@ -11083,16 +11428,13 @@ int LoadEXRImageFromMemory(EXRImage *exr_image, const EXRHeader *exr_header, const char **err) { if (exr_image == NULL || memory == NULL || (size < tinyexr::kEXRVersionSize)) { - if (err) { - (*err) = "Invalid argument."; - } + tinyexr::SetErrorMessage("Invalid argument for LoadEXRImageFromMemory", + err); return TINYEXR_ERROR_INVALID_ARGUMENT; } if (exr_header->header_len == 0) { - if (err) { - (*err) = "EXRHeader is not initialized."; - } + tinyexr::SetErrorMessage("EXRHeader variable is not initialized.", err); return TINYEXR_ERROR_INVALID_ARGUMENT; } @@ -11109,26 +11451,22 @@ size_t SaveEXRImageToMemory(const EXRImage *exr_image, unsigned char **memory_out, const char **err) { if (exr_image == NULL || memory_out == NULL || exr_header->compression_type < 0) { - if (err) { - (*err) = "Invalid argument."; - } + tinyexr::SetErrorMessage("Invalid argument for SaveEXRImageToMemory", err); return 0; // @fixme } #if !TINYEXR_USE_PIZ if (exr_header->compression_type == TINYEXR_COMPRESSIONTYPE_PIZ) { - if (err) { - (*err) = "PIZ compression is not supported in this build."; - } + tinyexr::SetErrorMessage("PIZ compression is not supported in this build", + err); return 0; } #endif #if !TINYEXR_USE_ZFP if (exr_header->compression_type == TINYEXR_COMPRESSIONTYPE_ZFP) { - if (err) { - (*err) = "ZFP compression is not supported in this build."; - } + tinyexr::SetErrorMessage("ZFP compression is not supported in this build", + err); return 0; } #endif @@ -11136,9 +11474,8 @@ size_t SaveEXRImageToMemory(const EXRImage *exr_image, #if TINYEXR_USE_ZFP for (size_t i = 0; i < static_cast<size_t>(exr_header->num_channels); i++) { if (exr_header->requested_pixel_types[i] != TINYEXR_PIXELTYPE_FLOAT) { - if (err) { - (*err) = "Pixel type must be FLOAT for ZFP compression."; - } + tinyexr::SetErrorMessage("Pixel type must be FLOAT for ZFP compression", + err); return 0; } } @@ -11348,6 +11685,11 @@ size_t SaveEXRImageToMemory(const EXRImage *exr_image, if (exr_header->pixel_types[c] == TINYEXR_PIXELTYPE_HALF) { if (exr_header->requested_pixel_types[c] == TINYEXR_PIXELTYPE_FLOAT) { for (int y = 0; y < h; y++) { + // Assume increasing Y + float *line_ptr = reinterpret_cast<float *>(&buf.at( + static_cast<size_t>(pixel_data_size * y * exr_image->width) + + channel_offset_list[c] * + static_cast<size_t>(exr_image->width))); for (int x = 0; x < exr_image->width; x++) { tinyexr::FP16 h16; h16.u = reinterpret_cast<unsigned short **>( @@ -11357,30 +11699,27 @@ size_t SaveEXRImageToMemory(const EXRImage *exr_image, tinyexr::swap4(reinterpret_cast<unsigned int *>(&f32.f)); - // Assume increasing Y - float *line_ptr = reinterpret_cast<float *>(&buf.at( - static_cast<size_t>(pixel_data_size * y * exr_image->width) + - channel_offset_list[c] * - static_cast<size_t>(exr_image->width))); - line_ptr[x] = f32.f; + // line_ptr[x] = f32.f; + tinyexr::cpy4(line_ptr + x, &(f32.f)); } } } else if (exr_header->requested_pixel_types[c] == TINYEXR_PIXELTYPE_HALF) { for (int y = 0; y < h; y++) { + // Assume increasing Y + unsigned short *line_ptr = reinterpret_cast<unsigned short *>( + &buf.at(static_cast<size_t>(pixel_data_size * y * + exr_image->width) + + channel_offset_list[c] * + static_cast<size_t>(exr_image->width))); for (int x = 0; x < exr_image->width; x++) { unsigned short val = reinterpret_cast<unsigned short **>( exr_image->images)[c][(y + start_y) * exr_image->width + x]; tinyexr::swap2(&val); - // Assume increasing Y - unsigned short *line_ptr = reinterpret_cast<unsigned short *>( - &buf.at(static_cast<size_t>(pixel_data_size * y * - exr_image->width) + - channel_offset_list[c] * - static_cast<size_t>(exr_image->width))); - line_ptr[x] = val; + // line_ptr[x] = val; + tinyexr::cpy2(line_ptr + x, &val); } } } else { @@ -11390,6 +11729,12 @@ size_t SaveEXRImageToMemory(const EXRImage *exr_image, } else if (exr_header->pixel_types[c] == TINYEXR_PIXELTYPE_FLOAT) { if (exr_header->requested_pixel_types[c] == TINYEXR_PIXELTYPE_HALF) { for (int y = 0; y < h; y++) { + // Assume increasing Y + unsigned short *line_ptr = reinterpret_cast<unsigned short *>( + &buf.at(static_cast<size_t>(pixel_data_size * y * + exr_image->width) + + channel_offset_list[c] * + static_cast<size_t>(exr_image->width))); for (int x = 0; x < exr_image->width; x++) { tinyexr::FP32 f32; f32.f = reinterpret_cast<float **>( @@ -11400,30 +11745,26 @@ size_t SaveEXRImageToMemory(const EXRImage *exr_image, tinyexr::swap2(reinterpret_cast<unsigned short *>(&h16.u)); - // Assume increasing Y - unsigned short *line_ptr = reinterpret_cast<unsigned short *>( - &buf.at(static_cast<size_t>(pixel_data_size * y * - exr_image->width) + - channel_offset_list[c] * - static_cast<size_t>(exr_image->width))); - line_ptr[x] = h16.u; + // line_ptr[x] = h16.u; + tinyexr::cpy2(line_ptr + x, &(h16.u)); } } } else if (exr_header->requested_pixel_types[c] == TINYEXR_PIXELTYPE_FLOAT) { for (int y = 0; y < h; y++) { + // Assume increasing Y + float *line_ptr = reinterpret_cast<float *>(&buf.at( + static_cast<size_t>(pixel_data_size * y * exr_image->width) + + channel_offset_list[c] * + static_cast<size_t>(exr_image->width))); for (int x = 0; x < exr_image->width; x++) { float val = reinterpret_cast<float **>( exr_image->images)[c][(y + start_y) * exr_image->width + x]; tinyexr::swap4(reinterpret_cast<unsigned int *>(&val)); - // Assume increasing Y - float *line_ptr = reinterpret_cast<float *>(&buf.at( - static_cast<size_t>(pixel_data_size * y * exr_image->width) + - channel_offset_list[c] * - static_cast<size_t>(exr_image->width))); - line_ptr[x] = val; + // line_ptr[x] = val; + tinyexr::cpy4(line_ptr + x, &val); } } } else { @@ -11431,18 +11772,18 @@ size_t SaveEXRImageToMemory(const EXRImage *exr_image, } } else if (exr_header->pixel_types[c] == TINYEXR_PIXELTYPE_UINT) { for (int y = 0; y < h; y++) { + // Assume increasing Y + unsigned int *line_ptr = reinterpret_cast<unsigned int *>(&buf.at( + static_cast<size_t>(pixel_data_size * y * exr_image->width) + + channel_offset_list[c] * static_cast<size_t>(exr_image->width))); for (int x = 0; x < exr_image->width; x++) { unsigned int val = reinterpret_cast<unsigned int **>( exr_image->images)[c][(y + start_y) * exr_image->width + x]; tinyexr::swap4(&val); - // Assume increasing Y - unsigned int *line_ptr = reinterpret_cast<unsigned int *>(&buf.at( - static_cast<size_t>(pixel_data_size * y * exr_image->width) + - channel_offset_list[c] * - static_cast<size_t>(exr_image->width))); - line_ptr[x] = val; + // line_ptr[x] = val; + tinyexr::cpy4(line_ptr + x, &val); } } } @@ -11611,26 +11952,22 @@ int SaveEXRImageToFile(const EXRImage *exr_image, const EXRHeader *exr_header, const char *filename, const char **err) { if (exr_image == NULL || filename == NULL || exr_header->compression_type < 0) { - if (err) { - (*err) = "Invalid argument."; - } + tinyexr::SetErrorMessage("Invalid argument for SaveEXRImageToFile", err); return TINYEXR_ERROR_INVALID_ARGUMENT; } #if !TINYEXR_USE_PIZ if (exr_header->compression_type == TINYEXR_COMPRESSIONTYPE_PIZ) { - if (err) { - (*err) = "PIZ compression is not supported in this build."; - } + tinyexr::SetErrorMessage("PIZ compression is not supported in this build", + err); return 0; } #endif #if !TINYEXR_USE_ZFP if (exr_header->compression_type == TINYEXR_COMPRESSIONTYPE_ZFP) { - if (err) { - (*err) = "ZFP compression is not supported in this build."; - } + tinyexr::SetErrorMessage("ZFP compression is not supported in this build", + err); return 0; } #endif @@ -11642,9 +11979,7 @@ int SaveEXRImageToFile(const EXRImage *exr_image, const EXRHeader *exr_header, FILE *fp = fopen(filename, "wb"); #endif if (!fp) { - if (err) { - (*err) = "Cannot write a file."; - } + tinyexr::SetErrorMessage("Cannot write a file", err); return TINYEXR_ERROR_CANT_OPEN_FILE; } @@ -11663,27 +11998,23 @@ int SaveEXRImageToFile(const EXRImage *exr_image, const EXRHeader *exr_header, int LoadDeepEXR(DeepImage *deep_image, const char *filename, const char **err) { if (deep_image == NULL) { - if (err) { - (*err) = "Invalid argument."; - } + tinyexr::SetErrorMessage("Invalid argument for LoadDeepEXR", err); return TINYEXR_ERROR_INVALID_ARGUMENT; } #ifdef _MSC_VER FILE *fp = NULL; errno_t errcode = fopen_s(&fp, filename, "rb"); - if ((!errcode) || (!fp)) { - if (err) { - (*err) = "Cannot read file."; - } + if ((0 != errcode) || (!fp)) { + tinyexr::SetErrorMessage("Cannot read a file " + std::string(filename), + err); return TINYEXR_ERROR_CANT_OPEN_FILE; } #else FILE *fp = fopen(filename, "rb"); if (!fp) { - if (err) { - (*err) = "Cannot read file."; - } + tinyexr::SetErrorMessage("Cannot read a file " + std::string(filename), + err); return TINYEXR_ERROR_CANT_OPEN_FILE; } #endif @@ -11696,9 +12027,8 @@ int LoadDeepEXR(DeepImage *deep_image, const char *filename, const char **err) { if (filesize == 0) { fclose(fp); - if (err) { - (*err) = "File size is zero."; - } + tinyexr::SetErrorMessage("File size is zero : " + std::string(filename), + err); return TINYEXR_ERROR_INVALID_FILE; } @@ -11719,9 +12049,7 @@ int LoadDeepEXR(DeepImage *deep_image, const char *filename, const char **err) { const char header[] = {0x76, 0x2f, 0x31, 0x01}; if (memcmp(marker, header, 4) != 0) { - if (err) { - (*err) = "Invalid magic number."; - } + tinyexr::SetErrorMessage("Invalid magic number", err); return TINYEXR_ERROR_INVALID_MAGIC_NUMBER; } marker += 4; @@ -11732,9 +12060,7 @@ int LoadDeepEXR(DeepImage *deep_image, const char *filename, const char **err) { // ver 2.0, scanline, deep bit on(0x800) // must be [2, 0, 0, 0] if (marker[0] != 2 || marker[1] != 8 || marker[2] != 0 || marker[3] != 0) { - if (err) { - (*err) = "Unsupported version or scanline."; - } + tinyexr::SetErrorMessage("Unsupported version or scanline", err); return TINYEXR_ERROR_UNSUPPORTED_FORMAT; } @@ -11775,9 +12101,9 @@ int LoadDeepEXR(DeepImage *deep_image, const char *filename, const char **err) { if (attr_name.compare("compression") == 0) { compression_type = data[0]; if (compression_type > TINYEXR_COMPRESSIONTYPE_PIZ) { - if (err) { - (*err) = "Unsupported compression type."; - } + std::stringstream ss; + ss << "Unsupported compression type : " << compression_type; + tinyexr::SetErrorMessage(ss.str(), err); return TINYEXR_ERROR_UNSUPPORTED_FORMAT; } @@ -11794,18 +12120,14 @@ int LoadDeepEXR(DeepImage *deep_image, const char *filename, const char **err) { // ySampling: int if (!tinyexr::ReadChannelInfo(channels, data)) { - if (err) { - (*err) = "Failed to parse channel info."; - } + tinyexr::SetErrorMessage("Failed to parse channel info", err); return TINYEXR_ERROR_INVALID_DATA; } num_channels = static_cast<int>(channels.size()); if (num_channels < 1) { - if (err) { - (*err) = "Invalid channels format."; - } + tinyexr::SetErrorMessage("Invalid channels format", err); return TINYEXR_ERROR_INVALID_DATA; } @@ -11877,9 +12199,7 @@ int LoadDeepEXR(DeepImage *deep_image, const char *filename, const char **err) { #endif // OK } else { - if (err) { - (*err) = "Unsupported format."; - } + tinyexr::SetErrorMessage("Unsupported compression format", err); return TINYEXR_ERROR_UNSUPPORTED_FORMAT; } @@ -11936,8 +12256,9 @@ int LoadDeepEXR(DeepImage *deep_image, const char *filename, const char **err) { unsigned long dstLen = static_cast<unsigned long>(pixelOffsetTable.size() * sizeof(int)); if (!tinyexr::DecompressZip( - reinterpret_cast<unsigned char *>(&pixelOffsetTable.at(0)), &dstLen, - data_ptr + 28, static_cast<unsigned long>(packedOffsetTableSize))) { + reinterpret_cast<unsigned char *>(&pixelOffsetTable.at(0)), + &dstLen, data_ptr + 28, + static_cast<unsigned long>(packedOffsetTableSize))) { return false; } @@ -11955,9 +12276,9 @@ int LoadDeepEXR(DeepImage *deep_image, const char *filename, const char **err) { unsigned long dstLen = static_cast<unsigned long>(unpackedSampleDataSize); if (dstLen) { if (!tinyexr::DecompressZip( - reinterpret_cast<unsigned char *>(&sample_data.at(0)), &dstLen, - data_ptr + 28 + packedOffsetTableSize, - static_cast<unsigned long>(packedSampleDataSize))) { + reinterpret_cast<unsigned char *>(&sample_data.at(0)), &dstLen, + data_ptr + 28 + packedOffsetTableSize, + static_cast<unsigned long>(packedSampleDataSize))) { return false; } assert(dstLen == static_cast<unsigned long>(unpackedSampleDataSize)); @@ -12006,8 +12327,10 @@ int LoadDeepEXR(DeepImage *deep_image, const char *filename, const char **err) { if (channels[c].pixel_type == 0) { // UINT for (size_t x = 0; x < static_cast<size_t>(samples_per_line); x++) { - unsigned int ui = *reinterpret_cast<unsigned int *>( + unsigned int ui; + unsigned int *src_ptr = reinterpret_cast<unsigned int *>( &sample_data.at(size_t(data_offset) + x * sizeof(int))); + tinyexr::cpy4(&ui, src_ptr); deep_image->image[c][y][x] = static_cast<float>(ui); // @fixme } data_offset += @@ -12015,16 +12338,19 @@ int LoadDeepEXR(DeepImage *deep_image, const char *filename, const char **err) { } else if (channels[c].pixel_type == 1) { // half for (size_t x = 0; x < static_cast<size_t>(samples_per_line); x++) { tinyexr::FP16 f16; - f16.u = *reinterpret_cast<unsigned short *>( + const unsigned short *src_ptr = reinterpret_cast<unsigned short *>( &sample_data.at(size_t(data_offset) + x * sizeof(short))); + tinyexr::cpy2(&(f16.u), src_ptr); tinyexr::FP32 f32 = half_to_float(f16); deep_image->image[c][y][x] = f32.f; } data_offset += sizeof(short) * static_cast<size_t>(samples_per_line); } else { // float for (size_t x = 0; x < static_cast<size_t>(samples_per_line); x++) { - float f = *reinterpret_cast<float *>( + float f; + const float *src_ptr = reinterpret_cast<float *>( &sample_data.at(size_t(data_offset) + x * sizeof(float))); + tinyexr::cpy4(&f, src_ptr); deep_image->image[c][y][x] = f; } data_offset += sizeof(float) * static_cast<size_t>(samples_per_line); @@ -12065,6 +12391,13 @@ void InitEXRImage(EXRImage *exr_image) { exr_image->num_tiles = 0; } +void FreeEXRErrorMessage(const char *msg) { + if (msg) { + free(reinterpret_cast<void *>(const_cast<char *>(msg))); + } + return; +} + void InitEXRHeader(EXRHeader *exr_header) { if (exr_header == NULL) { return; @@ -12096,6 +12429,10 @@ int FreeEXRHeader(EXRHeader *exr_header) { } } + if (exr_header->custom_attributes) { + free(exr_header->custom_attributes); + } + return TINYEXR_SUCCESS; } @@ -12125,6 +12462,7 @@ int FreeEXRImage(EXRImage *exr_image) { free(exr_image->tiles[tid].images); } } + free(exr_image->tiles); } return TINYEXR_SUCCESS; @@ -12133,9 +12471,8 @@ int FreeEXRImage(EXRImage *exr_image) { int ParseEXRHeaderFromFile(EXRHeader *exr_header, const EXRVersion *exr_version, const char *filename, const char **err) { if (exr_header == NULL || exr_version == NULL || filename == NULL) { - if (err) { - (*err) = "Invalid argument."; - } + tinyexr::SetErrorMessage("Invalid argument for ParseEXRHeaderFromFile", + err); return TINYEXR_ERROR_INVALID_ARGUMENT; } @@ -12146,9 +12483,7 @@ int ParseEXRHeaderFromFile(EXRHeader *exr_header, const EXRVersion *exr_version, FILE *fp = fopen(filename, "rb"); #endif if (!fp) { - if (err) { - (*err) = "Cannot read file."; - } + tinyexr::SetErrorMessage("Cannot read file " + std::string(filename), err); return TINYEXR_ERROR_CANT_OPEN_FILE; } @@ -12166,9 +12501,8 @@ int ParseEXRHeaderFromFile(EXRHeader *exr_header, const EXRVersion *exr_version, fclose(fp); if (ret != filesize) { - if (err) { - (*err) = "fread error."; - } + tinyexr::SetErrorMessage("fread() error on " + std::string(filename), + err); return TINYEXR_ERROR_INVALID_FILE; } } @@ -12185,10 +12519,13 @@ int ParseEXRMultipartHeaderFromMemory(EXRHeader ***exr_headers, if (memory == NULL || exr_headers == NULL || num_headers == NULL || exr_version == NULL) { // Invalid argument + tinyexr::SetErrorMessage( + "Invalid argument for ParseEXRMultipartHeaderFromMemory", err); return TINYEXR_ERROR_INVALID_ARGUMENT; } if (size < tinyexr::kEXRVersionSize) { + tinyexr::SetErrorMessage("Data size too short", err); return TINYEXR_ERROR_INVALID_DATA; } @@ -12207,13 +12544,7 @@ int ParseEXRMultipartHeaderFromMemory(EXRHeader ***exr_headers, marker, marker_size); if (ret != TINYEXR_SUCCESS) { - if (err) { -#ifdef _WIN32 - (*err) = _strdup(err_str.c_str()); // may leak -#else - (*err) = strdup(err_str.c_str()); // may leak -#endif - } + tinyexr::SetErrorMessage(err_str, err); return ret; } @@ -12224,9 +12555,8 @@ int ParseEXRMultipartHeaderFromMemory(EXRHeader ***exr_headers, // `chunkCount` must exist in the header. if (info.chunk_count == 0) { - if (err) { - (*err) = "`chunkCount' attribute is not found in the header."; - } + tinyexr::SetErrorMessage( + "`chunkCount' attribute is not found in the header.", err); return TINYEXR_ERROR_INVALID_DATA; } @@ -12261,9 +12591,8 @@ int ParseEXRMultipartHeaderFromFile(EXRHeader ***exr_headers, int *num_headers, const char *filename, const char **err) { if (exr_headers == NULL || num_headers == NULL || exr_version == NULL || filename == NULL) { - if (err) { - (*err) = "Invalid argument."; - } + tinyexr::SetErrorMessage( + "Invalid argument for ParseEXRMultipartHeaderFromFile()", err); return TINYEXR_ERROR_INVALID_ARGUMENT; } @@ -12274,9 +12603,7 @@ int ParseEXRMultipartHeaderFromFile(EXRHeader ***exr_headers, int *num_headers, FILE *fp = fopen(filename, "rb"); #endif if (!fp) { - if (err) { - (*err) = "Cannot read file."; - } + tinyexr::SetErrorMessage("Cannot read file " + std::string(filename), err); return TINYEXR_ERROR_CANT_OPEN_FILE; } @@ -12294,9 +12621,7 @@ int ParseEXRMultipartHeaderFromFile(EXRHeader ***exr_headers, int *num_headers, fclose(fp); if (ret != filesize) { - if (err) { - (*err) = "fread error."; - } + tinyexr::SetErrorMessage("`fread' error. file may be corrupted.", err); return TINYEXR_ERROR_INVALID_FILE; } } @@ -12405,9 +12730,8 @@ int LoadEXRMultipartImageFromMemory(EXRImage *exr_images, const size_t size, const char **err) { if (exr_images == NULL || exr_headers == NULL || num_parts == 0 || memory == NULL || (size <= tinyexr::kEXRVersionSize)) { - if (err) { - (*err) = "Invalid argument."; - } + tinyexr::SetErrorMessage( + "Invalid argument for LoadEXRMultipartImageFromMemory()", err); return TINYEXR_ERROR_INVALID_ARGUMENT; } @@ -12415,9 +12739,7 @@ int LoadEXRMultipartImageFromMemory(EXRImage *exr_images, size_t total_header_size = 0; for (unsigned int i = 0; i < num_parts; i++) { if (exr_headers[i]->header_len == 0) { - if (err) { - (*err) = "EXRHeader is not initialized."; - } + tinyexr::SetErrorMessage("EXRHeader variable is not initialized.", err); return TINYEXR_ERROR_INVALID_ARGUMENT; } @@ -12452,9 +12774,8 @@ int LoadEXRMultipartImageFromMemory(EXRImage *exr_images, tinyexr::swap8(&offset); if (offset >= size) { - if (err) { - (*err) = "Invalid offset size."; - } + tinyexr::SetErrorMessage("Invalid offset size in EXR header chunks.", + err); return TINYEXR_ERROR_INVALID_DATA; } @@ -12479,14 +12800,19 @@ int LoadEXRMultipartImageFromMemory(EXRImage *exr_images, tinyexr::swap4(&part_no); if (part_no != i) { - assert(0); + tinyexr::SetErrorMessage("Invalid `part number' in EXR header chunks.", + err); return TINYEXR_ERROR_INVALID_DATA; } } + std::string e; int ret = tinyexr::DecodeChunk(&exr_images[i], exr_headers[i], offset_table, - memory, size); + memory, size, &e); if (ret != TINYEXR_SUCCESS) { + if (!e.empty()) { + tinyexr::SetErrorMessage(e, err); + } return ret; } } @@ -12499,9 +12825,8 @@ int LoadEXRMultipartImageFromFile(EXRImage *exr_images, unsigned int num_parts, const char *filename, const char **err) { if (exr_images == NULL || exr_headers == NULL || num_parts == 0) { - if (err) { - (*err) = "Invalid argument."; - } + tinyexr::SetErrorMessage( + "Invalid argument for LoadEXRMultipartImageFromFile", err); return TINYEXR_ERROR_INVALID_ARGUMENT; } @@ -12512,9 +12837,7 @@ int LoadEXRMultipartImageFromFile(EXRImage *exr_images, FILE *fp = fopen(filename, "rb"); #endif if (!fp) { - if (err) { - (*err) = "Cannot read file."; - } + tinyexr::SetErrorMessage("Cannot read file " + std::string(filename), err); return TINYEXR_ERROR_CANT_OPEN_FILE; } @@ -12670,5 +12993,10 @@ int SaveEXR(const float *data, int width, int height, int components, return ret; } +#ifdef __clang__ +// zero-as-null-ppinter-constant +#pragma clang diagnostic pop +#endif + #endif // TINYEXR_IMPLEMENTATION_DEIFNED #endif // TINYEXR_IMPLEMENTATION |