summaryrefslogtreecommitdiffstats
path: root/src/libs/7zip/unix/CPP/7zip/Compress/Rar3Vm.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/libs/7zip/unix/CPP/7zip/Compress/Rar3Vm.cpp')
-rw-r--r--src/libs/7zip/unix/CPP/7zip/Compress/Rar3Vm.cpp1091
1 files changed, 0 insertions, 1091 deletions
diff --git a/src/libs/7zip/unix/CPP/7zip/Compress/Rar3Vm.cpp b/src/libs/7zip/unix/CPP/7zip/Compress/Rar3Vm.cpp
deleted file mode 100644
index 74051dd79..000000000
--- a/src/libs/7zip/unix/CPP/7zip/Compress/Rar3Vm.cpp
+++ /dev/null
@@ -1,1091 +0,0 @@
-// Rar3Vm.cpp
-// According to unRAR license, this code may not be used to develop
-// a program that creates RAR archives
-
-/*
-Note:
- Due to performance considerations Rar VM may set Flags C incorrectly
- for some operands (SHL x, 0, ... ).
- Check implementation of concrete VM command
- to see if it sets flags right.
-*/
-
-#include "StdAfx.h"
-
-#include "../../../C/7zCrc.h"
-#include "../../../C/Alloc.h"
-
-#include "Rar3Vm.h"
-
-namespace NCompress {
-namespace NRar3 {
-
-UInt32 CMemBitDecoder::ReadBits(int numBits)
-{
- UInt32 res = 0;
- for (;;)
- {
- Byte b = _bitPos < _bitSize ? _data[_bitPos >> 3] : 0;
- int avail = (int)(8 - (_bitPos & 7));
- if (numBits <= avail)
- {
- _bitPos += numBits;
- return res | (b >> (avail - numBits)) & ((1 << numBits) - 1);
- }
- numBits -= avail;
- res |= (UInt32)(b & ((1 << avail) - 1)) << numBits;
- _bitPos += avail;
- }
-}
-
-UInt32 CMemBitDecoder::ReadBit() { return ReadBits(1); }
-
-namespace NVm {
-
-static const UInt32 kStackRegIndex = kNumRegs - 1;
-
-static const UInt32 FLAG_C = 1;
-static const UInt32 FLAG_Z = 2;
-static const UInt32 FLAG_S = 0x80000000;
-
-static const Byte CF_OP0 = 0;
-static const Byte CF_OP1 = 1;
-static const Byte CF_OP2 = 2;
-static const Byte CF_OPMASK = 3;
-static const Byte CF_BYTEMODE = 4;
-static const Byte CF_JUMP = 8;
-static const Byte CF_PROC = 16;
-static const Byte CF_USEFLAGS = 32;
-static const Byte CF_CHFLAGS = 64;
-
-static Byte kCmdFlags[]=
-{
- /* CMD_MOV */ CF_OP2 | CF_BYTEMODE,
- /* CMD_CMP */ CF_OP2 | CF_BYTEMODE | CF_CHFLAGS,
- /* CMD_ADD */ CF_OP2 | CF_BYTEMODE | CF_CHFLAGS,
- /* CMD_SUB */ CF_OP2 | CF_BYTEMODE | CF_CHFLAGS,
- /* CMD_JZ */ CF_OP1 | CF_JUMP | CF_USEFLAGS,
- /* CMD_JNZ */ CF_OP1 | CF_JUMP | CF_USEFLAGS,
- /* CMD_INC */ CF_OP1 | CF_BYTEMODE | CF_CHFLAGS,
- /* CMD_DEC */ CF_OP1 | CF_BYTEMODE | CF_CHFLAGS,
- /* CMD_JMP */ CF_OP1 | CF_JUMP,
- /* CMD_XOR */ CF_OP2 | CF_BYTEMODE | CF_CHFLAGS,
- /* CMD_AND */ CF_OP2 | CF_BYTEMODE | CF_CHFLAGS,
- /* CMD_OR */ CF_OP2 | CF_BYTEMODE | CF_CHFLAGS,
- /* CMD_TEST */ CF_OP2 | CF_BYTEMODE | CF_CHFLAGS,
- /* CMD_JS */ CF_OP1 | CF_JUMP | CF_USEFLAGS,
- /* CMD_JNS */ CF_OP1 | CF_JUMP | CF_USEFLAGS,
- /* CMD_JB */ CF_OP1 | CF_JUMP | CF_USEFLAGS,
- /* CMD_JBE */ CF_OP1 | CF_JUMP | CF_USEFLAGS,
- /* CMD_JA */ CF_OP1 | CF_JUMP | CF_USEFLAGS,
- /* CMD_JAE */ CF_OP1 | CF_JUMP | CF_USEFLAGS,
- /* CMD_PUSH */ CF_OP1,
- /* CMD_POP */ CF_OP1,
- /* CMD_CALL */ CF_OP1 | CF_PROC,
- /* CMD_RET */ CF_OP0 | CF_PROC,
- /* CMD_NOT */ CF_OP1 | CF_BYTEMODE,
- /* CMD_SHL */ CF_OP2 | CF_BYTEMODE | CF_CHFLAGS,
- /* CMD_SHR */ CF_OP2 | CF_BYTEMODE | CF_CHFLAGS,
- /* CMD_SAR */ CF_OP2 | CF_BYTEMODE | CF_CHFLAGS,
- /* CMD_NEG */ CF_OP1 | CF_BYTEMODE | CF_CHFLAGS,
- /* CMD_PUSHA */ CF_OP0,
- /* CMD_POPA */ CF_OP0,
- /* CMD_PUSHF */ CF_OP0 | CF_USEFLAGS,
- /* CMD_POPF */ CF_OP0 | CF_CHFLAGS,
- /* CMD_MOVZX */ CF_OP2,
- /* CMD_MOVSX */ CF_OP2,
- /* CMD_XCHG */ CF_OP2 | CF_BYTEMODE,
- /* CMD_MUL */ CF_OP2 | CF_BYTEMODE,
- /* CMD_DIV */ CF_OP2 | CF_BYTEMODE,
- /* CMD_ADC */ CF_OP2 | CF_BYTEMODE | CF_USEFLAGS | CF_CHFLAGS ,
- /* CMD_SBB */ CF_OP2 | CF_BYTEMODE | CF_USEFLAGS | CF_CHFLAGS ,
- /* CMD_PRINT */ CF_OP0
-};
-
-CVm::CVm(): Mem(NULL) {}
-
-bool CVm::Create()
-{
- if (Mem == NULL)
- Mem = (Byte *)::MyAlloc(kSpaceSize + 4);
- return (Mem != NULL);
-}
-
-CVm::~CVm()
-{
- ::MyFree(Mem);
-}
-
-// CVm::Execute can change CProgram object: it clears progarm if VM returns error.
-
-bool CVm::Execute(CProgram *prg, const CProgramInitState *initState,
- CBlockRef &outBlockRef, CRecordVector<Byte> &outGlobalData)
-{
- memcpy(R, initState->InitR, sizeof(initState->InitR));
- R[kStackRegIndex] = kSpaceSize;
- R[kNumRegs] = 0;
- Flags = 0;
-
- UInt32 globalSize = MyMin((UInt32)initState->GlobalData.Size(), kGlobalSize);
- if (globalSize != 0)
- memcpy(Mem + kGlobalOffset, &initState->GlobalData[0], globalSize);
- UInt32 staticSize = MyMin((UInt32)prg->StaticData.Size(), kGlobalSize - globalSize);
- if (staticSize != 0)
- memcpy(Mem + kGlobalOffset + globalSize, &prg->StaticData[0], staticSize);
-
- bool res = true;
- #ifdef RARVM_STANDARD_FILTERS
- if (prg->StandardFilterIndex >= 0)
- ExecuteStandardFilter(prg->StandardFilterIndex);
- else
- #endif
- {
- res = ExecuteCode(prg);
- if (!res)
- prg->Commands[0].OpCode = CMD_RET;
- }
- UInt32 newBlockPos = GetFixedGlobalValue32(NGlobalOffset::kBlockPos) & kSpaceMask;
- UInt32 newBlockSize = GetFixedGlobalValue32(NGlobalOffset::kBlockSize) & kSpaceMask;
- if (newBlockPos + newBlockSize >= kSpaceSize)
- newBlockPos = newBlockSize = 0;
- outBlockRef.Offset = newBlockPos;
- outBlockRef.Size = newBlockSize;
-
- outGlobalData.Clear();
- UInt32 dataSize = GetFixedGlobalValue32(NGlobalOffset::kGlobalMemOutSize);
- dataSize = MyMin(dataSize, kGlobalSize - kFixedGlobalSize);
- if (dataSize != 0)
- {
- dataSize += kFixedGlobalSize;
- outGlobalData.Reserve(dataSize);
- for (UInt32 i = 0; i < dataSize; i++)
- outGlobalData.Add(Mem[kGlobalOffset + i]);
- }
- return res;
-}
-
-
-#define SET_IP(IP) \
- if ((IP) >= numCommands) return true; \
- if (--maxOpCount <= 0) return false; \
- cmd = commands + (IP);
-
-#define GET_FLAG_S_B(res) (((res) & 0x80) ? FLAG_S : 0)
-#define SET_IP_OP1 { UInt32 val = GetOperand32(&cmd->Op1); SET_IP(val); }
-#define FLAGS_UPDATE_SZ Flags = res == 0 ? FLAG_Z : res & FLAG_S
-#define FLAGS_UPDATE_SZ_B Flags = (res & 0xFF) == 0 ? FLAG_Z : GET_FLAG_S_B(res)
-
-UInt32 CVm::GetOperand32(const COperand *op) const
-{
- switch(op->Type)
- {
- case OP_TYPE_REG: return R[op->Data];
- case OP_TYPE_REGMEM: return GetValue32(&Mem[(op->Base + R[op->Data]) & kSpaceMask]);
- default: return op->Data;
- }
-}
-
-void CVm::SetOperand32(const COperand *op, UInt32 val)
-{
- switch(op->Type)
- {
- case OP_TYPE_REG: R[op->Data] = val; return;
- case OP_TYPE_REGMEM: SetValue32(&Mem[(op->Base + R[op->Data]) & kSpaceMask], val); return;
- }
-}
-
-Byte CVm::GetOperand8(const COperand *op) const
-{
- switch(op->Type)
- {
- case OP_TYPE_REG: return (Byte)R[op->Data];
- case OP_TYPE_REGMEM: return Mem[(op->Base + R[op->Data]) & kSpaceMask];;
- default: return (Byte)op->Data;
- }
-}
-
-void CVm::SetOperand8(const COperand *op, Byte val)
-{
- switch(op->Type)
- {
- case OP_TYPE_REG: R[op->Data] = (R[op->Data] & 0xFFFFFF00) | val; return;
- case OP_TYPE_REGMEM: Mem[(op->Base + R[op->Data]) & kSpaceMask] = val; return;
- }
-}
-
-UInt32 CVm::GetOperand(bool byteMode, const COperand *op) const
-{
- if (byteMode)
- return GetOperand8(op);
- return GetOperand32(op);
-}
-
-void CVm::SetOperand(bool byteMode, const COperand *op, UInt32 val)
-{
- if (byteMode)
- SetOperand8(op, (Byte)(val & 0xFF));
- else
- SetOperand32(op, val);
-}
-
-bool CVm::ExecuteCode(const CProgram *prg)
-{
- Int32 maxOpCount = 25000000;
- const CCommand *commands = &prg->Commands[0];
- const CCommand *cmd = commands;
- UInt32 numCommands = prg->Commands.Size();
- for (;;)
- {
- switch(cmd->OpCode)
- {
- #ifndef RARVM_NO_VM
-
- case CMD_MOV:
- SetOperand32(&cmd->Op1, GetOperand32(&cmd->Op2));
- break;
- case CMD_MOVB:
- SetOperand8(&cmd->Op1, GetOperand8(&cmd->Op2));
- break;
- case CMD_CMP:
- {
- UInt32 v1 = GetOperand32(&cmd->Op1);
- UInt32 res = v1 - GetOperand32(&cmd->Op2);
- Flags = res == 0 ? FLAG_Z : (res > v1) | (res & FLAG_S);
- }
- break;
- case CMD_CMPB:
- {
- Byte v1 = GetOperand8(&cmd->Op1);
- Byte res = v1 - GetOperand8(&cmd->Op2);
- res &= 0xFF;
- Flags = res == 0 ? FLAG_Z : (res > v1) | GET_FLAG_S_B(res);
- }
- break;
- case CMD_ADD:
- {
- UInt32 v1 = GetOperand32(&cmd->Op1);
- UInt32 res = v1 + GetOperand32(&cmd->Op2);
- SetOperand32(&cmd->Op1, res);
- Flags = (res < v1) | (res == 0 ? FLAG_Z : (res & FLAG_S));
- }
- break;
- case CMD_ADDB:
- {
- Byte v1 = GetOperand8(&cmd->Op1);
- Byte res = v1 + GetOperand8(&cmd->Op2);
- res &= 0xFF;
- SetOperand8(&cmd->Op1, (Byte)res);
- Flags = (res < v1) | (res == 0 ? FLAG_Z : GET_FLAG_S_B(res));
- }
- break;
- case CMD_ADC:
- {
- UInt32 v1 = GetOperand(cmd->ByteMode, &cmd->Op1);
- UInt32 FC = (Flags & FLAG_C);
- UInt32 res = v1 + GetOperand(cmd->ByteMode, &cmd->Op2) + FC;
- if (cmd->ByteMode)
- res &= 0xFF;
- SetOperand(cmd->ByteMode, &cmd->Op1, res);
- Flags = (res < v1 || res == v1 && FC) | (res == 0 ? FLAG_Z : (res & FLAG_S));
- }
- break;
- case CMD_SUB:
- {
- UInt32 v1 = GetOperand32(&cmd->Op1);
- UInt32 res = v1 - GetOperand32(&cmd->Op2);
- SetOperand32(&cmd->Op1, res);
- Flags = res == 0 ? FLAG_Z : (res > v1) | (res & FLAG_S);
- }
- break;
- case CMD_SUBB:
- {
- UInt32 v1 = GetOperand8(&cmd->Op1);
- UInt32 res = v1 - GetOperand8(&cmd->Op2);
- SetOperand8(&cmd->Op1, (Byte)res);
- Flags = res == 0 ? FLAG_Z : (res > v1) | (res & FLAG_S);
- }
- break;
- case CMD_SBB:
- {
- UInt32 v1 = GetOperand(cmd->ByteMode, &cmd->Op1);
- UInt32 FC = (Flags & FLAG_C);
- UInt32 res = v1 - GetOperand(cmd->ByteMode, &cmd->Op2) - FC;
- // Flags = res == 0 ? FLAG_Z : (res > v1 || res == v1 && FC) | (res & FLAG_S);
- if (cmd->ByteMode)
- res &= 0xFF;
- SetOperand(cmd->ByteMode, &cmd->Op1, res);
- Flags = (res > v1 || res == v1 && FC) | (res == 0 ? FLAG_Z : (res & FLAG_S));
- }
- break;
- case CMD_INC:
- {
- UInt32 res = GetOperand32(&cmd->Op1) + 1;
- SetOperand32(&cmd->Op1, res);
- FLAGS_UPDATE_SZ;
- }
- break;
- case CMD_INCB:
- {
- Byte res = GetOperand8(&cmd->Op1) + 1;
- SetOperand8(&cmd->Op1, res);;
- FLAGS_UPDATE_SZ_B;
- }
- break;
- case CMD_DEC:
- {
- UInt32 res = GetOperand32(&cmd->Op1) - 1;
- SetOperand32(&cmd->Op1, res);
- FLAGS_UPDATE_SZ;
- }
- break;
- case CMD_DECB:
- {
- Byte res = GetOperand8(&cmd->Op1) - 1;
- SetOperand8(&cmd->Op1, res);;
- FLAGS_UPDATE_SZ_B;
- }
- break;
- case CMD_XOR:
- {
- UInt32 res = GetOperand32(&cmd->Op1) ^ GetOperand32(&cmd->Op2);
- SetOperand32(&cmd->Op1, res);
- FLAGS_UPDATE_SZ;
- }
- break;
- case CMD_XORB:
- {
- Byte res = GetOperand8(&cmd->Op1) ^ GetOperand8(&cmd->Op2);
- SetOperand8(&cmd->Op1, res);
- FLAGS_UPDATE_SZ_B;
- }
- break;
- case CMD_AND:
- {
- UInt32 res = GetOperand32(&cmd->Op1) & GetOperand32(&cmd->Op2);
- SetOperand32(&cmd->Op1, res);
- FLAGS_UPDATE_SZ;
- }
- break;
- case CMD_ANDB:
- {
- Byte res = GetOperand8(&cmd->Op1) & GetOperand8(&cmd->Op2);
- SetOperand8(&cmd->Op1, res);
- FLAGS_UPDATE_SZ_B;
- }
- break;
- case CMD_OR:
- {
- UInt32 res = GetOperand32(&cmd->Op1) | GetOperand32(&cmd->Op2);
- SetOperand32(&cmd->Op1, res);
- FLAGS_UPDATE_SZ;
- }
- break;
- case CMD_ORB:
- {
- Byte res = GetOperand8(&cmd->Op1) | GetOperand8(&cmd->Op2);
- SetOperand8(&cmd->Op1, res);
- FLAGS_UPDATE_SZ_B;
- }
- break;
- case CMD_TEST:
- {
- UInt32 res = GetOperand32(&cmd->Op1) & GetOperand32(&cmd->Op2);
- FLAGS_UPDATE_SZ;
- }
- break;
- case CMD_TESTB:
- {
- Byte res = GetOperand8(&cmd->Op1) & GetOperand8(&cmd->Op2);
- FLAGS_UPDATE_SZ_B;
- }
- break;
- case CMD_NOT:
- SetOperand(cmd->ByteMode, &cmd->Op1, ~GetOperand(cmd->ByteMode, &cmd->Op1));
- break;
- case CMD_NEG:
- {
- UInt32 res = 0 - GetOperand32(&cmd->Op1);
- SetOperand32(&cmd->Op1, res);
- Flags = res == 0 ? FLAG_Z : FLAG_C | (res & FLAG_S);
- }
- break;
- case CMD_NEGB:
- {
- Byte res = (Byte)(0 - GetOperand8(&cmd->Op1));
- SetOperand8(&cmd->Op1, res);
- Flags = res == 0 ? FLAG_Z : FLAG_C | GET_FLAG_S_B(res);
- }
- break;
-
- case CMD_SHL:
- {
- UInt32 v1 = GetOperand32(&cmd->Op1);
- int v2 = (int)GetOperand32(&cmd->Op2);
- UInt32 res = v1 << v2;
- SetOperand32(&cmd->Op1, res);
- Flags = (res == 0 ? FLAG_Z : (res & FLAG_S)) | ((v1 << (v2 - 1)) & 0x80000000 ? FLAG_C : 0);
- }
- break;
- case CMD_SHLB:
- {
- Byte v1 = GetOperand8(&cmd->Op1);
- int v2 = (int)GetOperand8(&cmd->Op2);
- Byte res = (Byte)(v1 << v2);
- SetOperand8(&cmd->Op1, res);
- Flags = (res == 0 ? FLAG_Z : GET_FLAG_S_B(res)) | ((v1 << (v2 - 1)) & 0x80 ? FLAG_C : 0);
- }
- break;
- case CMD_SHR:
- {
- UInt32 v1 = GetOperand32(&cmd->Op1);
- int v2 = (int)GetOperand32(&cmd->Op2);
- UInt32 res = v1 >> v2;
- SetOperand32(&cmd->Op1, res);
- Flags = (res == 0 ? FLAG_Z : (res & FLAG_S)) | ((v1 >> (v2 - 1)) & FLAG_C);
- }
- break;
- case CMD_SHRB:
- {
- Byte v1 = GetOperand8(&cmd->Op1);
- int v2 = (int)GetOperand8(&cmd->Op2);
- Byte res = (Byte)(v1 >> v2);
- SetOperand8(&cmd->Op1, res);
- Flags = (res == 0 ? FLAG_Z : GET_FLAG_S_B(res)) | ((v1 >> (v2 - 1)) & FLAG_C);
- }
- break;
- case CMD_SAR:
- {
- UInt32 v1 = GetOperand32(&cmd->Op1);
- int v2 = (int)GetOperand32(&cmd->Op2);
- UInt32 res = UInt32(((Int32)v1) >> v2);
- SetOperand32(&cmd->Op1, res);
- Flags= (res == 0 ? FLAG_Z : (res & FLAG_S)) | ((v1 >> (v2 - 1)) & FLAG_C);
- }
- break;
- case CMD_SARB:
- {
- Byte v1 = GetOperand8(&cmd->Op1);
- int v2 = (int)GetOperand8(&cmd->Op2);
- Byte res = (Byte)(((signed char)v1) >> v2);
- SetOperand8(&cmd->Op1, res);
- Flags= (res == 0 ? FLAG_Z : GET_FLAG_S_B(res)) | ((v1 >> (v2 - 1)) & FLAG_C);
- }
- break;
-
- case CMD_JMP:
- SET_IP_OP1;
- continue;
- case CMD_JZ:
- if ((Flags & FLAG_Z) != 0)
- {
- SET_IP_OP1;
- continue;
- }
- break;
- case CMD_JNZ:
- if ((Flags & FLAG_Z) == 0)
- {
- SET_IP_OP1;
- continue;
- }
- break;
- case CMD_JS:
- if ((Flags & FLAG_S) != 0)
- {
- SET_IP_OP1;
- continue;
- }
- break;
- case CMD_JNS:
- if ((Flags & FLAG_S) == 0)
- {
- SET_IP_OP1;
- continue;
- }
- break;
- case CMD_JB:
- if ((Flags & FLAG_C) != 0)
- {
- SET_IP_OP1;
- continue;
- }
- break;
- case CMD_JBE:
- if ((Flags & (FLAG_C | FLAG_Z)) != 0)
- {
- SET_IP_OP1;
- continue;
- }
- break;
- case CMD_JA:
- if ((Flags & (FLAG_C | FLAG_Z)) == 0)
- {
- SET_IP_OP1;
- continue;
- }
- break;
- case CMD_JAE:
- if ((Flags & FLAG_C) == 0)
- {
- SET_IP_OP1;
- continue;
- }
- break;
-
- case CMD_PUSH:
- R[kStackRegIndex] -= 4;
- SetValue32(&Mem[R[kStackRegIndex] & kSpaceMask], GetOperand32(&cmd->Op1));
- break;
- case CMD_POP:
- SetOperand32(&cmd->Op1, GetValue32(&Mem[R[kStackRegIndex] & kSpaceMask]));
- R[kStackRegIndex] += 4;
- break;
- case CMD_CALL:
- R[kStackRegIndex] -= 4;
- SetValue32(&Mem[R[kStackRegIndex] & kSpaceMask], (UInt32)(cmd - commands + 1));
- SET_IP_OP1;
- continue;
-
- case CMD_PUSHA:
- {
- for (UInt32 i = 0, SP = R[kStackRegIndex] - 4; i < kNumRegs; i++, SP -= 4)
- SetValue32(&Mem[SP & kSpaceMask], R[i]);
- R[kStackRegIndex] -= kNumRegs * 4;
- }
- break;
- case CMD_POPA:
- {
- for (UInt32 i = 0, SP = R[kStackRegIndex]; i < kNumRegs; i++, SP += 4)
- R[kStackRegIndex - i] = GetValue32(&Mem[SP & kSpaceMask]);
- }
- break;
- case CMD_PUSHF:
- R[kStackRegIndex] -= 4;
- SetValue32(&Mem[R[kStackRegIndex]&kSpaceMask], Flags);
- break;
- case CMD_POPF:
- Flags = GetValue32(&Mem[R[kStackRegIndex] & kSpaceMask]);
- R[kStackRegIndex] += 4;
- break;
-
- case CMD_MOVZX:
- SetOperand32(&cmd->Op1, GetOperand8(&cmd->Op2));
- break;
- case CMD_MOVSX:
- SetOperand32(&cmd->Op1, (UInt32)(Int32)(signed char)GetOperand8(&cmd->Op2));
- break;
- case CMD_XCHG:
- {
- UInt32 v1 = GetOperand(cmd->ByteMode, &cmd->Op1);
- SetOperand(cmd->ByteMode, &cmd->Op1, GetOperand(cmd->ByteMode, &cmd->Op2));
- SetOperand(cmd->ByteMode, &cmd->Op2, v1);
- }
- break;
- case CMD_MUL:
- {
- UInt32 res = GetOperand32(&cmd->Op1) * GetOperand32(&cmd->Op2);
- SetOperand32(&cmd->Op1, res);
- }
- break;
- case CMD_MULB:
- {
- Byte res = GetOperand8(&cmd->Op1) * GetOperand8(&cmd->Op2);
- SetOperand8(&cmd->Op1, res);
- }
- break;
- case CMD_DIV:
- {
- UInt32 divider = GetOperand(cmd->ByteMode, &cmd->Op2);
- if (divider != 0)
- {
- UInt32 res = GetOperand(cmd->ByteMode, &cmd->Op1) / divider;
- SetOperand(cmd->ByteMode, &cmd->Op1, res);
- }
- }
- break;
-
- #endif
-
- case CMD_RET:
- {
- if (R[kStackRegIndex] >= kSpaceSize)
- return true;
- UInt32 ip = GetValue32(&Mem[R[kStackRegIndex] & kSpaceMask]);
- SET_IP(ip);
- R[kStackRegIndex] += 4;
- continue;
- }
- case CMD_PRINT:
- break;
- }
- cmd++;
- --maxOpCount;
- }
-}
-
-
-//////////////////////////////////////////////////////
-// Read program
-
-UInt32 ReadEncodedUInt32(CMemBitDecoder &inp)
-{
- switch(inp.ReadBits(2))
- {
- case 0:
- return inp.ReadBits(4);
- case 1:
- {
- UInt32 v = inp.ReadBits(4);
- if (v == 0)
- return 0xFFFFFF00 | inp.ReadBits(8);
- else
- return (v << 4) | inp.ReadBits(4);
- }
- case 2:
- return inp.ReadBits(16);
- default:
- return inp.ReadBits(32);
- }
-}
-
-void CVm::DecodeArg(CMemBitDecoder &inp, COperand &op, bool byteMode)
-{
- if (inp.ReadBit())
- {
- op.Type = OP_TYPE_REG;
- op.Data = inp.ReadBits(kNumRegBits);
- }
- else if (inp.ReadBit() == 0)
- {
- op.Type = OP_TYPE_INT;
- if (byteMode)
- op.Data = inp.ReadBits(8);
- else
- op.Data = ReadEncodedUInt32(inp);
- }
- else
- {
- op.Type = OP_TYPE_REGMEM;
- if (inp.ReadBit() == 0)
- {
- op.Data = inp.ReadBits(kNumRegBits);
- op.Base = 0;
- }
- else
- {
- if (inp.ReadBit() == 0)
- op.Data = inp.ReadBits(kNumRegBits);
- else
- op.Data = kNumRegs;
- op.Base = ReadEncodedUInt32(inp);
- }
- }
-}
-
-void CVm::ReadVmProgram(const Byte *code, UInt32 codeSize, CProgram *prg)
-{
- CMemBitDecoder inp;
- inp.Init(code, codeSize);
-
- prg->StaticData.Clear();
- if (inp.ReadBit())
- {
- UInt32 dataSize = ReadEncodedUInt32(inp) + 1;
- for (UInt32 i = 0; inp.Avail() && i < dataSize; i++)
- prg->StaticData.Add((Byte)inp.ReadBits(8));
- }
- while (inp.Avail())
- {
- prg->Commands.Add(CCommand());
- CCommand *cmd = &prg->Commands.Back();
- if (inp.ReadBit() == 0)
- cmd->OpCode = (ECommand)inp.ReadBits(3);
- else
- cmd->OpCode = (ECommand)(8 + inp.ReadBits(5));
- if (kCmdFlags[cmd->OpCode] & CF_BYTEMODE)
- cmd->ByteMode = (inp.ReadBit()) ? true : false;
- else
- cmd->ByteMode = 0;
- int opNum = (kCmdFlags[cmd->OpCode] & CF_OPMASK);
- if (opNum > 0)
- {
- DecodeArg(inp, cmd->Op1, cmd->ByteMode);
- if (opNum == 2)
- DecodeArg(inp, cmd->Op2, cmd->ByteMode);
- else
- {
- if (cmd->Op1.Type == OP_TYPE_INT && (kCmdFlags[cmd->OpCode] & (CF_JUMP | CF_PROC)))
- {
- int Distance = cmd->Op1.Data;
- if (Distance >= 256)
- Distance -= 256;
- else
- {
- if (Distance >= 136)
- Distance -= 264;
- else if (Distance >= 16)
- Distance -= 8;
- else if (Distance >= 8)
- Distance -= 16;
- Distance += prg->Commands.Size() - 1;
- }
- cmd->Op1.Data = Distance;
- }
- }
- }
- if (cmd->ByteMode)
- {
- switch (cmd->OpCode)
- {
- case CMD_MOV: cmd->OpCode = CMD_MOVB; break;
- case CMD_CMP: cmd->OpCode = CMD_CMPB; break;
- case CMD_ADD: cmd->OpCode = CMD_ADDB; break;
- case CMD_SUB: cmd->OpCode = CMD_SUBB; break;
- case CMD_INC: cmd->OpCode = CMD_INCB; break;
- case CMD_DEC: cmd->OpCode = CMD_DECB; break;
- case CMD_XOR: cmd->OpCode = CMD_XORB; break;
- case CMD_AND: cmd->OpCode = CMD_ANDB; break;
- case CMD_OR: cmd->OpCode = CMD_ORB; break;
- case CMD_TEST: cmd->OpCode = CMD_TESTB; break;
- case CMD_NEG: cmd->OpCode = CMD_NEGB; break;
- case CMD_SHL: cmd->OpCode = CMD_SHLB; break;
- case CMD_SHR: cmd->OpCode = CMD_SHRB; break;
- case CMD_SAR: cmd->OpCode = CMD_SARB; break;
- case CMD_MUL: cmd->OpCode = CMD_MULB; break;
- }
- }
- }
-}
-
-#ifdef RARVM_STANDARD_FILTERS
-
-enum EStandardFilter
-{
- SF_E8,
- SF_E8E9,
- SF_ITANIUM,
- SF_RGB,
- SF_AUDIO,
- SF_DELTA,
- SF_UPCASE
-};
-
-struct StandardFilterSignature
-{
- UInt32 Length;
- UInt32 CRC;
- EStandardFilter Type;
-}
-kStdFilters[]=
-{
- { 53, 0xad576887, SF_E8 },
- { 57, 0x3cd7e57e, SF_E8E9 },
- { 120, 0x3769893f, SF_ITANIUM },
- { 29, 0x0e06077d, SF_DELTA },
- { 149, 0x1c2c5dc8, SF_RGB },
- { 216, 0xbc85e701, SF_AUDIO },
- { 40, 0x46b9c560, SF_UPCASE }
-};
-
-static int FindStandardFilter(const Byte *code, UInt32 codeSize)
-{
- UInt32 crc = CrcCalc(code, codeSize);
- for (int i = 0; i < sizeof(kStdFilters) / sizeof(kStdFilters[0]); i++)
- {
- StandardFilterSignature &sfs = kStdFilters[i];
- if (sfs.CRC == crc && sfs.Length == codeSize)
- return i;
- }
- return -1;
-}
-
-#endif
-
-void CVm::PrepareProgram(const Byte *code, UInt32 codeSize, CProgram *prg)
-{
- Byte xorSum = 0;
- for (UInt32 i = 1; i < codeSize; i++)
- xorSum ^= code[i];
-
- prg->Commands.Clear();
- #ifdef RARVM_STANDARD_FILTERS
- prg->StandardFilterIndex = -1;
- #endif
-
- if (xorSum == code[0] && codeSize > 0)
- {
- #ifdef RARVM_STANDARD_FILTERS
- prg->StandardFilterIndex = FindStandardFilter(code, codeSize);
- if (prg->StandardFilterIndex >= 0)
- return;
- #endif
- // 1 byte for checksum
- ReadVmProgram(code + 1, codeSize - 1, prg);
- }
- prg->Commands.Add(CCommand());
- CCommand *cmd = &prg->Commands.Back();
- cmd->OpCode = CMD_RET;
-}
-
-void CVm::SetMemory(UInt32 pos, const Byte *data, UInt32 dataSize)
-{
- if (pos < kSpaceSize && data != Mem + pos)
- memmove(Mem + pos, data, MyMin(dataSize, kSpaceSize - pos));
-}
-
-#ifdef RARVM_STANDARD_FILTERS
-
-static void E8E9Decode(Byte *data, UInt32 dataSize, UInt32 fileOffset, bool e9)
-{
- if (dataSize <= 4)
- return;
- dataSize -= 4;
- const UInt32 kFileSize = 0x1000000;
- Byte cmpByte2 = (e9 ? 0xE9 : 0xE8);
- for (UInt32 curPos = 0; curPos < dataSize;)
- {
- Byte curByte = *(data++);
- curPos++;
- if (curByte == 0xE8 || curByte == cmpByte2)
- {
- UInt32 offset = curPos + fileOffset;
- UInt32 addr = (Int32)GetValue32(data);
- if (addr < kFileSize)
- SetValue32(data, addr - offset);
- else if ((Int32)addr < 0 && (Int32)(addr + offset) >= 0)
- SetValue32(data, addr + kFileSize);
- data += 4;
- curPos += 4;
- }
- }
-}
-
-static inline UInt32 ItaniumGetOpType(const Byte *data, int bitPos)
-{
- return (data[(unsigned int)bitPos >> 3] >> (bitPos & 7)) & 0xF;
-}
-
-
-static void ItaniumDecode(Byte *data, UInt32 dataSize, UInt32 fileOffset)
-{
- UInt32 curPos = 0;
- fileOffset >>= 4;
- while (curPos < dataSize - 21)
- {
- int b = (data[0] & 0x1F) - 0x10;
- if (b >= 0)
- {
- static Byte kCmdMasks[16] = {4,4,6,6,0,0,7,7,4,4,0,0,4,4,0,0};
- Byte cmdMask = kCmdMasks[b];
- if (cmdMask != 0)
- for (int i = 0; i < 3; i++)
- if (cmdMask & (1 << i))
- {
- int startPos = i * 41 + 18;
- if (ItaniumGetOpType(data, startPos + 24) == 5)
- {
- const UInt32 kMask = 0xFFFFF;
- Byte *p = data + ((unsigned int)startPos >> 3);
- UInt32 bitField = ((UInt32)p[0]) | ((UInt32)p[1] << 8) | ((UInt32)p[2] << 16);
- int inBit = (startPos & 7);
- UInt32 offset = (bitField >> inBit) & kMask;
- UInt32 andMask = ~(kMask << inBit);
- bitField = ((offset - fileOffset) & kMask) << inBit;
- for (int j = 0; j < 3; j++)
- {
- p[j] &= andMask;
- p[j] |= bitField;
- andMask >>= 8;
- bitField >>= 8;
- }
- }
- }
- }
- data += 16;
- curPos += 16;
- fileOffset++;
- }
-}
-
-static void DeltaDecode(Byte *data, UInt32 dataSize, UInt32 numChannels)
-{
- UInt32 srcPos = 0;
- UInt32 border = dataSize * 2;
- for (UInt32 curChannel = 0; curChannel < numChannels; curChannel++)
- {
- Byte prevByte = 0;
- for (UInt32 destPos = dataSize + curChannel; destPos < border; destPos += numChannels)
- data[destPos] = (prevByte = prevByte - data[srcPos++]);
- }
-}
-
-static void RgbDecode(Byte *srcData, UInt32 dataSize, UInt32 width, UInt32 posR)
-{
- Byte *destData = srcData + dataSize;
- const UInt32 numChannels = 3;
- for (UInt32 curChannel = 0; curChannel < numChannels; curChannel++)
- {
- Byte prevByte = 0;
-
- for (UInt32 i = curChannel; i < dataSize; i+= numChannels)
- {
- unsigned int predicted;
- if (i < width)
- predicted = prevByte;
- else
- {
- unsigned int upperLeftByte = destData[i - width];
- unsigned int upperByte = destData[i - width + 3];
- predicted = prevByte + upperByte - upperLeftByte;
- int pa = abs((int)(predicted - prevByte));
- int pb = abs((int)(predicted - upperByte));
- int pc = abs((int)(predicted - upperLeftByte));
- if (pa <= pb && pa <= pc)
- predicted = prevByte;
- else
- if (pb <= pc)
- predicted = upperByte;
- else
- predicted = upperLeftByte;
- }
- destData[i] = prevByte = (Byte)(predicted - *(srcData++));
- }
- }
- if (dataSize < 3)
- return;
- for (UInt32 i = posR, border = dataSize - 2; i < border; i += 3)
- {
- Byte g = destData[i + 1];
- destData[i] = destData[i] + g;
- destData[i + 2] = destData[i + 2] + g;
- }
-}
-
-static void AudioDecode(Byte *srcData, UInt32 dataSize, UInt32 numChannels)
-{
- Byte *destData = srcData + dataSize;
- for (UInt32 curChannel = 0; curChannel < numChannels; curChannel++)
- {
- UInt32 prevByte = 0, prevDelta = 0, dif[7];
- Int32 D1 = 0, D2 = 0, D3;
- Int32 K1 = 0, K2 = 0, K3 = 0;
- memset(dif, 0, sizeof(dif));
-
- for (UInt32 i = curChannel, byteCount = 0; i < dataSize; i += numChannels, byteCount++)
- {
- D3 = D2;
- D2 = prevDelta - D1;
- D1 = prevDelta;
-
- UInt32 predicted = 8 * prevByte + K1 * D1 + K2 * D2 + K3 * D3;
- predicted = (predicted >> 3) & 0xFF;
-
- UInt32 curByte = *(srcData++);
-
- predicted -= curByte;
- destData[i] = (Byte)predicted;
- prevDelta = (UInt32)(Int32)(signed char)(predicted - prevByte);
- prevByte = predicted;
-
- Int32 D = ((Int32)(signed char)curByte) << 3;
-
- dif[0] += abs(D);
- dif[1] += abs(D - D1);
- dif[2] += abs(D + D1);
- dif[3] += abs(D - D2);
- dif[4] += abs(D + D2);
- dif[5] += abs(D - D3);
- dif[6] += abs(D + D3);
-
- if ((byteCount & 0x1F) == 0)
- {
- UInt32 minDif = dif[0], numMinDif = 0;
- dif[0] = 0;
- for (int j = 1; j < sizeof(dif) / sizeof(dif[0]); j++)
- {
- if (dif[j] < minDif)
- {
- minDif = dif[j];
- numMinDif = j;
- }
- dif[j] = 0;
- }
- switch (numMinDif)
- {
- case 1: if (K1 >= -16) K1--; break;
- case 2: if (K1 < 16) K1++; break;
- case 3: if (K2 >= -16) K2--; break;
- case 4: if (K2 < 16) K2++; break;
- case 5: if (K3 >= -16) K3--; break;
- case 6: if (K3 < 16) K3++; break;
- }
- }
- }
- }
-}
-
-static UInt32 UpCaseDecode(Byte *data, UInt32 dataSize)
-{
- UInt32 srcPos = 0, destPos = dataSize;
- while (srcPos < dataSize)
- {
- Byte curByte = data[srcPos++];
- if (curByte == 2 && (curByte = data[srcPos++]) != 2)
- curByte -= 32;
- data[destPos++] = curByte;
- }
- return destPos - dataSize;
-}
-
-void CVm::ExecuteStandardFilter(int filterIndex)
-{
- UInt32 dataSize = R[4];
- if (dataSize >= kGlobalOffset)
- return;
- EStandardFilter filterType = kStdFilters[filterIndex].Type;
-
- switch (filterType)
- {
- case SF_E8:
- case SF_E8E9:
- E8E9Decode(Mem, dataSize, R[6], (filterType == SF_E8E9));
- break;
- case SF_ITANIUM:
- ItaniumDecode(Mem, dataSize, R[6]);
- break;
- case SF_DELTA:
- if (dataSize >= kGlobalOffset / 2)
- break;
- SetBlockPos(dataSize);
- DeltaDecode(Mem, dataSize, R[0]);
- break;
- case SF_RGB:
- if (dataSize >= kGlobalOffset / 2)
- break;
- {
- UInt32 width = R[0];
- if (width <= 3)
- break;
- SetBlockPos(dataSize);
- RgbDecode(Mem, dataSize, width, R[1]);
- }
- break;
- case SF_AUDIO:
- if (dataSize >= kGlobalOffset / 2)
- break;
- SetBlockPos(dataSize);
- AudioDecode(Mem, dataSize, R[0]);
- break;
- case SF_UPCASE:
- if (dataSize >= kGlobalOffset / 2)
- break;
- UInt32 destSize = UpCaseDecode(Mem, dataSize);
- SetBlockSize(destSize);
- SetBlockPos(dataSize);
- break;
- }
-}
-
-#endif
-
-}}}