Annotation of elwix/tools/oldlzma/SRC/7zip/Compress/Branch/x86_2.cpp, revision 1.1.1.1

1.1       misho       1: // x86_2.cpp
                      2: 
                      3: #include "StdAfx.h"
                      4: #include "x86_2.h"
                      5: 
                      6: #include "../../../Common/Alloc.h"
                      7: 
                      8: static const int kBufferSize = 1 << 17;
                      9: 
                     10: inline bool IsJcc(Byte b0, Byte b1)
                     11: {
                     12:   return (b0 == 0x0F && (b1 & 0xF0) == 0x80);
                     13: }
                     14: 
                     15: #ifndef EXTRACT_ONLY
                     16: 
                     17: static bool inline Test86MSByte(Byte b)
                     18: {
                     19:   return (b == 0 || b == 0xFF);
                     20: }
                     21: 
                     22: bool CBCJ2_x86_Encoder::Create()
                     23: {
                     24:   if (!_mainStream.Create(1 << 16))
                     25:     return false;
                     26:   if (!_callStream.Create(1 << 20))
                     27:     return false;
                     28:   if (!_jumpStream.Create(1 << 20))
                     29:     return false;
                     30:   if (!_rangeEncoder.Create(1 << 20))
                     31:     return false;
                     32:   if (_buffer == 0)
                     33:   {
                     34:     _buffer = (Byte *)BigAlloc(kBufferSize);
                     35:     if (_buffer == 0)
                     36:       return false;
                     37:   }
                     38:   return true;
                     39: }
                     40: 
                     41: CBCJ2_x86_Encoder::~CBCJ2_x86_Encoder()
                     42: {
                     43:   BigFree(_buffer);
                     44: }
                     45: 
                     46: HRESULT CBCJ2_x86_Encoder::Flush()
                     47: {
                     48:   RINOK(_mainStream.Flush());
                     49:   RINOK(_callStream.Flush());
                     50:   RINOK(_jumpStream.Flush());
                     51:   _rangeEncoder.FlushData();
                     52:   return _rangeEncoder.FlushStream();
                     53: }
                     54: 
                     55: const UInt32 kDefaultLimit = (1 << 24);
                     56: 
                     57: HRESULT CBCJ2_x86_Encoder::CodeReal(ISequentialInStream **inStreams,
                     58:       const UInt64 **inSizes,
                     59:       UInt32 numInStreams,
                     60:       ISequentialOutStream **outStreams,
                     61:       const UInt64 **outSizes,
                     62:       UInt32 numOutStreams,
                     63:       ICompressProgressInfo *progress)
                     64: {
                     65:   if (numInStreams != 1 || numOutStreams != 4)
                     66:     return E_INVALIDARG;
                     67: 
                     68:   if (!Create())
                     69:     return E_OUTOFMEMORY;
                     70: 
                     71:   bool sizeIsDefined = false;
                     72:   UInt64 inSize;
                     73:   if (inSizes != NULL)
                     74:     if (inSizes[0] != NULL)
                     75:     {
                     76:       inSize = *inSizes[0];
                     77:       if (inSize <= kDefaultLimit)
                     78:         sizeIsDefined = true;
                     79:     }
                     80: 
                     81:   ISequentialInStream *inStream = inStreams[0];
                     82: 
                     83:   _mainStream.SetStream(outStreams[0]);
                     84:   _mainStream.Init();
                     85:   _callStream.SetStream(outStreams[1]);
                     86:   _callStream.Init();
                     87:   _jumpStream.SetStream(outStreams[2]);
                     88:   _jumpStream.Init();
                     89:   _rangeEncoder.SetStream(outStreams[3]);
                     90:   _rangeEncoder.Init();
                     91:   for (int i = 0; i < 256; i++)
                     92:     _statusE8Encoder[i].Init();
                     93:   _statusE9Encoder.Init();
                     94:   _statusJccEncoder.Init();
                     95:   CCoderReleaser releaser(this);
                     96: 
                     97:   CMyComPtr<ICompressGetSubStreamSize> getSubStreamSize;
                     98:   {
                     99:     inStream->QueryInterface(IID_ICompressGetSubStreamSize, (void **)&getSubStreamSize);
                    100:   }
                    101: 
                    102:   UInt32 nowPos = 0;
                    103:   UInt64 nowPos64 = 0;
                    104:   UInt32 bufferPos = 0;
                    105:   UInt32 processedSize;
                    106: 
                    107:   Byte prevByte = 0;
                    108: 
                    109:   UInt64 subStreamIndex = 0;
                    110:   UInt64 subStreamStartPos  = 0;
                    111:   UInt64 subStreamEndPos = 0;
                    112: 
                    113:   while(true)
                    114:   {
                    115:     UInt32 size = kBufferSize - bufferPos;
                    116:     RINOK(inStream->Read(_buffer + bufferPos, size, &processedSize));
                    117:     UInt32 endPos = bufferPos + processedSize;
                    118:     
                    119:     if (endPos < 5)
                    120:     {
                    121:       // change it 
                    122:       for (bufferPos = 0; bufferPos < endPos; bufferPos++)
                    123:       {
                    124:         Byte b = _buffer[bufferPos];
                    125:         _mainStream.WriteByte(b);
                    126:         if (b == 0xE8)
                    127:           _statusE8Encoder[prevByte].Encode(&_rangeEncoder, 0);
                    128:         else if (b == 0xE9)
                    129:           _statusE9Encoder.Encode(&_rangeEncoder, 0);
                    130:         else if (IsJcc(prevByte, b))
                    131:           _statusJccEncoder.Encode(&_rangeEncoder, 0);
                    132:         prevByte = b;
                    133:       }
                    134:       return Flush();
                    135:     }
                    136: 
                    137:     bufferPos = 0;
                    138: 
                    139:     UInt32 limit = endPos - 5;
                    140:     while(bufferPos <= limit)
                    141:     {
                    142:       Byte b = _buffer[bufferPos];
                    143:       _mainStream.WriteByte(b);
                    144:       if (b != 0xE8 && b != 0xE9 && !IsJcc(prevByte, b))
                    145:       {
                    146:         bufferPos++;
                    147:         prevByte = b;
                    148:         continue;
                    149:       }
                    150:       Byte nextByte = _buffer[bufferPos + 4];
                    151:       UInt32 src = 
                    152:         (UInt32(nextByte) << 24) |
                    153:         (UInt32(_buffer[bufferPos + 3]) << 16) |
                    154:         (UInt32(_buffer[bufferPos + 2]) << 8) |
                    155:         (_buffer[bufferPos + 1]);
                    156:       UInt32 dest = (nowPos + bufferPos + 5) + src;
                    157:       // if (Test86MSByte(nextByte))
                    158:       bool convert;
                    159:       if (getSubStreamSize != NULL)
                    160:       {
                    161:         UInt64 currentPos = (nowPos64 + bufferPos);
                    162:         while (subStreamEndPos < currentPos)
                    163:         {
                    164:           UInt64 subStreamSize;
                    165:           HRESULT result = getSubStreamSize->GetSubStreamSize(subStreamIndex, &subStreamSize);
                    166:           if (result == S_OK)
                    167:           {
                    168:             subStreamStartPos = subStreamEndPos;
                    169:             subStreamEndPos += subStreamSize;          
                    170:             subStreamIndex++;
                    171:           }
                    172:           else if (result == S_FALSE || result == E_NOTIMPL)
                    173:           {
                    174:             getSubStreamSize.Release();
                    175:             subStreamStartPos = 0;
                    176:             subStreamEndPos = subStreamStartPos - 1;          
                    177:           }
                    178:           else
                    179:             return result;
                    180:         }
                    181:         if (getSubStreamSize == NULL)
                    182:         {
                    183:           if (sizeIsDefined)
                    184:             convert = (dest < inSize);
                    185:           else
                    186:             convert = Test86MSByte(nextByte);
                    187:         }
                    188:         else if (subStreamEndPos - subStreamStartPos > kDefaultLimit)
                    189:           convert = Test86MSByte(nextByte);
                    190:         else
                    191:         {
                    192:           UInt64 dest64 = (currentPos + 5) + Int64(Int32(src));
                    193:           convert = (dest64 >= subStreamStartPos && dest64 < subStreamEndPos);
                    194:         }
                    195:       }
                    196:       else if (sizeIsDefined)
                    197:         convert = (dest < inSize);
                    198:       else
                    199:         convert = Test86MSByte(nextByte);
                    200:       if (convert)
                    201:       {
                    202:         if (b == 0xE8)
                    203:           _statusE8Encoder[prevByte].Encode(&_rangeEncoder, 1);
                    204:         else if (b == 0xE9)
                    205:           _statusE9Encoder.Encode(&_rangeEncoder, 1);
                    206:         else 
                    207:           _statusJccEncoder.Encode(&_rangeEncoder, 1);
                    208: 
                    209:         bufferPos += 5;
                    210:         if (b == 0xE8)
                    211:         {
                    212:           _callStream.WriteByte((Byte)(dest >> 24));
                    213:           _callStream.WriteByte((Byte)(dest >> 16));
                    214:           _callStream.WriteByte((Byte)(dest >> 8));
                    215:           _callStream.WriteByte((Byte)(dest));
                    216:         }
                    217:         else 
                    218:         {
                    219:           _jumpStream.WriteByte((Byte)(dest >> 24));
                    220:           _jumpStream.WriteByte((Byte)(dest >> 16));
                    221:           _jumpStream.WriteByte((Byte)(dest >> 8));
                    222:           _jumpStream.WriteByte((Byte)(dest));
                    223:         }
                    224:         prevByte = nextByte;
                    225:       }
                    226:       else
                    227:       {
                    228:         if (b == 0xE8)
                    229:           _statusE8Encoder[prevByte].Encode(&_rangeEncoder, 0);
                    230:         else if (b == 0xE9)
                    231:           _statusE9Encoder.Encode(&_rangeEncoder, 0);
                    232:         else
                    233:           _statusJccEncoder.Encode(&_rangeEncoder, 0);
                    234:         bufferPos++;
                    235:         prevByte = b;
                    236:       }
                    237:     }
                    238:     nowPos += bufferPos;
                    239:     nowPos64 += bufferPos;
                    240: 
                    241:     if (progress != NULL)
                    242:     {
                    243:       RINOK(progress->SetRatioInfo(&nowPos64, NULL));
                    244:     }
                    245:  
                    246:     UInt32 i = 0;
                    247:     while(bufferPos < endPos)
                    248:       _buffer[i++] = _buffer[bufferPos++];
                    249:     bufferPos = i;
                    250:   }
                    251: }
                    252: 
                    253: STDMETHODIMP CBCJ2_x86_Encoder::Code(ISequentialInStream **inStreams,
                    254:       const UInt64 **inSizes,
                    255:       UInt32 numInStreams,
                    256:       ISequentialOutStream **outStreams,
                    257:       const UInt64 **outSizes,
                    258:       UInt32 numOutStreams,
                    259:       ICompressProgressInfo *progress)
                    260: {
                    261:   try
                    262:   {
                    263:     return CodeReal(inStreams, inSizes, numInStreams,
                    264:       outStreams, outSizes,numOutStreams, progress);
                    265:   }
                    266:   catch(const COutBufferException &e) { return e.ErrorCode; }
                    267:   catch(...) { return S_FALSE; }
                    268: }
                    269: 
                    270: #endif
                    271: 
                    272: HRESULT CBCJ2_x86_Decoder::CodeReal(ISequentialInStream **inStreams,
                    273:       const UInt64 **inSizes,
                    274:       UInt32 numInStreams,
                    275:       ISequentialOutStream **outStreams,
                    276:       const UInt64 **outSizes,
                    277:       UInt32 numOutStreams,
                    278:       ICompressProgressInfo *progress)
                    279: {
                    280:   if (numInStreams != 4 || numOutStreams != 1)
                    281:     return E_INVALIDARG;
                    282: 
                    283:   if (!_mainInStream.Create(1 << 16))
                    284:     return E_OUTOFMEMORY;
                    285:   if (!_callStream.Create(1 << 20))
                    286:     return E_OUTOFMEMORY;
                    287:   if (!_jumpStream.Create(1 << 16))
                    288:     return E_OUTOFMEMORY;
                    289:   if (!_rangeDecoder.Create(1 << 20))
                    290:     return E_OUTOFMEMORY;
                    291:   if (!_outStream.Create(1 << 16))
                    292:     return E_OUTOFMEMORY;
                    293: 
                    294:   _mainInStream.SetStream(inStreams[0]);
                    295:   _callStream.SetStream(inStreams[1]);
                    296:   _jumpStream.SetStream(inStreams[2]);
                    297:   _rangeDecoder.SetStream(inStreams[3]);
                    298:   _outStream.SetStream(outStreams[0]);
                    299: 
                    300:   _mainInStream.Init();
                    301:   _callStream.Init();
                    302:   _jumpStream.Init();
                    303:   _rangeDecoder.Init();
                    304:   _outStream.Init();
                    305: 
                    306:   for (int i = 0; i < 256; i++)
                    307:     _statusE8Decoder[i].Init();
                    308:   _statusE9Decoder.Init();
                    309:   _statusJccDecoder.Init();
                    310: 
                    311:   CCoderReleaser releaser(this);
                    312: 
                    313:   Byte prevByte = 0;
                    314:   UInt32 processedBytes = 0;
                    315:   while(true)
                    316:   {
                    317:     if (processedBytes > (1 << 20) && progress != NULL)
                    318:     {
                    319:       UInt64 nowPos64 = _outStream.GetProcessedSize();
                    320:       RINOK(progress->SetRatioInfo(NULL, &nowPos64));
                    321:       processedBytes = 0;
                    322:     }
                    323:     processedBytes++;
                    324:     Byte b;
                    325:     if (!_mainInStream.ReadByte(b))
                    326:       return Flush();
                    327:     _outStream.WriteByte(b);
                    328:     if (b != 0xE8 && b != 0xE9 && !IsJcc(prevByte, b))
                    329:     {
                    330:       prevByte = b;
                    331:       continue;
                    332:     }
                    333:     bool status;
                    334:     if (b == 0xE8)
                    335:       status = (_statusE8Decoder[prevByte].Decode(&_rangeDecoder) == 1);
                    336:     else if (b == 0xE9)
                    337:       status = (_statusE9Decoder.Decode(&_rangeDecoder) == 1);
                    338:     else
                    339:       status = (_statusJccDecoder.Decode(&_rangeDecoder) == 1);
                    340:     if (status)
                    341:     {
                    342:       UInt32 src;
                    343:       if (b == 0xE8)
                    344:       {
                    345:         Byte b0;
                    346:         if(!_callStream.ReadByte(b0))
                    347:           return S_FALSE;
                    348:         src = ((UInt32)b0) << 24;
                    349:         if(!_callStream.ReadByte(b0))
                    350:           return S_FALSE;
                    351:         src |= ((UInt32)b0) << 16;
                    352:         if(!_callStream.ReadByte(b0))
                    353:           return S_FALSE;
                    354:         src |= ((UInt32)b0) << 8;
                    355:         if(!_callStream.ReadByte(b0))
                    356:           return S_FALSE;
                    357:         src |= ((UInt32)b0);
                    358:       }
                    359:       else
                    360:       {
                    361:         Byte b0;
                    362:         if(!_jumpStream.ReadByte(b0))
                    363:           return S_FALSE;
                    364:         src = ((UInt32)b0) << 24;
                    365:         if(!_jumpStream.ReadByte(b0))
                    366:           return S_FALSE;
                    367:         src |= ((UInt32)b0) << 16;
                    368:         if(!_jumpStream.ReadByte(b0))
                    369:           return S_FALSE;
                    370:         src |= ((UInt32)b0) << 8;
                    371:         if(!_jumpStream.ReadByte(b0))
                    372:           return S_FALSE;
                    373:         src |= ((UInt32)b0);
                    374:       }
                    375:       UInt32 dest = src - (UInt32(_outStream.GetProcessedSize()) + 4) ;
                    376:       _outStream.WriteByte((Byte)(dest));
                    377:       _outStream.WriteByte((Byte)(dest >> 8));
                    378:       _outStream.WriteByte((Byte)(dest >> 16));
                    379:       _outStream.WriteByte((Byte)(dest >> 24));
                    380:       prevByte = (dest >> 24);
                    381:       processedBytes += 4;
                    382:     }
                    383:     else
                    384:       prevByte = b;
                    385:   }
                    386: }
                    387: 
                    388: STDMETHODIMP CBCJ2_x86_Decoder::Code(ISequentialInStream **inStreams,
                    389:       const UInt64 **inSizes,
                    390:       UInt32 numInStreams,
                    391:       ISequentialOutStream **outStreams,
                    392:       const UInt64 **outSizes,
                    393:       UInt32 numOutStreams,
                    394:       ICompressProgressInfo *progress)
                    395: {
                    396:   try
                    397:   {
                    398:     return CodeReal(inStreams, inSizes, numInStreams,
                    399:         outStreams, outSizes,numOutStreams, progress);
                    400:   }
                    401:   catch(const COutBufferException &e) { return e.ErrorCode; }
                    402:   catch(...) { return S_FALSE; }
                    403: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>