summaryrefslogtreecommitdiffstats
path: root/source/core
diff options
context:
space:
mode:
authorjsmall-nvidia <jsmall@nvidia.com>2018-10-09 11:51:41 -0400
committerGitHub <noreply@github.com>2018-10-09 11:51:41 -0400
commit7ea9ff03f4fc766f21d5896aea220d17f236dd70 (patch)
tree6b705d44424e250a68f435837f545a74c1437883 /source/core
parent4cb2a19ef192424c0a4eb205a773624563222383 (diff)
Feature/var byte encoding (#665)
* * Remove the need for IRHighLevelDecoration in Emit * Use the IRLayoutDecoration for GeometryShaderPrimitiveTypeModifier * Initial look at at variable byte encoding, and simple unit test. * Fixing problems with comparison due to naming differences with slang/fxc. * * More tests and perf improvements for byte encoding. * Mechanism to detect processor and processor features in main slang header. * Split out cpu based defines into slang-cpu-defines.h so do not polute slang.h * Support for variable byte encoding on serialization. * Removed unused flag. * Fix warning. * Fix calcMsByte32 for 0 values without using intrinsic. * Fix a mistake in calculating maximum instruction size.
Diffstat (limited to 'source/core')
-rw-r--r--source/core/core.vcxproj4
-rw-r--r--source/core/core.vcxproj.filters8
-rw-r--r--source/core/list.h2
-rw-r--r--source/core/slang-byte-encode-util.cpp283
-rw-r--r--source/core/slang-byte-encode-util.h196
-rw-r--r--source/core/slang-cpu-defines.h89
6 files changed, 579 insertions, 3 deletions
diff --git a/source/core/core.vcxproj b/source/core/core.vcxproj
index 8ec4b7031..ec6195940 100644
--- a/source/core/core.vcxproj
+++ b/source/core/core.vcxproj
@@ -182,6 +182,7 @@
<ClInclude Include="list.h" />
<ClInclude Include="platform.h" />
<ClInclude Include="secure-crt.h" />
+ <ClInclude Include="slang-byte-encode-util.h" />
<ClInclude Include="slang-free-list.h" />
<ClInclude Include="slang-io.h" />
<ClInclude Include="slang-math.h" />
@@ -197,6 +198,7 @@
</ItemGroup>
<ItemGroup>
<ClCompile Include="platform.cpp" />
+ <ClCompile Include="slang-byte-encode-util.cpp" />
<ClCompile Include="slang-free-list.cpp" />
<ClCompile Include="slang-io.cpp" />
<ClCompile Include="slang-memory-arena.cpp" />
@@ -213,4 +215,4 @@
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
-</Project> \ No newline at end of file
+</Project> \ No newline at end of file
diff --git a/source/core/core.vcxproj.filters b/source/core/core.vcxproj.filters
index f30cad939..f9eeef43a 100644
--- a/source/core/core.vcxproj.filters
+++ b/source/core/core.vcxproj.filters
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
+<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Header Files">
@@ -81,6 +81,9 @@
<ClInclude Include="type-traits.h">
<Filter>Header Files</Filter>
</ClInclude>
+ <ClInclude Include="slang-byte-encode-util.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="platform.cpp">
@@ -113,6 +116,9 @@
<ClCompile Include="token-reader.cpp">
<Filter>Source Files</Filter>
</ClCompile>
+ <ClCompile Include="slang-byte-encode-util.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
</ItemGroup>
<ItemGroup>
<None Include="core.natvis">
diff --git a/source/core/list.h b/source/core/list.h
index cddcbb6c0..11d798dcf 100644
--- a/source/core/list.h
+++ b/source/core/list.h
@@ -472,7 +472,7 @@ namespace Slang
if (bufferSize > _count && _count > 0)
{
T * newBuffer = Allocate(_count);
- for (int i = 0; i < _count; i++)
+ for (UInt i = 0; i < _count; i++)
newBuffer[i] = static_cast<T&&>(buffer[i]);
FreeBuffer();
buffer = newBuffer;
diff --git a/source/core/slang-byte-encode-util.cpp b/source/core/slang-byte-encode-util.cpp
new file mode 100644
index 000000000..6eabdc16f
--- /dev/null
+++ b/source/core/slang-byte-encode-util.cpp
@@ -0,0 +1,283 @@
+#include "slang-byte-encode-util.h"
+
+
+
+namespace Slang {
+
+// Descriptions of algorithms here...
+// https://github.com/stoklund/varint
+
+#if SLANG_LITTLE_ENDIAN && SLANG_UNALIGNED_ACCESS
+// Testing on i7, unaligned access is around 40% faster
+# define SLANG_BYTE_ENCODE_USE_UNALIGNED_ACCESS 1
+#endif
+
+#ifndef SLANG_BYTE_ENCODE_USE_UNALIGNED_ACCESS
+# define SLANG_BYTE_ENCODE_USE_UNALIGNED_ACCESS 0
+#endif
+
+#define SLANG_REPEAT_2(n) n, n
+#define SLANG_REPEAT_4(n) SLANG_REPEAT_2(n), SLANG_REPEAT_2(n)
+#define SLANG_REPEAT_8(n) SLANG_REPEAT_4(n), SLANG_REPEAT_4(n)
+#define SLANG_REPEAT_16(n) SLANG_REPEAT_8(n), SLANG_REPEAT_8(n)
+#define SLANG_REPEAT_32(n) SLANG_REPEAT_16(n), SLANG_REPEAT_16(n)
+#define SLANG_REPEAT_64(n) SLANG_REPEAT_32(n), SLANG_REPEAT_32(n)
+#define SLANG_REPEAT_128(n) SLANG_REPEAT_64(n), SLANG_REPEAT_64(n)
+
+/* static */const int8_t ByteEncodeUtil::s_msb8[256] =
+{
+ - 1,
+ 0,
+ SLANG_REPEAT_2(1),
+ SLANG_REPEAT_4(2),
+ SLANG_REPEAT_8(3),
+ SLANG_REPEAT_16(4),
+ SLANG_REPEAT_32(5),
+ SLANG_REPEAT_64(6),
+ SLANG_REPEAT_128(7),
+};
+
+/* static */size_t ByteEncodeUtil::calcEncodeLiteSizeUInt32(const uint32_t* in, size_t num)
+{
+ size_t totalNumEncodeBytes = 0;
+
+ for (size_t i = 0; i < num; i++)
+ {
+ const uint32_t v = in[i];
+
+ if (v < kLiteCut1)
+ {
+ totalNumEncodeBytes += 1;
+ }
+ else if (v <= kLiteCut1 + 255 * (kLiteCut2 - 1 - kLiteCut1))
+ {
+ totalNumEncodeBytes += 2;
+ }
+ else
+ {
+ totalNumEncodeBytes += calcNonZeroMsByte32(v) + 2;
+ }
+ }
+ return totalNumEncodeBytes;
+}
+
+/* static */size_t ByteEncodeUtil::encodeLiteUInt32(const uint32_t* in, size_t num, uint8_t* encodeOut)
+{
+ uint8_t* encodeStart = encodeOut;
+
+ for (size_t i = 0; i < num; ++i)
+ {
+ uint32_t v = in[i];
+
+ if(v < kLiteCut1)
+ {
+ *encodeOut++ = uint8_t(v);
+ }
+ else if (v <= kLiteCut1 + 255 * (kLiteCut2 - 1 - kLiteCut1))
+ {
+ v -= kLiteCut1;
+
+ encodeOut[0] = uint8_t(kLiteCut1 + (v >> 8));
+ encodeOut[1] = uint8_t(v);
+ encodeOut += 2;
+ }
+ else
+ {
+ uint8_t* encodeOutStart = encodeOut++;
+ while (v)
+ {
+ *encodeOut++ = uint8_t(v);
+ v >>= 8;
+ }
+ // Finally write the size to the start
+ const int numBytes = int(encodeOut - encodeOutStart);
+ encodeOutStart[0] = uint8_t(kLiteCut2 + (numBytes - 2));
+ }
+ }
+ return size_t(encodeOut - encodeStart);
+}
+
+/* static */void ByteEncodeUtil::encodeLiteUInt32(const uint32_t* in, size_t num, List<uint8_t>& encodeArrayOut)
+{
+ // Make sure there is at least enough space for all bytes
+ encodeArrayOut.SetSize(num);
+
+ uint8_t* encodeOut = encodeArrayOut.begin();
+ uint8_t* encodeOutEnd = encodeArrayOut.end();
+
+ for (size_t i = 0; i < num; ++i)
+ {
+ // Check if we need some more space
+ if (encodeOut + kMaxLiteEncodeUInt32 > encodeOutEnd)
+ {
+ const size_t offset = size_t(encodeOut - encodeArrayOut.begin());
+
+ const UInt oldCapacity = encodeArrayOut.Capacity();
+
+ // Make some more space
+ encodeArrayOut.Reserve(oldCapacity + (oldCapacity >> 1) + kMaxLiteEncodeUInt32);
+ // Make the size the capacity
+ const UInt capacity = encodeArrayOut.Capacity();
+ encodeArrayOut.SetSize(capacity);
+
+ encodeOut = encodeArrayOut.begin() + offset;
+ encodeOutEnd = encodeArrayOut.end();
+ }
+
+ uint32_t v = in[i];
+
+ if (v < kLiteCut1)
+ {
+ *encodeOut++ = uint8_t(v);
+ }
+ else if (v <= kLiteCut1 + 255 * (kLiteCut2 - 1 - kLiteCut1))
+ {
+ v -= kLiteCut1;
+
+ encodeOut[0] = uint8_t(kLiteCut1 + (v >> 8));
+ encodeOut[1] = uint8_t(v);
+ encodeOut += 2;
+ }
+ else
+ {
+ uint8_t* encodeOutStart = encodeOut++;
+ while (v)
+ {
+ *encodeOut++ = uint8_t(v);
+ v >>= 8;
+ }
+ // Finally write the size to the start
+ const int numBytes = int(encodeOut - encodeOutStart);
+ encodeOutStart[0] = uint8_t(kLiteCut2 + (numBytes - 2));
+ }
+ }
+
+ encodeArrayOut.SetSize(UInt(encodeOut - encodeArrayOut.begin()));
+ encodeArrayOut.Compress();
+}
+
+/* static */int ByteEncodeUtil::encodeLiteUInt32(uint32_t in, uint8_t out[kMaxLiteEncodeUInt32])
+{
+ // 0-184 1 byte value = B0
+ // 185 - 248 2 bytes value = 185 + 256 * (B0 - 185) + B1
+ // 249 - 255 3 - 9 bytes value = (B0 - 249 + 2) little - endian bytes following B0.
+
+ if (in < kLiteCut1)
+ {
+ out[0] = uint8_t(in);
+ return 1;
+ }
+ else if (in <= kLiteCut1 + 255 * (kLiteCut2 - 1 - kLiteCut1))
+ {
+ in -= kLiteCut1;
+
+ out[0] = uint8_t(kLiteCut1 + (in >> 8));
+ out[1] = uint8_t(in);
+ return 2;
+ }
+ else
+ {
+ int numBytes = 1;
+ while (in)
+ {
+ out[numBytes++] = uint8_t(in);
+ in >>= 8;
+ }
+ // Finally write the size
+ out[0] = uint8_t(kLiteCut2 + (numBytes - 2));
+ return numBytes;
+ }
+}
+
+static const uint32_t s_unalignedUInt32Mask[5] =
+{
+ 0x00000000,
+ 0x000000ff,
+ 0x0000ffff,
+ 0x00ffffff,
+ 0xffffffff,
+};
+
+/* static */int ByteEncodeUtil::decodeLiteUInt32(const uint8_t* in, uint32_t* out)
+{
+ uint8_t b0 = *in++;
+ if (b0 < kLiteCut1)
+ {
+ *out = uint32_t(b0);
+ return 1;
+ }
+ else if (b0 < kLiteCut2)
+ {
+ uint8_t b1 = *in++;
+ *out = kLiteCut1 + b1 + (uint32_t(b0 - kLiteCut1) << 8);
+ return 2;
+ }
+ else
+ {
+ int numBytesRemaining = b0 - kLiteCut2 + 2 - 1;
+
+#if SLANG_BYTE_ENCODE_USE_UNALIGNED_ACCESS
+ //const uint32_t mask = s_unalignedUInt32Mask[numBytesRemaining];
+ const uint32_t mask = ~(uint32_t(0xffffff00) << ((numBytesRemaining - 1) * 8));
+ const uint32_t value = (*(const uint32_t*)in) & mask;
+#else
+ // This works on all cpus although slower
+ uint32_t value = in[0];
+
+ switch (numBytesRemaining)
+ {
+ case 4: value |= uint32_t(in[3]) << 24; /* fall thru */
+ case 3: value |= uint32_t(in[2]) << 16; /* fall thru */
+ case 2: value |= uint32_t(in[1]) << 8; /* fall thru */
+ case 1: break;
+ }
+#endif
+ *out = value;
+ return numBytesRemaining + 1;
+ }
+}
+
+/* static */size_t ByteEncodeUtil::decodeLiteUInt32(const uint8_t* encodeIn, size_t numValues, uint32_t* valuesOut)
+{
+ const uint8_t* encodeStart = encodeIn;
+
+ for (size_t i = 0; i < numValues; ++i)
+ {
+ uint8_t b0 = *encodeIn++;
+ if (b0 < kLiteCut1)
+ {
+ valuesOut[i] = uint32_t(b0);
+ }
+ else if (b0 < kLiteCut2)
+ {
+ uint8_t b1 = *encodeIn++;
+ valuesOut[i] = kLiteCut1 + b1 + (uint32_t(b0 - kLiteCut1) << 8);
+ }
+ else
+ {
+ int numBytesRemaining = b0 - kLiteCut2 + 2 - 1;
+
+#if SLANG_BYTE_ENCODE_USE_UNALIGNED_ACCESS
+ const uint32_t mask = s_unalignedUInt32Mask[numBytesRemaining];
+ //const uint32_t mask = ~(uint32_t(0xffffff00) << ((numBytesRemaining - 1) * 8));
+ const uint32_t value = (*(const uint32_t*)encodeIn) & mask;
+#else
+ // This works on all cpus although slower
+ uint32_t value = encodeIn[0];
+ switch (numBytesRemaining)
+ {
+ case 4: value |= uint32_t(encodeIn[3]) << 24; /* fall thru */
+ case 3: value |= uint32_t(encodeIn[2]) << 16; /* fall thru */
+ case 2: value |= uint32_t(encodeIn[1]) << 8; /* fall thru */
+ case 1: break;
+ }
+#endif
+ valuesOut[i] = value;
+ encodeIn += numBytesRemaining;
+ }
+ }
+
+ return size_t(encodeIn - encodeStart);
+}
+
+} // namespace Slang
diff --git a/source/core/slang-byte-encode-util.h b/source/core/slang-byte-encode-util.h
new file mode 100644
index 000000000..77ddc2f65
--- /dev/null
+++ b/source/core/slang-byte-encode-util.h
@@ -0,0 +1,196 @@
+#ifndef SLANG_BYTE_ENCODE_UTIL_H
+#define SLANG_BYTE_ENCODE_UTIL_H
+
+#include "list.h"
+
+#include "slang-cpu-defines.h"
+
+namespace Slang {
+
+struct ByteEncodeUtil
+{
+ enum
+ {
+ kMaxLiteEncodeUInt32 = 5, /// One byte for prefix, the remaining 4 bytes hold the value
+ // Cut values for 'Lite' encoding style
+ kLiteCut1 = 185,
+ kLiteCut2 = 249,
+ };
+
+ /** Find the most significant bit for 8 bits
+ @param v The value to find most significant bit on
+ @return The most significant bit, or -1 if no bits are set
+ */
+ SLANG_FORCE_INLINE static int calcMsb8(uint32_t v);
+
+ /** Find the most significant bit for 32 bits
+ @param v The value to find most significant bit on
+ @return The most significant bit, or -1 if no bits are set
+ */
+ SLANG_FORCE_INLINE static int calcMsb32(uint32_t v);
+
+ /** Calculates the 'most significant' byte ie the highest bytes that is non zero.
+ Note return value is *undefined* if in is 0.
+ @param in Value - cannot be 0.
+ @return The byte index of the highest byte that is non zero.
+ */
+ SLANG_FORCE_INLINE static int calcNonZeroMsByte32(uint32_t in);
+
+ /** Calculates the 'most significant' byte ie the highest bytes that is non zero.
+ @param in Value - cannot be 0.
+ @return The byte index of the highest byte that is non zero.
+ */
+ SLANG_FORCE_INLINE static int calcMsByte32(uint32_t in);
+
+ /// Calculate the size of encoding bytes
+ static size_t calcEncodeLiteSizeUInt32(const uint32_t* in, size_t num);
+
+ /// Calculate the size of a single value
+ static size_t calcEncodeLiteSizeUInt32(uint32_t in);
+
+ /** Encodes a uint32_t as an integer
+ @return the number of bytes needed to encode */
+ static int encodeLiteUInt32(uint32_t in, uint8_t out[kMaxLiteEncodeUInt32]);
+
+ /** Decode a lite encoding.
+ @param in The lite encoded bytes
+ @param out Value constructed
+ @return number of bytes on in consumed */
+ static int decodeLiteUInt32(const uint8_t* in, uint32_t* out);
+
+ /** Encode an array of uint32_t
+ @param in The values to encode
+ @param num The amount of values to encode
+ @param encodeOut The buffer to hold the encoded value. MUST be large enough to hold the encoding
+ @return The size of the encoding in bytes
+ */
+ static size_t encodeLiteUInt32(const uint32_t* in, size_t num, uint8_t* encodeOut);
+
+ /** Encode an array of uint32_t
+ @param in The values to encode
+ @param num The amount of values to encode
+ @param encodeOut The buffer to hold the encoded value.
+ */
+ static void encodeLiteUInt32(const uint32_t* in, size_t num, List<uint8_t>& encodeOut);
+
+ /** Encode an array of uint32_t
+ @param encodeIn The encoded values
+ @param numValues The amount of values to be decoded (NOTE! This is the number of valuesOut, not encodeIn)
+ @param valuesOut The buffer to hold the encoded value. MUST be large enough to hold the encoding
+ @return The amount of bytes decoded
+ */
+ static size_t decodeLiteUInt32(const uint8_t* encodeIn, size_t numValues, uint32_t* valuesOut);
+
+ /// Table that maps 8 bits to it's most significant bit. If 0 returns -1.
+ static const int8_t s_msb8[256];
+};
+
+#if SLANG_VC
+// Works on ARM and x86/64 on visual studio compiler
+
+// ---------------------------------------------------------------------------
+SLANG_FORCE_INLINE int ByteEncodeUtil::calcNonZeroMsByte32(uint32_t in)
+{
+ SLANG_ASSERT(in != 0);
+ // Can use intrinsic
+ // https://msdn.microsoft.com/en-us/library/fbxyd7zd.aspx
+ unsigned long index;
+ _BitScanReverse(&index, in);
+ return index >> 3;
+}
+
+// ---------------------------------------------------------------------------
+SLANG_FORCE_INLINE int ByteEncodeUtil::calcMsByte32(uint32_t in)
+{
+ if (in == 0)
+ {
+ return -1;
+ }
+ // Can use intrinsic
+ // https://msdn.microsoft.com/en-us/library/fbxyd7zd.aspx
+ unsigned long index;
+ _BitScanReverse(&index, in);
+ return index >> 3;
+}
+
+// ---------------------------------------------------------------------------
+SLANG_FORCE_INLINE /* static */int ByteEncodeUtil::calcMsb8(uint32_t v)
+{
+ SLANG_ASSERT((v & 0xffffff00) == 0);
+ if (v == 0)
+ {
+ return -1;
+ }
+ unsigned long index;
+ _BitScanReverse(&index, v);
+ return index;
+}
+
+// ---------------------------------------------------------------------------
+SLANG_FORCE_INLINE /* static */int ByteEncodeUtil::calcMsb32(uint32_t v)
+{
+ if (v == 0)
+ {
+ return -1;
+ }
+ unsigned long index;
+ _BitScanReverse(&index, v);
+ return index;
+}
+
+#else
+
+// ---------------------------------------------------------------------------
+SLANG_FORCE_INLINE /* static */int ByteEncodeUtil::calcNonZeroMsByte32(uint32_t in)
+{
+ return (in & 0xffff0000) ?
+ ((in & 0xff000000) ? 3 : 2) :
+ ((in & 0x0000ff00) ? 1 : 0);
+}
+
+// ---------------------------------------------------------------------------
+SLANG_FORCE_INLINE /* static */int ByteEncodeUtil::calcMsByte32(uint32_t in)
+{
+ return (in & 0xffff0000) ?
+ ((in & 0xff000000) ? 3 : 2) :
+ ((in & 0x0000ff00) ? 1 :
+ ((in == 0) ? -1 : 0));
+}
+
+// ---------------------------------------------------------------------------
+SLANG_FORCE_INLINE /* static */int ByteEncodeUtil::calcMsb8(uint32_t v)
+{
+ SLANG_ASSERT((v & 0xffffff00) == 0);
+ return s_msb8[v];
+}
+
+// ---------------------------------------------------------------------------
+SLANG_FORCE_INLINE /* static */int ByteEncodeUtil::calcMsb32(uint32_t v)
+{
+ return (v & 0xffff0000) ?
+ ((v & 0xff000000) ? s_msb8[v >> 24] + 24 : s_msb8[v >> 16] + 16) :
+ ((v & 0x0000ff00) ? s_msb8[v >> 8] + 8 : s_msb8[v]);
+}
+
+#endif
+
+// ---------------------------------------------------------------------------
+inline /* static */size_t ByteEncodeUtil::calcEncodeLiteSizeUInt32(uint32_t v)
+{
+ if (v < kLiteCut1)
+ {
+ return 1;
+ }
+ else if (v <= kLiteCut1 + 255 * (kLiteCut2 - 1 - kLiteCut1))
+ {
+ return 2;
+ }
+ else
+ {
+ return calcNonZeroMsByte32(v) + 2;
+ }
+}
+
+} // namespace Slang
+
+#endif // SLANG_BYTE_ENCODE_UTIL_H
diff --git a/source/core/slang-cpu-defines.h b/source/core/slang-cpu-defines.h
new file mode 100644
index 000000000..dc76008b9
--- /dev/null
+++ b/source/core/slang-cpu-defines.h
@@ -0,0 +1,89 @@
+#ifndef SLANG_CPU_DEFINES_H
+#define SLANG_CPU_DEFINES_H
+
+/* Macros for detecting processor */
+#if defined(_M_ARM) || defined(__ARM_EABI__)
+// This is special case for nVidia tegra
+# define SLANG_PROCESSOR_ARM 1
+#elif defined(__i386__) || defined(_M_IX86)
+# define SLANG_PROCESSOR_X86 1
+#elif defined(_M_AMD64) || defined(_M_X64) || defined(__amd64) || defined(__x86_64)
+# define SLANG_PROCESSOR_X86_64 1
+#elif defined(_PPC_) || defined(__ppc__) || defined(__POWERPC__) || defined(_M_PPC)
+# if defined(__powerpc64__) || defined(__ppc64__) || defined(__PPC64__) || defined(__64BIT__) || defined(_LP64) || defined(__LP64__)
+# define SLANG_PROCESSOR_POWER_PC_64 1
+# else
+# define SLANG_PROCESSOR_POWER_PC 1
+# endif
+#elif defined(__arm__)
+# define SLANG_PROCESSOR_ARM 1
+#elif defined(__aarch64__)
+# define SLANG_PROCESSOR_ARM_64 1
+#endif
+
+#ifndef SLANG_PROCESSOR_ARM
+# define SLANG_PROCESSOR_ARM 0
+#endif
+
+#ifndef SLANG_PROCESSOR_ARM_64
+# define SLANG_PROCESSOR_ARM_64 0
+#endif
+
+#ifndef SLANG_PROCESSOR_X86
+# define SLANG_PROCESSOR_X86 0
+#endif
+
+#ifndef SLANG_PROCESSOR_X86_64
+# define SLANG_PROCESSOR_X86_64 0
+#endif
+
+#ifndef SLANG_PROCESSOR_POWER_PC
+# define SLANG_PROCESSOR_POWER_PC 0
+#endif
+
+#ifndef SLANG_PROCESSOR_POWER_PC_64
+# define SLANG_PROCESSOR_POWER_PC_64 0
+#endif
+
+// Processor families
+
+#define SLANG_PROCESSOR_FAMILY_X86 (SLANG_PROCESSOR_X86_64 | SLANG_PROCESSOR_X86)
+#define SLANG_PROCESSOR_FAMILY_ARM (SLANG_PROCESSOR_ARM | SLANG_PROCESSOR_ARM_64)
+#define SLANG_PROCESSOR_FAMILY_POWER_PC (SLANG_PROCESSOR_POWER_PC_64 | SLANG_PROCESSOR_POWER_PC)
+
+#define SLANG_PTR_IS_64 (SLANG_PROCESSOR_ARM_64 | SLANG_PROCESSOR_X86_64 | SLANG_PROCESSOR_POWER_PC_64)
+#define SLANG_PTR_IS_32 (SLANG_PTR_IS_64 ^ 1)
+
+// Processor features
+#if SLANG_PROCESSOR_FAMILY_X86
+# define SLANG_LITTLE_ENDIAN 1
+# define SLANG_UNALIGNED_ACCESS 1
+#elif SLANG_PROCESSOR_FAMILY_ARM
+# if defined(__ARMEB__)
+# define SLANG_BIG_ENDIAN 1
+# else
+# define SLANG_LITTLE_ENDIAN 1
+# endif
+#elif SLANG_PROCESSOR_FAMILY_POWER_PC
+# define SLANG_BIG_ENDIAN 1
+#endif
+
+#ifndef SLANG_LITTLE_ENDIAN
+# define SLANG_LITTLE_ENDIAN 0
+#endif
+
+#ifndef SLANG_BIG_ENDIAN
+# define SLANG_BIG_ENDIAN 0
+#endif
+
+#ifndef SLANG_UNALIGNED_ACCESS
+# define SLANG_UNALIGNED_ACCESS 0
+#endif
+
+// One endianess must be set
+#if ((SLANG_BIG_ENDIAN | SLANG_LITTLE_ENDIAN) == 0)
+# error "Couldn't determine endianess"
+#endif
+
+
+#endif // SLANG_CPU_DEFINES_H \ No newline at end of file