diff options
Diffstat (limited to 'CPP/7zip/Compress/Rar/Rar3Vm.h')
-rwxr-xr-x | CPP/7zip/Compress/Rar/Rar3Vm.h | 219 |
1 files changed, 219 insertions, 0 deletions
diff --git a/CPP/7zip/Compress/Rar/Rar3Vm.h b/CPP/7zip/Compress/Rar/Rar3Vm.h new file mode 100755 index 00000000..d0a4f82c --- /dev/null +++ b/CPP/7zip/Compress/Rar/Rar3Vm.h @@ -0,0 +1,219 @@ +// Rar3Vm.h +// According to unRAR license, +// this code may not be used to develop a +// RAR (WinRAR) compatible archiver + +#ifndef __RAR3VM_H +#define __RAR3VM_H + +#include "Common/Types.h" +#include "Common/Vector.h" + +#define RARVM_STANDARD_FILTERS +#if defined(_M_IX86) || defined(_M_X64) || defined(_M_AMD64) || defined(__i386__) || defined(__x86_64__) // || defined(_M_IA64) || defined(__ia64__) +// Define RARVM_LITTLE_ENDIAN_UNALIGN, if CPU is LITTLE_ENDIAN and if it supports +// unaligned 32-bit memory accesses. +// It's for speed optimization, if you are not sure, just don't define it. +#define RARVM_LITTLE_ENDIAN_UNALIGN +#endif + +namespace NCompress { +namespace NRar3 { + +class CMemBitDecoder +{ + const Byte *_data; + UInt32 _bitSize; + UInt32 _bitPos; +public: + void Init(const Byte *data, UInt32 byteSize) + { + _data = data; + _bitSize = (byteSize << 3); + _bitPos = 0; + } + UInt32 ReadBits(int numBits); + UInt32 ReadBit(); + bool Avail() const { return (_bitPos < _bitSize); } +}; + +namespace NVm { + +inline UInt32 GetValue32(const void *addr) +{ + #ifdef RARVM_LITTLE_ENDIAN_UNALIGN + return *(const UInt32 *)addr; + #else + const Byte *b = (const Byte *)addr; + return UInt32((UInt32)b[0]|((UInt32)b[1]<<8)|((UInt32)b[2]<<16)|((UInt32)b[3]<<24)); + #endif +} + +inline void SetValue32(void *addr, UInt32 value) +{ + #ifdef RARVM_LITTLE_ENDIAN_UNALIGN + *(UInt32 *)addr = value; + #else + ((Byte *)addr)[0] = (Byte)value; + ((Byte *)addr)[1] = (Byte)(value >> 8); + ((Byte *)addr)[2] = (Byte)(value >> 16); + ((Byte *)addr)[3] = (Byte)(value >> 24); + #endif +} + +UInt32 ReadEncodedUInt32(CMemBitDecoder &inp); + +const int kNumRegBits = 3; +const UInt32 kNumRegs = 1 << kNumRegBits; +const UInt32 kNumGpRegs = kNumRegs - 1; + +const UInt32 kSpaceSize = 0x40000; +const UInt32 kSpaceMask = kSpaceSize -1; +const UInt32 kGlobalOffset = 0x3C000; +const UInt32 kGlobalSize = 0x2000; +const UInt32 kFixedGlobalSize = 64; + +namespace NGlobalOffset +{ + const UInt32 kBlockSize = 0x1C; + const UInt32 kBlockPos = 0x20; + const UInt32 kExecCount = 0x2C; + const UInt32 kGlobalMemOutSize = 0x30; +}; + +enum ECommand +{ + CMD_MOV, CMD_CMP, CMD_ADD, CMD_SUB, CMD_JZ, CMD_JNZ, CMD_INC, CMD_DEC, + CMD_JMP, CMD_XOR, CMD_AND, CMD_OR, CMD_TEST, CMD_JS, CMD_JNS, CMD_JB, + CMD_JBE, CMD_JA, CMD_JAE, CMD_PUSH, CMD_POP, CMD_CALL, CMD_RET, CMD_NOT, + CMD_SHL, CMD_SHR, CMD_SAR, CMD_NEG, CMD_PUSHA,CMD_POPA, CMD_PUSHF,CMD_POPF, + CMD_MOVZX,CMD_MOVSX,CMD_XCHG, CMD_MUL, CMD_DIV, CMD_ADC, CMD_SBB, CMD_PRINT, + + CMD_MOVB, CMD_CMPB, CMD_ADDB, CMD_SUBB, CMD_INCB, CMD_DECB, + CMD_XORB, CMD_ANDB, CMD_ORB, CMD_TESTB,CMD_NEGB, + CMD_SHLB, CMD_SHRB, CMD_SARB, CMD_MULB +}; + +enum EOpType {OP_TYPE_REG, OP_TYPE_INT, OP_TYPE_REGMEM, OP_TYPE_NONE}; + +// Addr in COperand object can link (point) to CVm object!!! + +struct COperand +{ + EOpType Type; + UInt32 Data; + UInt32 Base; + COperand(): Type(OP_TYPE_NONE), Data(0), Base(0) {} +}; + +struct CCommand +{ + ECommand OpCode; + bool ByteMode; + COperand Op1, Op2; +}; + +struct CBlockRef +{ + UInt32 Offset; + UInt32 Size; +}; + +struct CProgram +{ + CRecordVector<CCommand> Commands; + #ifdef RARVM_STANDARD_FILTERS + int StandardFilterIndex; + #endif + CRecordVector<Byte> StaticData; +}; + +struct CProgramInitState +{ + UInt32 InitR[kNumGpRegs]; + CRecordVector<Byte> GlobalData; + + void AllocateEmptyFixedGlobal() + { + GlobalData.Clear(); + GlobalData.Reserve(NVm::kFixedGlobalSize); + for (UInt32 i = 0; i < NVm::kFixedGlobalSize; i++) + GlobalData.Add(0); + } +}; + +class CVm +{ + static UInt32 GetValue(bool byteMode, const void *addr) + { + if (byteMode) + return(*(const Byte *)addr); + else + { + #ifdef RARVM_LITTLE_ENDIAN_UNALIGN + return *(const UInt32 *)addr; + #else + const Byte *b = (const Byte *)addr; + return UInt32((UInt32)b[0]|((UInt32)b[1]<<8)|((UInt32)b[2]<<16)|((UInt32)b[3]<<24)); + #endif + } + } + + static void SetValue(bool byteMode, void *addr, UInt32 value) + { + if (byteMode) + *(Byte *)addr = (Byte)value; + else + { + #ifdef RARVM_LITTLE_ENDIAN_UNALIGN + *(UInt32 *)addr = value; + #else + ((Byte *)addr)[0] = (Byte)value; + ((Byte *)addr)[1] = (Byte)(value >> 8); + ((Byte *)addr)[2] = (Byte)(value >> 16); + ((Byte *)addr)[3] = (Byte)(value >> 24); + #endif + } + } + + UInt32 GetFixedGlobalValue32(UInt32 globalOffset) { return GetValue(false, &Mem[kGlobalOffset + globalOffset]); } + + void SetBlockSize(UInt32 v) { SetValue(&Mem[kGlobalOffset + NGlobalOffset::kBlockSize], v); } + void SetBlockPos(UInt32 v) { SetValue(&Mem[kGlobalOffset + NGlobalOffset::kBlockPos], v); } +public: + static void SetValue(void *addr, UInt32 value) { SetValue(false, addr, value); } +private: + UInt32 GetOperand32(const COperand *op) const; + void SetOperand32(const COperand *op, UInt32 val); + Byte GetOperand8(const COperand *op) const; + void SetOperand8(const COperand *op, Byte val); + UInt32 GetOperand(bool byteMode, const COperand *op) const; + void SetOperand(bool byteMode, const COperand *op, UInt32 val); + + void DecodeArg(CMemBitDecoder &inp, COperand &op, bool byteMode); + + bool ExecuteCode(const CProgram *prg); + + #ifdef RARVM_STANDARD_FILTERS + void ExecuteStandardFilter(int filterIndex); + #endif + + Byte *Mem; + UInt32 R[kNumRegs + 1]; // R[kNumRegs] = 0 always (speed optimization) + UInt32 Flags; + void ReadVmProgram(const Byte *code, UInt32 codeSize, CProgram *prg); +public: + CVm(); + ~CVm(); + bool Create(); + void PrepareProgram(const Byte *code, UInt32 codeSize, CProgram *prg); + void SetMemory(UInt32 pos, const Byte *data, UInt32 dataSize); + bool Execute(CProgram *prg, const CProgramInitState *initState, + CBlockRef &outBlockRef, CRecordVector<Byte> &outGlobalData); + const Byte *GetDataPointer(UInt32 offset) const { return Mem + offset; } + +}; + +#endif + +}}} |