1baa3858d3f5d128a5c8466b700098109edcad5f2repo sync/* Bcj2.c -- Converter for x86 code (BCJ2) 2baa3858d3f5d128a5c8466b700098109edcad5f2repo sync2008-10-04 : Igor Pavlov : Public domain */ 3baa3858d3f5d128a5c8466b700098109edcad5f2repo sync 4baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#include "Bcj2.h" 5baa3858d3f5d128a5c8466b700098109edcad5f2repo sync 6baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#ifdef _LZMA_PROB32 7baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#define CProb UInt32 8baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#else 9baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#define CProb UInt16 10baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#endif 11baa3858d3f5d128a5c8466b700098109edcad5f2repo sync 12baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#define IsJcc(b0, b1) ((b0) == 0x0F && ((b1) & 0xF0) == 0x80) 13baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#define IsJ(b0, b1) ((b1 & 0xFE) == 0xE8 || IsJcc(b0, b1)) 14baa3858d3f5d128a5c8466b700098109edcad5f2repo sync 15baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#define kNumTopBits 24 16baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#define kTopValue ((UInt32)1 << kNumTopBits) 17baa3858d3f5d128a5c8466b700098109edcad5f2repo sync 18baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#define kNumBitModelTotalBits 11 19baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#define kBitModelTotal (1 << kNumBitModelTotalBits) 20baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#define kNumMoveBits 5 21baa3858d3f5d128a5c8466b700098109edcad5f2repo sync 22baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#define RC_READ_BYTE (*buffer++) 23baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#define RC_TEST { if (buffer == bufferLim) return SZ_ERROR_DATA; } 24baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#define RC_INIT2 code = 0; range = 0xFFFFFFFF; \ 25baa3858d3f5d128a5c8466b700098109edcad5f2repo sync { int i; for (i = 0; i < 5; i++) { RC_TEST; code = (code << 8) | RC_READ_BYTE; }} 26baa3858d3f5d128a5c8466b700098109edcad5f2repo sync 27baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#define NORMALIZE if (range < kTopValue) { RC_TEST; range <<= 8; code = (code << 8) | RC_READ_BYTE; } 28baa3858d3f5d128a5c8466b700098109edcad5f2repo sync 29baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#define IF_BIT_0(p) ttt = *(p); bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound) 30baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#define UPDATE_0(p) range = bound; *(p) = (CProb)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits)); NORMALIZE; 31baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#define UPDATE_1(p) range -= bound; code -= bound; *(p) = (CProb)(ttt - (ttt >> kNumMoveBits)); NORMALIZE; 32baa3858d3f5d128a5c8466b700098109edcad5f2repo sync 33baa3858d3f5d128a5c8466b700098109edcad5f2repo syncint Bcj2_Decode( 34baa3858d3f5d128a5c8466b700098109edcad5f2repo sync const Byte *buf0, SizeT size0, 35baa3858d3f5d128a5c8466b700098109edcad5f2repo sync const Byte *buf1, SizeT size1, 36baa3858d3f5d128a5c8466b700098109edcad5f2repo sync const Byte *buf2, SizeT size2, 37baa3858d3f5d128a5c8466b700098109edcad5f2repo sync const Byte *buf3, SizeT size3, 38baa3858d3f5d128a5c8466b700098109edcad5f2repo sync Byte *outBuf, SizeT outSize) 39baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{ 40baa3858d3f5d128a5c8466b700098109edcad5f2repo sync CProb p[256 + 2]; 41baa3858d3f5d128a5c8466b700098109edcad5f2repo sync SizeT inPos = 0, outPos = 0; 42baa3858d3f5d128a5c8466b700098109edcad5f2repo sync 43baa3858d3f5d128a5c8466b700098109edcad5f2repo sync const Byte *buffer, *bufferLim; 44baa3858d3f5d128a5c8466b700098109edcad5f2repo sync UInt32 range, code; 45baa3858d3f5d128a5c8466b700098109edcad5f2repo sync Byte prevByte = 0; 46baa3858d3f5d128a5c8466b700098109edcad5f2repo sync 47baa3858d3f5d128a5c8466b700098109edcad5f2repo sync unsigned int i; 48baa3858d3f5d128a5c8466b700098109edcad5f2repo sync for (i = 0; i < sizeof(p) / sizeof(p[0]); i++) 49baa3858d3f5d128a5c8466b700098109edcad5f2repo sync p[i] = kBitModelTotal >> 1; 50baa3858d3f5d128a5c8466b700098109edcad5f2repo sync 51baa3858d3f5d128a5c8466b700098109edcad5f2repo sync buffer = buf3; 52baa3858d3f5d128a5c8466b700098109edcad5f2repo sync bufferLim = buffer + size3; 53baa3858d3f5d128a5c8466b700098109edcad5f2repo sync RC_INIT2 54baa3858d3f5d128a5c8466b700098109edcad5f2repo sync 55baa3858d3f5d128a5c8466b700098109edcad5f2repo sync if (outSize == 0) 56baa3858d3f5d128a5c8466b700098109edcad5f2repo sync return SZ_OK; 57baa3858d3f5d128a5c8466b700098109edcad5f2repo sync 58baa3858d3f5d128a5c8466b700098109edcad5f2repo sync for (;;) 59baa3858d3f5d128a5c8466b700098109edcad5f2repo sync { 60baa3858d3f5d128a5c8466b700098109edcad5f2repo sync Byte b; 61baa3858d3f5d128a5c8466b700098109edcad5f2repo sync CProb *prob; 62baa3858d3f5d128a5c8466b700098109edcad5f2repo sync UInt32 bound; 63baa3858d3f5d128a5c8466b700098109edcad5f2repo sync UInt32 ttt; 64baa3858d3f5d128a5c8466b700098109edcad5f2repo sync 65baa3858d3f5d128a5c8466b700098109edcad5f2repo sync SizeT limit = size0 - inPos; 66baa3858d3f5d128a5c8466b700098109edcad5f2repo sync if (outSize - outPos < limit) 67baa3858d3f5d128a5c8466b700098109edcad5f2repo sync limit = outSize - outPos; 68baa3858d3f5d128a5c8466b700098109edcad5f2repo sync while (limit != 0) 69baa3858d3f5d128a5c8466b700098109edcad5f2repo sync { 70baa3858d3f5d128a5c8466b700098109edcad5f2repo sync Byte b = buf0[inPos]; 71baa3858d3f5d128a5c8466b700098109edcad5f2repo sync outBuf[outPos++] = b; 72baa3858d3f5d128a5c8466b700098109edcad5f2repo sync if (IsJ(prevByte, b)) 73baa3858d3f5d128a5c8466b700098109edcad5f2repo sync break; 74baa3858d3f5d128a5c8466b700098109edcad5f2repo sync inPos++; 75baa3858d3f5d128a5c8466b700098109edcad5f2repo sync prevByte = b; 76baa3858d3f5d128a5c8466b700098109edcad5f2repo sync limit--; 77baa3858d3f5d128a5c8466b700098109edcad5f2repo sync } 78baa3858d3f5d128a5c8466b700098109edcad5f2repo sync 79baa3858d3f5d128a5c8466b700098109edcad5f2repo sync if (limit == 0 || outPos == outSize) 80baa3858d3f5d128a5c8466b700098109edcad5f2repo sync break; 81baa3858d3f5d128a5c8466b700098109edcad5f2repo sync 82baa3858d3f5d128a5c8466b700098109edcad5f2repo sync b = buf0[inPos++]; 83baa3858d3f5d128a5c8466b700098109edcad5f2repo sync 84baa3858d3f5d128a5c8466b700098109edcad5f2repo sync if (b == 0xE8) 85baa3858d3f5d128a5c8466b700098109edcad5f2repo sync prob = p + prevByte; 86baa3858d3f5d128a5c8466b700098109edcad5f2repo sync else if (b == 0xE9) 87baa3858d3f5d128a5c8466b700098109edcad5f2repo sync prob = p + 256; 88baa3858d3f5d128a5c8466b700098109edcad5f2repo sync else 89baa3858d3f5d128a5c8466b700098109edcad5f2repo sync prob = p + 257; 90baa3858d3f5d128a5c8466b700098109edcad5f2repo sync 91baa3858d3f5d128a5c8466b700098109edcad5f2repo sync IF_BIT_0(prob) 92baa3858d3f5d128a5c8466b700098109edcad5f2repo sync { 93baa3858d3f5d128a5c8466b700098109edcad5f2repo sync UPDATE_0(prob) 94baa3858d3f5d128a5c8466b700098109edcad5f2repo sync prevByte = b; 95baa3858d3f5d128a5c8466b700098109edcad5f2repo sync } 96baa3858d3f5d128a5c8466b700098109edcad5f2repo sync else 97baa3858d3f5d128a5c8466b700098109edcad5f2repo sync { 98baa3858d3f5d128a5c8466b700098109edcad5f2repo sync UInt32 dest; 99baa3858d3f5d128a5c8466b700098109edcad5f2repo sync const Byte *v; 100baa3858d3f5d128a5c8466b700098109edcad5f2repo sync UPDATE_1(prob) 101baa3858d3f5d128a5c8466b700098109edcad5f2repo sync if (b == 0xE8) 102baa3858d3f5d128a5c8466b700098109edcad5f2repo sync { 103baa3858d3f5d128a5c8466b700098109edcad5f2repo sync v = buf1; 104baa3858d3f5d128a5c8466b700098109edcad5f2repo sync if (size1 < 4) 105baa3858d3f5d128a5c8466b700098109edcad5f2repo sync return SZ_ERROR_DATA; 106baa3858d3f5d128a5c8466b700098109edcad5f2repo sync buf1 += 4; 107baa3858d3f5d128a5c8466b700098109edcad5f2repo sync size1 -= 4; 108baa3858d3f5d128a5c8466b700098109edcad5f2repo sync } 109baa3858d3f5d128a5c8466b700098109edcad5f2repo sync else 110baa3858d3f5d128a5c8466b700098109edcad5f2repo sync { 111baa3858d3f5d128a5c8466b700098109edcad5f2repo sync v = buf2; 112baa3858d3f5d128a5c8466b700098109edcad5f2repo sync if (size2 < 4) 113baa3858d3f5d128a5c8466b700098109edcad5f2repo sync return SZ_ERROR_DATA; 114baa3858d3f5d128a5c8466b700098109edcad5f2repo sync buf2 += 4; 115baa3858d3f5d128a5c8466b700098109edcad5f2repo sync size2 -= 4; 116baa3858d3f5d128a5c8466b700098109edcad5f2repo sync } 117baa3858d3f5d128a5c8466b700098109edcad5f2repo sync dest = (((UInt32)v[0] << 24) | ((UInt32)v[1] << 16) | 118baa3858d3f5d128a5c8466b700098109edcad5f2repo sync ((UInt32)v[2] << 8) | ((UInt32)v[3])) - ((UInt32)outPos + 4); 119baa3858d3f5d128a5c8466b700098109edcad5f2repo sync outBuf[outPos++] = (Byte)dest; 120baa3858d3f5d128a5c8466b700098109edcad5f2repo sync if (outPos == outSize) 121baa3858d3f5d128a5c8466b700098109edcad5f2repo sync break; 122baa3858d3f5d128a5c8466b700098109edcad5f2repo sync outBuf[outPos++] = (Byte)(dest >> 8); 123baa3858d3f5d128a5c8466b700098109edcad5f2repo sync if (outPos == outSize) 124baa3858d3f5d128a5c8466b700098109edcad5f2repo sync break; 125baa3858d3f5d128a5c8466b700098109edcad5f2repo sync outBuf[outPos++] = (Byte)(dest >> 16); 126baa3858d3f5d128a5c8466b700098109edcad5f2repo sync if (outPos == outSize) 127baa3858d3f5d128a5c8466b700098109edcad5f2repo sync break; 128baa3858d3f5d128a5c8466b700098109edcad5f2repo sync outBuf[outPos++] = prevByte = (Byte)(dest >> 24); 129baa3858d3f5d128a5c8466b700098109edcad5f2repo sync } 130baa3858d3f5d128a5c8466b700098109edcad5f2repo sync } 131baa3858d3f5d128a5c8466b700098109edcad5f2repo sync return (outPos == outSize) ? SZ_OK : SZ_ERROR_DATA; 132baa3858d3f5d128a5c8466b700098109edcad5f2repo sync} 133