diff -r 000000000000 -r 307788aac0a8 realtimenetprots/sipfw/SigComp/SigCompEngine/src/Udvm.cpp --- /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(state_length); + iStateOperationRequests[i].iStateAddress = + static_cast(state_address); + iStateOperationRequests[i].iStateInstruction = + static_cast(state_instruction); + iStateOperationRequests[i].iMinimumAccessLength = + static_cast(minimum_access_length); + iStateOperationRequests[i].iStateRetentionPriority = + static_cast(state_retention_priority); + iStateOperationRequests[i].iStateValue = new (ELeave) + CArrayFixFlat(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(state_length); + iStateOperationRequests[i].iStateAddress = + static_cast(state_address); + iStateOperationRequests[i].iStateInstruction = + static_cast(state_instruction); + iStateOperationRequests[i].iMinimumAccessLength = + static_cast(minimum_access_length); + iStateOperationRequests[i].iStateRetentionPriority = + static_cast(state_retention_priority); + iStateOperationRequests[i].iStateValue = new (ELeave) + CArrayFixFlat(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(partial_identifier_start); + iStateOperationRequests[i].iPartialIdentifierLength = + static_cast(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