xref: /aosp_15_r20/external/lzma/CPP/7zip/Compress/Rar3Vm.cpp (revision f6dc9357d832569d4d1f5d24eacdb3935a1ae8e6)
1*f6dc9357SAndroid Build Coastguard Worker // Rar3Vm.cpp
2*f6dc9357SAndroid Build Coastguard Worker // According to unRAR license, this code may not be used to develop
3*f6dc9357SAndroid Build Coastguard Worker // a program that creates RAR archives
4*f6dc9357SAndroid Build Coastguard Worker 
5*f6dc9357SAndroid Build Coastguard Worker /*
6*f6dc9357SAndroid Build Coastguard Worker Note:
7*f6dc9357SAndroid Build Coastguard Worker   Due to performance considerations Rar VM may set Flags C incorrectly
8*f6dc9357SAndroid Build Coastguard Worker   for some operands (SHL x, 0, ... ).
9*f6dc9357SAndroid Build Coastguard Worker   Check implementation of concrete VM command
10*f6dc9357SAndroid Build Coastguard Worker   to see if it sets flags right.
11*f6dc9357SAndroid Build Coastguard Worker */
12*f6dc9357SAndroid Build Coastguard Worker 
13*f6dc9357SAndroid Build Coastguard Worker #include "StdAfx.h"
14*f6dc9357SAndroid Build Coastguard Worker 
15*f6dc9357SAndroid Build Coastguard Worker #include <stdlib.h>
16*f6dc9357SAndroid Build Coastguard Worker 
17*f6dc9357SAndroid Build Coastguard Worker #include "../../../C/7zCrc.h"
18*f6dc9357SAndroid Build Coastguard Worker #include "../../../C/Alloc.h"
19*f6dc9357SAndroid Build Coastguard Worker 
20*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/Defs.h"
21*f6dc9357SAndroid Build Coastguard Worker 
22*f6dc9357SAndroid Build Coastguard Worker #include "Rar3Vm.h"
23*f6dc9357SAndroid Build Coastguard Worker 
24*f6dc9357SAndroid Build Coastguard Worker namespace NCompress {
25*f6dc9357SAndroid Build Coastguard Worker namespace NRar3 {
26*f6dc9357SAndroid Build Coastguard Worker 
ReadBits(unsigned numBits)27*f6dc9357SAndroid Build Coastguard Worker UInt32 CMemBitDecoder::ReadBits(unsigned numBits)
28*f6dc9357SAndroid Build Coastguard Worker {
29*f6dc9357SAndroid Build Coastguard Worker   UInt32 res = 0;
30*f6dc9357SAndroid Build Coastguard Worker   for (;;)
31*f6dc9357SAndroid Build Coastguard Worker   {
32*f6dc9357SAndroid Build Coastguard Worker     const unsigned b = _bitPos < _bitSize ? (unsigned)_data[_bitPos >> 3] : 0;
33*f6dc9357SAndroid Build Coastguard Worker     const unsigned avail = (unsigned)(8 - (_bitPos & 7));
34*f6dc9357SAndroid Build Coastguard Worker     if (numBits <= avail)
35*f6dc9357SAndroid Build Coastguard Worker     {
36*f6dc9357SAndroid Build Coastguard Worker       _bitPos += numBits;
37*f6dc9357SAndroid Build Coastguard Worker       return res | ((b >> (avail - numBits)) & ((1 << numBits) - 1));
38*f6dc9357SAndroid Build Coastguard Worker     }
39*f6dc9357SAndroid Build Coastguard Worker     numBits -= avail;
40*f6dc9357SAndroid Build Coastguard Worker     res |= (UInt32)(b & ((1 << avail) - 1)) << numBits;
41*f6dc9357SAndroid Build Coastguard Worker     _bitPos += avail;
42*f6dc9357SAndroid Build Coastguard Worker   }
43*f6dc9357SAndroid Build Coastguard Worker }
44*f6dc9357SAndroid Build Coastguard Worker 
ReadBit()45*f6dc9357SAndroid Build Coastguard Worker UInt32 CMemBitDecoder::ReadBit() { return ReadBits(1); }
46*f6dc9357SAndroid Build Coastguard Worker 
ReadEncodedUInt32()47*f6dc9357SAndroid Build Coastguard Worker UInt32 CMemBitDecoder::ReadEncodedUInt32()
48*f6dc9357SAndroid Build Coastguard Worker {
49*f6dc9357SAndroid Build Coastguard Worker   const unsigned v = (unsigned)ReadBits(2);
50*f6dc9357SAndroid Build Coastguard Worker   UInt32 res = ReadBits(4u << v);
51*f6dc9357SAndroid Build Coastguard Worker   if (v == 1 && res < 16)
52*f6dc9357SAndroid Build Coastguard Worker     res = 0xFFFFFF00 | (res << 4) | ReadBits(4);
53*f6dc9357SAndroid Build Coastguard Worker   return res;
54*f6dc9357SAndroid Build Coastguard Worker }
55*f6dc9357SAndroid Build Coastguard Worker 
56*f6dc9357SAndroid Build Coastguard Worker namespace NVm {
57*f6dc9357SAndroid Build Coastguard Worker 
58*f6dc9357SAndroid Build Coastguard Worker static const UInt32 kStackRegIndex = kNumRegs - 1;
59*f6dc9357SAndroid Build Coastguard Worker 
60*f6dc9357SAndroid Build Coastguard Worker #ifdef Z7_RARVM_VM_ENABLE
61*f6dc9357SAndroid Build Coastguard Worker 
62*f6dc9357SAndroid Build Coastguard Worker #if   defined(Z7_GCC_VERSION)   && (Z7_GCC_VERSION   >= 40400) \
63*f6dc9357SAndroid Build Coastguard Worker    || defined(Z7_CLANG_VERSION) && (Z7_CLANG_VERSION >= 30000)
64*f6dc9357SAndroid Build Coastguard Worker // enumeration values not explicitly handled in switch
65*f6dc9357SAndroid Build Coastguard Worker #pragma GCC diagnostic ignored "-Wswitch-enum"
66*f6dc9357SAndroid Build Coastguard Worker #endif
67*f6dc9357SAndroid Build Coastguard Worker 
68*f6dc9357SAndroid Build Coastguard Worker static const UInt32 FLAG_C = 1;
69*f6dc9357SAndroid Build Coastguard Worker static const UInt32 FLAG_Z = 2;
70*f6dc9357SAndroid Build Coastguard Worker static const UInt32 FLAG_S = 0x80000000;
71*f6dc9357SAndroid Build Coastguard Worker 
72*f6dc9357SAndroid Build Coastguard Worker static const Byte CF_OP0 = 0;
73*f6dc9357SAndroid Build Coastguard Worker static const Byte CF_OP1 = 1;
74*f6dc9357SAndroid Build Coastguard Worker static const Byte CF_OP2 = 2;
75*f6dc9357SAndroid Build Coastguard Worker static const Byte CF_OPMASK = 3;
76*f6dc9357SAndroid Build Coastguard Worker static const Byte CF_BYTEMODE = 4;
77*f6dc9357SAndroid Build Coastguard Worker static const Byte CF_JUMP = 8;
78*f6dc9357SAndroid Build Coastguard Worker static const Byte CF_PROC = 16;
79*f6dc9357SAndroid Build Coastguard Worker static const Byte CF_USEFLAGS = 32;
80*f6dc9357SAndroid Build Coastguard Worker static const Byte CF_CHFLAGS = 64;
81*f6dc9357SAndroid Build Coastguard Worker 
82*f6dc9357SAndroid Build Coastguard Worker static const Byte kCmdFlags[]=
83*f6dc9357SAndroid Build Coastguard Worker {
84*f6dc9357SAndroid Build Coastguard Worker   /* CMD_MOV   */ CF_OP2 | CF_BYTEMODE,
85*f6dc9357SAndroid Build Coastguard Worker   /* CMD_CMP   */ CF_OP2 | CF_BYTEMODE | CF_CHFLAGS,
86*f6dc9357SAndroid Build Coastguard Worker   /* CMD_ADD   */ CF_OP2 | CF_BYTEMODE | CF_CHFLAGS,
87*f6dc9357SAndroid Build Coastguard Worker   /* CMD_SUB   */ CF_OP2 | CF_BYTEMODE | CF_CHFLAGS,
88*f6dc9357SAndroid Build Coastguard Worker   /* CMD_JZ    */ CF_OP1 | CF_JUMP | CF_USEFLAGS,
89*f6dc9357SAndroid Build Coastguard Worker   /* CMD_JNZ   */ CF_OP1 | CF_JUMP | CF_USEFLAGS,
90*f6dc9357SAndroid Build Coastguard Worker   /* CMD_INC   */ CF_OP1 | CF_BYTEMODE | CF_CHFLAGS,
91*f6dc9357SAndroid Build Coastguard Worker   /* CMD_DEC   */ CF_OP1 | CF_BYTEMODE | CF_CHFLAGS,
92*f6dc9357SAndroid Build Coastguard Worker   /* CMD_JMP   */ CF_OP1 | CF_JUMP,
93*f6dc9357SAndroid Build Coastguard Worker   /* CMD_XOR   */ CF_OP2 | CF_BYTEMODE | CF_CHFLAGS,
94*f6dc9357SAndroid Build Coastguard Worker   /* CMD_AND   */ CF_OP2 | CF_BYTEMODE | CF_CHFLAGS,
95*f6dc9357SAndroid Build Coastguard Worker   /* CMD_OR    */ CF_OP2 | CF_BYTEMODE | CF_CHFLAGS,
96*f6dc9357SAndroid Build Coastguard Worker   /* CMD_TEST  */ CF_OP2 | CF_BYTEMODE | CF_CHFLAGS,
97*f6dc9357SAndroid Build Coastguard Worker   /* CMD_JS    */ CF_OP1 | CF_JUMP | CF_USEFLAGS,
98*f6dc9357SAndroid Build Coastguard Worker   /* CMD_JNS   */ CF_OP1 | CF_JUMP | CF_USEFLAGS,
99*f6dc9357SAndroid Build Coastguard Worker   /* CMD_JB    */ CF_OP1 | CF_JUMP | CF_USEFLAGS,
100*f6dc9357SAndroid Build Coastguard Worker   /* CMD_JBE   */ CF_OP1 | CF_JUMP | CF_USEFLAGS,
101*f6dc9357SAndroid Build Coastguard Worker   /* CMD_JA    */ CF_OP1 | CF_JUMP | CF_USEFLAGS,
102*f6dc9357SAndroid Build Coastguard Worker   /* CMD_JAE   */ CF_OP1 | CF_JUMP | CF_USEFLAGS,
103*f6dc9357SAndroid Build Coastguard Worker   /* CMD_PUSH  */ CF_OP1,
104*f6dc9357SAndroid Build Coastguard Worker   /* CMD_POP   */ CF_OP1,
105*f6dc9357SAndroid Build Coastguard Worker   /* CMD_CALL  */ CF_OP1 | CF_PROC,
106*f6dc9357SAndroid Build Coastguard Worker   /* CMD_RET   */ CF_OP0 | CF_PROC,
107*f6dc9357SAndroid Build Coastguard Worker   /* CMD_NOT   */ CF_OP1 | CF_BYTEMODE,
108*f6dc9357SAndroid Build Coastguard Worker   /* CMD_SHL   */ CF_OP2 | CF_BYTEMODE | CF_CHFLAGS,
109*f6dc9357SAndroid Build Coastguard Worker   /* CMD_SHR   */ CF_OP2 | CF_BYTEMODE | CF_CHFLAGS,
110*f6dc9357SAndroid Build Coastguard Worker   /* CMD_SAR   */ CF_OP2 | CF_BYTEMODE | CF_CHFLAGS,
111*f6dc9357SAndroid Build Coastguard Worker   /* CMD_NEG   */ CF_OP1 | CF_BYTEMODE | CF_CHFLAGS,
112*f6dc9357SAndroid Build Coastguard Worker   /* CMD_PUSHA */ CF_OP0,
113*f6dc9357SAndroid Build Coastguard Worker   /* CMD_POPA  */ CF_OP0,
114*f6dc9357SAndroid Build Coastguard Worker   /* CMD_PUSHF */ CF_OP0 | CF_USEFLAGS,
115*f6dc9357SAndroid Build Coastguard Worker   /* CMD_POPF  */ CF_OP0 | CF_CHFLAGS,
116*f6dc9357SAndroid Build Coastguard Worker   /* CMD_MOVZX */ CF_OP2,
117*f6dc9357SAndroid Build Coastguard Worker   /* CMD_MOVSX */ CF_OP2,
118*f6dc9357SAndroid Build Coastguard Worker   /* CMD_XCHG  */ CF_OP2 | CF_BYTEMODE,
119*f6dc9357SAndroid Build Coastguard Worker   /* CMD_MUL   */ CF_OP2 | CF_BYTEMODE,
120*f6dc9357SAndroid Build Coastguard Worker   /* CMD_DIV   */ CF_OP2 | CF_BYTEMODE,
121*f6dc9357SAndroid Build Coastguard Worker   /* CMD_ADC   */ CF_OP2 | CF_BYTEMODE | CF_USEFLAGS | CF_CHFLAGS ,
122*f6dc9357SAndroid Build Coastguard Worker   /* CMD_SBB   */ CF_OP2 | CF_BYTEMODE | CF_USEFLAGS | CF_CHFLAGS ,
123*f6dc9357SAndroid Build Coastguard Worker   /* CMD_PRINT */ CF_OP0
124*f6dc9357SAndroid Build Coastguard Worker };
125*f6dc9357SAndroid Build Coastguard Worker 
126*f6dc9357SAndroid Build Coastguard Worker #endif
127*f6dc9357SAndroid Build Coastguard Worker 
128*f6dc9357SAndroid Build Coastguard Worker 
CVm()129*f6dc9357SAndroid Build Coastguard Worker CVm::CVm(): Mem(NULL) {}
130*f6dc9357SAndroid Build Coastguard Worker 
Create()131*f6dc9357SAndroid Build Coastguard Worker bool CVm::Create()
132*f6dc9357SAndroid Build Coastguard Worker {
133*f6dc9357SAndroid Build Coastguard Worker   if (!Mem)
134*f6dc9357SAndroid Build Coastguard Worker     Mem = (Byte *)::MyAlloc(kSpaceSize + 4);
135*f6dc9357SAndroid Build Coastguard Worker   return (Mem != NULL);
136*f6dc9357SAndroid Build Coastguard Worker }
137*f6dc9357SAndroid Build Coastguard Worker 
~CVm()138*f6dc9357SAndroid Build Coastguard Worker CVm::~CVm()
139*f6dc9357SAndroid Build Coastguard Worker {
140*f6dc9357SAndroid Build Coastguard Worker   ::MyFree(Mem);
141*f6dc9357SAndroid Build Coastguard Worker }
142*f6dc9357SAndroid Build Coastguard Worker 
143*f6dc9357SAndroid Build Coastguard Worker // CVm::Execute can change CProgram object: it clears progarm if VM returns error.
144*f6dc9357SAndroid Build Coastguard Worker 
Execute(CProgram * prg,const CProgramInitState * initState,CBlockRef & outBlockRef,CRecordVector<Byte> & outGlobalData)145*f6dc9357SAndroid Build Coastguard Worker bool CVm::Execute(CProgram *prg, const CProgramInitState *initState,
146*f6dc9357SAndroid Build Coastguard Worker     CBlockRef &outBlockRef, CRecordVector<Byte> &outGlobalData)
147*f6dc9357SAndroid Build Coastguard Worker {
148*f6dc9357SAndroid Build Coastguard Worker   memcpy(R, initState->InitR, sizeof(initState->InitR));
149*f6dc9357SAndroid Build Coastguard Worker   R[kStackRegIndex] = kSpaceSize;
150*f6dc9357SAndroid Build Coastguard Worker   R[kNumRegs] = 0;
151*f6dc9357SAndroid Build Coastguard Worker   Flags = 0;
152*f6dc9357SAndroid Build Coastguard Worker 
153*f6dc9357SAndroid Build Coastguard Worker   const UInt32 globalSize = MyMin((UInt32)initState->GlobalData.Size(), kGlobalSize);
154*f6dc9357SAndroid Build Coastguard Worker   if (globalSize != 0)
155*f6dc9357SAndroid Build Coastguard Worker     memcpy(Mem + kGlobalOffset, &initState->GlobalData[0], globalSize);
156*f6dc9357SAndroid Build Coastguard Worker   UInt32 staticSize = MyMin((UInt32)prg->StaticData.Size(), kGlobalSize - globalSize);
157*f6dc9357SAndroid Build Coastguard Worker   if (staticSize != 0)
158*f6dc9357SAndroid Build Coastguard Worker     memcpy(Mem + kGlobalOffset + globalSize, &prg->StaticData[0], staticSize);
159*f6dc9357SAndroid Build Coastguard Worker 
160*f6dc9357SAndroid Build Coastguard Worker   bool res = true;
161*f6dc9357SAndroid Build Coastguard Worker 
162*f6dc9357SAndroid Build Coastguard Worker   #ifdef Z7_RARVM_STANDARD_FILTERS
163*f6dc9357SAndroid Build Coastguard Worker   if (prg->StandardFilterIndex >= 0)
164*f6dc9357SAndroid Build Coastguard Worker     res = ExecuteStandardFilter((unsigned)prg->StandardFilterIndex);
165*f6dc9357SAndroid Build Coastguard Worker   else
166*f6dc9357SAndroid Build Coastguard Worker   #endif
167*f6dc9357SAndroid Build Coastguard Worker   {
168*f6dc9357SAndroid Build Coastguard Worker     #ifdef Z7_RARVM_VM_ENABLE
169*f6dc9357SAndroid Build Coastguard Worker     res = ExecuteCode(prg);
170*f6dc9357SAndroid Build Coastguard Worker     if (!res)
171*f6dc9357SAndroid Build Coastguard Worker     {
172*f6dc9357SAndroid Build Coastguard Worker       prg->Commands.Clear();
173*f6dc9357SAndroid Build Coastguard Worker       prg->Commands.Add(CCommand());
174*f6dc9357SAndroid Build Coastguard Worker       prg->Commands.Back().OpCode = CMD_RET;
175*f6dc9357SAndroid Build Coastguard Worker     }
176*f6dc9357SAndroid Build Coastguard Worker     #else
177*f6dc9357SAndroid Build Coastguard Worker     res = false;
178*f6dc9357SAndroid Build Coastguard Worker     #endif
179*f6dc9357SAndroid Build Coastguard Worker   }
180*f6dc9357SAndroid Build Coastguard Worker 
181*f6dc9357SAndroid Build Coastguard Worker   UInt32 newBlockPos = GetFixedGlobalValue32(NGlobalOffset::kBlockPos) & kSpaceMask;
182*f6dc9357SAndroid Build Coastguard Worker   UInt32 newBlockSize = GetFixedGlobalValue32(NGlobalOffset::kBlockSize) & kSpaceMask;
183*f6dc9357SAndroid Build Coastguard Worker   if (newBlockPos + newBlockSize >= kSpaceSize)
184*f6dc9357SAndroid Build Coastguard Worker     newBlockPos = newBlockSize = 0;
185*f6dc9357SAndroid Build Coastguard Worker   outBlockRef.Offset = newBlockPos;
186*f6dc9357SAndroid Build Coastguard Worker   outBlockRef.Size = newBlockSize;
187*f6dc9357SAndroid Build Coastguard Worker 
188*f6dc9357SAndroid Build Coastguard Worker   outGlobalData.Clear();
189*f6dc9357SAndroid Build Coastguard Worker   UInt32 dataSize = GetFixedGlobalValue32(NGlobalOffset::kGlobalMemOutSize);
190*f6dc9357SAndroid Build Coastguard Worker   dataSize = MyMin(dataSize, kGlobalSize - kFixedGlobalSize);
191*f6dc9357SAndroid Build Coastguard Worker   if (dataSize != 0)
192*f6dc9357SAndroid Build Coastguard Worker   {
193*f6dc9357SAndroid Build Coastguard Worker     dataSize += kFixedGlobalSize;
194*f6dc9357SAndroid Build Coastguard Worker     outGlobalData.ClearAndSetSize(dataSize);
195*f6dc9357SAndroid Build Coastguard Worker     memcpy(&outGlobalData[0], Mem + kGlobalOffset, dataSize);
196*f6dc9357SAndroid Build Coastguard Worker   }
197*f6dc9357SAndroid Build Coastguard Worker 
198*f6dc9357SAndroid Build Coastguard Worker   return res;
199*f6dc9357SAndroid Build Coastguard Worker }
200*f6dc9357SAndroid Build Coastguard Worker 
201*f6dc9357SAndroid Build Coastguard Worker #ifdef Z7_RARVM_VM_ENABLE
202*f6dc9357SAndroid Build Coastguard Worker 
203*f6dc9357SAndroid Build Coastguard Worker #define SET_IP(IP) \
204*f6dc9357SAndroid Build Coastguard Worker   if ((IP) >= numCommands) return true; \
205*f6dc9357SAndroid Build Coastguard Worker   if (--maxOpCount <= 0) return false; \
206*f6dc9357SAndroid Build Coastguard Worker   cmd = commands + (IP);
207*f6dc9357SAndroid Build Coastguard Worker 
208*f6dc9357SAndroid Build Coastguard Worker #define GET_FLAG_S_B(res) (((res) & 0x80) ? FLAG_S : 0)
209*f6dc9357SAndroid Build Coastguard Worker #define SET_IP_OP1 { const UInt32 val = GetOperand32(&cmd->Op1); SET_IP(val) }
210*f6dc9357SAndroid Build Coastguard Worker #define FLAGS_UPDATE_SZ Flags = res == 0 ? FLAG_Z : res & FLAG_S
211*f6dc9357SAndroid Build Coastguard Worker #define FLAGS_UPDATE_SZ_B Flags = (res & 0xFF) == 0 ? FLAG_Z : GET_FLAG_S_B(res)
212*f6dc9357SAndroid Build Coastguard Worker 
GetOperand32(const COperand * op) const213*f6dc9357SAndroid Build Coastguard Worker UInt32 CVm::GetOperand32(const COperand *op) const
214*f6dc9357SAndroid Build Coastguard Worker {
215*f6dc9357SAndroid Build Coastguard Worker   switch (op->Type)
216*f6dc9357SAndroid Build Coastguard Worker   {
217*f6dc9357SAndroid Build Coastguard Worker     case OP_TYPE_REG: return R[op->Data];
218*f6dc9357SAndroid Build Coastguard Worker     case OP_TYPE_REGMEM: return GetValue32(&Mem[(op->Base + R[op->Data]) & kSpaceMask]);
219*f6dc9357SAndroid Build Coastguard Worker     default: return op->Data;
220*f6dc9357SAndroid Build Coastguard Worker   }
221*f6dc9357SAndroid Build Coastguard Worker }
222*f6dc9357SAndroid Build Coastguard Worker 
SetOperand32(const COperand * op,UInt32 val)223*f6dc9357SAndroid Build Coastguard Worker void CVm::SetOperand32(const COperand *op, UInt32 val)
224*f6dc9357SAndroid Build Coastguard Worker {
225*f6dc9357SAndroid Build Coastguard Worker   switch (op->Type)
226*f6dc9357SAndroid Build Coastguard Worker   {
227*f6dc9357SAndroid Build Coastguard Worker     case OP_TYPE_REG: R[op->Data] = val; return;
228*f6dc9357SAndroid Build Coastguard Worker     case OP_TYPE_REGMEM: SetValue32(&Mem[(op->Base + R[op->Data]) & kSpaceMask], val); return;
229*f6dc9357SAndroid Build Coastguard Worker     default: break;
230*f6dc9357SAndroid Build Coastguard Worker   }
231*f6dc9357SAndroid Build Coastguard Worker }
232*f6dc9357SAndroid Build Coastguard Worker 
GetOperand8(const COperand * op) const233*f6dc9357SAndroid Build Coastguard Worker Byte CVm::GetOperand8(const COperand *op) const
234*f6dc9357SAndroid Build Coastguard Worker {
235*f6dc9357SAndroid Build Coastguard Worker   switch (op->Type)
236*f6dc9357SAndroid Build Coastguard Worker   {
237*f6dc9357SAndroid Build Coastguard Worker     case OP_TYPE_REG: return (Byte)R[op->Data];
238*f6dc9357SAndroid Build Coastguard Worker     case OP_TYPE_REGMEM: return Mem[(op->Base + R[op->Data]) & kSpaceMask];
239*f6dc9357SAndroid Build Coastguard Worker     default: return (Byte)op->Data;
240*f6dc9357SAndroid Build Coastguard Worker   }
241*f6dc9357SAndroid Build Coastguard Worker }
242*f6dc9357SAndroid Build Coastguard Worker 
SetOperand8(const COperand * op,Byte val)243*f6dc9357SAndroid Build Coastguard Worker void CVm::SetOperand8(const COperand *op, Byte val)
244*f6dc9357SAndroid Build Coastguard Worker {
245*f6dc9357SAndroid Build Coastguard Worker   switch (op->Type)
246*f6dc9357SAndroid Build Coastguard Worker   {
247*f6dc9357SAndroid Build Coastguard Worker     case OP_TYPE_REG: R[op->Data] = (R[op->Data] & 0xFFFFFF00) | val; return;
248*f6dc9357SAndroid Build Coastguard Worker     case OP_TYPE_REGMEM: Mem[(op->Base + R[op->Data]) & kSpaceMask] = val; return;
249*f6dc9357SAndroid Build Coastguard Worker     default: break;
250*f6dc9357SAndroid Build Coastguard Worker   }
251*f6dc9357SAndroid Build Coastguard Worker }
252*f6dc9357SAndroid Build Coastguard Worker 
GetOperand(bool byteMode,const COperand * op) const253*f6dc9357SAndroid Build Coastguard Worker UInt32 CVm::GetOperand(bool byteMode, const COperand *op) const
254*f6dc9357SAndroid Build Coastguard Worker {
255*f6dc9357SAndroid Build Coastguard Worker   if (byteMode)
256*f6dc9357SAndroid Build Coastguard Worker     return GetOperand8(op);
257*f6dc9357SAndroid Build Coastguard Worker   return GetOperand32(op);
258*f6dc9357SAndroid Build Coastguard Worker }
259*f6dc9357SAndroid Build Coastguard Worker 
SetOperand(bool byteMode,const COperand * op,UInt32 val)260*f6dc9357SAndroid Build Coastguard Worker void CVm::SetOperand(bool byteMode, const COperand *op, UInt32 val)
261*f6dc9357SAndroid Build Coastguard Worker {
262*f6dc9357SAndroid Build Coastguard Worker   if (byteMode)
263*f6dc9357SAndroid Build Coastguard Worker     SetOperand8(op, (Byte)(val & 0xFF));
264*f6dc9357SAndroid Build Coastguard Worker   else
265*f6dc9357SAndroid Build Coastguard Worker     SetOperand32(op, val);
266*f6dc9357SAndroid Build Coastguard Worker }
267*f6dc9357SAndroid Build Coastguard Worker 
ExecuteCode(const CProgram * prg)268*f6dc9357SAndroid Build Coastguard Worker bool CVm::ExecuteCode(const CProgram *prg)
269*f6dc9357SAndroid Build Coastguard Worker {
270*f6dc9357SAndroid Build Coastguard Worker   Int32 maxOpCount = 25000000;
271*f6dc9357SAndroid Build Coastguard Worker   const CCommand *commands = &prg->Commands[0];
272*f6dc9357SAndroid Build Coastguard Worker   const CCommand *cmd = commands;
273*f6dc9357SAndroid Build Coastguard Worker   const UInt32 numCommands = prg->Commands.Size();
274*f6dc9357SAndroid Build Coastguard Worker   if (numCommands == 0)
275*f6dc9357SAndroid Build Coastguard Worker     return false;
276*f6dc9357SAndroid Build Coastguard Worker 
277*f6dc9357SAndroid Build Coastguard Worker   for (;;)
278*f6dc9357SAndroid Build Coastguard Worker   {
279*f6dc9357SAndroid Build Coastguard Worker     switch (cmd->OpCode)
280*f6dc9357SAndroid Build Coastguard Worker     {
281*f6dc9357SAndroid Build Coastguard Worker       case CMD_MOV:
282*f6dc9357SAndroid Build Coastguard Worker         SetOperand32(&cmd->Op1, GetOperand32(&cmd->Op2));
283*f6dc9357SAndroid Build Coastguard Worker         break;
284*f6dc9357SAndroid Build Coastguard Worker       case CMD_MOVB:
285*f6dc9357SAndroid Build Coastguard Worker         SetOperand8(&cmd->Op1, GetOperand8(&cmd->Op2));
286*f6dc9357SAndroid Build Coastguard Worker         break;
287*f6dc9357SAndroid Build Coastguard Worker       case CMD_CMP:
288*f6dc9357SAndroid Build Coastguard Worker         {
289*f6dc9357SAndroid Build Coastguard Worker           const UInt32 v1 = GetOperand32(&cmd->Op1);
290*f6dc9357SAndroid Build Coastguard Worker           const UInt32 res = v1 - GetOperand32(&cmd->Op2);
291*f6dc9357SAndroid Build Coastguard Worker           Flags = res == 0 ? FLAG_Z : (res > v1) | (res & FLAG_S);
292*f6dc9357SAndroid Build Coastguard Worker         }
293*f6dc9357SAndroid Build Coastguard Worker         break;
294*f6dc9357SAndroid Build Coastguard Worker       case CMD_CMPB:
295*f6dc9357SAndroid Build Coastguard Worker         {
296*f6dc9357SAndroid Build Coastguard Worker           const Byte v1 = GetOperand8(&cmd->Op1);
297*f6dc9357SAndroid Build Coastguard Worker           const Byte res = (Byte)((v1 - GetOperand8(&cmd->Op2)) & 0xFF);
298*f6dc9357SAndroid Build Coastguard Worker           Flags = res == 0 ? FLAG_Z : (res > v1) | GET_FLAG_S_B(res);
299*f6dc9357SAndroid Build Coastguard Worker         }
300*f6dc9357SAndroid Build Coastguard Worker         break;
301*f6dc9357SAndroid Build Coastguard Worker       case CMD_ADD:
302*f6dc9357SAndroid Build Coastguard Worker         {
303*f6dc9357SAndroid Build Coastguard Worker           const UInt32 v1 = GetOperand32(&cmd->Op1);
304*f6dc9357SAndroid Build Coastguard Worker           const UInt32 res = v1 + GetOperand32(&cmd->Op2);
305*f6dc9357SAndroid Build Coastguard Worker           SetOperand32(&cmd->Op1, res);
306*f6dc9357SAndroid Build Coastguard Worker           Flags = (res < v1) | (res == 0 ? FLAG_Z : (res & FLAG_S));
307*f6dc9357SAndroid Build Coastguard Worker         }
308*f6dc9357SAndroid Build Coastguard Worker         break;
309*f6dc9357SAndroid Build Coastguard Worker       case CMD_ADDB:
310*f6dc9357SAndroid Build Coastguard Worker         {
311*f6dc9357SAndroid Build Coastguard Worker           const Byte v1 = GetOperand8(&cmd->Op1);
312*f6dc9357SAndroid Build Coastguard Worker           const Byte res = (Byte)((v1 + GetOperand8(&cmd->Op2)) & 0xFF);
313*f6dc9357SAndroid Build Coastguard Worker           SetOperand8(&cmd->Op1, (Byte)res);
314*f6dc9357SAndroid Build Coastguard Worker           Flags = (res < v1) | (res == 0 ? FLAG_Z : GET_FLAG_S_B(res));
315*f6dc9357SAndroid Build Coastguard Worker         }
316*f6dc9357SAndroid Build Coastguard Worker         break;
317*f6dc9357SAndroid Build Coastguard Worker       case CMD_ADC:
318*f6dc9357SAndroid Build Coastguard Worker         {
319*f6dc9357SAndroid Build Coastguard Worker           const UInt32 v1 = GetOperand(cmd->ByteMode, &cmd->Op1);
320*f6dc9357SAndroid Build Coastguard Worker           const UInt32 FC = (Flags & FLAG_C);
321*f6dc9357SAndroid Build Coastguard Worker           UInt32 res = v1 + GetOperand(cmd->ByteMode, &cmd->Op2) + FC;
322*f6dc9357SAndroid Build Coastguard Worker           if (cmd->ByteMode)
323*f6dc9357SAndroid Build Coastguard Worker             res &= 0xFF;
324*f6dc9357SAndroid Build Coastguard Worker           SetOperand(cmd->ByteMode, &cmd->Op1, res);
325*f6dc9357SAndroid Build Coastguard Worker           Flags = (res < v1 || (res == v1 && FC)) | (res == 0 ? FLAG_Z : (res & FLAG_S));
326*f6dc9357SAndroid Build Coastguard Worker         }
327*f6dc9357SAndroid Build Coastguard Worker         break;
328*f6dc9357SAndroid Build Coastguard Worker       case CMD_SUB:
329*f6dc9357SAndroid Build Coastguard Worker         {
330*f6dc9357SAndroid Build Coastguard Worker           const UInt32 v1 = GetOperand32(&cmd->Op1);
331*f6dc9357SAndroid Build Coastguard Worker           const UInt32 res = v1 - GetOperand32(&cmd->Op2);
332*f6dc9357SAndroid Build Coastguard Worker           SetOperand32(&cmd->Op1, res);
333*f6dc9357SAndroid Build Coastguard Worker           Flags = res == 0 ? FLAG_Z : (res > v1) | (res & FLAG_S);
334*f6dc9357SAndroid Build Coastguard Worker         }
335*f6dc9357SAndroid Build Coastguard Worker         break;
336*f6dc9357SAndroid Build Coastguard Worker       case CMD_SUBB:
337*f6dc9357SAndroid Build Coastguard Worker         {
338*f6dc9357SAndroid Build Coastguard Worker           const UInt32 v1 = GetOperand8(&cmd->Op1);
339*f6dc9357SAndroid Build Coastguard Worker           const UInt32 res = v1 - GetOperand8(&cmd->Op2);
340*f6dc9357SAndroid Build Coastguard Worker           SetOperand8(&cmd->Op1, (Byte)res);
341*f6dc9357SAndroid Build Coastguard Worker           Flags = res == 0 ? FLAG_Z : (res > v1) | (res & FLAG_S);
342*f6dc9357SAndroid Build Coastguard Worker         }
343*f6dc9357SAndroid Build Coastguard Worker         break;
344*f6dc9357SAndroid Build Coastguard Worker       case CMD_SBB:
345*f6dc9357SAndroid Build Coastguard Worker         {
346*f6dc9357SAndroid Build Coastguard Worker           const UInt32 v1 = GetOperand(cmd->ByteMode, &cmd->Op1);
347*f6dc9357SAndroid Build Coastguard Worker           const UInt32 FC = (Flags & FLAG_C);
348*f6dc9357SAndroid Build Coastguard Worker           UInt32 res = v1 - GetOperand(cmd->ByteMode, &cmd->Op2) - FC;
349*f6dc9357SAndroid Build Coastguard Worker           // Flags = res == 0 ? FLAG_Z : (res > v1 || res == v1 && FC) | (res & FLAG_S);
350*f6dc9357SAndroid Build Coastguard Worker           if (cmd->ByteMode)
351*f6dc9357SAndroid Build Coastguard Worker             res &= 0xFF;
352*f6dc9357SAndroid Build Coastguard Worker           SetOperand(cmd->ByteMode, &cmd->Op1, res);
353*f6dc9357SAndroid Build Coastguard Worker           Flags = (res > v1 || (res == v1 && FC)) | (res == 0 ? FLAG_Z : (res & FLAG_S));
354*f6dc9357SAndroid Build Coastguard Worker         }
355*f6dc9357SAndroid Build Coastguard Worker         break;
356*f6dc9357SAndroid Build Coastguard Worker       case CMD_INC:
357*f6dc9357SAndroid Build Coastguard Worker         {
358*f6dc9357SAndroid Build Coastguard Worker           const UInt32 res = GetOperand32(&cmd->Op1) + 1;
359*f6dc9357SAndroid Build Coastguard Worker           SetOperand32(&cmd->Op1, res);
360*f6dc9357SAndroid Build Coastguard Worker           FLAGS_UPDATE_SZ;
361*f6dc9357SAndroid Build Coastguard Worker         }
362*f6dc9357SAndroid Build Coastguard Worker         break;
363*f6dc9357SAndroid Build Coastguard Worker       case CMD_INCB:
364*f6dc9357SAndroid Build Coastguard Worker         {
365*f6dc9357SAndroid Build Coastguard Worker           const Byte res = (Byte)(GetOperand8(&cmd->Op1) + 1);
366*f6dc9357SAndroid Build Coastguard Worker           SetOperand8(&cmd->Op1, res);
367*f6dc9357SAndroid Build Coastguard Worker           FLAGS_UPDATE_SZ_B;
368*f6dc9357SAndroid Build Coastguard Worker         }
369*f6dc9357SAndroid Build Coastguard Worker         break;
370*f6dc9357SAndroid Build Coastguard Worker       case CMD_DEC:
371*f6dc9357SAndroid Build Coastguard Worker         {
372*f6dc9357SAndroid Build Coastguard Worker           const UInt32 res = GetOperand32(&cmd->Op1) - 1;
373*f6dc9357SAndroid Build Coastguard Worker           SetOperand32(&cmd->Op1, res);
374*f6dc9357SAndroid Build Coastguard Worker           FLAGS_UPDATE_SZ;
375*f6dc9357SAndroid Build Coastguard Worker         }
376*f6dc9357SAndroid Build Coastguard Worker         break;
377*f6dc9357SAndroid Build Coastguard Worker       case CMD_DECB:
378*f6dc9357SAndroid Build Coastguard Worker         {
379*f6dc9357SAndroid Build Coastguard Worker           const Byte res = (Byte)(GetOperand8(&cmd->Op1) - 1);
380*f6dc9357SAndroid Build Coastguard Worker           SetOperand8(&cmd->Op1, res);
381*f6dc9357SAndroid Build Coastguard Worker           FLAGS_UPDATE_SZ_B;
382*f6dc9357SAndroid Build Coastguard Worker         }
383*f6dc9357SAndroid Build Coastguard Worker         break;
384*f6dc9357SAndroid Build Coastguard Worker       case CMD_XOR:
385*f6dc9357SAndroid Build Coastguard Worker         {
386*f6dc9357SAndroid Build Coastguard Worker           const UInt32 res = GetOperand32(&cmd->Op1) ^ GetOperand32(&cmd->Op2);
387*f6dc9357SAndroid Build Coastguard Worker           SetOperand32(&cmd->Op1, res);
388*f6dc9357SAndroid Build Coastguard Worker           FLAGS_UPDATE_SZ;
389*f6dc9357SAndroid Build Coastguard Worker         }
390*f6dc9357SAndroid Build Coastguard Worker         break;
391*f6dc9357SAndroid Build Coastguard Worker       case CMD_XORB:
392*f6dc9357SAndroid Build Coastguard Worker         {
393*f6dc9357SAndroid Build Coastguard Worker           const Byte res = (Byte)(GetOperand8(&cmd->Op1) ^ GetOperand8(&cmd->Op2));
394*f6dc9357SAndroid Build Coastguard Worker           SetOperand8(&cmd->Op1, res);
395*f6dc9357SAndroid Build Coastguard Worker           FLAGS_UPDATE_SZ_B;
396*f6dc9357SAndroid Build Coastguard Worker         }
397*f6dc9357SAndroid Build Coastguard Worker         break;
398*f6dc9357SAndroid Build Coastguard Worker       case CMD_AND:
399*f6dc9357SAndroid Build Coastguard Worker         {
400*f6dc9357SAndroid Build Coastguard Worker           const UInt32 res = GetOperand32(&cmd->Op1) & GetOperand32(&cmd->Op2);
401*f6dc9357SAndroid Build Coastguard Worker           SetOperand32(&cmd->Op1, res);
402*f6dc9357SAndroid Build Coastguard Worker           FLAGS_UPDATE_SZ;
403*f6dc9357SAndroid Build Coastguard Worker         }
404*f6dc9357SAndroid Build Coastguard Worker         break;
405*f6dc9357SAndroid Build Coastguard Worker       case CMD_ANDB:
406*f6dc9357SAndroid Build Coastguard Worker         {
407*f6dc9357SAndroid Build Coastguard Worker           const Byte res = (Byte)(GetOperand8(&cmd->Op1) & GetOperand8(&cmd->Op2));
408*f6dc9357SAndroid Build Coastguard Worker           SetOperand8(&cmd->Op1, res);
409*f6dc9357SAndroid Build Coastguard Worker           FLAGS_UPDATE_SZ_B;
410*f6dc9357SAndroid Build Coastguard Worker         }
411*f6dc9357SAndroid Build Coastguard Worker         break;
412*f6dc9357SAndroid Build Coastguard Worker       case CMD_OR:
413*f6dc9357SAndroid Build Coastguard Worker         {
414*f6dc9357SAndroid Build Coastguard Worker           const UInt32 res = GetOperand32(&cmd->Op1) | GetOperand32(&cmd->Op2);
415*f6dc9357SAndroid Build Coastguard Worker           SetOperand32(&cmd->Op1, res);
416*f6dc9357SAndroid Build Coastguard Worker           FLAGS_UPDATE_SZ;
417*f6dc9357SAndroid Build Coastguard Worker         }
418*f6dc9357SAndroid Build Coastguard Worker         break;
419*f6dc9357SAndroid Build Coastguard Worker       case CMD_ORB:
420*f6dc9357SAndroid Build Coastguard Worker         {
421*f6dc9357SAndroid Build Coastguard Worker           const Byte res = (Byte)(GetOperand8(&cmd->Op1) | GetOperand8(&cmd->Op2));
422*f6dc9357SAndroid Build Coastguard Worker           SetOperand8(&cmd->Op1, res);
423*f6dc9357SAndroid Build Coastguard Worker           FLAGS_UPDATE_SZ_B;
424*f6dc9357SAndroid Build Coastguard Worker         }
425*f6dc9357SAndroid Build Coastguard Worker         break;
426*f6dc9357SAndroid Build Coastguard Worker       case CMD_TEST:
427*f6dc9357SAndroid Build Coastguard Worker         {
428*f6dc9357SAndroid Build Coastguard Worker           const UInt32 res = GetOperand32(&cmd->Op1) & GetOperand32(&cmd->Op2);
429*f6dc9357SAndroid Build Coastguard Worker           FLAGS_UPDATE_SZ;
430*f6dc9357SAndroid Build Coastguard Worker         }
431*f6dc9357SAndroid Build Coastguard Worker         break;
432*f6dc9357SAndroid Build Coastguard Worker       case CMD_TESTB:
433*f6dc9357SAndroid Build Coastguard Worker         {
434*f6dc9357SAndroid Build Coastguard Worker           const Byte res = (Byte)(GetOperand8(&cmd->Op1) & GetOperand8(&cmd->Op2));
435*f6dc9357SAndroid Build Coastguard Worker           FLAGS_UPDATE_SZ_B;
436*f6dc9357SAndroid Build Coastguard Worker         }
437*f6dc9357SAndroid Build Coastguard Worker         break;
438*f6dc9357SAndroid Build Coastguard Worker       case CMD_NOT:
439*f6dc9357SAndroid Build Coastguard Worker         SetOperand(cmd->ByteMode, &cmd->Op1, ~GetOperand(cmd->ByteMode, &cmd->Op1));
440*f6dc9357SAndroid Build Coastguard Worker         break;
441*f6dc9357SAndroid Build Coastguard Worker       case CMD_NEG:
442*f6dc9357SAndroid Build Coastguard Worker         {
443*f6dc9357SAndroid Build Coastguard Worker           const UInt32 res = 0 - GetOperand32(&cmd->Op1);
444*f6dc9357SAndroid Build Coastguard Worker           SetOperand32(&cmd->Op1, res);
445*f6dc9357SAndroid Build Coastguard Worker           Flags = res == 0 ? FLAG_Z : FLAG_C | (res & FLAG_S);
446*f6dc9357SAndroid Build Coastguard Worker         }
447*f6dc9357SAndroid Build Coastguard Worker         break;
448*f6dc9357SAndroid Build Coastguard Worker       case CMD_NEGB:
449*f6dc9357SAndroid Build Coastguard Worker         {
450*f6dc9357SAndroid Build Coastguard Worker           const Byte res = (Byte)(0 - GetOperand8(&cmd->Op1));
451*f6dc9357SAndroid Build Coastguard Worker           SetOperand8(&cmd->Op1, res);
452*f6dc9357SAndroid Build Coastguard Worker           Flags = res == 0 ? FLAG_Z : FLAG_C | GET_FLAG_S_B(res);
453*f6dc9357SAndroid Build Coastguard Worker         }
454*f6dc9357SAndroid Build Coastguard Worker         break;
455*f6dc9357SAndroid Build Coastguard Worker 
456*f6dc9357SAndroid Build Coastguard Worker       case CMD_SHL:
457*f6dc9357SAndroid Build Coastguard Worker         {
458*f6dc9357SAndroid Build Coastguard Worker           const UInt32 v1 = GetOperand32(&cmd->Op1);
459*f6dc9357SAndroid Build Coastguard Worker           const int v2 = (int)GetOperand32(&cmd->Op2);
460*f6dc9357SAndroid Build Coastguard Worker           const UInt32 res = v1 << v2;
461*f6dc9357SAndroid Build Coastguard Worker           SetOperand32(&cmd->Op1, res);
462*f6dc9357SAndroid Build Coastguard Worker           Flags = (res == 0 ? FLAG_Z : (res & FLAG_S)) | ((v1 << (v2 - 1)) & 0x80000000 ? FLAG_C : 0);
463*f6dc9357SAndroid Build Coastguard Worker         }
464*f6dc9357SAndroid Build Coastguard Worker         break;
465*f6dc9357SAndroid Build Coastguard Worker       case CMD_SHLB:
466*f6dc9357SAndroid Build Coastguard Worker         {
467*f6dc9357SAndroid Build Coastguard Worker           const Byte v1 = GetOperand8(&cmd->Op1);
468*f6dc9357SAndroid Build Coastguard Worker           const int v2 = (int)GetOperand8(&cmd->Op2);
469*f6dc9357SAndroid Build Coastguard Worker           const Byte res = (Byte)(v1 << v2);
470*f6dc9357SAndroid Build Coastguard Worker           SetOperand8(&cmd->Op1, res);
471*f6dc9357SAndroid Build Coastguard Worker           Flags = (res == 0 ? FLAG_Z : GET_FLAG_S_B(res)) | ((v1 << (v2 - 1)) & 0x80 ? FLAG_C : 0);
472*f6dc9357SAndroid Build Coastguard Worker         }
473*f6dc9357SAndroid Build Coastguard Worker         break;
474*f6dc9357SAndroid Build Coastguard Worker       case CMD_SHR:
475*f6dc9357SAndroid Build Coastguard Worker         {
476*f6dc9357SAndroid Build Coastguard Worker           const UInt32 v1 = GetOperand32(&cmd->Op1);
477*f6dc9357SAndroid Build Coastguard Worker           const int v2 = (int)GetOperand32(&cmd->Op2);
478*f6dc9357SAndroid Build Coastguard Worker           const UInt32 res = v1 >> v2;
479*f6dc9357SAndroid Build Coastguard Worker           SetOperand32(&cmd->Op1, res);
480*f6dc9357SAndroid Build Coastguard Worker           Flags = (res == 0 ? FLAG_Z : (res & FLAG_S)) | ((v1 >> (v2 - 1)) & FLAG_C);
481*f6dc9357SAndroid Build Coastguard Worker         }
482*f6dc9357SAndroid Build Coastguard Worker         break;
483*f6dc9357SAndroid Build Coastguard Worker       case CMD_SHRB:
484*f6dc9357SAndroid Build Coastguard Worker         {
485*f6dc9357SAndroid Build Coastguard Worker           const Byte v1 = GetOperand8(&cmd->Op1);
486*f6dc9357SAndroid Build Coastguard Worker           const int v2 = (int)GetOperand8(&cmd->Op2);
487*f6dc9357SAndroid Build Coastguard Worker           const Byte res = (Byte)(v1 >> v2);
488*f6dc9357SAndroid Build Coastguard Worker           SetOperand8(&cmd->Op1, res);
489*f6dc9357SAndroid Build Coastguard Worker           Flags = (res == 0 ? FLAG_Z : GET_FLAG_S_B(res)) | ((v1 >> (v2 - 1)) & FLAG_C);
490*f6dc9357SAndroid Build Coastguard Worker         }
491*f6dc9357SAndroid Build Coastguard Worker         break;
492*f6dc9357SAndroid Build Coastguard Worker       case CMD_SAR:
493*f6dc9357SAndroid Build Coastguard Worker         {
494*f6dc9357SAndroid Build Coastguard Worker           const UInt32 v1 = GetOperand32(&cmd->Op1);
495*f6dc9357SAndroid Build Coastguard Worker           const int v2 = (int)GetOperand32(&cmd->Op2);
496*f6dc9357SAndroid Build Coastguard Worker           const UInt32 res = UInt32(((Int32)v1) >> v2);
497*f6dc9357SAndroid Build Coastguard Worker           SetOperand32(&cmd->Op1, res);
498*f6dc9357SAndroid Build Coastguard Worker           Flags= (res == 0 ? FLAG_Z : (res & FLAG_S)) | ((v1 >> (v2 - 1)) & FLAG_C);
499*f6dc9357SAndroid Build Coastguard Worker         }
500*f6dc9357SAndroid Build Coastguard Worker         break;
501*f6dc9357SAndroid Build Coastguard Worker       case CMD_SARB:
502*f6dc9357SAndroid Build Coastguard Worker         {
503*f6dc9357SAndroid Build Coastguard Worker           const Byte v1 = GetOperand8(&cmd->Op1);
504*f6dc9357SAndroid Build Coastguard Worker           const int v2 = (int)GetOperand8(&cmd->Op2);
505*f6dc9357SAndroid Build Coastguard Worker           const Byte res = (Byte)(((signed char)v1) >> v2);
506*f6dc9357SAndroid Build Coastguard Worker           SetOperand8(&cmd->Op1, res);
507*f6dc9357SAndroid Build Coastguard Worker           Flags= (res == 0 ? FLAG_Z : GET_FLAG_S_B(res)) | ((v1 >> (v2 - 1)) & FLAG_C);
508*f6dc9357SAndroid Build Coastguard Worker         }
509*f6dc9357SAndroid Build Coastguard Worker         break;
510*f6dc9357SAndroid Build Coastguard Worker 
511*f6dc9357SAndroid Build Coastguard Worker       case CMD_JMP:
512*f6dc9357SAndroid Build Coastguard Worker         SET_IP_OP1
513*f6dc9357SAndroid Build Coastguard Worker         continue;
514*f6dc9357SAndroid Build Coastguard Worker       case CMD_JZ:
515*f6dc9357SAndroid Build Coastguard Worker         if ((Flags & FLAG_Z) != 0)
516*f6dc9357SAndroid Build Coastguard Worker         {
517*f6dc9357SAndroid Build Coastguard Worker           SET_IP_OP1
518*f6dc9357SAndroid Build Coastguard Worker           continue;
519*f6dc9357SAndroid Build Coastguard Worker         }
520*f6dc9357SAndroid Build Coastguard Worker         break;
521*f6dc9357SAndroid Build Coastguard Worker       case CMD_JNZ:
522*f6dc9357SAndroid Build Coastguard Worker         if ((Flags & FLAG_Z) == 0)
523*f6dc9357SAndroid Build Coastguard Worker         {
524*f6dc9357SAndroid Build Coastguard Worker           SET_IP_OP1
525*f6dc9357SAndroid Build Coastguard Worker           continue;
526*f6dc9357SAndroid Build Coastguard Worker         }
527*f6dc9357SAndroid Build Coastguard Worker         break;
528*f6dc9357SAndroid Build Coastguard Worker       case CMD_JS:
529*f6dc9357SAndroid Build Coastguard Worker         if ((Flags & FLAG_S) != 0)
530*f6dc9357SAndroid Build Coastguard Worker         {
531*f6dc9357SAndroid Build Coastguard Worker           SET_IP_OP1
532*f6dc9357SAndroid Build Coastguard Worker           continue;
533*f6dc9357SAndroid Build Coastguard Worker         }
534*f6dc9357SAndroid Build Coastguard Worker         break;
535*f6dc9357SAndroid Build Coastguard Worker       case CMD_JNS:
536*f6dc9357SAndroid Build Coastguard Worker         if ((Flags & FLAG_S) == 0)
537*f6dc9357SAndroid Build Coastguard Worker         {
538*f6dc9357SAndroid Build Coastguard Worker           SET_IP_OP1
539*f6dc9357SAndroid Build Coastguard Worker           continue;
540*f6dc9357SAndroid Build Coastguard Worker         }
541*f6dc9357SAndroid Build Coastguard Worker         break;
542*f6dc9357SAndroid Build Coastguard Worker       case CMD_JB:
543*f6dc9357SAndroid Build Coastguard Worker         if ((Flags & FLAG_C) != 0)
544*f6dc9357SAndroid Build Coastguard Worker         {
545*f6dc9357SAndroid Build Coastguard Worker           SET_IP_OP1
546*f6dc9357SAndroid Build Coastguard Worker           continue;
547*f6dc9357SAndroid Build Coastguard Worker         }
548*f6dc9357SAndroid Build Coastguard Worker         break;
549*f6dc9357SAndroid Build Coastguard Worker       case CMD_JBE:
550*f6dc9357SAndroid Build Coastguard Worker         if ((Flags & (FLAG_C | FLAG_Z)) != 0)
551*f6dc9357SAndroid Build Coastguard Worker         {
552*f6dc9357SAndroid Build Coastguard Worker           SET_IP_OP1
553*f6dc9357SAndroid Build Coastguard Worker           continue;
554*f6dc9357SAndroid Build Coastguard Worker         }
555*f6dc9357SAndroid Build Coastguard Worker         break;
556*f6dc9357SAndroid Build Coastguard Worker       case CMD_JA:
557*f6dc9357SAndroid Build Coastguard Worker         if ((Flags & (FLAG_C | FLAG_Z)) == 0)
558*f6dc9357SAndroid Build Coastguard Worker         {
559*f6dc9357SAndroid Build Coastguard Worker           SET_IP_OP1
560*f6dc9357SAndroid Build Coastguard Worker           continue;
561*f6dc9357SAndroid Build Coastguard Worker         }
562*f6dc9357SAndroid Build Coastguard Worker         break;
563*f6dc9357SAndroid Build Coastguard Worker       case CMD_JAE:
564*f6dc9357SAndroid Build Coastguard Worker         if ((Flags & FLAG_C) == 0)
565*f6dc9357SAndroid Build Coastguard Worker         {
566*f6dc9357SAndroid Build Coastguard Worker           SET_IP_OP1
567*f6dc9357SAndroid Build Coastguard Worker           continue;
568*f6dc9357SAndroid Build Coastguard Worker         }
569*f6dc9357SAndroid Build Coastguard Worker         break;
570*f6dc9357SAndroid Build Coastguard Worker 
571*f6dc9357SAndroid Build Coastguard Worker       case CMD_PUSH:
572*f6dc9357SAndroid Build Coastguard Worker         R[kStackRegIndex] -= 4;
573*f6dc9357SAndroid Build Coastguard Worker         SetValue32(&Mem[R[kStackRegIndex] & kSpaceMask], GetOperand32(&cmd->Op1));
574*f6dc9357SAndroid Build Coastguard Worker         break;
575*f6dc9357SAndroid Build Coastguard Worker       case CMD_POP:
576*f6dc9357SAndroid Build Coastguard Worker         SetOperand32(&cmd->Op1, GetValue32(&Mem[R[kStackRegIndex] & kSpaceMask]));
577*f6dc9357SAndroid Build Coastguard Worker         R[kStackRegIndex] += 4;
578*f6dc9357SAndroid Build Coastguard Worker         break;
579*f6dc9357SAndroid Build Coastguard Worker       case CMD_CALL:
580*f6dc9357SAndroid Build Coastguard Worker         R[kStackRegIndex] -= 4;
581*f6dc9357SAndroid Build Coastguard Worker         SetValue32(&Mem[R[kStackRegIndex] & kSpaceMask], (UInt32)(cmd - commands + 1));
582*f6dc9357SAndroid Build Coastguard Worker         SET_IP_OP1
583*f6dc9357SAndroid Build Coastguard Worker         continue;
584*f6dc9357SAndroid Build Coastguard Worker 
585*f6dc9357SAndroid Build Coastguard Worker       case CMD_PUSHA:
586*f6dc9357SAndroid Build Coastguard Worker         {
587*f6dc9357SAndroid Build Coastguard Worker           for (UInt32 i = 0, SP = R[kStackRegIndex] - 4; i < kNumRegs; i++, SP -= 4)
588*f6dc9357SAndroid Build Coastguard Worker             SetValue32(&Mem[SP & kSpaceMask], R[i]);
589*f6dc9357SAndroid Build Coastguard Worker           R[kStackRegIndex] -= kNumRegs * 4;
590*f6dc9357SAndroid Build Coastguard Worker         }
591*f6dc9357SAndroid Build Coastguard Worker         break;
592*f6dc9357SAndroid Build Coastguard Worker       case CMD_POPA:
593*f6dc9357SAndroid Build Coastguard Worker         {
594*f6dc9357SAndroid Build Coastguard Worker           for (UInt32 i = 0, SP = R[kStackRegIndex]; i < kNumRegs; i++, SP += 4)
595*f6dc9357SAndroid Build Coastguard Worker             R[kStackRegIndex - i] = GetValue32(&Mem[SP & kSpaceMask]);
596*f6dc9357SAndroid Build Coastguard Worker         }
597*f6dc9357SAndroid Build Coastguard Worker         break;
598*f6dc9357SAndroid Build Coastguard Worker       case CMD_PUSHF:
599*f6dc9357SAndroid Build Coastguard Worker         R[kStackRegIndex] -= 4;
600*f6dc9357SAndroid Build Coastguard Worker         SetValue32(&Mem[R[kStackRegIndex]&kSpaceMask], Flags);
601*f6dc9357SAndroid Build Coastguard Worker         break;
602*f6dc9357SAndroid Build Coastguard Worker       case CMD_POPF:
603*f6dc9357SAndroid Build Coastguard Worker         Flags = GetValue32(&Mem[R[kStackRegIndex] & kSpaceMask]);
604*f6dc9357SAndroid Build Coastguard Worker         R[kStackRegIndex] += 4;
605*f6dc9357SAndroid Build Coastguard Worker         break;
606*f6dc9357SAndroid Build Coastguard Worker 
607*f6dc9357SAndroid Build Coastguard Worker       case CMD_MOVZX:
608*f6dc9357SAndroid Build Coastguard Worker         SetOperand32(&cmd->Op1, GetOperand8(&cmd->Op2));
609*f6dc9357SAndroid Build Coastguard Worker         break;
610*f6dc9357SAndroid Build Coastguard Worker       case CMD_MOVSX:
611*f6dc9357SAndroid Build Coastguard Worker         SetOperand32(&cmd->Op1, (UInt32)(Int32)(signed char)GetOperand8(&cmd->Op2));
612*f6dc9357SAndroid Build Coastguard Worker         break;
613*f6dc9357SAndroid Build Coastguard Worker       case CMD_XCHG:
614*f6dc9357SAndroid Build Coastguard Worker         {
615*f6dc9357SAndroid Build Coastguard Worker           const UInt32 v1 = GetOperand(cmd->ByteMode, &cmd->Op1);
616*f6dc9357SAndroid Build Coastguard Worker           SetOperand(cmd->ByteMode, &cmd->Op1, GetOperand(cmd->ByteMode, &cmd->Op2));
617*f6dc9357SAndroid Build Coastguard Worker           SetOperand(cmd->ByteMode, &cmd->Op2, v1);
618*f6dc9357SAndroid Build Coastguard Worker         }
619*f6dc9357SAndroid Build Coastguard Worker         break;
620*f6dc9357SAndroid Build Coastguard Worker       case CMD_MUL:
621*f6dc9357SAndroid Build Coastguard Worker         {
622*f6dc9357SAndroid Build Coastguard Worker           const UInt32 res = GetOperand32(&cmd->Op1) * GetOperand32(&cmd->Op2);
623*f6dc9357SAndroid Build Coastguard Worker           SetOperand32(&cmd->Op1, res);
624*f6dc9357SAndroid Build Coastguard Worker         }
625*f6dc9357SAndroid Build Coastguard Worker         break;
626*f6dc9357SAndroid Build Coastguard Worker       case CMD_MULB:
627*f6dc9357SAndroid Build Coastguard Worker         {
628*f6dc9357SAndroid Build Coastguard Worker           const Byte res = (Byte)(GetOperand8(&cmd->Op1) * GetOperand8(&cmd->Op2));
629*f6dc9357SAndroid Build Coastguard Worker           SetOperand8(&cmd->Op1, res);
630*f6dc9357SAndroid Build Coastguard Worker         }
631*f6dc9357SAndroid Build Coastguard Worker         break;
632*f6dc9357SAndroid Build Coastguard Worker       case CMD_DIV:
633*f6dc9357SAndroid Build Coastguard Worker         {
634*f6dc9357SAndroid Build Coastguard Worker           const UInt32 divider = GetOperand(cmd->ByteMode, &cmd->Op2);
635*f6dc9357SAndroid Build Coastguard Worker           if (divider != 0)
636*f6dc9357SAndroid Build Coastguard Worker           {
637*f6dc9357SAndroid Build Coastguard Worker             const UInt32 res = GetOperand(cmd->ByteMode, &cmd->Op1) / divider;
638*f6dc9357SAndroid Build Coastguard Worker             SetOperand(cmd->ByteMode, &cmd->Op1, res);
639*f6dc9357SAndroid Build Coastguard Worker           }
640*f6dc9357SAndroid Build Coastguard Worker         }
641*f6dc9357SAndroid Build Coastguard Worker         break;
642*f6dc9357SAndroid Build Coastguard Worker 
643*f6dc9357SAndroid Build Coastguard Worker       case CMD_RET:
644*f6dc9357SAndroid Build Coastguard Worker         {
645*f6dc9357SAndroid Build Coastguard Worker           if (R[kStackRegIndex] >= kSpaceSize)
646*f6dc9357SAndroid Build Coastguard Worker             return true;
647*f6dc9357SAndroid Build Coastguard Worker           const UInt32 ip = GetValue32(&Mem[R[kStackRegIndex] & kSpaceMask]);
648*f6dc9357SAndroid Build Coastguard Worker           SET_IP(ip)
649*f6dc9357SAndroid Build Coastguard Worker           R[kStackRegIndex] += 4;
650*f6dc9357SAndroid Build Coastguard Worker           continue;
651*f6dc9357SAndroid Build Coastguard Worker         }
652*f6dc9357SAndroid Build Coastguard Worker       case CMD_PRINT:
653*f6dc9357SAndroid Build Coastguard Worker         break;
654*f6dc9357SAndroid Build Coastguard Worker     }
655*f6dc9357SAndroid Build Coastguard Worker     cmd++;
656*f6dc9357SAndroid Build Coastguard Worker     --maxOpCount;
657*f6dc9357SAndroid Build Coastguard Worker   }
658*f6dc9357SAndroid Build Coastguard Worker }
659*f6dc9357SAndroid Build Coastguard Worker 
660*f6dc9357SAndroid Build Coastguard Worker //////////////////////////////////////////////////////
661*f6dc9357SAndroid Build Coastguard Worker // Read program
662*f6dc9357SAndroid Build Coastguard Worker 
DecodeArg(CMemBitDecoder & inp,COperand & op,bool byteMode)663*f6dc9357SAndroid Build Coastguard Worker static void DecodeArg(CMemBitDecoder &inp, COperand &op, bool byteMode)
664*f6dc9357SAndroid Build Coastguard Worker {
665*f6dc9357SAndroid Build Coastguard Worker   if (inp.ReadBit())
666*f6dc9357SAndroid Build Coastguard Worker   {
667*f6dc9357SAndroid Build Coastguard Worker     op.Type = OP_TYPE_REG;
668*f6dc9357SAndroid Build Coastguard Worker     op.Data = inp.ReadBits(kNumRegBits);
669*f6dc9357SAndroid Build Coastguard Worker   }
670*f6dc9357SAndroid Build Coastguard Worker   else if (inp.ReadBit() == 0)
671*f6dc9357SAndroid Build Coastguard Worker   {
672*f6dc9357SAndroid Build Coastguard Worker     op.Type = OP_TYPE_INT;
673*f6dc9357SAndroid Build Coastguard Worker     if (byteMode)
674*f6dc9357SAndroid Build Coastguard Worker       op.Data = inp.ReadBits(8);
675*f6dc9357SAndroid Build Coastguard Worker     else
676*f6dc9357SAndroid Build Coastguard Worker       op.Data = inp.ReadEncodedUInt32();
677*f6dc9357SAndroid Build Coastguard Worker   }
678*f6dc9357SAndroid Build Coastguard Worker   else
679*f6dc9357SAndroid Build Coastguard Worker   {
680*f6dc9357SAndroid Build Coastguard Worker     op.Type = OP_TYPE_REGMEM;
681*f6dc9357SAndroid Build Coastguard Worker     if (inp.ReadBit() == 0)
682*f6dc9357SAndroid Build Coastguard Worker     {
683*f6dc9357SAndroid Build Coastguard Worker       op.Data = inp.ReadBits(kNumRegBits);
684*f6dc9357SAndroid Build Coastguard Worker       op.Base = 0;
685*f6dc9357SAndroid Build Coastguard Worker     }
686*f6dc9357SAndroid Build Coastguard Worker     else
687*f6dc9357SAndroid Build Coastguard Worker     {
688*f6dc9357SAndroid Build Coastguard Worker       if (inp.ReadBit() == 0)
689*f6dc9357SAndroid Build Coastguard Worker         op.Data = inp.ReadBits(kNumRegBits);
690*f6dc9357SAndroid Build Coastguard Worker       else
691*f6dc9357SAndroid Build Coastguard Worker         op.Data = kNumRegs;
692*f6dc9357SAndroid Build Coastguard Worker       op.Base = inp.ReadEncodedUInt32();
693*f6dc9357SAndroid Build Coastguard Worker     }
694*f6dc9357SAndroid Build Coastguard Worker   }
695*f6dc9357SAndroid Build Coastguard Worker }
696*f6dc9357SAndroid Build Coastguard Worker 
ReadProgram(const Byte * code,UInt32 codeSize)697*f6dc9357SAndroid Build Coastguard Worker void CProgram::ReadProgram(const Byte *code, UInt32 codeSize)
698*f6dc9357SAndroid Build Coastguard Worker {
699*f6dc9357SAndroid Build Coastguard Worker   CMemBitDecoder inp;
700*f6dc9357SAndroid Build Coastguard Worker   inp.Init(code, codeSize);
701*f6dc9357SAndroid Build Coastguard Worker 
702*f6dc9357SAndroid Build Coastguard Worker   StaticData.Clear();
703*f6dc9357SAndroid Build Coastguard Worker 
704*f6dc9357SAndroid Build Coastguard Worker   if (inp.ReadBit())
705*f6dc9357SAndroid Build Coastguard Worker   {
706*f6dc9357SAndroid Build Coastguard Worker     const UInt32 dataSize = inp.ReadEncodedUInt32() + 1;
707*f6dc9357SAndroid Build Coastguard Worker     for (UInt32 i = 0; inp.Avail() && i < dataSize; i++)
708*f6dc9357SAndroid Build Coastguard Worker       StaticData.Add((Byte)inp.ReadBits(8));
709*f6dc9357SAndroid Build Coastguard Worker   }
710*f6dc9357SAndroid Build Coastguard Worker 
711*f6dc9357SAndroid Build Coastguard Worker   while (inp.Avail())
712*f6dc9357SAndroid Build Coastguard Worker   {
713*f6dc9357SAndroid Build Coastguard Worker     Commands.Add(CCommand());
714*f6dc9357SAndroid Build Coastguard Worker     CCommand *cmd = &Commands.Back();
715*f6dc9357SAndroid Build Coastguard Worker 
716*f6dc9357SAndroid Build Coastguard Worker     unsigned opCode;
717*f6dc9357SAndroid Build Coastguard Worker     if (inp.ReadBit() == 0)
718*f6dc9357SAndroid Build Coastguard Worker       opCode = inp.ReadBits(3);
719*f6dc9357SAndroid Build Coastguard Worker     else
720*f6dc9357SAndroid Build Coastguard Worker       opCode = 8 + inp.ReadBits(5);
721*f6dc9357SAndroid Build Coastguard Worker     cmd->OpCode = (ECommand)opCode;
722*f6dc9357SAndroid Build Coastguard Worker     const unsigned cmdFlags = kCmdFlags[opCode];
723*f6dc9357SAndroid Build Coastguard Worker     if (cmdFlags & CF_BYTEMODE)
724*f6dc9357SAndroid Build Coastguard Worker       cmd->ByteMode = (inp.ReadBit()) ? true : false;
725*f6dc9357SAndroid Build Coastguard Worker     else
726*f6dc9357SAndroid Build Coastguard Worker       cmd->ByteMode = 0;
727*f6dc9357SAndroid Build Coastguard Worker 
728*f6dc9357SAndroid Build Coastguard Worker     const unsigned opNum = (cmdFlags & CF_OPMASK);
729*f6dc9357SAndroid Build Coastguard Worker 
730*f6dc9357SAndroid Build Coastguard Worker     if (opNum)
731*f6dc9357SAndroid Build Coastguard Worker     {
732*f6dc9357SAndroid Build Coastguard Worker       DecodeArg(inp, cmd->Op1, cmd->ByteMode);
733*f6dc9357SAndroid Build Coastguard Worker       if (opNum == 2)
734*f6dc9357SAndroid Build Coastguard Worker         DecodeArg(inp, cmd->Op2, cmd->ByteMode);
735*f6dc9357SAndroid Build Coastguard Worker       else
736*f6dc9357SAndroid Build Coastguard Worker       {
737*f6dc9357SAndroid Build Coastguard Worker         if (cmd->Op1.Type == OP_TYPE_INT && (cmdFlags & (CF_JUMP | CF_PROC)))
738*f6dc9357SAndroid Build Coastguard Worker         {
739*f6dc9357SAndroid Build Coastguard Worker           Int32 dist = (Int32)cmd->Op1.Data;
740*f6dc9357SAndroid Build Coastguard Worker           if (dist >= 256)
741*f6dc9357SAndroid Build Coastguard Worker             dist -= 256;
742*f6dc9357SAndroid Build Coastguard Worker           else
743*f6dc9357SAndroid Build Coastguard Worker           {
744*f6dc9357SAndroid Build Coastguard Worker             if (dist >= 136)
745*f6dc9357SAndroid Build Coastguard Worker               dist -= 264;
746*f6dc9357SAndroid Build Coastguard Worker             else if (dist >= 16)
747*f6dc9357SAndroid Build Coastguard Worker               dist -= 8;
748*f6dc9357SAndroid Build Coastguard Worker             else if (dist >= 8)
749*f6dc9357SAndroid Build Coastguard Worker               dist -= 16;
750*f6dc9357SAndroid Build Coastguard Worker             dist += Commands.Size() - 1;
751*f6dc9357SAndroid Build Coastguard Worker           }
752*f6dc9357SAndroid Build Coastguard Worker           cmd->Op1.Data = (UInt32)dist;
753*f6dc9357SAndroid Build Coastguard Worker         }
754*f6dc9357SAndroid Build Coastguard Worker       }
755*f6dc9357SAndroid Build Coastguard Worker     }
756*f6dc9357SAndroid Build Coastguard Worker 
757*f6dc9357SAndroid Build Coastguard Worker     if (cmd->ByteMode)
758*f6dc9357SAndroid Build Coastguard Worker     {
759*f6dc9357SAndroid Build Coastguard Worker       switch (cmd->OpCode)
760*f6dc9357SAndroid Build Coastguard Worker       {
761*f6dc9357SAndroid Build Coastguard Worker         case CMD_MOV: cmd->OpCode = CMD_MOVB; break;
762*f6dc9357SAndroid Build Coastguard Worker         case CMD_CMP: cmd->OpCode = CMD_CMPB; break;
763*f6dc9357SAndroid Build Coastguard Worker         case CMD_ADD: cmd->OpCode = CMD_ADDB; break;
764*f6dc9357SAndroid Build Coastguard Worker         case CMD_SUB: cmd->OpCode = CMD_SUBB; break;
765*f6dc9357SAndroid Build Coastguard Worker         case CMD_INC: cmd->OpCode = CMD_INCB; break;
766*f6dc9357SAndroid Build Coastguard Worker         case CMD_DEC: cmd->OpCode = CMD_DECB; break;
767*f6dc9357SAndroid Build Coastguard Worker         case CMD_XOR: cmd->OpCode = CMD_XORB; break;
768*f6dc9357SAndroid Build Coastguard Worker         case CMD_AND: cmd->OpCode = CMD_ANDB; break;
769*f6dc9357SAndroid Build Coastguard Worker         case CMD_OR: cmd->OpCode = CMD_ORB; break;
770*f6dc9357SAndroid Build Coastguard Worker         case CMD_TEST: cmd->OpCode = CMD_TESTB; break;
771*f6dc9357SAndroid Build Coastguard Worker         case CMD_NEG: cmd->OpCode = CMD_NEGB; break;
772*f6dc9357SAndroid Build Coastguard Worker         case CMD_SHL: cmd->OpCode = CMD_SHLB; break;
773*f6dc9357SAndroid Build Coastguard Worker         case CMD_SHR: cmd->OpCode = CMD_SHRB; break;
774*f6dc9357SAndroid Build Coastguard Worker         case CMD_SAR: cmd->OpCode = CMD_SARB; break;
775*f6dc9357SAndroid Build Coastguard Worker         case CMD_MUL: cmd->OpCode = CMD_MULB; break;
776*f6dc9357SAndroid Build Coastguard Worker         default: break;
777*f6dc9357SAndroid Build Coastguard Worker       }
778*f6dc9357SAndroid Build Coastguard Worker     }
779*f6dc9357SAndroid Build Coastguard Worker   }
780*f6dc9357SAndroid Build Coastguard Worker }
781*f6dc9357SAndroid Build Coastguard Worker 
782*f6dc9357SAndroid Build Coastguard Worker #endif
783*f6dc9357SAndroid Build Coastguard Worker 
784*f6dc9357SAndroid Build Coastguard Worker 
785*f6dc9357SAndroid Build Coastguard Worker #ifdef Z7_RARVM_STANDARD_FILTERS
786*f6dc9357SAndroid Build Coastguard Worker 
787*f6dc9357SAndroid Build Coastguard Worker enum EStandardFilter
788*f6dc9357SAndroid Build Coastguard Worker {
789*f6dc9357SAndroid Build Coastguard Worker   SF_E8,
790*f6dc9357SAndroid Build Coastguard Worker   SF_E8E9,
791*f6dc9357SAndroid Build Coastguard Worker   SF_ITANIUM,
792*f6dc9357SAndroid Build Coastguard Worker   SF_RGB,
793*f6dc9357SAndroid Build Coastguard Worker   SF_AUDIO,
794*f6dc9357SAndroid Build Coastguard Worker   SF_DELTA
795*f6dc9357SAndroid Build Coastguard Worker   // SF_UPCASE
796*f6dc9357SAndroid Build Coastguard Worker };
797*f6dc9357SAndroid Build Coastguard Worker 
798*f6dc9357SAndroid Build Coastguard Worker static const struct CStandardFilterSignature
799*f6dc9357SAndroid Build Coastguard Worker {
800*f6dc9357SAndroid Build Coastguard Worker   UInt32 Length;
801*f6dc9357SAndroid Build Coastguard Worker   UInt32 CRC;
802*f6dc9357SAndroid Build Coastguard Worker   EStandardFilter Type;
803*f6dc9357SAndroid Build Coastguard Worker }
804*f6dc9357SAndroid Build Coastguard Worker kStdFilters[]=
805*f6dc9357SAndroid Build Coastguard Worker {
806*f6dc9357SAndroid Build Coastguard Worker   {  53, 0xad576887, SF_E8 },
807*f6dc9357SAndroid Build Coastguard Worker   {  57, 0x3cd7e57e, SF_E8E9 },
808*f6dc9357SAndroid Build Coastguard Worker   { 120, 0x3769893f, SF_ITANIUM },
809*f6dc9357SAndroid Build Coastguard Worker   {  29, 0x0e06077d, SF_DELTA },
810*f6dc9357SAndroid Build Coastguard Worker   { 149, 0x1c2c5dc8, SF_RGB },
811*f6dc9357SAndroid Build Coastguard Worker   { 216, 0xbc85e701, SF_AUDIO }
812*f6dc9357SAndroid Build Coastguard Worker   // {  40, 0x46b9c560, SF_UPCASE }
813*f6dc9357SAndroid Build Coastguard Worker };
814*f6dc9357SAndroid Build Coastguard Worker 
FindStandardFilter(const Byte * code,UInt32 codeSize)815*f6dc9357SAndroid Build Coastguard Worker static int FindStandardFilter(const Byte *code, UInt32 codeSize)
816*f6dc9357SAndroid Build Coastguard Worker {
817*f6dc9357SAndroid Build Coastguard Worker   // return -1; // for debug VM execution
818*f6dc9357SAndroid Build Coastguard Worker   const UInt32 crc = CrcCalc(code, codeSize);
819*f6dc9357SAndroid Build Coastguard Worker   for (unsigned i = 0; i < Z7_ARRAY_SIZE(kStdFilters); i++)
820*f6dc9357SAndroid Build Coastguard Worker   {
821*f6dc9357SAndroid Build Coastguard Worker     const CStandardFilterSignature &sfs = kStdFilters[i];
822*f6dc9357SAndroid Build Coastguard Worker     if (sfs.CRC == crc && sfs.Length == codeSize)
823*f6dc9357SAndroid Build Coastguard Worker       return (int)i;
824*f6dc9357SAndroid Build Coastguard Worker   }
825*f6dc9357SAndroid Build Coastguard Worker   return -1;
826*f6dc9357SAndroid Build Coastguard Worker }
827*f6dc9357SAndroid Build Coastguard Worker 
828*f6dc9357SAndroid Build Coastguard Worker #endif
829*f6dc9357SAndroid Build Coastguard Worker 
830*f6dc9357SAndroid Build Coastguard Worker 
PrepareProgram(const Byte * code,UInt32 codeSize)831*f6dc9357SAndroid Build Coastguard Worker bool CProgram::PrepareProgram(const Byte *code, UInt32 codeSize)
832*f6dc9357SAndroid Build Coastguard Worker {
833*f6dc9357SAndroid Build Coastguard Worker   IsSupported = false;
834*f6dc9357SAndroid Build Coastguard Worker 
835*f6dc9357SAndroid Build Coastguard Worker   #ifdef Z7_RARVM_VM_ENABLE
836*f6dc9357SAndroid Build Coastguard Worker   Commands.Clear();
837*f6dc9357SAndroid Build Coastguard Worker   #endif
838*f6dc9357SAndroid Build Coastguard Worker 
839*f6dc9357SAndroid Build Coastguard Worker   #ifdef Z7_RARVM_STANDARD_FILTERS
840*f6dc9357SAndroid Build Coastguard Worker   StandardFilterIndex = -1;
841*f6dc9357SAndroid Build Coastguard Worker   #endif
842*f6dc9357SAndroid Build Coastguard Worker 
843*f6dc9357SAndroid Build Coastguard Worker   bool isOK = false;
844*f6dc9357SAndroid Build Coastguard Worker 
845*f6dc9357SAndroid Build Coastguard Worker   Byte xorSum = 0;
846*f6dc9357SAndroid Build Coastguard Worker   for (UInt32 i = 0; i < codeSize; i++)
847*f6dc9357SAndroid Build Coastguard Worker     xorSum ^= code[i];
848*f6dc9357SAndroid Build Coastguard Worker 
849*f6dc9357SAndroid Build Coastguard Worker   if (xorSum == 0 && codeSize != 0)
850*f6dc9357SAndroid Build Coastguard Worker   {
851*f6dc9357SAndroid Build Coastguard Worker     IsSupported = true;
852*f6dc9357SAndroid Build Coastguard Worker     isOK = true;
853*f6dc9357SAndroid Build Coastguard Worker     #ifdef Z7_RARVM_STANDARD_FILTERS
854*f6dc9357SAndroid Build Coastguard Worker     StandardFilterIndex = FindStandardFilter(code, codeSize);
855*f6dc9357SAndroid Build Coastguard Worker     if (StandardFilterIndex >= 0)
856*f6dc9357SAndroid Build Coastguard Worker       return true;
857*f6dc9357SAndroid Build Coastguard Worker     #endif
858*f6dc9357SAndroid Build Coastguard Worker 
859*f6dc9357SAndroid Build Coastguard Worker     #ifdef Z7_RARVM_VM_ENABLE
860*f6dc9357SAndroid Build Coastguard Worker     ReadProgram(code + 1, codeSize - 1);
861*f6dc9357SAndroid Build Coastguard Worker     #else
862*f6dc9357SAndroid Build Coastguard Worker     IsSupported = false;
863*f6dc9357SAndroid Build Coastguard Worker     #endif
864*f6dc9357SAndroid Build Coastguard Worker   }
865*f6dc9357SAndroid Build Coastguard Worker 
866*f6dc9357SAndroid Build Coastguard Worker   #ifdef Z7_RARVM_VM_ENABLE
867*f6dc9357SAndroid Build Coastguard Worker   Commands.Add(CCommand());
868*f6dc9357SAndroid Build Coastguard Worker   Commands.Back().OpCode = CMD_RET;
869*f6dc9357SAndroid Build Coastguard Worker   #endif
870*f6dc9357SAndroid Build Coastguard Worker 
871*f6dc9357SAndroid Build Coastguard Worker   return isOK;
872*f6dc9357SAndroid Build Coastguard Worker }
873*f6dc9357SAndroid Build Coastguard Worker 
SetMemory(UInt32 pos,const Byte * data,UInt32 dataSize)874*f6dc9357SAndroid Build Coastguard Worker void CVm::SetMemory(UInt32 pos, const Byte *data, UInt32 dataSize)
875*f6dc9357SAndroid Build Coastguard Worker {
876*f6dc9357SAndroid Build Coastguard Worker   if (pos < kSpaceSize && data != Mem + pos)
877*f6dc9357SAndroid Build Coastguard Worker     memmove(Mem + pos, data, MyMin(dataSize, kSpaceSize - pos));
878*f6dc9357SAndroid Build Coastguard Worker }
879*f6dc9357SAndroid Build Coastguard Worker 
880*f6dc9357SAndroid Build Coastguard Worker #ifdef Z7_RARVM_STANDARD_FILTERS
881*f6dc9357SAndroid Build Coastguard Worker 
E8E9Decode(Byte * data,UInt32 dataSize,UInt32 fileOffset,bool e9)882*f6dc9357SAndroid Build Coastguard Worker static void E8E9Decode(Byte *data, UInt32 dataSize, UInt32 fileOffset, bool e9)
883*f6dc9357SAndroid Build Coastguard Worker {
884*f6dc9357SAndroid Build Coastguard Worker   if (dataSize <= 4)
885*f6dc9357SAndroid Build Coastguard Worker     return;
886*f6dc9357SAndroid Build Coastguard Worker   dataSize -= 4;
887*f6dc9357SAndroid Build Coastguard Worker   const UInt32 kFileSize = 0x1000000;
888*f6dc9357SAndroid Build Coastguard Worker   const Byte cmpMask = (Byte)(e9 ? 0xFE : 0xFF);
889*f6dc9357SAndroid Build Coastguard Worker   for (UInt32 curPos = 0; curPos < dataSize;)
890*f6dc9357SAndroid Build Coastguard Worker   {
891*f6dc9357SAndroid Build Coastguard Worker     curPos++;
892*f6dc9357SAndroid Build Coastguard Worker     if (((*data++) & cmpMask) == 0xE8)
893*f6dc9357SAndroid Build Coastguard Worker     {
894*f6dc9357SAndroid Build Coastguard Worker       UInt32 offset = curPos + fileOffset;
895*f6dc9357SAndroid Build Coastguard Worker       UInt32 addr = GetValue32(data);
896*f6dc9357SAndroid Build Coastguard Worker       if (addr < kFileSize)
897*f6dc9357SAndroid Build Coastguard Worker         SetValue32(data, addr - offset);
898*f6dc9357SAndroid Build Coastguard Worker       else if ((addr & 0x80000000) != 0 && ((addr + offset) & 0x80000000) == 0)
899*f6dc9357SAndroid Build Coastguard Worker         SetValue32(data, addr + kFileSize);
900*f6dc9357SAndroid Build Coastguard Worker       data += 4;
901*f6dc9357SAndroid Build Coastguard Worker       curPos += 4;
902*f6dc9357SAndroid Build Coastguard Worker     }
903*f6dc9357SAndroid Build Coastguard Worker   }
904*f6dc9357SAndroid Build Coastguard Worker }
905*f6dc9357SAndroid Build Coastguard Worker 
906*f6dc9357SAndroid Build Coastguard Worker 
ItaniumDecode(Byte * data,UInt32 dataSize,UInt32 fileOffset)907*f6dc9357SAndroid Build Coastguard Worker static void ItaniumDecode(Byte *data, UInt32 dataSize, UInt32 fileOffset)
908*f6dc9357SAndroid Build Coastguard Worker {
909*f6dc9357SAndroid Build Coastguard Worker   if (dataSize <= 21)
910*f6dc9357SAndroid Build Coastguard Worker     return;
911*f6dc9357SAndroid Build Coastguard Worker   fileOffset >>= 4;
912*f6dc9357SAndroid Build Coastguard Worker   dataSize -= 21;
913*f6dc9357SAndroid Build Coastguard Worker   dataSize += 15;
914*f6dc9357SAndroid Build Coastguard Worker   dataSize >>= 4;
915*f6dc9357SAndroid Build Coastguard Worker   dataSize += fileOffset;
916*f6dc9357SAndroid Build Coastguard Worker   do
917*f6dc9357SAndroid Build Coastguard Worker   {
918*f6dc9357SAndroid Build Coastguard Worker     unsigned m = ((UInt32)0x334B0000 >> (data[0] & 0x1E)) & 3;
919*f6dc9357SAndroid Build Coastguard Worker     if (m)
920*f6dc9357SAndroid Build Coastguard Worker     {
921*f6dc9357SAndroid Build Coastguard Worker       m++;
922*f6dc9357SAndroid Build Coastguard Worker       do
923*f6dc9357SAndroid Build Coastguard Worker       {
924*f6dc9357SAndroid Build Coastguard Worker         Byte *p = data + ((size_t)m * 5 - 8);
925*f6dc9357SAndroid Build Coastguard Worker         if (((p[3] >> m) & 15) == 5)
926*f6dc9357SAndroid Build Coastguard Worker         {
927*f6dc9357SAndroid Build Coastguard Worker           const UInt32 kMask = 0xFFFFF;
928*f6dc9357SAndroid Build Coastguard Worker           // UInt32 raw = ((UInt32)p[0]) | ((UInt32)p[1] << 8) | ((UInt32)p[2] << 16);
929*f6dc9357SAndroid Build Coastguard Worker           UInt32 raw = GetUi32(p);
930*f6dc9357SAndroid Build Coastguard Worker           UInt32 v = raw >> m;
931*f6dc9357SAndroid Build Coastguard Worker           v -= fileOffset;
932*f6dc9357SAndroid Build Coastguard Worker           v &= kMask;
933*f6dc9357SAndroid Build Coastguard Worker           raw &= ~(kMask << m);
934*f6dc9357SAndroid Build Coastguard Worker           raw |= (v << m);
935*f6dc9357SAndroid Build Coastguard Worker           // p[0] = (Byte)raw; p[1] = (Byte)(raw >> 8); p[2] = (Byte)(raw >> 16);
936*f6dc9357SAndroid Build Coastguard Worker           SetUi32(p, raw)
937*f6dc9357SAndroid Build Coastguard Worker         }
938*f6dc9357SAndroid Build Coastguard Worker       }
939*f6dc9357SAndroid Build Coastguard Worker       while (++m <= 4);
940*f6dc9357SAndroid Build Coastguard Worker     }
941*f6dc9357SAndroid Build Coastguard Worker     data += 16;
942*f6dc9357SAndroid Build Coastguard Worker   }
943*f6dc9357SAndroid Build Coastguard Worker   while (++fileOffset != dataSize);
944*f6dc9357SAndroid Build Coastguard Worker }
945*f6dc9357SAndroid Build Coastguard Worker 
946*f6dc9357SAndroid Build Coastguard Worker 
DeltaDecode(Byte * data,UInt32 dataSize,UInt32 numChannels)947*f6dc9357SAndroid Build Coastguard Worker static void DeltaDecode(Byte *data, UInt32 dataSize, UInt32 numChannels)
948*f6dc9357SAndroid Build Coastguard Worker {
949*f6dc9357SAndroid Build Coastguard Worker   UInt32 srcPos = 0;
950*f6dc9357SAndroid Build Coastguard Worker   const UInt32 border = dataSize * 2;
951*f6dc9357SAndroid Build Coastguard Worker   for (UInt32 curChannel = 0; curChannel < numChannels; curChannel++)
952*f6dc9357SAndroid Build Coastguard Worker   {
953*f6dc9357SAndroid Build Coastguard Worker     Byte prevByte = 0;
954*f6dc9357SAndroid Build Coastguard Worker     for (UInt32 destPos = dataSize + curChannel; destPos < border; destPos += numChannels)
955*f6dc9357SAndroid Build Coastguard Worker       data[destPos] = (prevByte = (Byte)(prevByte - data[srcPos++]));
956*f6dc9357SAndroid Build Coastguard Worker   }
957*f6dc9357SAndroid Build Coastguard Worker }
958*f6dc9357SAndroid Build Coastguard Worker 
RgbDecode(Byte * srcData,UInt32 dataSize,UInt32 width,UInt32 posR)959*f6dc9357SAndroid Build Coastguard Worker static void RgbDecode(Byte *srcData, UInt32 dataSize, UInt32 width, UInt32 posR)
960*f6dc9357SAndroid Build Coastguard Worker {
961*f6dc9357SAndroid Build Coastguard Worker   Byte *destData = srcData + dataSize;
962*f6dc9357SAndroid Build Coastguard Worker   const UInt32 kNumChannels = 3;
963*f6dc9357SAndroid Build Coastguard Worker 
964*f6dc9357SAndroid Build Coastguard Worker   for (UInt32 curChannel = 0; curChannel < kNumChannels; curChannel++)
965*f6dc9357SAndroid Build Coastguard Worker   {
966*f6dc9357SAndroid Build Coastguard Worker     Byte prevByte = 0;
967*f6dc9357SAndroid Build Coastguard Worker 
968*f6dc9357SAndroid Build Coastguard Worker     for (UInt32 i = curChannel; i < dataSize; i += kNumChannels)
969*f6dc9357SAndroid Build Coastguard Worker     {
970*f6dc9357SAndroid Build Coastguard Worker       unsigned predicted;
971*f6dc9357SAndroid Build Coastguard Worker       if (i < width)
972*f6dc9357SAndroid Build Coastguard Worker         predicted = prevByte;
973*f6dc9357SAndroid Build Coastguard Worker       else
974*f6dc9357SAndroid Build Coastguard Worker       {
975*f6dc9357SAndroid Build Coastguard Worker         const unsigned upperLeftByte = destData[i - width];
976*f6dc9357SAndroid Build Coastguard Worker         const unsigned upperByte = destData[i - width + 3];
977*f6dc9357SAndroid Build Coastguard Worker         predicted = prevByte + upperByte - upperLeftByte;
978*f6dc9357SAndroid Build Coastguard Worker         const int pa = abs((int)(predicted - prevByte));
979*f6dc9357SAndroid Build Coastguard Worker         const int pb = abs((int)(predicted - upperByte));
980*f6dc9357SAndroid Build Coastguard Worker         const int pc = abs((int)(predicted - upperLeftByte));
981*f6dc9357SAndroid Build Coastguard Worker         if (pa <= pb && pa <= pc)
982*f6dc9357SAndroid Build Coastguard Worker           predicted = prevByte;
983*f6dc9357SAndroid Build Coastguard Worker         else
984*f6dc9357SAndroid Build Coastguard Worker           if (pb <= pc)
985*f6dc9357SAndroid Build Coastguard Worker             predicted = upperByte;
986*f6dc9357SAndroid Build Coastguard Worker           else
987*f6dc9357SAndroid Build Coastguard Worker             predicted = upperLeftByte;
988*f6dc9357SAndroid Build Coastguard Worker       }
989*f6dc9357SAndroid Build Coastguard Worker       destData[i] = prevByte = (Byte)(predicted - *(srcData++));
990*f6dc9357SAndroid Build Coastguard Worker     }
991*f6dc9357SAndroid Build Coastguard Worker   }
992*f6dc9357SAndroid Build Coastguard Worker   if (dataSize < 3)
993*f6dc9357SAndroid Build Coastguard Worker     return;
994*f6dc9357SAndroid Build Coastguard Worker   const UInt32 border = dataSize - 2;
995*f6dc9357SAndroid Build Coastguard Worker   for (UInt32 i = posR; i < border; i += 3)
996*f6dc9357SAndroid Build Coastguard Worker   {
997*f6dc9357SAndroid Build Coastguard Worker     const Byte g = destData[i + 1];
998*f6dc9357SAndroid Build Coastguard Worker     destData[i    ] = (Byte)(destData[i    ] + g);
999*f6dc9357SAndroid Build Coastguard Worker     destData[i + 2] = (Byte)(destData[i + 2] + g);
1000*f6dc9357SAndroid Build Coastguard Worker   }
1001*f6dc9357SAndroid Build Coastguard Worker }
1002*f6dc9357SAndroid Build Coastguard Worker 
1003*f6dc9357SAndroid Build Coastguard Worker #define my_abs(x) (unsigned)abs(x)
1004*f6dc9357SAndroid Build Coastguard Worker 
AudioDecode(Byte * srcData,UInt32 dataSize,UInt32 numChannels)1005*f6dc9357SAndroid Build Coastguard Worker static void AudioDecode(Byte *srcData, UInt32 dataSize, UInt32 numChannels)
1006*f6dc9357SAndroid Build Coastguard Worker {
1007*f6dc9357SAndroid Build Coastguard Worker   Byte *destData = srcData + dataSize;
1008*f6dc9357SAndroid Build Coastguard Worker   for (UInt32 curChannel = 0; curChannel < numChannels; curChannel++)
1009*f6dc9357SAndroid Build Coastguard Worker   {
1010*f6dc9357SAndroid Build Coastguard Worker     UInt32 prevByte = 0, prevDelta = 0, dif[7];
1011*f6dc9357SAndroid Build Coastguard Worker     Int32 D1 = 0, D2 = 0, D3;
1012*f6dc9357SAndroid Build Coastguard Worker     Int32 K1 = 0, K2 = 0, K3 = 0;
1013*f6dc9357SAndroid Build Coastguard Worker     memset(dif, 0, sizeof(dif));
1014*f6dc9357SAndroid Build Coastguard Worker 
1015*f6dc9357SAndroid Build Coastguard Worker     for (UInt32 i = curChannel, byteCount = 0; i < dataSize; i += numChannels, byteCount++)
1016*f6dc9357SAndroid Build Coastguard Worker     {
1017*f6dc9357SAndroid Build Coastguard Worker       D3 = D2;
1018*f6dc9357SAndroid Build Coastguard Worker       D2 = (Int32)prevDelta - D1;
1019*f6dc9357SAndroid Build Coastguard Worker       D1 = (Int32)prevDelta;
1020*f6dc9357SAndroid Build Coastguard Worker 
1021*f6dc9357SAndroid Build Coastguard Worker       UInt32 predicted = (UInt32)((Int32)(8 * prevByte) + K1 * D1 + K2 * D2 + K3 * D3);
1022*f6dc9357SAndroid Build Coastguard Worker       predicted = (predicted >> 3) & 0xFF;
1023*f6dc9357SAndroid Build Coastguard Worker 
1024*f6dc9357SAndroid Build Coastguard Worker       const UInt32 curByte = *(srcData++);
1025*f6dc9357SAndroid Build Coastguard Worker 
1026*f6dc9357SAndroid Build Coastguard Worker       predicted -= curByte;
1027*f6dc9357SAndroid Build Coastguard Worker       destData[i] = (Byte)predicted;
1028*f6dc9357SAndroid Build Coastguard Worker       prevDelta = (UInt32)(Int32)(signed char)(predicted - prevByte);
1029*f6dc9357SAndroid Build Coastguard Worker       prevByte = predicted;
1030*f6dc9357SAndroid Build Coastguard Worker 
1031*f6dc9357SAndroid Build Coastguard Worker       const Int32 D = ((Int32)(signed char)curByte) << 3;
1032*f6dc9357SAndroid Build Coastguard Worker 
1033*f6dc9357SAndroid Build Coastguard Worker       dif[0] += my_abs(D);
1034*f6dc9357SAndroid Build Coastguard Worker       dif[1] += my_abs(D - D1);
1035*f6dc9357SAndroid Build Coastguard Worker       dif[2] += my_abs(D + D1);
1036*f6dc9357SAndroid Build Coastguard Worker       dif[3] += my_abs(D - D2);
1037*f6dc9357SAndroid Build Coastguard Worker       dif[4] += my_abs(D + D2);
1038*f6dc9357SAndroid Build Coastguard Worker       dif[5] += my_abs(D - D3);
1039*f6dc9357SAndroid Build Coastguard Worker       dif[6] += my_abs(D + D3);
1040*f6dc9357SAndroid Build Coastguard Worker 
1041*f6dc9357SAndroid Build Coastguard Worker       if ((byteCount & 0x1F) == 0)
1042*f6dc9357SAndroid Build Coastguard Worker       {
1043*f6dc9357SAndroid Build Coastguard Worker         UInt32 minDif = dif[0], numMinDif = 0;
1044*f6dc9357SAndroid Build Coastguard Worker         dif[0] = 0;
1045*f6dc9357SAndroid Build Coastguard Worker         for (unsigned j = 1; j < Z7_ARRAY_SIZE(dif); j++)
1046*f6dc9357SAndroid Build Coastguard Worker         {
1047*f6dc9357SAndroid Build Coastguard Worker           if (dif[j] < minDif)
1048*f6dc9357SAndroid Build Coastguard Worker           {
1049*f6dc9357SAndroid Build Coastguard Worker             minDif = dif[j];
1050*f6dc9357SAndroid Build Coastguard Worker             numMinDif = j;
1051*f6dc9357SAndroid Build Coastguard Worker           }
1052*f6dc9357SAndroid Build Coastguard Worker           dif[j] = 0;
1053*f6dc9357SAndroid Build Coastguard Worker         }
1054*f6dc9357SAndroid Build Coastguard Worker         switch (numMinDif)
1055*f6dc9357SAndroid Build Coastguard Worker         {
1056*f6dc9357SAndroid Build Coastguard Worker           case 1: if (K1 >= -16) K1--; break;
1057*f6dc9357SAndroid Build Coastguard Worker           case 2: if (K1 <   16) K1++; break;
1058*f6dc9357SAndroid Build Coastguard Worker           case 3: if (K2 >= -16) K2--; break;
1059*f6dc9357SAndroid Build Coastguard Worker           case 4: if (K2 <   16) K2++; break;
1060*f6dc9357SAndroid Build Coastguard Worker           case 5: if (K3 >= -16) K3--; break;
1061*f6dc9357SAndroid Build Coastguard Worker           case 6: if (K3 <   16) K3++; break;
1062*f6dc9357SAndroid Build Coastguard Worker         }
1063*f6dc9357SAndroid Build Coastguard Worker       }
1064*f6dc9357SAndroid Build Coastguard Worker     }
1065*f6dc9357SAndroid Build Coastguard Worker   }
1066*f6dc9357SAndroid Build Coastguard Worker }
1067*f6dc9357SAndroid Build Coastguard Worker 
1068*f6dc9357SAndroid Build Coastguard Worker /*
1069*f6dc9357SAndroid Build Coastguard Worker static UInt32 UpCaseDecode(Byte *data, UInt32 dataSize)
1070*f6dc9357SAndroid Build Coastguard Worker {
1071*f6dc9357SAndroid Build Coastguard Worker   UInt32 srcPos = 0, destPos = dataSize;
1072*f6dc9357SAndroid Build Coastguard Worker   while (srcPos < dataSize)
1073*f6dc9357SAndroid Build Coastguard Worker   {
1074*f6dc9357SAndroid Build Coastguard Worker     Byte curByte = data[srcPos++];
1075*f6dc9357SAndroid Build Coastguard Worker     if (curByte == 2 && (curByte = data[srcPos++]) != 2)
1076*f6dc9357SAndroid Build Coastguard Worker       curByte -= 32;
1077*f6dc9357SAndroid Build Coastguard Worker     data[destPos++] = curByte;
1078*f6dc9357SAndroid Build Coastguard Worker   }
1079*f6dc9357SAndroid Build Coastguard Worker   return destPos - dataSize;
1080*f6dc9357SAndroid Build Coastguard Worker }
1081*f6dc9357SAndroid Build Coastguard Worker */
1082*f6dc9357SAndroid Build Coastguard Worker 
ExecuteStandardFilter(unsigned filterIndex)1083*f6dc9357SAndroid Build Coastguard Worker bool CVm::ExecuteStandardFilter(unsigned filterIndex)
1084*f6dc9357SAndroid Build Coastguard Worker {
1085*f6dc9357SAndroid Build Coastguard Worker   const UInt32 dataSize = R[4];
1086*f6dc9357SAndroid Build Coastguard Worker   if (dataSize >= kGlobalOffset)
1087*f6dc9357SAndroid Build Coastguard Worker     return false;
1088*f6dc9357SAndroid Build Coastguard Worker   EStandardFilter filterType = kStdFilters[filterIndex].Type;
1089*f6dc9357SAndroid Build Coastguard Worker 
1090*f6dc9357SAndroid Build Coastguard Worker   switch (filterType)
1091*f6dc9357SAndroid Build Coastguard Worker   {
1092*f6dc9357SAndroid Build Coastguard Worker     case SF_E8:
1093*f6dc9357SAndroid Build Coastguard Worker     case SF_E8E9:
1094*f6dc9357SAndroid Build Coastguard Worker       E8E9Decode(Mem, dataSize, R[6], (filterType == SF_E8E9));
1095*f6dc9357SAndroid Build Coastguard Worker       break;
1096*f6dc9357SAndroid Build Coastguard Worker 
1097*f6dc9357SAndroid Build Coastguard Worker     case SF_ITANIUM:
1098*f6dc9357SAndroid Build Coastguard Worker       ItaniumDecode(Mem, dataSize, R[6]);
1099*f6dc9357SAndroid Build Coastguard Worker       break;
1100*f6dc9357SAndroid Build Coastguard Worker 
1101*f6dc9357SAndroid Build Coastguard Worker     case SF_DELTA:
1102*f6dc9357SAndroid Build Coastguard Worker     {
1103*f6dc9357SAndroid Build Coastguard Worker       if (dataSize >= kGlobalOffset / 2)
1104*f6dc9357SAndroid Build Coastguard Worker         return false;
1105*f6dc9357SAndroid Build Coastguard Worker       const UInt32 numChannels = R[0];
1106*f6dc9357SAndroid Build Coastguard Worker       if (numChannels == 0 || numChannels > 1024) // unrar 5.5.5
1107*f6dc9357SAndroid Build Coastguard Worker         return false;
1108*f6dc9357SAndroid Build Coastguard Worker       SetBlockPos(dataSize);
1109*f6dc9357SAndroid Build Coastguard Worker       DeltaDecode(Mem, dataSize, numChannels);
1110*f6dc9357SAndroid Build Coastguard Worker       break;
1111*f6dc9357SAndroid Build Coastguard Worker     }
1112*f6dc9357SAndroid Build Coastguard Worker 
1113*f6dc9357SAndroid Build Coastguard Worker     case SF_RGB:
1114*f6dc9357SAndroid Build Coastguard Worker     {
1115*f6dc9357SAndroid Build Coastguard Worker       if (dataSize >= kGlobalOffset / 2 || dataSize < 3) // unrar 5.5.5
1116*f6dc9357SAndroid Build Coastguard Worker         return false;
1117*f6dc9357SAndroid Build Coastguard Worker       const UInt32 width = R[0];
1118*f6dc9357SAndroid Build Coastguard Worker       const UInt32 posR = R[1];
1119*f6dc9357SAndroid Build Coastguard Worker       if (width < 3 || width - 3 > dataSize || posR > 2) // unrar 5.5.5
1120*f6dc9357SAndroid Build Coastguard Worker         return false;
1121*f6dc9357SAndroid Build Coastguard Worker       SetBlockPos(dataSize);
1122*f6dc9357SAndroid Build Coastguard Worker       RgbDecode(Mem, dataSize, width, posR);
1123*f6dc9357SAndroid Build Coastguard Worker       break;
1124*f6dc9357SAndroid Build Coastguard Worker     }
1125*f6dc9357SAndroid Build Coastguard Worker 
1126*f6dc9357SAndroid Build Coastguard Worker     case SF_AUDIO:
1127*f6dc9357SAndroid Build Coastguard Worker     {
1128*f6dc9357SAndroid Build Coastguard Worker       if (dataSize >= kGlobalOffset / 2)
1129*f6dc9357SAndroid Build Coastguard Worker         return false;
1130*f6dc9357SAndroid Build Coastguard Worker       const UInt32 numChannels = R[0];
1131*f6dc9357SAndroid Build Coastguard Worker       if (numChannels == 0 || numChannels > 128) // unrar 5.5.5
1132*f6dc9357SAndroid Build Coastguard Worker         return false;
1133*f6dc9357SAndroid Build Coastguard Worker       SetBlockPos(dataSize);
1134*f6dc9357SAndroid Build Coastguard Worker       AudioDecode(Mem, dataSize, numChannels);
1135*f6dc9357SAndroid Build Coastguard Worker       break;
1136*f6dc9357SAndroid Build Coastguard Worker     }
1137*f6dc9357SAndroid Build Coastguard Worker 
1138*f6dc9357SAndroid Build Coastguard Worker     /*
1139*f6dc9357SAndroid Build Coastguard Worker     case SF_UPCASE:
1140*f6dc9357SAndroid Build Coastguard Worker       if (dataSize >= kGlobalOffset / 2)
1141*f6dc9357SAndroid Build Coastguard Worker         return false;
1142*f6dc9357SAndroid Build Coastguard Worker       UInt32 destSize = UpCaseDecode(Mem, dataSize);
1143*f6dc9357SAndroid Build Coastguard Worker       SetBlockSize(destSize);
1144*f6dc9357SAndroid Build Coastguard Worker       SetBlockPos(dataSize);
1145*f6dc9357SAndroid Build Coastguard Worker       break;
1146*f6dc9357SAndroid Build Coastguard Worker     */
1147*f6dc9357SAndroid Build Coastguard Worker   }
1148*f6dc9357SAndroid Build Coastguard Worker   return true;
1149*f6dc9357SAndroid Build Coastguard Worker }
1150*f6dc9357SAndroid Build Coastguard Worker 
1151*f6dc9357SAndroid Build Coastguard Worker #endif
1152*f6dc9357SAndroid Build Coastguard Worker 
1153*f6dc9357SAndroid Build Coastguard Worker }}}
1154