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