--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/realtimenetprots/sipfw/SigComp/SigCompEngine/src/Udvm.cpp Tue Feb 02 01:03:15 2010 +0200
@@ -0,0 +1,2174 @@
+// Copyright (c) 2003-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Name : Udvm.cpp
+// Part of : SigComp / UDVM
+// UDVM core
+// Version : 1.0
+//
+
+
+
+
+// INCLUDE FILES
+#include "Udvm.h"
+#include "UdvmMemory.h"
+#include "sigcompcompartment.h"
+#include "StateMgr.h"
+#include "Crc.h"
+#include "MessageReader.h"
+
+// ============================ MEMBER FUNCTIONS ==============================
+
+void CUdvm::ConstructL(CStateMgr* aStateMgr,
+ TUint aMemSize,
+ TUint aCyclesPerBit)
+ {
+ iExecuteOpcode[EOpcode_DECOMPRESSION_FAILURE] =
+ &CUdvm::ExecuteOpcodeDecompressionFailureL;
+ iExecuteOpcode[EOpcode_AND] = &CUdvm::ExecuteOpcodeAndL;
+ iExecuteOpcode[EOpcode_OR] = &CUdvm::ExecuteOpcodeOrL;
+ iExecuteOpcode[EOpcode_NOT] = &CUdvm::ExecuteOpcodeNotL;
+ iExecuteOpcode[EOpcode_LSHIFT] = &CUdvm::ExecuteOpcodeLShiftL;
+ iExecuteOpcode[EOpcode_RSHIFT] = &CUdvm::ExecuteOpcodeRShiftL;
+ iExecuteOpcode[EOpcode_ADD] = &CUdvm::ExecuteOpcodeAddL;
+ iExecuteOpcode[EOpcode_SUBTRACT] = &CUdvm::ExecuteOpcodeSubtractL;
+ iExecuteOpcode[EOpcode_MULTIPLY] = &CUdvm::ExecuteOpcodeMultiplyL;
+ iExecuteOpcode[EOpcode_DIVIDE] = &CUdvm::ExecuteOpcodeDivideL;
+ iExecuteOpcode[EOpcode_REMAINDER] = &CUdvm::ExecuteOpcodeRemainderL;
+ iExecuteOpcode[EOpcode_SORT_ASCENDING] = &CUdvm::ExecuteOpcodeAscendingL;
+ iExecuteOpcode[EOpcode_SORT_DESCENDING] = &CUdvm::ExecuteOpcodeDescendingL;
+ iExecuteOpcode[EOpcode_SHA_1] = &CUdvm::ExecuteOpcodeSha1L;
+ iExecuteOpcode[EOpcode_LOAD] = &CUdvm::ExecuteOpcodeLoadL;
+ iExecuteOpcode[EOpcode_MULTILOAD] = &CUdvm::ExecuteOpcodeMultiloadL;
+ iExecuteOpcode[EOpcode_PUSH] = &CUdvm::ExecuteOpcodePushL;
+ iExecuteOpcode[EOpcode_POP] = &CUdvm::ExecuteOpcodePopL;
+ iExecuteOpcode[EOpcode_COPY] = &CUdvm::ExecuteOpcodeCopyL;
+ iExecuteOpcode[EOpcode_COPY_LITERAL] = &CUdvm::ExecuteOpcodeCopyLiteralL;
+ iExecuteOpcode[EOpcode_COPY_OFFSET] = &CUdvm::ExecuteOpcodeCopyOffsetL;
+ iExecuteOpcode[EOpcode_MEMSET] = &CUdvm::ExecuteOpcodeMemsetL;
+ iExecuteOpcode[EOpcode_JUMP] = &CUdvm::ExecuteOpcodeJumpL;
+ iExecuteOpcode[EOpcode_COMPARE] = &CUdvm::ExecuteOpcodeCompareL;
+ iExecuteOpcode[EOpcode_CALL] = &CUdvm::ExecuteOpcodeCallL;
+ iExecuteOpcode[EOpcode_RETURN] = &CUdvm::ExecuteOpcodeReturnL;
+ iExecuteOpcode[EOpcode_SWITCH] = &CUdvm::ExecuteOpcodeSwitchL;
+ iExecuteOpcode[EOpcode_CRC] = &CUdvm::ExecuteOpcodeCrcL;
+ iExecuteOpcode[EOpcode_INPUT_BYTES] = &CUdvm::ExecuteOpcodeInputBytesL;
+ iExecuteOpcode[EOpcode_INPUT_BITS] = &CUdvm::ExecuteOpcodeInputBitsL;
+ iExecuteOpcode[EOpcode_INPUT_HUFFMAN] = &CUdvm::ExecuteOpcodeInputHuffmanL;
+ iExecuteOpcode[EOpcode_STATE_ACCESS] = &CUdvm::ExecuteOpcodeStateAccessL;
+ iExecuteOpcode[EOpcode_STATE_CREATE] = &CUdvm::ExecuteOpcodeStateCreateL;
+ iExecuteOpcode[EOpcode_STATE_FREE] = &CUdvm::ExecuteOpcodeStateFreeL;
+ iExecuteOpcode[EOpcode_OUTPUT] = &CUdvm::ExecuteOpcodeOutputL;
+ iExecuteOpcode[EOpcode_END_MESSAGE] = &CUdvm::ExecuteOpcodeEndMessageL;
+
+ iStateMgr = aStateMgr;
+ iUdvmMemory = CUdvmMemory::NewL(aMemSize);
+
+ iCyclesPerBit = aCyclesPerBit;
+
+ iSHA1 = CSHA1::NewL();
+ }
+
+CUdvm::CUdvm() : iReturnedFeedback(NULL, 0),
+ iRequestedFeedback(NULL, 0),
+ iReturnedParameters(NULL, 0)
+ {
+ }
+
+CUdvm* CUdvm::NewLC(CStateMgr* aStateMgr,
+ TUint aMemSize,
+ TUint aCyclesPerBit)
+ {
+ CUdvm* self= new (ELeave) CUdvm();
+ CleanupStack::PushL(self);
+ self->ConstructL(aStateMgr, aMemSize, aCyclesPerBit);
+ return self;
+ }
+
+CUdvm* CUdvm::NewL(CStateMgr* aStateMgr, TUint aMemSize, TUint aCyclesPerBit)
+ {
+ CUdvm* self= NewLC(aStateMgr, aMemSize, aCyclesPerBit);
+ CleanupStack::Pop();
+ return self;
+ }
+
+// Destructor
+CUdvm::~CUdvm()
+ {
+
+ DenyStateOperations();
+
+ delete iUdvmMemory;
+ delete iSHA1;
+ }
+
+
+// ---------------------------------------------------------------------------
+
+/*
+ 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7
+ +---+---+---+---+---+---+---+---+ +---+---+---+---+---+---+---+---+
+ | 1 1 1 1 1 | T | len | | 1 1 1 1 1 | T | 0 |
+ +---+---+---+---+---+---+---+---+ +---+---+---+---+---+---+---+---+
+ | | | |
+ : returned feedback item : : returned feedback item :
+ | | | |
+ +---+---+---+---+---+---+---+---+ +---+---+---+---+---+---+---+---+
+ | | | code_len |
+ : partial state identifier : +---+---+---+---+---+---+---+---+
+ | | | code_len | destination |
+ +---+---+---+---+---+---+---+---+ +---+---+---+---+---+---+---+---+
+ | | | |
+ : remaining SigComp message : : uploaded UDVM bytecode :
+ | | | |
+ +---+---+---+---+---+---+---+---+ +---+---+---+---+---+---+---+---+
+ | |
+ : remaining SigComp message :
+ | |
+ +---+---+---+---+---+---+---+---+
+
+ 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7
+ +---+---+---+---+---+---+---+---+ +---+---+---+---+---+---+---+---+
+ | 0 | returned_feedback_field | | 1 | returned_feedback_length |
+ +---+---+---+---+---+---+---+---+ +---+---+---+---+---+---+---+---+
+ | |
+ : returned_feedback_field :
+ | |
+ +---+---+---+---+---+---+---+---+
+
+ Encoding: Length of partial state identifier
+
+ 01 6 bytes
+ 10 9 bytes
+ 11 12 bytes
+
+ Encoding: Destination address:
+
+ 0000 reserved
+ 0001 2 * 64 = 128
+ 0010 3 * 64 = 196
+ 0011 4 * 64 = 256
+ : :
+ 1111 16 * 64 = 1024
+
+ Note that the encoding 0000 is reserved for future SigComp versions,
+ and causes a decompression failure in Version 0x01.
+*/
+
+void CUdvm::SetReturnedFeedbackL(TBool aT, CMessageReader* aMsgReader)
+ {
+
+ if (aT)
+ {
+ // returned feedback item
+
+ TUint rff;
+ if (aMsgReader->ReadByte(rff) != KErrNone)
+ {
+ User::Leave(CSigComp::EIncompleteMessage);
+ }
+
+ if (rff & KReturnedFeedbackFieldMask)
+ {
+ // long form
+
+ // use decompression memory after udvm memory to store returned
+ // feedback
+ TUint8* udvmMem = iUdvmMemory->MemoryPtr();
+ TUint udvmFreeMemSize = iUdvmMemory->FreeMemorySize();
+ iReturnedFeedback.Set(&udvmMem[udvmFreeMemSize],
+ 0, rff & KReturnedFeedbackLengthMask);
+ if (aMsgReader->ReadBlock(iReturnedFeedback) != KErrNone)
+ {
+ User::Leave(CSigComp::EIncompleteMessage);
+ }
+ }
+ else
+ {
+ // short form
+
+ // use decompression memory after udvm memory to store returned
+ // feedback
+ TUint8* udvmMem = iUdvmMemory->MemoryPtr();
+ TUint udvmFreeMemSize = iUdvmMemory->FreeMemorySize();
+ iReturnedFeedback.Set(&udvmMem[udvmFreeMemSize], 0, 1);
+ iReturnedFeedback.Append(rff);
+ }
+ }
+ else
+ {
+ iReturnedFeedback.Set(NULL, 0, 0);
+ }
+ }
+
+void CUdvm::UploadStateInMessageL(TUint aLen, CMessageReader* aMsgReader)
+ {
+
+ // RFC3320:
+ // The len field encodes the number of transmitted bytes as follows:
+ //
+ // Encoding: Length of partial state identifier
+ // 01 6 bytes
+ // 10 9 bytes
+ // 11 12 bytes
+ TUint id_len = (aLen + 1) * 3;
+
+ TBuf8<12> psi;
+ if (aMsgReader->ReadBlock(psi, id_len) != KErrNone)
+ {
+ User::Leave(CSigComp::EIncompleteMessage);
+ }
+
+ // upload state item
+ UploadStateL(id_len, psi.Ptr());
+ }
+
+void CUdvm::UploadBytecodeInMessageL(CMessageReader* aMsgReader)
+ {
+
+ TUint tmp;
+
+ // get first byte of 16-bit big-endian value
+ if (aMsgReader->ReadByte(tmp) != KErrNone)
+ {
+ User::Leave(CSigComp::EIncompleteMessage);
+ }
+
+ // code length is most significant 12 bits
+ TUint code_len = tmp << 4;
+
+ // get second byte of 16-bit big-endian value
+ if (aMsgReader->ReadByte(tmp) != KErrNone)
+ {
+ User::Leave(CSigComp::EIncompleteMessage);
+ }
+
+ code_len |= tmp >> 4;
+
+ // destination is less significant 4 bits
+ TUint destination = tmp & 0x000f;
+
+ // The destination field is encoded as follows:
+ //
+ // Encoding: Destination address:
+ // 0000 reserved
+ // 0001 2 * 64 = 128
+ // 0010 3 * 64 = 196
+ // 0011 4 * 64 = 256
+ // : :
+ // 1111 16 * 64 = 1024
+ //
+ // Note that the encoding 0000 is reserved for future SigComp versions,
+ // and causes a decompression failure in Version 0x01.
+
+ if (destination == 0)
+ {
+ User::Leave(CSigComp::EDecompressionFailure);
+ }
+
+ // destination decoding - see above
+ destination = (destination + 1) * 64;
+
+ // upload code_len bytes of bytecode at destination
+ UploadCodeL(destination, code_len, aMsgReader);
+ }
+
+// ----------------------------------------------------------------------------
+// CUdvm::DecompressL
+// dispatch message and run bytecode
+// ----------------------------------------------------------------------------
+//
+
+CBufBase* CUdvm::DecompressL(const TDesC8& aMessage, TUint& aBytesConsumed,
+ TBool aStreamBasedProtocol)
+ {
+
+ CMessageReader* msgReader = new (ELeave)CMessageReader(aMessage,
+ aStreamBasedProtocol);
+ CleanupStack::PushL(msgReader);
+
+ if (msgReader->SkipDelimiters() != KErrNone)
+ {
+ User::Leave(CSigComp::EIncompleteMessage);
+ }
+
+ TUint tmp;
+ if (msgReader->ReadByte(tmp) != KErrNone)
+ {
+ User::Leave(CSigComp::EIncompleteMessage);
+ }
+
+ //is sigcomp message?
+ if ((tmp & KSigCompHeaderMask) != KSigCompHeaderMask)
+ {
+ User::Leave(CSigComp::EIncompleteMessage);
+ }
+
+ // get T bit from header
+ TBool t = tmp & KSigCompHeaderTMask;
+ // partial state identifier length
+ TUint len = tmp & KSigCompHeaderLenMask;
+
+ // initialize udvm memory
+ if (aStreamBasedProtocol)
+ {
+ iUdvmMemory->InitMemoryL(iUdvmMemory->MemorySize()/2, iCyclesPerBit);
+ }
+ else
+ {
+ iUdvmMemory->InitMemoryL(aMessage.Length(), iCyclesPerBit);
+ }
+ // T bit set, returned feedback present
+ SetReturnedFeedbackL(t, msgReader);
+
+ if (len)
+ {
+ // partial state identifier
+ UploadStateInMessageL(len, msgReader);
+ }
+ else
+ {
+ // bytecode
+ UploadBytecodeInMessageL(msgReader);
+ }
+
+ // available cycles, as defined in RFC3220 chapter 8.6
+ iAvailableCycles = (8 * aMessage.Length() + 1000) * iCyclesPerBit;
+
+ // prepare output buffer
+ CBufFlat* outputBuffer = CBufFlat::NewL(128);
+ CleanupStack::PushL(outputBuffer);
+ outputBuffer->SetReserveL(128);
+ iOutputBuffer = outputBuffer; // used for parameter passing to Opcodes
+
+ // execute code
+ ExecuteCodeL(msgReader);
+
+ iOutputBuffer = NULL;
+ CleanupStack::Pop(outputBuffer);
+
+ // skip end delimiter
+ if (aStreamBasedProtocol)
+ {
+ msgReader->SkipDelimiters(1);
+ }
+
+ // get message bytes consumed
+ aBytesConsumed = msgReader->Pos();
+
+ outputBuffer->Compress();
+
+ CleanupStack::PopAndDestroy(msgReader);
+
+ return outputBuffer;
+ }
+
+// ----------------------------------------------------------------------------
+// CUdvm::ByteCopyingFragmentL
+//
+// ----------------------------------------------------------------------------
+//
+
+inline TUint CUdvm::ByteCopyingFragmentL(TUint& aAddress,
+ TUint& aLength,
+ TUint aBcl,
+ TUint aBcr) const
+ {
+
+ TUint len;
+
+ if (((aAddress + 1) <= aBcr) && ((aAddress + aLength) > aBcr))
+ {
+ len = aBcr - aAddress;
+ }
+ else
+ {
+ len = aLength;
+ }
+
+ if ((aAddress + len) > iUdvmMemory->FreeMemorySize())
+ {
+ User::Leave(CSigComp::EDecompressionFailure);
+ }
+
+ aLength -= len;
+ aAddress = aBcl;
+
+ return len;
+ }
+
+// ----------------------------------------------------------------------------
+// CUdvm::UploadCodeL
+// upload bytecode, initialize UDVM memory and registers
+// ----------------------------------------------------------------------------
+//
+
+void CUdvm::UploadCodeL(TUint aDest, TUint aLen, CMessageReader* aMsgReader)
+ {
+
+ // init memory
+ iUdvmMemory->WriteMem16L(EMem_partial_state_ID_length, 0x0000);
+ iUdvmMemory->WriteMem16L(EMem_state_length, 0x0000);
+
+ // upload code
+ iUdvmMemory->CheckMemAccessL(aDest & KMaxUdvmMemoryMask, aLen);
+ TPtr8 codePtr(iUdvmMemory->MemoryPtr() +
+ (aDest & KMaxUdvmMemoryMask), aLen);
+ if (aMsgReader->ReadBlock(codePtr) != KErrNone)
+ {
+ User::Leave(CSigComp::EIncompleteMessage);
+ }
+
+ iCodeStart = aDest;
+ }
+
+
+// ----------------------------------------------------------------------------
+// CUdvm::UploadStateL
+// upload state item, initialize UDVM memory and registers
+// ----------------------------------------------------------------------------
+//
+
+void CUdvm::UploadStateL(TUint aStateLen, const TUint8* aState)
+ {
+
+ TStateItem* si = iStateMgr->FindStateItem(TPtrC8(aState, aStateLen));
+
+ if (si == NULL)
+ {
+ User::Leave(CSigComp::EDecompressionFailure);
+ }
+
+ TestStateAccessLenL(si, aStateLen);
+
+ // init memory
+ iUdvmMemory->WriteMem16L(EMem_partial_state_ID_length, aStateLen);
+ iUdvmMemory->WriteMem16L(EMem_state_length, si->iStateLength);
+
+ // upload state value
+ iUdvmMemory->CopyToMemL(si->iStateAddress & KMaxUdvmMemoryMask,
+ si->iStateValue,
+ si->iStateLength);
+
+ iCodeStart = si->iStateInstruction;
+ }
+
+
+// ----------------------------------------------------------------------------
+// CUdvm::TestStateAccessLenL
+// test state access lenght
+// ----------------------------------------------------------------------------
+//
+
+void CUdvm::TestStateAccessLenL(const TStateItem* aStateItem,
+ TUint aAccessLen) const
+ {
+
+ if (aAccessLen < aStateItem->iMinimumAccessLength)
+ {
+ User::Leave(CSigComp::EDecompressionFailure);
+ }
+ }
+
+
+// ----------------------------------------------------------------------------
+// CUdvm::InputMessageBitsL
+// input message bits
+// ----------------------------------------------------------------------------
+//
+
+TUint CUdvm::InputMessageBitsL(TUint aSize, TUint aP, TUint aF)
+ {
+ // aP and aF are flags from input_bit_order UDVM register
+
+ // iLastUsedInputBit is number of used bits from readed byte,
+ // zero if need to read next byte
+
+ //output value
+ TUint val = 0;
+
+ //it may be needed later, depending on aF flag.
+ TUint l = aSize;
+
+ //to store the return value of ReadByte function
+ TInt ret = 0;
+
+ // get aSize bits, aF aP flags indicates from which side bits are taken
+ // (MSB or LSB order)
+ // as described in RFC 3220 chapter 8.2.
+ while (aSize)
+ {
+ if (iLastUsedInputBit == 0)
+ {
+ ret = iInputMessageReader->ReadByte(iLastInputByte);
+
+ if(ret != KErrNone)
+ User::Leave( ret );
+ }
+
+ if (aP)
+ {
+ if (aF)
+ {
+ // put LSB of input byte as MSB of output 16-bit word
+ val >>= 1;
+ val |= ((iLastInputByte & 1) << 15);
+ }
+ else
+ {
+ // put LSB of input byte as LSB of output 16-bit word
+ val <<= 1;
+ val |= (iLastInputByte & 1);
+ }
+
+ iLastInputByte >>= 1;
+ }
+ else
+ {
+ if (aF)
+ {
+ // put MSB of input byte as MSB of output 16-bit word
+ val >>= 1;
+ val |= ((iLastInputByte & 0x80) << 8);
+ }
+ else
+ {
+ // put MSB of input byte as LSB of output 16-bit word
+ val <<= 1;
+ val |= ((iLastInputByte & 0x80) >> 7);
+ }
+
+ iLastInputByte <<= 1;
+ }
+
+ //next bit
+ iLastUsedInputBit++;
+
+ if (iLastUsedInputBit > 7)
+ {
+ iLastUsedInputBit = 0;
+ }
+
+ aSize--;
+ }
+
+ //if MSB we have to move it to the right.
+ if (aF)
+ {
+ val >>= (16 - l);
+ }
+
+ return val;
+ }
+
+
+// ----------------------------------------------------------------------------
+// CUdvm::DecodeLiteralOperandL
+// decode literal bytecode operand
+// ----------------------------------------------------------------------------
+//
+
+TUint CUdvm::DecodeLiteralOperandL(TUint& aAddress) const
+ {
+
+ TUint value = 0;
+ TUint8 tmp = iUdvmMemory->ReadMem8L(aAddress++);
+
+ // Bytecode: Operand value: Range:
+
+ if ((tmp & 0x80) == 0x00)
+ {
+ // 0nnnnnnn N 0 - 127
+ value = tmp & 0x7f;
+ }
+ else if ((tmp & 0xc0) == 0x80)
+ {
+ // 10nnnnnn nnnnnnnn N 0 - 16383
+ value = ((tmp & 0x3f) << 8) + iUdvmMemory->ReadMem8L(aAddress++);
+ }
+ else if ((tmp & 0xff) == 0xc0)
+ {
+ // 11000000 nnnnnnnn nnnnnnnn N 0 - 65535
+ value = (iUdvmMemory->ReadMem8L(aAddress) << 8)+
+ iUdvmMemory->ReadMem8L(aAddress + 1);
+ aAddress += 2;
+ }
+ else
+ {
+ // argument error
+ User::Leave(CSigComp::EDecompressionFailure);
+ }
+
+ return value;
+ }
+
+
+// ----------------------------------------------------------------------------
+// CUdvm::DecodeReferenceOperandL
+// decode reference bytecode operand
+// ----------------------------------------------------------------------------
+//
+
+TUint CUdvm::DecodeReferenceOperandL(TUint& aAddress) const
+ {
+
+ TUint value = 0;
+ TUint8 tmp = iUdvmMemory->ReadMem8L(aAddress++);
+
+ // Bytecode: Operand value: Range:
+
+ if ((tmp & 0x80) == 0x00)
+ {
+ // 0nnnnnnn memory[2 * N] 0 - 65535
+ value = (tmp & 0x7f) * 2;
+ }
+ else if ((tmp & 0xc0) == 0x80)
+ {
+ // 10nnnnnn nnnnnnnn memory[2 * N] 0 - 65535
+ value = (((tmp & 0x3f) << 8) + iUdvmMemory->ReadMem8L(aAddress++)) * 2;
+ }
+ else if ((tmp & 0xff) == 0xc0)
+ {
+ // 11000000 nnnnnnnn nnnnnnnn memory[N] 0 - 65535
+ value = (iUdvmMemory->ReadMem8L(aAddress) << 8)+
+ iUdvmMemory->ReadMem8L(aAddress + 1);
+ aAddress += 2;
+ }
+ else
+ {
+ // argument error
+ User::Leave(CSigComp::EDecompressionFailure);
+ }
+
+ return value;
+ }
+
+
+// ----------------------------------------------------------------------------
+// CUdvm::DecodeMultitypeOperandL
+// decode multitype bytecode operand
+// ----------------------------------------------------------------------------
+//
+
+TUint CUdvm::DecodeMultitypeOperandL(TUint& aAddress) const
+ {
+
+ TUint value = 0;
+ TUint8 tmp = iUdvmMemory->ReadMem8L(aAddress++);
+
+ // Bytecode: Operand value: Range:
+
+ if ((tmp & 0xc0) == 0x00)
+ {
+ // 00nnnnnn N 0 - 63
+ value = tmp & 0x3f;
+ }
+ else if ((tmp & 0xc0) == 0x40)
+ {
+ // 01nnnnnn memory[2 * N] 0 - 65535
+ value = iUdvmMemory->ReadMem16L((tmp & 0x3f) * 2);
+ }
+ else if ((tmp & 0xfe) == 0x86)
+ {
+ // 1000011n 2 ^ (N + 6) 64 , 128
+ value = 1 << ((tmp & 0x01) + 6);
+ }
+ else if ((tmp & 0xf8) == 0x88)
+ {
+ // 10001nnn 2 ^ (N + 8) 256 , ... , 32768
+ value = 1 << ((tmp & 0x07) + 8);
+ }
+ else if ((tmp & 0xe0) == 0xe0)
+ {
+ // 111nnnnn N + 65504 65504 - 65535
+ value = (tmp & 0x1f) + 65504;
+ }
+ else if ((tmp & 0xf0) == 0x90)
+ {
+ // 1001nnnn nnnnnnnn N + 61440 61440 - 65535
+ value = ((tmp & 0x0f) << 8) + iUdvmMemory->ReadMem8L(aAddress++) +
+ 61440;
+ }
+ else if ((tmp & 0xe0) == 0xa0)
+ {
+ // 101nnnnn nnnnnnnn N 0 - 8191
+ value = ((tmp & 0x1f) << 8) + iUdvmMemory->ReadMem8L(aAddress++);
+ }
+ else if ((tmp & 0xe0) == 0xc0)
+ {
+ // 110nnnnn nnnnnnnn memory[N] 0 - 65535
+ value = iUdvmMemory->ReadMem16L(((tmp & 0x1f) << 8)+
+ iUdvmMemory->ReadMem8L(aAddress++));
+ }
+ else if ((tmp & 0xff) == 0x80)
+ {
+ // 10000000 nnnnnnnn nnnnnnnn N 0 - 65535
+ value = (iUdvmMemory->ReadMem8L(aAddress) << 8)+
+ iUdvmMemory->ReadMem8L(aAddress + 1);
+ aAddress += 2;
+ }
+ else if ((tmp & 0xff) == 0x81)
+ {
+ // 10000001 nnnnnnnn nnnnnnnn memory[N] 0 - 65535
+ value = iUdvmMemory->ReadMem16L((iUdvmMemory->ReadMem8L(aAddress) << 8)
+ + iUdvmMemory->ReadMem8L(aAddress + 1));
+ aAddress += 2;
+ }
+ else
+ {
+ // argument error
+ User::Leave(CSigComp::EDecompressionFailure);
+ }
+
+ return value;
+ }
+
+// ----------------------------------------------------------------------------
+// CUdvm::DecodeAddressOperandL
+// decode address bytecode operand
+// ----------------------------------------------------------------------------
+//
+
+TUint CUdvm::DecodeAddressOperandL(TUint aPc, TUint& aAddress) const
+ {
+ return (DecodeMultitypeOperandL(aAddress) + aPc) & KMaxUdvmMemoryMask;
+ }
+
+
+// ----------------------------------------------------------------------------
+
+TBool CUdvm::ExecuteOpcodeDecompressionFailureL(TUint& /*aPc2*/)
+ {
+ iCycles += 1;
+ User::Leave(CSigComp::EDecompressionFailure);
+ return EFalse; //not covered, never called because of above Leave().
+ }
+
+TBool CUdvm::ExecuteOpcodeAndL(TUint& aPc2)
+ {
+ // AND ($operand_1, %operand_2)
+
+ TUint op1 = DecodeReferenceOperandL(aPc2);
+ TUint op2 = DecodeMultitypeOperandL(aPc2);
+
+ iUdvmMemory->WriteMem16L(op1, iUdvmMemory->ReadMem16L(op1) & op2);
+ iCycles += 1;
+ return EFalse;
+ }
+
+TBool CUdvm::ExecuteOpcodeOrL(TUint& aPc2)
+ {
+ // OR ($operand_1, %operand_2)
+
+ TUint op1 = DecodeReferenceOperandL(aPc2);
+ TUint op2 = DecodeMultitypeOperandL(aPc2);
+
+ iUdvmMemory->WriteMem16L(op1, iUdvmMemory->ReadMem16L(op1) | op2);
+ iCycles += 1;
+ return EFalse;
+ }
+
+TBool CUdvm::ExecuteOpcodeNotL(TUint& aPc2)
+ {
+ // NOT ($operand_1)
+
+ TUint op1 = DecodeReferenceOperandL(aPc2);
+
+ iUdvmMemory->WriteMem16L(op1, iUdvmMemory->ReadMem16L(op1) ^
+ KMax16BitValueMask);
+ iCycles += 1;
+ return EFalse;
+ }
+
+TBool CUdvm::ExecuteOpcodeLShiftL(TUint& aPc2)
+ {
+ // LSHIFT ($operand_1, %operand_2)
+
+ TUint op1 = DecodeReferenceOperandL(aPc2);
+ TUint op2 = DecodeMultitypeOperandL(aPc2);
+
+ iUdvmMemory->WriteMem16L(op1, (iUdvmMemory->ReadMem16L(op1) << op2) &
+ KMax16BitValueMask);
+ iCycles += 1;
+ return EFalse;
+ }
+
+TBool CUdvm::ExecuteOpcodeRShiftL(TUint& aPc2)
+ {
+ // RSHIFT ($operand_1, %operand_2)
+
+ TUint op1 = DecodeReferenceOperandL(aPc2);
+ TUint op2 = DecodeMultitypeOperandL(aPc2);
+
+ iUdvmMemory->WriteMem16L(op1, (iUdvmMemory->ReadMem16L(op1) >> op2) &
+ KMax16BitValueMask);
+ iCycles += 1;
+ return EFalse;
+ }
+
+TBool CUdvm::ExecuteOpcodeAddL(TUint& aPc2)
+ {
+ // ADD ($operand_1, %operand_2)
+
+ TUint op1 = DecodeReferenceOperandL(aPc2);
+ TUint op2 = DecodeMultitypeOperandL(aPc2);
+
+ iUdvmMemory->WriteMem16L(op1, (iUdvmMemory->ReadMem16L(op1) + op2) &
+ KMax16BitValueMask);
+ iCycles += 1;
+ return EFalse;
+ }
+
+TBool CUdvm::ExecuteOpcodeSubtractL(TUint& aPc2)
+ {
+ // SUBTRACT ($operand_1, %operand_2)
+
+ TUint op1 = DecodeReferenceOperandL(aPc2);
+ TUint op2 = DecodeMultitypeOperandL(aPc2);
+
+ iUdvmMemory->WriteMem16L(op1, (iUdvmMemory->ReadMem16L(op1) - op2) &
+ KMax16BitValueMask);
+ iCycles += 1;
+ return EFalse;
+ }
+
+TBool CUdvm::ExecuteOpcodeMultiplyL(TUint& aPc2)
+ {
+ // MULTIPLY ($operand_1, %operand_2)
+
+ TUint op1 = DecodeReferenceOperandL(aPc2);
+ TUint op2 = DecodeMultitypeOperandL(aPc2);
+
+ iUdvmMemory->WriteMem16L(op1, (iUdvmMemory->ReadMem16L(op1) * op2) &
+ KMax16BitValueMask);
+ iCycles += 1;
+ return EFalse;
+ }
+
+TBool CUdvm::ExecuteOpcodeDivideL(TUint& aPc2)
+ {
+ // DIVIDE ($operand_1, %operand_2)
+
+ TUint op1 = DecodeReferenceOperandL(aPc2);
+ TUint op2 = DecodeMultitypeOperandL(aPc2);
+
+ if (op2 == 0)
+ {
+ User::Leave(CSigComp::EDecompressionFailure);
+ }
+
+ iUdvmMemory->WriteMem16L(op1, (iUdvmMemory->ReadMem16L(op1) / op2) &
+ KMax16BitValueMask);
+ iCycles += 1;
+ return EFalse;
+ }
+
+TBool CUdvm::ExecuteOpcodeRemainderL(TUint& aPc2)
+ {
+ // REMAINDER ($operand_1, %operand_2)
+
+ TUint op1 = DecodeReferenceOperandL(aPc2);
+ TUint op2 = DecodeMultitypeOperandL(aPc2);
+
+ if (op2 == 0)
+ {
+ User::Leave(CSigComp::EDecompressionFailure);
+ }
+
+ iUdvmMemory->WriteMem16L(op1, (iUdvmMemory->ReadMem16L(op1) % op2) &
+ KMax16BitValueMask);
+ iCycles += 1;
+ return EFalse;
+ }
+
+TBool CUdvm::ExecuteOpcodeAscendingL(TUint& aPc2)
+ {
+ // SORT-ASCENDING (%start, %n, %k)
+
+ TUint start = DecodeMultitypeOperandL(aPc2);
+ TUint n = DecodeMultitypeOperandL(aPc2);
+ TUint k = DecodeMultitypeOperandL(aPc2);
+
+ TBool sort;
+ TUint16 a;
+ TUint16 b;
+
+ do
+ {
+ sort = EFalse;
+
+ for (TUint i = 0; i < (k - 1); i++)
+ {
+ a = iUdvmMemory->ReadMem16L(start + 2 * i);
+ b = iUdvmMemory->ReadMem16L(start + 2 * (i + 1));
+
+ if (a > b)
+ {
+ iUdvmMemory->WriteMem16L(start + i * 2, b);
+ iUdvmMemory->WriteMem16L(start + (i + 1) * 2, a);
+ for (TUint j = 1; j < n; j++)
+ {
+ a = iUdvmMemory->ReadMem16L(start + j * k * 2 + i * 2);
+ iUdvmMemory->WriteMem16L(start + j * k * 2 + i * 2,
+ iUdvmMemory->ReadMem16L(start + j * k * 2 + (i + 1) * 2));
+ iUdvmMemory->WriteMem16L(start + j * k * 2 + (i + 1) * 2,
+ a);
+ }
+ sort = ETrue;
+ }
+ }
+ }
+ while (sort);
+
+ //cost = 1 + k * (ceiling(log2(k)) + n)
+ TInt i;
+ for (i = 15; i >= 0 && !(k & (1 << i));)
+ {
+ i--;
+ }
+
+ if (k & (~(1 << i)))
+ {
+ i++;
+ }
+
+ iCycles += (1 + (k * (i + n)));
+ return EFalse;
+ }
+
+TBool CUdvm::ExecuteOpcodeDescendingL(TUint& aPc2)
+ {
+ // SORT-DESCENDING (%start, %n, %k)
+
+ TUint start = DecodeMultitypeOperandL(aPc2);
+ TUint n = DecodeMultitypeOperandL(aPc2);
+ TUint k = DecodeMultitypeOperandL(aPc2);
+
+ TBool sort;
+ TUint16 a;
+ TUint16 b;
+
+ do
+ {
+ sort = EFalse;
+
+ for (TUint i = 0; i < (k - 1); i++)
+ {
+ a = iUdvmMemory->ReadMem16L(start + i * 2);
+ b = iUdvmMemory->ReadMem16L(start + (i + 1) * 2);
+
+ if (a < b)
+ {
+ iUdvmMemory->WriteMem16L(start + i * 2, b);
+ iUdvmMemory->WriteMem16L(start + (i + 1) * 2, a);
+ for (TUint j = 1; j < n; j++)
+ {
+ a = iUdvmMemory->ReadMem16L(start + j * k * 2 + i * 2);
+ iUdvmMemory->WriteMem16L(start + j * k * 2 + i * 2,
+ iUdvmMemory->ReadMem16L(start + j * k * 2 + (i + 1) * 2));
+ iUdvmMemory->WriteMem16L(start + j * k * 2 + (i + 1) * 2,
+ a);
+ }
+ sort = ETrue;
+ }
+ }
+ }
+ while (sort);
+
+ // cost = 1 + k * (ceiling(log2(k)) + n)
+ TInt i;
+ for (i = 15; i >= 0 && !(k & (1 << i));)
+ {
+ i--;
+ }
+
+ if (k & (~(1 << i)))
+ {
+ i++;
+ }
+ iCycles += 1 + k * (i + n);
+ return EFalse;
+ }
+
+TBool CUdvm::ExecuteOpcodeSha1L(TUint& aPc2)
+ {
+ // SHA-1 (%position, %length, %destination)
+ // NOTE: byte copying
+
+ TUint position = DecodeMultitypeOperandL(aPc2);
+ TUint length = DecodeMultitypeOperandL(aPc2);
+ TUint destination = DecodeMultitypeOperandL(aPc2);
+
+ iCycles += 1 + length;
+
+ TUint bcl = iUdvmMemory->ReadMem16L(EReg_byte_copy_left);
+ TUint bcr = iUdvmMemory->ReadMem16L(EReg_byte_copy_right);
+
+ iSHA1->Reset();
+
+ while (length)
+ {
+ TUint nextpos = position;
+ TUint len = ByteCopyingFragmentL(nextpos,
+ length,
+ bcl,
+ bcr);
+
+ if (len)
+ {
+ TPtrC8 data = TPtrC8(&iUdvmMemory->MemoryPtr()[position], len);
+ iSHA1->Hash(data);
+ }
+
+ position = nextpos;
+ }
+
+ TPtrC8 hash = iSHA1->Hash(KNullDesC8);
+ const TUint8* SHA1result = hash.Ptr();
+
+ TUint respos = 0;
+ length = 20;
+
+ while (length)
+ {
+ TUint newdest = destination;
+ TUint len = ByteCopyingFragmentL(newdest,
+ length,
+ bcl,
+ bcr);
+
+ for (TUint i = 0; i < len; i++)
+ {
+ iUdvmMemory->MemoryPtr()[destination + i] = SHA1result[respos + i];
+ }
+
+ destination = newdest;
+ respos += len;
+ }
+ return EFalse;
+ }
+
+TBool CUdvm::ExecuteOpcodeLoadL(TUint& aPc2)
+ {
+ // LOAD (%address, %value)
+
+ TUint address = DecodeMultitypeOperandL(aPc2);
+ TUint value = DecodeMultitypeOperandL(aPc2);
+
+ iUdvmMemory->WriteMem16L(address, value);
+ iCycles += 1;
+ return EFalse;
+ }
+
+TBool CUdvm::ExecuteOpcodeMultiloadL(TUint& aPc2)
+ {
+ // MULTILOAD (%address, #n, %value_0, ..., %value_n-1)
+
+ TUint pc = aPc2 - 1;
+
+ TUint address = DecodeMultitypeOperandL(aPc2);
+ TUint n = DecodeLiteralOperandL(aPc2);
+
+ for (TUint i = 0; i < n; i++)
+ {
+ TUint value = DecodeMultitypeOperandL(aPc2);
+
+ // check overlaping instruction location
+ if (!((address >= aPc2) || ((address + n * 2) <= pc)))
+ {
+ User::Leave(CSigComp::EDecompressionFailure);
+ }
+
+ iUdvmMemory->WriteMem16L(address + i * 2, value);
+ }
+ iCycles += 1 + n;
+ return EFalse;
+ }
+
+TBool CUdvm::ExecuteOpcodePushL(TUint& aPc2)
+ {
+ // PUSH (%value)
+
+ TUint value = DecodeMultitypeOperandL(aPc2);
+
+ TUint sl = iUdvmMemory->ReadMem16L(EReg_stack_location);
+ TUint sf = iUdvmMemory->ReadMem16L(sl);
+
+ iUdvmMemory->WriteMem16L((sl + 2 + sf * 2) & KMaxUdvmMemoryMask, value);
+ iUdvmMemory->WriteMem16L(sl, (sf + 1) & KMax16BitValueMask);
+ iCycles += 1;
+ return EFalse;
+ }
+
+TBool CUdvm::ExecuteOpcodePopL(TUint& aPc2)
+ {
+ // POP (%address)
+
+ TUint address = DecodeMultitypeOperandL(aPc2);
+
+ TUint sl = iUdvmMemory->ReadMem16L(EReg_stack_location);
+ TUint sf = (iUdvmMemory->ReadMem16L(sl) - 1) & KMaxUdvmMemoryMask;
+
+ iUdvmMemory->WriteMem16L(sl, sf);
+ iUdvmMemory->WriteMem16L(address,
+ iUdvmMemory->ReadMem16L((sl + 2 + sf * 2) &
+ KMaxUdvmMemoryMask));
+ iCycles += 1;
+ return EFalse;
+ }
+
+TBool CUdvm::ExecuteOpcodeCopyL(TUint& aPc2)
+ {
+ // COPY (%position, %length, %destination)
+ // NOTE: byte copying
+
+ TUint position = DecodeMultitypeOperandL(aPc2);
+ TUint length = DecodeMultitypeOperandL(aPc2);
+ TUint destination = DecodeMultitypeOperandL(aPc2);
+
+ iCycles += 1 + length;
+
+ TUint bcl = iUdvmMemory->ReadMem16L(EReg_byte_copy_left);
+ TUint bcr = iUdvmMemory->ReadMem16L(EReg_byte_copy_right);
+
+ while (length)
+ {
+ iUdvmMemory->WriteMem8L(destination, iUdvmMemory->ReadMem8L(position));
+
+ destination++;
+ destination &= KMaxUdvmMemoryMask;
+ position++;
+ position &= KMaxUdvmMemoryMask;
+
+ length--;
+
+ if (destination == bcr)
+ {
+ destination = bcl;
+ }
+
+ if (position == bcr)
+ {
+ position = bcl;
+ }
+ }
+ return EFalse;
+ }
+
+TBool CUdvm::ExecuteOpcodeCopyLiteralL(TUint& aPc2)
+ {
+ // COPY-LITERAL (%position, %length, $destination)
+ // NOTE: byte copying
+
+ TUint position = DecodeMultitypeOperandL(aPc2);
+ TUint length = DecodeMultitypeOperandL(aPc2);
+ TUint destination = DecodeReferenceOperandL(aPc2);
+
+ iCycles += 1 + length;
+
+ if (length)
+ {
+ TUint bcl = iUdvmMemory->ReadMem16L(EReg_byte_copy_left);
+ TUint bcr = iUdvmMemory->ReadMem16L(EReg_byte_copy_right);
+
+ TUint dest = iUdvmMemory->ReadMem16L(destination);
+
+ while (length)
+ {
+ iUdvmMemory->WriteMem8L(dest, iUdvmMemory->ReadMem8L(position));
+
+ dest++;
+ dest &= KMaxUdvmMemoryMask;
+ position++;
+ position &= KMaxUdvmMemoryMask;
+
+ length--;
+
+ if (dest == bcr)
+ {
+ dest = bcl;
+ }
+
+ if (position == bcr)
+ {
+ position = bcl;
+ }
+ }
+ iUdvmMemory->WriteMem16L(destination, dest);
+ }
+ return EFalse;
+ }
+
+TBool CUdvm::ExecuteOpcodeCopyOffsetL(TUint& aPc2)
+ {
+ // COPY-OFFSET (%offset, %length, $destination)
+ // NOTE: byte copying
+
+ TUint offset = DecodeMultitypeOperandL(aPc2);
+ TUint length = DecodeMultitypeOperandL(aPc2);
+ TUint destination = DecodeReferenceOperandL(aPc2);
+
+ iCycles += 1 + length; // not 1+length+offset !!!
+
+ if (length)
+ {
+ TUint bcl = iUdvmMemory->ReadMem16L(EReg_byte_copy_left);
+ TUint bcr = iUdvmMemory->ReadMem16L(EReg_byte_copy_right);
+
+ TUint dest = iUdvmMemory->ReadMem16L(destination);
+
+ TUint position = dest;
+ while (offset)
+ {
+ if (position == bcl)
+ {
+ position = (bcr - 1) & KMaxUdvmMemoryMask;
+ }
+ else
+ {
+ position--;
+ }
+ offset--;
+ }
+
+ while (length)
+ {
+ iUdvmMemory->WriteMem8L(dest, iUdvmMemory->ReadMem8L(position));
+
+ dest++;
+ dest &= KMaxUdvmMemoryMask;
+ position++;
+ position &= KMaxUdvmMemoryMask;
+
+ length--;
+
+ if (dest == bcr)
+ {
+ dest = bcl;
+ }
+
+ if (position == bcr)
+ {
+ position = bcl;
+ }
+ }
+
+ iUdvmMemory->WriteMem16L(destination, dest);
+ }
+ return EFalse;
+ }
+
+TBool CUdvm::ExecuteOpcodeMemsetL(TUint& aPc2)
+ {
+ // MEMSET (%address, %length, %start_value, %offset)
+ // NOTE: byte copying
+
+ TUint address = DecodeMultitypeOperandL(aPc2);
+ TUint length = DecodeMultitypeOperandL(aPc2);
+ TUint value = DecodeMultitypeOperandL(aPc2);
+ TUint offset = DecodeMultitypeOperandL(aPc2);
+
+ iCycles += 1 + length;
+
+ if (length)
+ {
+ TUint bcl = iUdvmMemory->ReadMem16L(EReg_byte_copy_left);
+ TUint bcr = iUdvmMemory->ReadMem16L(EReg_byte_copy_right);
+
+ while (length)
+ {
+ iUdvmMemory->WriteMem8L(address, value);
+ value = (value + offset) & KMax8BitValueMask;
+
+ address++;
+ address &= KMaxUdvmMemoryMask;
+ length--;
+
+ if (address == bcr)
+ {
+ address = bcl;
+ }
+ }
+ }
+ return EFalse;
+ }
+
+TBool CUdvm::ExecuteOpcodeCompareL(TUint& aPc2)
+ {
+ /*
+ COMPARE (%value_1, %value_2, @address_1,
+ @address_2, @address_3)
+ */
+
+ TUint pc = aPc2 - 1;
+
+ TUint value1 = DecodeMultitypeOperandL(aPc2);
+ TUint value2 = DecodeMultitypeOperandL(aPc2);
+ TUint address1 = DecodeAddressOperandL(pc, aPc2);
+ TUint address2 = DecodeAddressOperandL(pc, aPc2);
+ TUint address3 = DecodeAddressOperandL(pc, aPc2);
+
+ if (value1 < value2)
+ {
+ aPc2 = address1;
+ }
+ else if (value1 == value2)
+ {
+ aPc2 = address2;
+ }
+ else // if (value1 > value2)
+ {
+ aPc2 = address3;
+ }
+ iCycles += 1;
+ return EFalse;
+ }
+
+TBool CUdvm::ExecuteOpcodeCallL(TUint& aPc2)
+ {
+ // CALL (@address)
+
+ TUint pc = aPc2 - 1;
+
+ TUint address = DecodeAddressOperandL(pc, aPc2);
+
+ TUint sl = iUdvmMemory->ReadMem16L(EReg_stack_location);
+ TUint sf = iUdvmMemory->ReadMem16L(sl);
+
+ iUdvmMemory->WriteMem16L((sl + 2 + sf * 2) & KMaxUdvmMemoryMask, aPc2);
+ iUdvmMemory->WriteMem16L(sl, (sf + 1) & KMax16BitValueMask);
+
+ aPc2 = address;
+ iCycles += 1;
+ return EFalse;
+ }
+
+TBool CUdvm::ExecuteOpcodeReturnL(TUint& aPc2)
+ {
+ // RETURN
+
+ TUint sl = iUdvmMemory->ReadMem16L(EReg_stack_location);
+ TUint sf = (iUdvmMemory->ReadMem16L(sl) - 1) & KMaxUdvmMemoryMask;
+
+ iUdvmMemory->WriteMem16L(sl, sf);
+ aPc2 = iUdvmMemory->ReadMem16L((sl + 2 + sf * 2) & KMaxUdvmMemoryMask);
+
+ iCycles += 1;
+ return EFalse;
+ }
+
+TBool CUdvm::ExecuteOpcodeSwitchL(TUint& aPc2)
+ {
+ // SWITCH (#n, %j, @address_0, @address_1, ... , @address_n-1)
+
+ TUint pc = aPc2 - 1;
+
+ TUint n = DecodeLiteralOperandL(aPc2);
+ TUint j = DecodeMultitypeOperandL(aPc2);
+
+ if (j >= n)
+ {
+ User::Leave(CSigComp::EDecompressionFailure);
+ }
+
+ TUint address;
+ do
+ {
+ address = DecodeAddressOperandL(pc, aPc2);
+ }
+ while (j--);
+
+ aPc2 = address;
+
+ iCycles += 1 + n;
+ return EFalse;
+ }
+
+TBool CUdvm::ExecuteOpcodeCrcL(TUint& aPc2)
+ {
+ // CRC (%value, %position, %length, @address)
+ // NOTE: byte copying
+
+ TUint pc = aPc2 - 1;
+
+ TUint value = DecodeMultitypeOperandL(aPc2);
+ TUint position = DecodeMultitypeOperandL(aPc2);
+ TUint length = DecodeMultitypeOperandL(aPc2);
+ TUint address = DecodeAddressOperandL(pc, aPc2);
+
+ iCycles += 1 + length;
+
+ TUint bcl = iUdvmMemory->ReadMem16L(EReg_byte_copy_left);
+ TUint bcr = iUdvmMemory->ReadMem16L(EReg_byte_copy_right);
+
+ TUint16 crc = Crc::KFcsInit;
+
+ while (length)
+ {
+ TUint nextpos = position;
+ TUint len = ByteCopyingFragmentL(nextpos,
+ length,
+ bcl,
+ bcr);
+
+ if (len)
+ {
+ crc = Crc::Calc(&iUdvmMemory->MemoryPtr()[position], len, crc);
+ }
+
+ position = nextpos;
+ }
+
+ if (crc != value)
+ {
+ aPc2 = address;
+ }
+ return EFalse;
+ }
+
+TBool CUdvm::ExecuteOpcodeInputBytesL(TUint& aPc2)
+ {
+ // INPUT-BYTES (%length, %destination, @address)
+ // NOTE: byte copying
+
+ TUint pc = aPc2 - 1;
+
+ TUint length = DecodeMultitypeOperandL(aPc2);
+ TUint destination = DecodeMultitypeOperandL(aPc2);
+ TUint address = DecodeAddressOperandL(pc, aPc2);
+
+ iCycles += 1 + length;
+
+ if (iLastUsedInputBit)
+ {
+ iLastUsedInputBit = 0;
+ }
+
+ if (iInputMessageReader->Avail(length) != KErrNone)
+ {
+ aPc2 = address;
+ }
+ else
+ {
+ TUint bcl = iUdvmMemory->ReadMem16L(EReg_byte_copy_left);
+ TUint bcr = iUdvmMemory->ReadMem16L(EReg_byte_copy_right);
+
+ while (length)
+ {
+ TUint nextdest = destination;
+ TUint len = ByteCopyingFragmentL(nextdest,
+ length,
+ bcl,
+ bcr);
+
+ if (len)
+ {
+ TPtr8 blockPtr(iUdvmMemory->MemoryPtr() + destination, len);
+ iInputMessageReader->ReadBlock(blockPtr);
+ }
+
+ destination = nextdest;
+ }
+ }
+ return EFalse;
+ }
+
+TBool CUdvm::ExecuteOpcodeInputBitsL(TUint& aPc2)
+ {
+ // INPUT-BITS (%length, %destination, @address)
+
+ TUint pc = aPc2 - 1;
+
+ TUint length = DecodeMultitypeOperandL(aPc2);
+ TUint destination = DecodeMultitypeOperandL(aPc2);
+ TUint address = DecodeAddressOperandL(pc, aPc2);
+
+ iCycles += 1;
+
+ if (length > 16)
+ {
+ User::Leave(CSigComp::EDecompressionFailure);
+ }
+
+ TUint ibo = iUdvmMemory->ReadMem16L(EReg_input_bit_order);
+
+ if (ibo & (~(EIBOFlag_P | EIBOFlag_H | EIBOFlag_F)))
+ {
+ User::Leave(CSigComp::EDecompressionFailure);
+ }
+
+ if ((iLastIBO ^ ibo) & EIBOFlag_P)
+ {
+ // P bit changed
+ iLastUsedInputBit = 0;
+ }
+
+ // bytes to read
+ TUint btr = (length - ((8 - iLastUsedInputBit) & 7) + 7) >> 3;
+
+ if (iInputMessageReader->Avail(btr) != KErrNone)
+ {
+ aPc2 = address;
+ }
+ else
+ {
+ iUdvmMemory->WriteMem16L(destination,
+ InputMessageBitsL(length,
+ ibo&EIBOFlag_P,
+ ibo&EIBOFlag_F));
+ }
+ iLastIBO = ibo;
+ return EFalse;
+ }
+
+TBool CUdvm::ExecuteOpcodeInputHuffmanL(TUint& aPc2)
+ {
+ // INPUT-HUFFMAN (%destination, @address, #n,
+ // bits_1, %lower_bound_1,%upper_bound_1, %uncompressed_1, ...,
+ // bits_n, %lower_bound_n,%upper_bound_n, %uncompressed_n)
+
+ TUint pc = aPc2 - 1;
+
+ TUint destination = DecodeMultitypeOperandL(aPc2);
+ TUint address = DecodeAddressOperandL(pc, aPc2);
+ TUint n = DecodeLiteralOperandL(aPc2);
+
+ iCycles += 1 + n;
+
+ TUint ibo = iUdvmMemory->ReadMem16L(EReg_input_bit_order);
+
+ if (ibo & (~(EIBOFlag_P | EIBOFlag_H | EIBOFlag_F)))
+ {
+ User::Leave(CSigComp::EDecompressionFailure);
+ }
+
+ if ((iLastIBO ^ ibo) & EIBOFlag_P)
+ {
+ // P bit changed
+ iLastUsedInputBit = 0;
+ }
+
+ TUint p = ibo & EIBOFlag_P;
+ TUint h = ibo & EIBOFlag_H;
+
+ TUint val = 0;
+ TUint bits = 0;
+ TUint len;
+ TUint lower;
+ TUint upper;
+ TUint uncompressed;
+
+ TBool quit = EFalse;
+ while (n && !quit)
+ {
+ len = DecodeMultitypeOperandL(aPc2);
+ lower = DecodeMultitypeOperandL(aPc2);
+ upper = DecodeMultitypeOperandL(aPc2);
+ uncompressed = DecodeMultitypeOperandL(aPc2);
+
+ bits += len;
+ if (bits > 16)
+ {
+ User::Leave(CSigComp::EDecompressionFailure);
+ }
+
+ // bytes to read
+ TUint btr = (len - ((8 - iLastUsedInputBit) & 7) + 7) >> 3;
+
+ if (iInputMessageReader->Avail(btr) != KErrNone)
+ {
+ aPc2 = address;
+ n = 1;
+ quit = ETrue;
+ }
+
+ if (!quit)
+ {
+ val = (val << len) | InputMessageBitsL(len, p, h);
+
+ if ((val >= lower) && (val <= upper))
+ {
+ iUdvmMemory->WriteMem16L(destination,
+ (val + uncompressed - lower) & KMax16BitValueMask);
+ quit = ETrue;
+ }
+ if (!quit)
+ {
+ n--;
+ }
+ }
+ }
+
+ if (n == 0)
+ {
+ User::Leave(CSigComp::EDecompressionFailure);
+ }
+
+ n--;
+
+ while (n)
+ {
+ len = DecodeMultitypeOperandL(aPc2);
+ lower = DecodeMultitypeOperandL(aPc2);
+ upper = DecodeMultitypeOperandL(aPc2);
+ uncompressed = DecodeMultitypeOperandL(aPc2);
+ n--;
+ }
+
+ iLastIBO = ibo;
+ return EFalse;
+ }
+
+TBool CUdvm::ExecuteOpcodeStateAccessL(TUint& aPc2)
+ {
+ /*
+ STATE-ACCESS (%partial_identifier_start,
+ %partial_identifier_length,
+ state_begin,
+ %state_length,
+ %state_address, %state_instruction)
+ NOTE: byte copying
+ */
+
+ TUint partial_identifier_start = DecodeMultitypeOperandL(aPc2);
+ TUint partial_identifier_length = DecodeMultitypeOperandL(aPc2);
+ TUint state_begin = DecodeMultitypeOperandL(aPc2);
+ TUint state_length = DecodeMultitypeOperandL(aPc2);
+ TUint state_address = DecodeMultitypeOperandL(aPc2);
+ TUint state_instruction = DecodeMultitypeOperandL(aPc2);
+
+ if ((partial_identifier_length < KStateIdentifierMinLength) ||
+ (partial_identifier_length > KStateIdentifierMaxLength))
+ {
+ User::Leave(CSigComp::EDecompressionFailure);
+ }
+
+ __ASSERT_ALWAYS(partial_identifier_start < iUdvmMemory->MemorySize(),
+ User::Leave(CSigComp::EDecompressionFailure));
+
+
+ __ASSERT_ALWAYS(partial_identifier_start+partial_identifier_length <=
+ iUdvmMemory->MemorySize(),
+ User::Leave(CSigComp::EDecompressionFailure));
+
+ TStateItem* si = iStateMgr->FindStateItem(
+ TPtrC8(&iUdvmMemory->MemoryPtr()[partial_identifier_start],
+ partial_identifier_length));
+
+ if (si == NULL)
+ {
+ User::Leave(CSigComp::EDecompressionFailure);
+ }
+
+ TestStateAccessLenL(si, partial_identifier_length);
+
+ if (state_length == 0)
+ {
+ state_length = si->iStateLength;
+ }
+
+ if (state_address == 0)
+ {
+ state_address = si->iStateAddress;
+ }
+
+ if (state_instruction == 0)
+ {
+ state_instruction = si->iStateInstruction;
+ }
+
+ if ((state_begin + state_length) > si->iStateLength)
+ {
+ User::Leave(CSigComp::EDecompressionFailure);
+ }
+
+ iCycles += 1 + state_length;
+
+ TUint bcl = iUdvmMemory->ReadMem16L(EReg_byte_copy_left);
+ TUint bcr = iUdvmMemory->ReadMem16L(EReg_byte_copy_right);
+
+ while (state_length)
+ {
+ TUint nextdest = state_address;
+ TUint len = ByteCopyingFragmentL(nextdest,
+ state_length,
+ bcl,
+ bcr);
+
+ if (len)
+ {
+ iUdvmMemory->CopyToMemL(state_address,
+ &si->iStateValue[state_begin],
+ len);
+ state_begin += len;
+ }
+
+ state_address = nextdest;
+ }
+
+ if (state_instruction)
+ {
+ aPc2 = state_instruction;
+ }
+ return EFalse;
+ }
+
+TBool CUdvm::ExecuteOpcodeStateCreateL(TUint& aPc2)
+ {
+ /*
+ STATE-CREATE (%state_length,
+ %state_address,
+ %state_instruction,
+ %minimum_access_length,
+ %state_retention_priority)
+ */
+
+ if (iStateCreateRequestsNumber == KMaxStateOperations)
+ {
+ User::Leave(CSigComp::EDecompressionFailure);
+ }
+
+ TUint state_length = DecodeMultitypeOperandL(aPc2);
+ TUint state_address = DecodeMultitypeOperandL(aPc2);
+ TUint state_instruction = DecodeMultitypeOperandL(aPc2);
+ TUint minimum_access_length = DecodeMultitypeOperandL(aPc2);
+ TUint state_retention_priority = DecodeMultitypeOperandL(aPc2);
+
+ if ((minimum_access_length < KStateIdentifierMinLength) ||
+ (minimum_access_length > KStateIdentifierMaxLength) ||
+ (state_retention_priority == KMaxUdvmMemoryMask))
+ {
+ User::Leave(CSigComp::EDecompressionFailure);
+ }
+
+ TUint i = iStateCreateRequestsNumber+iStateFreeRequestsNumber;
+ iStateOperationRequests[i].iOperation = EOpcode_STATE_CREATE;
+ iStateOperationRequests[i].iStateLength =
+ static_cast<TUint16>(state_length);
+ iStateOperationRequests[i].iStateAddress =
+ static_cast<TUint16>(state_address);
+ iStateOperationRequests[i].iStateInstruction =
+ static_cast<TUint16>(state_instruction);
+ iStateOperationRequests[i].iMinimumAccessLength =
+ static_cast<TUint16>(minimum_access_length);
+ iStateOperationRequests[i].iStateRetentionPriority =
+ static_cast<TUint16>(state_retention_priority);
+ iStateOperationRequests[i].iStateValue = new (ELeave)
+ CArrayFixFlat<TUint8>(8);
+ iStateCreateRequestsNumber++;
+ iStateOperationRequests[i].iStateValue->ResizeL(state_length);
+
+ iCycles += 1 + state_length;
+
+ TUint bcl = iUdvmMemory->ReadMem16L(EReg_byte_copy_left);
+ TUint bcr = iUdvmMemory->ReadMem16L(EReg_byte_copy_right);
+
+ TUint state_begin = 0;
+ while (state_length)
+ {
+ TUint nextdest = state_address;
+ TUint len = ByteCopyingFragmentL(nextdest,
+ state_length,
+ bcl,
+ bcr);
+
+ if (len)
+ {
+ iUdvmMemory->CopyFromMemL(
+ &iStateOperationRequests[i].iStateValue->At(state_begin),
+ state_address,
+ len);
+ state_begin += len;
+ }
+ state_address = nextdest;
+ }
+ return EFalse;
+ }
+
+TBool CUdvm::ExecuteOpcodeEndMessageL(TUint& aPc2)
+ {
+ /*
+ END-MESSAGE (%requested_feedback_location,
+ %returned_parameters_location,
+ %state_length, %state_address,
+ %state_instruction,
+ %minimum_access_length,
+ %state_retention_priority)
+ NOTE: byte copying
+ */
+
+ TUint requested_feedback_location = DecodeMultitypeOperandL(aPc2);
+ TUint returned_parameters_location = DecodeMultitypeOperandL(aPc2);
+ TUint state_length = DecodeMultitypeOperandL(aPc2);
+ TUint state_address = DecodeMultitypeOperandL(aPc2);
+ TUint state_instruction = DecodeMultitypeOperandL(aPc2);
+ TUint minimum_access_length = DecodeMultitypeOperandL(aPc2);
+ TUint state_retention_priority = DecodeMultitypeOperandL(aPc2);
+
+ iCycles += 1 + state_length;
+
+ if ((minimum_access_length >= KStateIdentifierMinLength) &&
+ (minimum_access_length <= KStateIdentifierMaxLength) &&
+ (state_retention_priority != 0xffff))
+ {
+ if (iStateCreateRequestsNumber == KMaxStateOperations)
+ {
+ User::Leave(CSigComp::EDecompressionFailure);
+ }
+
+ TUint i = iStateCreateRequestsNumber+iStateFreeRequestsNumber;
+ iStateOperationRequests[i].iOperation = EOpcode_STATE_CREATE;
+ iStateOperationRequests[i].iStateLength =
+ static_cast<TUint16>(state_length);
+ iStateOperationRequests[i].iStateAddress =
+ static_cast<TUint16>(state_address);
+ iStateOperationRequests[i].iStateInstruction =
+ static_cast<TUint16>(state_instruction);
+ iStateOperationRequests[i].iMinimumAccessLength =
+ static_cast<TUint16>(minimum_access_length);
+ iStateOperationRequests[i].iStateRetentionPriority =
+ static_cast<TUint16>(state_retention_priority);
+ iStateOperationRequests[i].iStateValue = new (ELeave)
+ CArrayFixFlat<TUint8>(8);
+ iStateCreateRequestsNumber++;
+ iStateOperationRequests[i].iStateValue->ResizeL(state_length);
+
+ TUint bcl = iUdvmMemory->ReadMem16L(EReg_byte_copy_left);
+ TUint bcr = iUdvmMemory->ReadMem16L(EReg_byte_copy_right);
+
+ TUint state_begin = 0;
+ while (state_length)
+ {
+ TUint nextdest = state_address;
+ TUint len = ByteCopyingFragmentL(nextdest,
+ state_length,
+ bcl,
+ bcr);
+
+ if (len)
+ {
+ iUdvmMemory->CopyFromMemL(
+ &iStateOperationRequests[i].iStateValue->At(state_begin),
+ state_address,
+ len);
+ state_begin += len;
+ }
+
+ state_address = nextdest;
+ }
+ }
+
+ if (requested_feedback_location)
+ {
+ TUint rfl = requested_feedback_location;
+
+ TUint rf = iUdvmMemory->ReadMem8L(rfl);
+ rfl++;
+
+ if (rf & ERFFlag_Q)
+ {
+ // returned feedback item
+ TUint rff = iUdvmMemory->ReadMem8L(rfl);
+ rfl++;
+
+ if (rff & 0x80)
+ {
+ // long form
+ rfl += rff & 0x7f;
+ // check memory out of range
+ iUdvmMemory->ReadMem8L(rfl - 1);
+ }
+ }
+
+ iRequestedFeedback.Set(&iUdvmMemory->MemoryPtr()
+ [requested_feedback_location],
+ rfl - requested_feedback_location,
+ rfl - requested_feedback_location);
+ }
+ else
+ {
+ iRequestedFeedback.Set(NULL, 0, 0);
+ }
+
+ if (returned_parameters_location)
+ {
+ TUint rpl = returned_parameters_location;
+
+ iUdvmMemory->ReadMem8L(rpl); // cpb dms sms
+ rpl++;
+
+ iUdvmMemory->ReadMem8L(rpl); // version
+ rpl++;
+
+ TBool quit = EFalse;
+ TUint psi;
+ for (; !quit; )
+ {
+ psi = iUdvmMemory->ReadMem8L(rpl);
+ rpl++;
+
+ if ((psi < KStateIdentifierMinLength) ||
+ (psi > KStateIdentifierMaxLength))
+ {
+ quit = ETrue;
+ }
+ else
+ {
+ rpl += psi;
+ }
+ }
+
+ iReturnedParameters.Set(&iUdvmMemory->MemoryPtr()
+ [returned_parameters_location],
+ rpl - returned_parameters_location,
+ rpl - returned_parameters_location);
+ }
+ else
+ {
+ iReturnedParameters.Set(NULL, 0, 0);
+ }
+ return ETrue;
+ }
+
+TBool CUdvm::ExecuteOpcodeStateFreeL(TUint& aPc2)
+ {
+ /*
+ STATE-FREE (%partial_identifier_start,
+ %partial_identifier_length)
+ */
+
+ if (iStateFreeRequestsNumber == KMaxStateOperations)
+ {
+ User::Leave(CSigComp::EDecompressionFailure);
+ }
+
+ TUint partial_identifier_start = DecodeMultitypeOperandL(aPc2);
+ TUint partial_identifier_length = DecodeMultitypeOperandL(aPc2);
+
+ if ((partial_identifier_length < KStateIdentifierMinLength) ||
+ (partial_identifier_length > KStateIdentifierMaxLength))
+ {
+ User::Leave(CSigComp::EDecompressionFailure);
+ }
+
+ TUint i = iStateCreateRequestsNumber+iStateFreeRequestsNumber;
+ iStateOperationRequests[i].iOperation = EOpcode_STATE_FREE;
+ iStateOperationRequests[i].iPartialIdentifierStart =
+ static_cast<TUint16>(partial_identifier_start);
+ iStateOperationRequests[i].iPartialIdentifierLength =
+ static_cast<TUint16>(partial_identifier_length);
+ iStateFreeRequestsNumber++;
+ iCycles += 1;
+ return EFalse;
+ }
+
+TBool CUdvm::ExecuteOpcodeOutputL(TUint& aPc2)
+ {
+ // OUTPUT (%output_start, %output_length)
+ // NOTE: byte copying
+
+ TUint start = DecodeMultitypeOperandL(aPc2);
+ TUint length = DecodeMultitypeOperandL(aPc2);
+
+ iCycles += 1 + length;
+
+ TUint bcl = iUdvmMemory->ReadMem16L(EReg_byte_copy_left);
+ TUint bcr = iUdvmMemory->ReadMem16L(EReg_byte_copy_right);
+
+ while (length)
+ {
+ TUint nextstart = start;
+ TUint len = ByteCopyingFragmentL(nextstart, length, bcl, bcr);
+
+ if (len)
+ {
+ iOutputBuffer->InsertL(iOutputBuffer->Size(),
+ &iUdvmMemory->MemoryPtr()[start],
+ len);
+ }
+ start = nextstart;
+ }
+
+ // RFC 3320, chapter 9.4.8:
+ // Decompression failure occurs if the cumulative number of bytes
+ // provided to the dispatcher exceeds 65536 bytes.
+ if (iOutputBuffer->Size() > KMaxOutputSize)
+ {
+ User::Leave(CSigComp::EDecompressionFailure);
+ }
+
+ return EFalse;
+ }
+
+
+TBool CUdvm::ExecuteOpcodeJumpL(TUint& aPc2)
+ {
+ // JUMP (@address)
+ TUint pc = aPc2 - 1;
+ aPc2 = DecodeAddressOperandL(pc, aPc2);
+ iCycles += 1;
+ return EFalse;
+ }
+
+
+// ----------------------------------------------------------------------------
+// CUdvm::ExecuteCodeL
+// execute UDVM code
+// ----------------------------------------------------------------------------
+//
+
+void CUdvm::ExecuteCodeL(CMessageReader* aMsgReader)
+ {
+ iInputMessageReader = aMsgReader;
+ iLastUsedInputBit = 0;
+
+ TPtr8 retf(iReturnedFeedback);
+ DenyStateOperations();
+ iReturnedFeedback.Set(retf);
+
+ iOutputBuffer->Reset();
+
+ iCycles = 0;
+
+ TUint pc = iCodeStart;
+ TBool terminated = EFalse;
+
+ while (!terminated)
+ {
+ pc &= KMaxUdvmMemoryMask;
+ TUint8 opcode = iUdvmMemory->ReadMem8L(pc);
+ pc++;
+
+ if (opcode >= EOpcodesNumber)
+ {
+ // unknown opcode
+ User::Leave(CSigComp::EDecompressionFailure);
+ }
+
+ terminated = (this->*iExecuteOpcode[opcode])(pc);
+
+ if (iCycles > iAvailableCycles)
+ {
+ User::Leave(CSigComp::EDecompressionFailure);
+ }
+ }
+ }
+
+
+// ----------------------------------------------------------------------------
+// CUdvm::AllowStateOperationsL
+// allow for state operations
+// ----------------------------------------------------------------------------
+//
+
+TInt CUdvm::AllowStateOperationsL(CSigCompCompartment* aCompartment)
+ {
+ TInt sso = 0;
+
+ if (iStateMgr && aCompartment)
+ {
+ TInt soNum = iStateCreateRequestsNumber + iStateFreeRequestsNumber;
+
+ for (TInt i = 0; i < soNum; i++)
+ {
+ if (iStateOperationRequests[i].iOperation == EOpcode_STATE_CREATE)
+ {
+ if (iStateMgr->CreateStateL(aCompartment,
+ iStateOperationRequests[i].iStateLength,
+ iStateOperationRequests[i].iStateAddress,
+ iStateOperationRequests[i].iStateInstruction,
+ iStateOperationRequests[i].iMinimumAccessLength,
+ iStateOperationRequests[i].iStateLength ?
+ &iStateOperationRequests[i].iStateValue->At(0) : NULL,
+ iStateOperationRequests[i].iStateRetentionPriority) != NULL)
+ {
+ sso++;
+ }
+ }
+
+ if (iStateOperationRequests[i].iOperation == EOpcode_STATE_FREE)
+ {
+ if (iStateMgr->FreeStateL(aCompartment,
+ TPtrC8(
+ &iUdvmMemory->MemoryPtr()
+ [iStateOperationRequests[i].iPartialIdentifierStart],
+ iStateOperationRequests[i].iPartialIdentifierLength))
+ == KErrNone)
+ {
+ sso++;
+ }
+ }
+ }
+
+ if (sso == soNum)
+ {
+ iStateMgr->SetReturnedFeedbackL(*aCompartment,
+ iReturnedFeedback);
+ iStateMgr->SetRequestedFeedbackL(*aCompartment,
+ iRequestedFeedback);
+ iStateMgr->SetReturnedParametersL(*aCompartment,
+ iReturnedParameters);
+ }
+ }
+
+ return sso;
+ }
+
+
+// ----------------------------------------------------------------------------
+// CUdvm::DenyStateOperations
+// deny state operations
+// ----------------------------------------------------------------------------
+//
+
+void CUdvm::DenyStateOperations()
+ {
+
+ TUint soNum = iStateCreateRequestsNumber + iStateFreeRequestsNumber;
+
+ for (TUint i = 0; i < soNum; i++)
+ {
+ if (iStateOperationRequests[i].iOperation == EOpcode_STATE_CREATE)
+ {
+
+ delete iStateOperationRequests[i].iStateValue;
+ iStateOperationRequests[i].iStateValue = NULL;
+ }
+ }
+
+ iStateCreateRequestsNumber = 0;
+ iStateFreeRequestsNumber = 0;
+
+ iReturnedFeedback.Set(NULL, 0, 0);
+ iRequestedFeedback.Set(NULL, 0, 0);
+ iReturnedParameters.Set(NULL, 0, 0);
+ }
+
+
+// ----------------------------------------------------------------------------
+// CUdvm::CyclesConsumed
+// get consumed cycles number
+// ----------------------------------------------------------------------------
+//
+
+#if defined(SIGCOMP_DEBUG)
+
+TUint CUdvm::CyclesConsumed() const
+ {
+ return iCycles;
+ }
+
+#endif
+
+// End of File