rlm@1
|
1 // Rar3Vm.h
|
rlm@1
|
2 // According to unRAR license, this code may not be used to develop
|
rlm@1
|
3 // a program that creates RAR archives
|
rlm@1
|
4
|
rlm@1
|
5 #ifndef __COMPRESS_RAR3_VM_H
|
rlm@1
|
6 #define __COMPRESS_RAR3_VM_H
|
rlm@1
|
7
|
rlm@1
|
8 #include "../../../C/CpuArch.h"
|
rlm@1
|
9
|
rlm@1
|
10 #include "Common/MyVector.h"
|
rlm@1
|
11 #include "Common/Types.h"
|
rlm@1
|
12
|
rlm@1
|
13 #define RARVM_STANDARD_FILTERS
|
rlm@1
|
14
|
rlm@1
|
15 namespace NCompress {
|
rlm@1
|
16 namespace NRar3 {
|
rlm@1
|
17
|
rlm@1
|
18 class CMemBitDecoder
|
rlm@1
|
19 {
|
rlm@1
|
20 const Byte *_data;
|
rlm@1
|
21 UInt32 _bitSize;
|
rlm@1
|
22 UInt32 _bitPos;
|
rlm@1
|
23 public:
|
rlm@1
|
24 void Init(const Byte *data, UInt32 byteSize)
|
rlm@1
|
25 {
|
rlm@1
|
26 _data = data;
|
rlm@1
|
27 _bitSize = (byteSize << 3);
|
rlm@1
|
28 _bitPos = 0;
|
rlm@1
|
29 }
|
rlm@1
|
30 UInt32 ReadBits(int numBits);
|
rlm@1
|
31 UInt32 ReadBit();
|
rlm@1
|
32 bool Avail() const { return (_bitPos < _bitSize); }
|
rlm@1
|
33 };
|
rlm@1
|
34
|
rlm@1
|
35 namespace NVm {
|
rlm@1
|
36
|
rlm@1
|
37 inline UInt32 GetValue32(const void *addr) { return GetUi32(addr); }
|
rlm@1
|
38 inline void SetValue32(void *addr, UInt32 value) { SetUi32(addr, value); }
|
rlm@1
|
39
|
rlm@1
|
40 UInt32 ReadEncodedUInt32(CMemBitDecoder &inp);
|
rlm@1
|
41
|
rlm@1
|
42 const int kNumRegBits = 3;
|
rlm@1
|
43 const UInt32 kNumRegs = 1 << kNumRegBits;
|
rlm@1
|
44 const UInt32 kNumGpRegs = kNumRegs - 1;
|
rlm@1
|
45
|
rlm@1
|
46 const UInt32 kSpaceSize = 0x40000;
|
rlm@1
|
47 const UInt32 kSpaceMask = kSpaceSize -1;
|
rlm@1
|
48 const UInt32 kGlobalOffset = 0x3C000;
|
rlm@1
|
49 const UInt32 kGlobalSize = 0x2000;
|
rlm@1
|
50 const UInt32 kFixedGlobalSize = 64;
|
rlm@1
|
51
|
rlm@1
|
52 namespace NGlobalOffset
|
rlm@1
|
53 {
|
rlm@1
|
54 const UInt32 kBlockSize = 0x1C;
|
rlm@1
|
55 const UInt32 kBlockPos = 0x20;
|
rlm@1
|
56 const UInt32 kExecCount = 0x2C;
|
rlm@1
|
57 const UInt32 kGlobalMemOutSize = 0x30;
|
rlm@1
|
58 }
|
rlm@1
|
59
|
rlm@1
|
60 enum ECommand
|
rlm@1
|
61 {
|
rlm@1
|
62 CMD_MOV, CMD_CMP, CMD_ADD, CMD_SUB, CMD_JZ, CMD_JNZ, CMD_INC, CMD_DEC,
|
rlm@1
|
63 CMD_JMP, CMD_XOR, CMD_AND, CMD_OR, CMD_TEST, CMD_JS, CMD_JNS, CMD_JB,
|
rlm@1
|
64 CMD_JBE, CMD_JA, CMD_JAE, CMD_PUSH, CMD_POP, CMD_CALL, CMD_RET, CMD_NOT,
|
rlm@1
|
65 CMD_SHL, CMD_SHR, CMD_SAR, CMD_NEG, CMD_PUSHA,CMD_POPA, CMD_PUSHF,CMD_POPF,
|
rlm@1
|
66 CMD_MOVZX,CMD_MOVSX,CMD_XCHG, CMD_MUL, CMD_DIV, CMD_ADC, CMD_SBB, CMD_PRINT,
|
rlm@1
|
67
|
rlm@1
|
68 CMD_MOVB, CMD_CMPB, CMD_ADDB, CMD_SUBB, CMD_INCB, CMD_DECB,
|
rlm@1
|
69 CMD_XORB, CMD_ANDB, CMD_ORB, CMD_TESTB,CMD_NEGB,
|
rlm@1
|
70 CMD_SHLB, CMD_SHRB, CMD_SARB, CMD_MULB
|
rlm@1
|
71 };
|
rlm@1
|
72
|
rlm@1
|
73 enum EOpType {OP_TYPE_REG, OP_TYPE_INT, OP_TYPE_REGMEM, OP_TYPE_NONE};
|
rlm@1
|
74
|
rlm@1
|
75 // Addr in COperand object can link (point) to CVm object!!!
|
rlm@1
|
76
|
rlm@1
|
77 struct COperand
|
rlm@1
|
78 {
|
rlm@1
|
79 EOpType Type;
|
rlm@1
|
80 UInt32 Data;
|
rlm@1
|
81 UInt32 Base;
|
rlm@1
|
82 COperand(): Type(OP_TYPE_NONE), Data(0), Base(0) {}
|
rlm@1
|
83 };
|
rlm@1
|
84
|
rlm@1
|
85 struct CCommand
|
rlm@1
|
86 {
|
rlm@1
|
87 ECommand OpCode;
|
rlm@1
|
88 bool ByteMode;
|
rlm@1
|
89 COperand Op1, Op2;
|
rlm@1
|
90 };
|
rlm@1
|
91
|
rlm@1
|
92 struct CBlockRef
|
rlm@1
|
93 {
|
rlm@1
|
94 UInt32 Offset;
|
rlm@1
|
95 UInt32 Size;
|
rlm@1
|
96 };
|
rlm@1
|
97
|
rlm@1
|
98 struct CProgram
|
rlm@1
|
99 {
|
rlm@1
|
100 CRecordVector<CCommand> Commands;
|
rlm@1
|
101 #ifdef RARVM_STANDARD_FILTERS
|
rlm@1
|
102 int StandardFilterIndex;
|
rlm@1
|
103 #endif
|
rlm@1
|
104 CRecordVector<Byte> StaticData;
|
rlm@1
|
105 };
|
rlm@1
|
106
|
rlm@1
|
107 struct CProgramInitState
|
rlm@1
|
108 {
|
rlm@1
|
109 UInt32 InitR[kNumGpRegs];
|
rlm@1
|
110 CRecordVector<Byte> GlobalData;
|
rlm@1
|
111
|
rlm@1
|
112 void AllocateEmptyFixedGlobal()
|
rlm@1
|
113 {
|
rlm@1
|
114 GlobalData.Clear();
|
rlm@1
|
115 GlobalData.Reserve(NVm::kFixedGlobalSize);
|
rlm@1
|
116 for (UInt32 i = 0; i < NVm::kFixedGlobalSize; i++)
|
rlm@1
|
117 GlobalData.Add(0);
|
rlm@1
|
118 }
|
rlm@1
|
119 };
|
rlm@1
|
120
|
rlm@1
|
121 class CVm
|
rlm@1
|
122 {
|
rlm@1
|
123 static UInt32 GetValue(bool byteMode, const void *addr)
|
rlm@1
|
124 {
|
rlm@1
|
125 if (byteMode)
|
rlm@1
|
126 return(*(const Byte *)addr);
|
rlm@1
|
127 else
|
rlm@1
|
128 return GetUi32(addr);
|
rlm@1
|
129 }
|
rlm@1
|
130
|
rlm@1
|
131 static void SetValue(bool byteMode, void *addr, UInt32 value)
|
rlm@1
|
132 {
|
rlm@1
|
133 if (byteMode)
|
rlm@1
|
134 *(Byte *)addr = (Byte)value;
|
rlm@1
|
135 else
|
rlm@1
|
136 SetUi32(addr, value);
|
rlm@1
|
137 }
|
rlm@1
|
138
|
rlm@1
|
139 UInt32 GetFixedGlobalValue32(UInt32 globalOffset) { return GetValue(false, &Mem[kGlobalOffset + globalOffset]); }
|
rlm@1
|
140
|
rlm@1
|
141 void SetBlockSize(UInt32 v) { SetValue(&Mem[kGlobalOffset + NGlobalOffset::kBlockSize], v); }
|
rlm@1
|
142 void SetBlockPos(UInt32 v) { SetValue(&Mem[kGlobalOffset + NGlobalOffset::kBlockPos], v); }
|
rlm@1
|
143 public:
|
rlm@1
|
144 static void SetValue(void *addr, UInt32 value) { SetValue(false, addr, value); }
|
rlm@1
|
145 private:
|
rlm@1
|
146 UInt32 GetOperand32(const COperand *op) const;
|
rlm@1
|
147 void SetOperand32(const COperand *op, UInt32 val);
|
rlm@1
|
148 Byte GetOperand8(const COperand *op) const;
|
rlm@1
|
149 void SetOperand8(const COperand *op, Byte val);
|
rlm@1
|
150 UInt32 GetOperand(bool byteMode, const COperand *op) const;
|
rlm@1
|
151 void SetOperand(bool byteMode, const COperand *op, UInt32 val);
|
rlm@1
|
152
|
rlm@1
|
153 void DecodeArg(CMemBitDecoder &inp, COperand &op, bool byteMode);
|
rlm@1
|
154
|
rlm@1
|
155 bool ExecuteCode(const CProgram *prg);
|
rlm@1
|
156
|
rlm@1
|
157 #ifdef RARVM_STANDARD_FILTERS
|
rlm@1
|
158 void ExecuteStandardFilter(int filterIndex);
|
rlm@1
|
159 #endif
|
rlm@1
|
160
|
rlm@1
|
161 Byte *Mem;
|
rlm@1
|
162 UInt32 R[kNumRegs + 1]; // R[kNumRegs] = 0 always (speed optimization)
|
rlm@1
|
163 UInt32 Flags;
|
rlm@1
|
164 void ReadVmProgram(const Byte *code, UInt32 codeSize, CProgram *prg);
|
rlm@1
|
165 public:
|
rlm@1
|
166 CVm();
|
rlm@1
|
167 ~CVm();
|
rlm@1
|
168 bool Create();
|
rlm@1
|
169 void PrepareProgram(const Byte *code, UInt32 codeSize, CProgram *prg);
|
rlm@1
|
170 void SetMemory(UInt32 pos, const Byte *data, UInt32 dataSize);
|
rlm@1
|
171 bool Execute(CProgram *prg, const CProgramInitState *initState,
|
rlm@1
|
172 CBlockRef &outBlockRef, CRecordVector<Byte> &outGlobalData);
|
rlm@1
|
173 const Byte *GetDataPointer(UInt32 offset) const { return Mem + offset; }
|
rlm@1
|
174
|
rlm@1
|
175 };
|
rlm@1
|
176
|
rlm@1
|
177 #endif
|
rlm@1
|
178
|
rlm@1
|
179 }}}
|