--- /dev/null
+/* Bcj2.c -- BCJ2 Decoder (Converter for x86 code)\r
+2021-02-09 : Igor Pavlov : Public domain */\r
+\r
+#include "Precomp.h"\r
+\r
+#include "Bcj2.h"\r
+#include "CpuArch.h"\r
+\r
+#define CProb UInt16\r
+\r
+#define kTopValue ((UInt32)1 << 24)\r
+#define kNumModelBits 11\r
+#define kBitModelTotal (1 << kNumModelBits)\r
+#define kNumMoveBits 5\r
+\r
+#define _IF_BIT_0 ttt = *prob; bound = (p->range >> kNumModelBits) * ttt; if (p->code < bound)\r
+#define _UPDATE_0 p->range = bound; *prob = (CProb)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits));\r
+#define _UPDATE_1 p->range -= bound; p->code -= bound; *prob = (CProb)(ttt - (ttt >> kNumMoveBits));\r
+\r
+void Bcj2Dec_Init(CBcj2Dec *p)\r
+{\r
+ unsigned i;\r
+\r
+ p->state = BCJ2_DEC_STATE_OK;\r
+ p->ip = 0;\r
+ p->temp[3] = 0;\r
+ p->range = 0;\r
+ p->code = 0;\r
+ for (i = 0; i < sizeof(p->probs) / sizeof(p->probs[0]); i++)\r
+ p->probs[i] = kBitModelTotal >> 1;\r
+}\r
+\r
+SRes Bcj2Dec_Decode(CBcj2Dec *p)\r
+{\r
+ if (p->range <= 5)\r
+ {\r
+ p->state = BCJ2_DEC_STATE_OK;\r
+ for (; p->range != 5; p->range++)\r
+ {\r
+ if (p->range == 1 && p->code != 0)\r
+ return SZ_ERROR_DATA;\r
+ \r
+ if (p->bufs[BCJ2_STREAM_RC] == p->lims[BCJ2_STREAM_RC])\r
+ {\r
+ p->state = BCJ2_STREAM_RC;\r
+ return SZ_OK;\r
+ }\r
+\r
+ p->code = (p->code << 8) | *(p->bufs[BCJ2_STREAM_RC])++;\r
+ }\r
+ \r
+ if (p->code == 0xFFFFFFFF)\r
+ return SZ_ERROR_DATA;\r
+ \r
+ p->range = 0xFFFFFFFF;\r
+ }\r
+ else if (p->state >= BCJ2_DEC_STATE_ORIG_0)\r
+ {\r
+ while (p->state <= BCJ2_DEC_STATE_ORIG_3)\r
+ {\r
+ Byte *dest = p->dest;\r
+ if (dest == p->destLim)\r
+ return SZ_OK;\r
+ *dest = p->temp[(size_t)p->state - BCJ2_DEC_STATE_ORIG_0];\r
+ p->state++;\r
+ p->dest = dest + 1;\r
+ }\r
+ }\r
+\r
+ /*\r
+ if (BCJ2_IS_32BIT_STREAM(p->state))\r
+ {\r
+ const Byte *cur = p->bufs[p->state];\r
+ if (cur == p->lims[p->state])\r
+ return SZ_OK;\r
+ p->bufs[p->state] = cur + 4;\r
+ \r
+ {\r
+ UInt32 val;\r
+ Byte *dest;\r
+ SizeT rem;\r
+ \r
+ p->ip += 4;\r
+ val = GetBe32(cur) - p->ip;\r
+ dest = p->dest;\r
+ rem = p->destLim - dest;\r
+ if (rem < 4)\r
+ {\r
+ SizeT i;\r
+ SetUi32(p->temp, val);\r
+ for (i = 0; i < rem; i++)\r
+ dest[i] = p->temp[i];\r
+ p->dest = dest + rem;\r
+ p->state = BCJ2_DEC_STATE_ORIG_0 + (unsigned)rem;\r
+ return SZ_OK;\r
+ }\r
+ SetUi32(dest, val);\r
+ p->temp[3] = (Byte)(val >> 24);\r
+ p->dest = dest + 4;\r
+ p->state = BCJ2_DEC_STATE_OK;\r
+ }\r
+ }\r
+ */\r
+\r
+ for (;;)\r
+ {\r
+ if (BCJ2_IS_32BIT_STREAM(p->state))\r
+ p->state = BCJ2_DEC_STATE_OK;\r
+ else\r
+ {\r
+ if (p->range < kTopValue)\r
+ {\r
+ if (p->bufs[BCJ2_STREAM_RC] == p->lims[BCJ2_STREAM_RC])\r
+ {\r
+ p->state = BCJ2_STREAM_RC;\r
+ return SZ_OK;\r
+ }\r
+ p->range <<= 8;\r
+ p->code = (p->code << 8) | *(p->bufs[BCJ2_STREAM_RC])++;\r
+ }\r
+\r
+ {\r
+ const Byte *src = p->bufs[BCJ2_STREAM_MAIN];\r
+ const Byte *srcLim;\r
+ Byte *dest;\r
+ SizeT num = (SizeT)(p->lims[BCJ2_STREAM_MAIN] - src);\r
+ \r
+ if (num == 0)\r
+ {\r
+ p->state = BCJ2_STREAM_MAIN;\r
+ return SZ_OK;\r
+ }\r
+ \r
+ dest = p->dest;\r
+ if (num > (SizeT)(p->destLim - dest))\r
+ {\r
+ num = (SizeT)(p->destLim - dest);\r
+ if (num == 0)\r
+ {\r
+ p->state = BCJ2_DEC_STATE_ORIG;\r
+ return SZ_OK;\r
+ }\r
+ }\r
+ \r
+ srcLim = src + num;\r
+\r
+ if (p->temp[3] == 0x0F && (src[0] & 0xF0) == 0x80)\r
+ *dest = src[0];\r
+ else for (;;)\r
+ {\r
+ Byte b = *src;\r
+ *dest = b;\r
+ if (b != 0x0F)\r
+ {\r
+ if ((b & 0xFE) == 0xE8)\r
+ break;\r
+ dest++;\r
+ if (++src != srcLim)\r
+ continue;\r
+ break;\r
+ }\r
+ dest++;\r
+ if (++src == srcLim)\r
+ break;\r
+ if ((*src & 0xF0) != 0x80)\r
+ continue;\r
+ *dest = *src;\r
+ break;\r
+ }\r
+ \r
+ num = (SizeT)(src - p->bufs[BCJ2_STREAM_MAIN]);\r
+ \r
+ if (src == srcLim)\r
+ {\r
+ p->temp[3] = src[-1];\r
+ p->bufs[BCJ2_STREAM_MAIN] = src;\r
+ p->ip += (UInt32)num;\r
+ p->dest += num;\r
+ p->state =\r
+ p->bufs[BCJ2_STREAM_MAIN] ==\r
+ p->lims[BCJ2_STREAM_MAIN] ?\r
+ (unsigned)BCJ2_STREAM_MAIN :\r
+ (unsigned)BCJ2_DEC_STATE_ORIG;\r
+ return SZ_OK;\r
+ }\r
+ \r
+ {\r
+ UInt32 bound, ttt;\r
+ CProb *prob;\r
+ Byte b = src[0];\r
+ Byte prev = (Byte)(num == 0 ? p->temp[3] : src[-1]);\r
+ \r
+ p->temp[3] = b;\r
+ p->bufs[BCJ2_STREAM_MAIN] = src + 1;\r
+ num++;\r
+ p->ip += (UInt32)num;\r
+ p->dest += num;\r
+ \r
+ prob = p->probs + (unsigned)(b == 0xE8 ? 2 + (unsigned)prev : (b == 0xE9 ? 1 : 0));\r
+ \r
+ _IF_BIT_0\r
+ {\r
+ _UPDATE_0\r
+ continue;\r
+ }\r
+ _UPDATE_1\r
+ \r
+ }\r
+ }\r
+ }\r
+\r
+ {\r
+ UInt32 val;\r
+ unsigned cj = (p->temp[3] == 0xE8) ? BCJ2_STREAM_CALL : BCJ2_STREAM_JUMP;\r
+ const Byte *cur = p->bufs[cj];\r
+ Byte *dest;\r
+ SizeT rem;\r
+ \r
+ if (cur == p->lims[cj])\r
+ {\r
+ p->state = cj;\r
+ break;\r
+ }\r
+ \r
+ val = GetBe32(cur);\r
+ p->bufs[cj] = cur + 4;\r
+\r
+ p->ip += 4;\r
+ val -= p->ip;\r
+ dest = p->dest;\r
+ rem = (SizeT)(p->destLim - dest);\r
+ \r
+ if (rem < 4)\r
+ {\r
+ p->temp[0] = (Byte)val; if (rem > 0) dest[0] = (Byte)val; val >>= 8;\r
+ p->temp[1] = (Byte)val; if (rem > 1) dest[1] = (Byte)val; val >>= 8;\r
+ p->temp[2] = (Byte)val; if (rem > 2) dest[2] = (Byte)val; val >>= 8;\r
+ p->temp[3] = (Byte)val;\r
+ p->dest = dest + rem;\r
+ p->state = BCJ2_DEC_STATE_ORIG_0 + (unsigned)rem;\r
+ break;\r
+ }\r
+ \r
+ SetUi32(dest, val);\r
+ p->temp[3] = (Byte)(val >> 24);\r
+ p->dest = dest + 4;\r
+ }\r
+ }\r
+\r
+ if (p->range < kTopValue && p->bufs[BCJ2_STREAM_RC] != p->lims[BCJ2_STREAM_RC])\r
+ {\r
+ p->range <<= 8;\r
+ p->code = (p->code << 8) | *(p->bufs[BCJ2_STREAM_RC])++;\r
+ }\r
+\r
+ return SZ_OK;\r
+}\r