realtimenetprots/sipfw/SigComp/SigCompEngine/src/Udvm.cpp
changeset 0 307788aac0a8
equal deleted inserted replaced
-1:000000000000 0:307788aac0a8
       
     1 // Copyright (c) 2003-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 // Name        : Udvm.cpp
       
    15 // Part of     : SigComp / UDVM
       
    16 // UDVM core
       
    17 // Version     : 1.0
       
    18 //
       
    19 
       
    20 
       
    21 
       
    22 
       
    23 // INCLUDE FILES
       
    24 #include "Udvm.h"
       
    25 #include "UdvmMemory.h"
       
    26 #include "sigcompcompartment.h"
       
    27 #include "StateMgr.h"
       
    28 #include "Crc.h"
       
    29 #include "MessageReader.h"
       
    30 
       
    31 // ============================ MEMBER FUNCTIONS ==============================
       
    32 
       
    33 void CUdvm::ConstructL(CStateMgr* aStateMgr,
       
    34                        TUint aMemSize,
       
    35                        TUint aCyclesPerBit)
       
    36     {
       
    37     iExecuteOpcode[EOpcode_DECOMPRESSION_FAILURE] =
       
    38                    &CUdvm::ExecuteOpcodeDecompressionFailureL;
       
    39     iExecuteOpcode[EOpcode_AND] = &CUdvm::ExecuteOpcodeAndL;
       
    40     iExecuteOpcode[EOpcode_OR] = &CUdvm::ExecuteOpcodeOrL;
       
    41     iExecuteOpcode[EOpcode_NOT] = &CUdvm::ExecuteOpcodeNotL;
       
    42     iExecuteOpcode[EOpcode_LSHIFT] = &CUdvm::ExecuteOpcodeLShiftL;
       
    43     iExecuteOpcode[EOpcode_RSHIFT] = &CUdvm::ExecuteOpcodeRShiftL;
       
    44     iExecuteOpcode[EOpcode_ADD] = &CUdvm::ExecuteOpcodeAddL;
       
    45     iExecuteOpcode[EOpcode_SUBTRACT] = &CUdvm::ExecuteOpcodeSubtractL;
       
    46     iExecuteOpcode[EOpcode_MULTIPLY] = &CUdvm::ExecuteOpcodeMultiplyL;
       
    47     iExecuteOpcode[EOpcode_DIVIDE] = &CUdvm::ExecuteOpcodeDivideL;
       
    48     iExecuteOpcode[EOpcode_REMAINDER] = &CUdvm::ExecuteOpcodeRemainderL;
       
    49     iExecuteOpcode[EOpcode_SORT_ASCENDING] = &CUdvm::ExecuteOpcodeAscendingL;
       
    50     iExecuteOpcode[EOpcode_SORT_DESCENDING] = &CUdvm::ExecuteOpcodeDescendingL;
       
    51     iExecuteOpcode[EOpcode_SHA_1] = &CUdvm::ExecuteOpcodeSha1L;
       
    52     iExecuteOpcode[EOpcode_LOAD] = &CUdvm::ExecuteOpcodeLoadL;
       
    53     iExecuteOpcode[EOpcode_MULTILOAD] = &CUdvm::ExecuteOpcodeMultiloadL;
       
    54     iExecuteOpcode[EOpcode_PUSH] = &CUdvm::ExecuteOpcodePushL;
       
    55     iExecuteOpcode[EOpcode_POP] = &CUdvm::ExecuteOpcodePopL;
       
    56     iExecuteOpcode[EOpcode_COPY] = &CUdvm::ExecuteOpcodeCopyL;
       
    57     iExecuteOpcode[EOpcode_COPY_LITERAL] = &CUdvm::ExecuteOpcodeCopyLiteralL;
       
    58     iExecuteOpcode[EOpcode_COPY_OFFSET] = &CUdvm::ExecuteOpcodeCopyOffsetL;
       
    59     iExecuteOpcode[EOpcode_MEMSET] = &CUdvm::ExecuteOpcodeMemsetL;
       
    60     iExecuteOpcode[EOpcode_JUMP] = &CUdvm::ExecuteOpcodeJumpL;
       
    61     iExecuteOpcode[EOpcode_COMPARE] = &CUdvm::ExecuteOpcodeCompareL;
       
    62     iExecuteOpcode[EOpcode_CALL] = &CUdvm::ExecuteOpcodeCallL;
       
    63     iExecuteOpcode[EOpcode_RETURN] = &CUdvm::ExecuteOpcodeReturnL;
       
    64     iExecuteOpcode[EOpcode_SWITCH] = &CUdvm::ExecuteOpcodeSwitchL;
       
    65     iExecuteOpcode[EOpcode_CRC] = &CUdvm::ExecuteOpcodeCrcL;
       
    66     iExecuteOpcode[EOpcode_INPUT_BYTES] = &CUdvm::ExecuteOpcodeInputBytesL;
       
    67     iExecuteOpcode[EOpcode_INPUT_BITS] = &CUdvm::ExecuteOpcodeInputBitsL;
       
    68     iExecuteOpcode[EOpcode_INPUT_HUFFMAN] = &CUdvm::ExecuteOpcodeInputHuffmanL;
       
    69     iExecuteOpcode[EOpcode_STATE_ACCESS] = &CUdvm::ExecuteOpcodeStateAccessL;
       
    70     iExecuteOpcode[EOpcode_STATE_CREATE] = &CUdvm::ExecuteOpcodeStateCreateL;
       
    71     iExecuteOpcode[EOpcode_STATE_FREE] = &CUdvm::ExecuteOpcodeStateFreeL;
       
    72     iExecuteOpcode[EOpcode_OUTPUT] = &CUdvm::ExecuteOpcodeOutputL;
       
    73     iExecuteOpcode[EOpcode_END_MESSAGE] = &CUdvm::ExecuteOpcodeEndMessageL;
       
    74 
       
    75     iStateMgr = aStateMgr;
       
    76     iUdvmMemory = CUdvmMemory::NewL(aMemSize);
       
    77 
       
    78     iCyclesPerBit = aCyclesPerBit;
       
    79 
       
    80     iSHA1 = CSHA1::NewL();
       
    81     }
       
    82 
       
    83 CUdvm::CUdvm() : iReturnedFeedback(NULL, 0),
       
    84                  iRequestedFeedback(NULL, 0),
       
    85                  iReturnedParameters(NULL, 0)
       
    86     {
       
    87     }
       
    88 
       
    89 CUdvm* CUdvm::NewLC(CStateMgr* aStateMgr,
       
    90                     TUint aMemSize,
       
    91                     TUint aCyclesPerBit)
       
    92     {
       
    93     CUdvm* self= new (ELeave) CUdvm();
       
    94     CleanupStack::PushL(self);
       
    95     self->ConstructL(aStateMgr, aMemSize, aCyclesPerBit);
       
    96     return self;
       
    97     }
       
    98 
       
    99 CUdvm* CUdvm::NewL(CStateMgr* aStateMgr, TUint aMemSize, TUint aCyclesPerBit)
       
   100     {
       
   101     CUdvm* self= NewLC(aStateMgr, aMemSize, aCyclesPerBit);
       
   102     CleanupStack::Pop();
       
   103     return self;
       
   104     }
       
   105 
       
   106 // Destructor
       
   107 CUdvm::~CUdvm()
       
   108     {
       
   109 
       
   110     DenyStateOperations();
       
   111 
       
   112     delete iUdvmMemory;
       
   113     delete iSHA1;
       
   114     }
       
   115 
       
   116 
       
   117 // ---------------------------------------------------------------------------
       
   118 
       
   119 /*
       
   120      0   1   2   3   4   5   6   7       0   1   2   3   4   5   6   7
       
   121    +---+---+---+---+---+---+---+---+   +---+---+---+---+---+---+---+---+
       
   122    | 1   1   1   1   1 | T |  len  |   | 1   1   1   1   1 | T |   0   |
       
   123    +---+---+---+---+---+---+---+---+   +---+---+---+---+---+---+---+---+
       
   124    |                               |   |                               |
       
   125    :    returned feedback item     :   :    returned feedback item     :
       
   126    |                               |   |                               |
       
   127    +---+---+---+---+---+---+---+---+   +---+---+---+---+---+---+---+---+
       
   128    |                               |   |           code_len            |
       
   129    :   partial state identifier    :   +---+---+---+---+---+---+---+---+
       
   130    |                               |   |   code_len    |  destination  |
       
   131    +---+---+---+---+---+---+---+---+   +---+---+---+---+---+---+---+---+
       
   132    |                               |   |                               |
       
   133    :   remaining SigComp message   :   :    uploaded UDVM bytecode     :
       
   134    |                               |   |                               |
       
   135    +---+---+---+---+---+---+---+---+   +---+---+---+---+---+---+---+---+
       
   136                                        |                               |
       
   137                                        :   remaining SigComp message   :
       
   138                                        |                               |
       
   139                                        +---+---+---+---+---+---+---+---+
       
   140 
       
   141      0   1   2   3   4   5   6   7       0   1   2   3   4   5   6   7
       
   142    +---+---+---+---+---+---+---+---+   +---+---+---+---+---+---+---+---+
       
   143    | 0 |  returned_feedback_field  |   | 1 | returned_feedback_length  |
       
   144    +---+---+---+---+---+---+---+---+   +---+---+---+---+---+---+---+---+
       
   145                                        |                               |
       
   146                                        :    returned_feedback_field    :
       
   147                                        |                               |
       
   148                                        +---+---+---+---+---+---+---+---+
       
   149 
       
   150    Encoding:   Length of partial state identifier
       
   151 
       
   152    01          6 bytes
       
   153    10          9 bytes
       
   154    11          12 bytes
       
   155 
       
   156    Encoding:   Destination address:
       
   157 
       
   158    0000        reserved
       
   159    0001        2  *  64  =  128
       
   160    0010        3  *  64  =  196
       
   161    0011        4  *  64  =  256
       
   162      :                :
       
   163    1111        16 *  64  =  1024
       
   164 
       
   165    Note that the encoding 0000 is reserved for future SigComp versions,
       
   166    and causes a decompression failure in Version 0x01.
       
   167 */
       
   168 
       
   169 void CUdvm::SetReturnedFeedbackL(TBool aT, CMessageReader* aMsgReader)
       
   170     {
       
   171 
       
   172     if (aT)
       
   173         {
       
   174         // returned feedback item
       
   175 
       
   176         TUint rff;
       
   177         if (aMsgReader->ReadByte(rff) != KErrNone)
       
   178             {
       
   179             User::Leave(CSigComp::EIncompleteMessage);
       
   180             }
       
   181 
       
   182         if (rff & KReturnedFeedbackFieldMask)
       
   183             {
       
   184             // long form
       
   185 
       
   186             // use decompression memory after udvm memory to store returned
       
   187             // feedback
       
   188             TUint8* udvmMem = iUdvmMemory->MemoryPtr();
       
   189             TUint udvmFreeMemSize = iUdvmMemory->FreeMemorySize();
       
   190             iReturnedFeedback.Set(&udvmMem[udvmFreeMemSize],
       
   191                                   0, rff & KReturnedFeedbackLengthMask);
       
   192             if (aMsgReader->ReadBlock(iReturnedFeedback) != KErrNone)
       
   193                 {
       
   194                 User::Leave(CSigComp::EIncompleteMessage);
       
   195                 }
       
   196             }
       
   197         else
       
   198             {
       
   199             // short form
       
   200 
       
   201             // use decompression memory after udvm memory to store returned
       
   202             // feedback
       
   203             TUint8* udvmMem = iUdvmMemory->MemoryPtr();
       
   204             TUint udvmFreeMemSize = iUdvmMemory->FreeMemorySize();
       
   205             iReturnedFeedback.Set(&udvmMem[udvmFreeMemSize], 0, 1);
       
   206             iReturnedFeedback.Append(rff);
       
   207             }
       
   208         }
       
   209     else
       
   210         {
       
   211         iReturnedFeedback.Set(NULL, 0, 0);
       
   212         }
       
   213     }
       
   214 
       
   215 void CUdvm::UploadStateInMessageL(TUint aLen, CMessageReader* aMsgReader)
       
   216     {
       
   217 
       
   218     // RFC3320:
       
   219     // The len field encodes the number of transmitted bytes as follows:
       
   220     //
       
   221     //   Encoding:   Length of partial state identifier
       
   222     //   01          6 bytes
       
   223     //   10          9 bytes
       
   224     //   11          12 bytes
       
   225     TUint id_len = (aLen + 1) * 3;
       
   226 
       
   227     TBuf8<12> psi;
       
   228     if (aMsgReader->ReadBlock(psi, id_len) != KErrNone)
       
   229         {
       
   230         User::Leave(CSigComp::EIncompleteMessage);
       
   231         }
       
   232 
       
   233     // upload state item
       
   234     UploadStateL(id_len, psi.Ptr());
       
   235     }
       
   236 
       
   237 void CUdvm::UploadBytecodeInMessageL(CMessageReader* aMsgReader)
       
   238     {
       
   239 
       
   240     TUint tmp;
       
   241 
       
   242     // get first byte of 16-bit big-endian value
       
   243     if (aMsgReader->ReadByte(tmp) != KErrNone)
       
   244         {
       
   245         User::Leave(CSigComp::EIncompleteMessage);
       
   246         }
       
   247 
       
   248     // code length is most significant 12 bits
       
   249     TUint code_len = tmp << 4;
       
   250 
       
   251     // get second byte of 16-bit big-endian value
       
   252     if (aMsgReader->ReadByte(tmp) != KErrNone)
       
   253         {
       
   254         User::Leave(CSigComp::EIncompleteMessage);
       
   255         }
       
   256 
       
   257     code_len |= tmp >> 4;
       
   258 
       
   259     // destination is less significant 4 bits
       
   260     TUint destination = tmp & 0x000f;
       
   261 
       
   262     // The destination field is encoded as follows:
       
   263     //
       
   264     //                     Encoding:   Destination address:
       
   265     //                     0000        reserved
       
   266     //                     0001        2  *  64  =  128
       
   267     //                     0010        3  *  64  =  196
       
   268     //                     0011        4  *  64  =  256
       
   269     //                       :                :
       
   270     //                     1111        16 *  64  =  1024
       
   271     //
       
   272     //   Note that the encoding 0000 is reserved for future SigComp versions,
       
   273     //   and causes a decompression failure in Version 0x01.
       
   274 
       
   275     if (destination == 0)
       
   276         {
       
   277         User::Leave(CSigComp::EDecompressionFailure);
       
   278         }
       
   279 
       
   280     // destination decoding - see above
       
   281     destination = (destination + 1) * 64;
       
   282 
       
   283     // upload code_len bytes of bytecode at destination
       
   284     UploadCodeL(destination, code_len, aMsgReader);
       
   285     }
       
   286 
       
   287 // ----------------------------------------------------------------------------
       
   288 // CUdvm::DecompressL
       
   289 // dispatch message and run bytecode
       
   290 // ----------------------------------------------------------------------------
       
   291 //
       
   292 
       
   293 CBufBase* CUdvm::DecompressL(const TDesC8& aMessage, TUint& aBytesConsumed,
       
   294                              TBool aStreamBasedProtocol)
       
   295     {
       
   296 
       
   297     CMessageReader* msgReader = new (ELeave)CMessageReader(aMessage,
       
   298                                                          aStreamBasedProtocol);
       
   299     CleanupStack::PushL(msgReader);
       
   300 
       
   301     if (msgReader->SkipDelimiters() != KErrNone)
       
   302         {
       
   303         User::Leave(CSigComp::EIncompleteMessage);
       
   304         }
       
   305 
       
   306     TUint tmp;
       
   307     if (msgReader->ReadByte(tmp) != KErrNone)
       
   308         {
       
   309         User::Leave(CSigComp::EIncompleteMessage);
       
   310         }
       
   311 
       
   312     //is sigcomp message?
       
   313     if ((tmp & KSigCompHeaderMask) != KSigCompHeaderMask)
       
   314         {
       
   315         User::Leave(CSigComp::EIncompleteMessage);
       
   316         }
       
   317 
       
   318     // get T bit from header
       
   319     TBool t = tmp & KSigCompHeaderTMask;
       
   320     // partial state identifier length
       
   321     TUint len = tmp & KSigCompHeaderLenMask;
       
   322 
       
   323     // initialize udvm memory
       
   324     if (aStreamBasedProtocol)
       
   325         {
       
   326         iUdvmMemory->InitMemoryL(iUdvmMemory->MemorySize()/2, iCyclesPerBit);
       
   327         }
       
   328     else
       
   329         {
       
   330         iUdvmMemory->InitMemoryL(aMessage.Length(), iCyclesPerBit);
       
   331         }
       
   332     // T bit set, returned feedback present
       
   333     SetReturnedFeedbackL(t, msgReader);
       
   334 
       
   335     if (len)
       
   336         {
       
   337         // partial state identifier
       
   338         UploadStateInMessageL(len, msgReader);
       
   339         }
       
   340     else
       
   341         {
       
   342         // bytecode
       
   343         UploadBytecodeInMessageL(msgReader);
       
   344         }
       
   345 
       
   346     // available cycles, as defined in RFC3220 chapter 8.6
       
   347     iAvailableCycles = (8 * aMessage.Length() + 1000) * iCyclesPerBit;
       
   348 
       
   349     // prepare output buffer
       
   350     CBufFlat* outputBuffer = CBufFlat::NewL(128);
       
   351     CleanupStack::PushL(outputBuffer);
       
   352     outputBuffer->SetReserveL(128);
       
   353     iOutputBuffer = outputBuffer; // used for parameter passing to Opcodes
       
   354 
       
   355     // execute code
       
   356     ExecuteCodeL(msgReader);
       
   357 
       
   358     iOutputBuffer = NULL;
       
   359     CleanupStack::Pop(outputBuffer);
       
   360 
       
   361     // skip end delimiter
       
   362     if (aStreamBasedProtocol)
       
   363         {
       
   364         msgReader->SkipDelimiters(1);
       
   365         }
       
   366 
       
   367     // get message bytes consumed
       
   368     aBytesConsumed = msgReader->Pos();
       
   369 
       
   370     outputBuffer->Compress();
       
   371 
       
   372     CleanupStack::PopAndDestroy(msgReader);
       
   373 
       
   374     return outputBuffer;
       
   375     }
       
   376 
       
   377 // ----------------------------------------------------------------------------
       
   378 // CUdvm::ByteCopyingFragmentL
       
   379 //
       
   380 // ----------------------------------------------------------------------------
       
   381 //
       
   382 
       
   383 inline TUint CUdvm::ByteCopyingFragmentL(TUint& aAddress,
       
   384                                          TUint& aLength,
       
   385                                          TUint aBcl,
       
   386                                          TUint aBcr) const
       
   387     {
       
   388 
       
   389     TUint len;
       
   390 
       
   391     if (((aAddress + 1) <= aBcr) && ((aAddress + aLength) > aBcr))
       
   392         {
       
   393         len = aBcr - aAddress;
       
   394         }
       
   395     else
       
   396         {
       
   397         len = aLength;
       
   398         }
       
   399 
       
   400     if ((aAddress + len) > iUdvmMemory->FreeMemorySize())
       
   401         {
       
   402         User::Leave(CSigComp::EDecompressionFailure);
       
   403         }
       
   404 
       
   405     aLength -= len;
       
   406     aAddress = aBcl;
       
   407 
       
   408     return len;
       
   409     }
       
   410 
       
   411 // ----------------------------------------------------------------------------
       
   412 // CUdvm::UploadCodeL
       
   413 // upload bytecode, initialize UDVM memory and registers
       
   414 // ----------------------------------------------------------------------------
       
   415 //
       
   416 
       
   417 void CUdvm::UploadCodeL(TUint aDest, TUint aLen, CMessageReader* aMsgReader)
       
   418     {
       
   419 
       
   420     // init memory
       
   421     iUdvmMemory->WriteMem16L(EMem_partial_state_ID_length, 0x0000);
       
   422     iUdvmMemory->WriteMem16L(EMem_state_length, 0x0000);
       
   423 
       
   424     // upload code
       
   425     iUdvmMemory->CheckMemAccessL(aDest & KMaxUdvmMemoryMask, aLen);
       
   426     TPtr8 codePtr(iUdvmMemory->MemoryPtr() +
       
   427                   (aDest & KMaxUdvmMemoryMask), aLen);
       
   428     if (aMsgReader->ReadBlock(codePtr) != KErrNone)
       
   429         {
       
   430         User::Leave(CSigComp::EIncompleteMessage);
       
   431                 }
       
   432 
       
   433     iCodeStart = aDest;
       
   434     }
       
   435 
       
   436 
       
   437 // ----------------------------------------------------------------------------
       
   438 // CUdvm::UploadStateL
       
   439 // upload state item, initialize UDVM memory and registers
       
   440 // ----------------------------------------------------------------------------
       
   441 //
       
   442 
       
   443 void CUdvm::UploadStateL(TUint aStateLen, const TUint8* aState)
       
   444     {
       
   445 
       
   446     TStateItem* si = iStateMgr->FindStateItem(TPtrC8(aState, aStateLen));
       
   447 
       
   448     if (si == NULL)
       
   449         {
       
   450         User::Leave(CSigComp::EDecompressionFailure);
       
   451         }
       
   452 
       
   453     TestStateAccessLenL(si, aStateLen);
       
   454 
       
   455     // init memory
       
   456     iUdvmMemory->WriteMem16L(EMem_partial_state_ID_length, aStateLen);
       
   457     iUdvmMemory->WriteMem16L(EMem_state_length, si->iStateLength);
       
   458 
       
   459     // upload state value
       
   460     iUdvmMemory->CopyToMemL(si->iStateAddress & KMaxUdvmMemoryMask,
       
   461                             si->iStateValue,
       
   462                             si->iStateLength);
       
   463 
       
   464     iCodeStart = si->iStateInstruction;
       
   465     }
       
   466 
       
   467 
       
   468 // ----------------------------------------------------------------------------
       
   469 // CUdvm::TestStateAccessLenL
       
   470 // test state access lenght
       
   471 // ----------------------------------------------------------------------------
       
   472 //
       
   473 
       
   474 void CUdvm::TestStateAccessLenL(const TStateItem* aStateItem,
       
   475                                 TUint aAccessLen) const
       
   476     {
       
   477 
       
   478     if (aAccessLen < aStateItem->iMinimumAccessLength)
       
   479         {
       
   480         User::Leave(CSigComp::EDecompressionFailure);
       
   481         }
       
   482     }
       
   483 
       
   484 
       
   485 // ----------------------------------------------------------------------------
       
   486 // CUdvm::InputMessageBitsL
       
   487 // input message bits
       
   488 // ----------------------------------------------------------------------------
       
   489 //
       
   490 
       
   491 TUint CUdvm::InputMessageBitsL(TUint aSize, TUint aP, TUint aF)
       
   492     {
       
   493     // aP and aF are flags from input_bit_order UDVM register
       
   494 
       
   495     // iLastUsedInputBit is number of used bits from readed byte,
       
   496     // zero if need to read next byte
       
   497 
       
   498     //output value
       
   499     TUint val = 0;
       
   500 
       
   501     //it may be needed later, depending on aF flag.
       
   502     TUint l = aSize;
       
   503 
       
   504     //to store the return value of ReadByte function
       
   505     TInt ret = 0;
       
   506 
       
   507     // get aSize bits, aF aP flags indicates from which side bits are taken
       
   508     // (MSB or LSB order)
       
   509     // as described in RFC 3220 chapter 8.2.
       
   510     while (aSize)
       
   511         {
       
   512         if (iLastUsedInputBit == 0)
       
   513             {
       
   514             ret = iInputMessageReader->ReadByte(iLastInputByte);
       
   515 
       
   516             if(ret != KErrNone)
       
   517             	User::Leave( ret );
       
   518             }
       
   519 
       
   520         if (aP)
       
   521             {
       
   522             if (aF)
       
   523                 {
       
   524                 // put LSB of input byte as MSB of output 16-bit word
       
   525                 val >>= 1;
       
   526                 val |= ((iLastInputByte & 1) << 15);
       
   527                 }
       
   528             else
       
   529                 {
       
   530                 // put LSB of input byte as LSB of output 16-bit word
       
   531                 val <<= 1;
       
   532                 val |= (iLastInputByte & 1);
       
   533                 }
       
   534 
       
   535             iLastInputByte >>= 1;
       
   536             }
       
   537         else
       
   538             {
       
   539             if (aF)
       
   540                 {
       
   541                 // put MSB of input byte as MSB of output 16-bit word
       
   542                 val >>= 1;
       
   543                 val |= ((iLastInputByte & 0x80) << 8);
       
   544                 }
       
   545             else
       
   546                 {
       
   547                 // put MSB of input byte as LSB of output 16-bit word
       
   548                 val <<= 1;
       
   549                 val |= ((iLastInputByte & 0x80) >> 7);
       
   550                 }
       
   551 
       
   552             iLastInputByte <<= 1;
       
   553             }
       
   554 
       
   555         //next bit
       
   556         iLastUsedInputBit++;
       
   557 
       
   558         if (iLastUsedInputBit > 7)
       
   559             {
       
   560             iLastUsedInputBit = 0;
       
   561             }
       
   562 
       
   563         aSize--;
       
   564         }
       
   565 
       
   566     //if MSB we have to move it to the right.
       
   567     if (aF)
       
   568         {
       
   569         val >>= (16 - l);
       
   570         }
       
   571 
       
   572     return val;
       
   573     }
       
   574 
       
   575 
       
   576 // ----------------------------------------------------------------------------
       
   577 // CUdvm::DecodeLiteralOperandL
       
   578 // decode literal bytecode operand
       
   579 // ----------------------------------------------------------------------------
       
   580 //
       
   581 
       
   582 TUint CUdvm::DecodeLiteralOperandL(TUint& aAddress) const
       
   583     {
       
   584 
       
   585     TUint value = 0;
       
   586     TUint8 tmp = iUdvmMemory->ReadMem8L(aAddress++);
       
   587 
       
   588         // Bytecode:                       Operand value:      Range:
       
   589 
       
   590     if ((tmp & 0x80) == 0x00)
       
   591         {
       
   592         // 0nnnnnnn                        N                   0 - 127
       
   593         value = tmp & 0x7f;
       
   594         }
       
   595     else if ((tmp & 0xc0) == 0x80)
       
   596         {
       
   597         // 10nnnnnn nnnnnnnn               N                   0 - 16383
       
   598         value = ((tmp & 0x3f) << 8) + iUdvmMemory->ReadMem8L(aAddress++);
       
   599         }
       
   600     else if ((tmp & 0xff) == 0xc0)
       
   601         {
       
   602         // 11000000 nnnnnnnn nnnnnnnn      N                   0 - 65535
       
   603         value = (iUdvmMemory->ReadMem8L(aAddress) << 8)+
       
   604                  iUdvmMemory->ReadMem8L(aAddress + 1);
       
   605         aAddress += 2;
       
   606         }
       
   607     else
       
   608         {
       
   609         // argument error
       
   610         User::Leave(CSigComp::EDecompressionFailure);
       
   611         }
       
   612 
       
   613     return value;
       
   614     }
       
   615 
       
   616 
       
   617 // ----------------------------------------------------------------------------
       
   618 // CUdvm::DecodeReferenceOperandL
       
   619 // decode reference bytecode operand
       
   620 // ----------------------------------------------------------------------------
       
   621 //
       
   622 
       
   623 TUint CUdvm::DecodeReferenceOperandL(TUint& aAddress) const
       
   624     {
       
   625 
       
   626     TUint value = 0;
       
   627     TUint8 tmp = iUdvmMemory->ReadMem8L(aAddress++);
       
   628 
       
   629         // Bytecode:                       Operand value:      Range:
       
   630 
       
   631     if ((tmp & 0x80) == 0x00)
       
   632         {
       
   633         // 0nnnnnnn                        memory[2 * N]       0 - 65535
       
   634         value = (tmp & 0x7f) * 2;
       
   635         }
       
   636     else if ((tmp & 0xc0) == 0x80)
       
   637         {
       
   638         // 10nnnnnn nnnnnnnn               memory[2 * N]       0 - 65535
       
   639         value = (((tmp & 0x3f) << 8) + iUdvmMemory->ReadMem8L(aAddress++)) * 2;
       
   640         }
       
   641     else if ((tmp & 0xff) == 0xc0)
       
   642         {
       
   643         // 11000000 nnnnnnnn nnnnnnnn      memory[N]           0 - 65535
       
   644         value = (iUdvmMemory->ReadMem8L(aAddress) << 8)+
       
   645                  iUdvmMemory->ReadMem8L(aAddress + 1);
       
   646         aAddress += 2;
       
   647         }
       
   648     else
       
   649         {
       
   650         // argument error
       
   651         User::Leave(CSigComp::EDecompressionFailure);
       
   652         }
       
   653 
       
   654     return value;
       
   655     }
       
   656 
       
   657 
       
   658 // ----------------------------------------------------------------------------
       
   659 // CUdvm::DecodeMultitypeOperandL
       
   660 // decode multitype bytecode operand
       
   661 // ----------------------------------------------------------------------------
       
   662 //
       
   663 
       
   664 TUint CUdvm::DecodeMultitypeOperandL(TUint& aAddress) const
       
   665     {
       
   666 
       
   667     TUint value = 0;
       
   668     TUint8 tmp = iUdvmMemory->ReadMem8L(aAddress++);
       
   669 
       
   670         // Bytecode:                       Operand value:      Range:
       
   671 
       
   672     if ((tmp & 0xc0) == 0x00)
       
   673         {
       
   674         // 00nnnnnn                        N                   0 - 63
       
   675         value = tmp & 0x3f;
       
   676         }
       
   677     else if ((tmp & 0xc0) == 0x40)
       
   678         {
       
   679         // 01nnnnnn                        memory[2 * N]       0 - 65535
       
   680         value = iUdvmMemory->ReadMem16L((tmp & 0x3f) * 2);
       
   681         }
       
   682     else if ((tmp & 0xfe) == 0x86)
       
   683         {
       
   684         // 1000011n                        2 ^ (N + 6)        64 , 128
       
   685         value = 1 << ((tmp & 0x01) + 6);
       
   686         }
       
   687     else if ((tmp & 0xf8) == 0x88)
       
   688         {
       
   689         // 10001nnn                        2 ^ (N + 8)    256 , ... , 32768
       
   690         value = 1 << ((tmp & 0x07) + 8);
       
   691         }
       
   692     else if ((tmp & 0xe0) == 0xe0)
       
   693         {
       
   694         // 111nnnnn                        N + 65504       65504 - 65535
       
   695         value = (tmp & 0x1f) + 65504;
       
   696         }
       
   697     else if ((tmp & 0xf0) == 0x90)
       
   698         {
       
   699         // 1001nnnn nnnnnnnn               N + 61440       61440 - 65535
       
   700         value = ((tmp & 0x0f) << 8) + iUdvmMemory->ReadMem8L(aAddress++) +
       
   701                 61440;
       
   702         }
       
   703     else if ((tmp & 0xe0) == 0xa0)
       
   704         {
       
   705         // 101nnnnn nnnnnnnn               N                   0 - 8191
       
   706         value = ((tmp & 0x1f) << 8) + iUdvmMemory->ReadMem8L(aAddress++);
       
   707         }
       
   708     else if ((tmp & 0xe0) == 0xc0)
       
   709         {
       
   710         // 110nnnnn nnnnnnnn               memory[N]           0 - 65535
       
   711         value = iUdvmMemory->ReadMem16L(((tmp & 0x1f) << 8)+
       
   712                                         iUdvmMemory->ReadMem8L(aAddress++));
       
   713         }
       
   714     else if ((tmp & 0xff) == 0x80)
       
   715         {
       
   716         // 10000000 nnnnnnnn nnnnnnnn      N                   0 - 65535
       
   717         value = (iUdvmMemory->ReadMem8L(aAddress) << 8)+
       
   718                  iUdvmMemory->ReadMem8L(aAddress + 1);
       
   719         aAddress += 2;
       
   720         }
       
   721     else if ((tmp & 0xff) == 0x81)
       
   722         {
       
   723         // 10000001 nnnnnnnn nnnnnnnn      memory[N]           0 - 65535
       
   724         value = iUdvmMemory->ReadMem16L((iUdvmMemory->ReadMem8L(aAddress) << 8)
       
   725                 + iUdvmMemory->ReadMem8L(aAddress + 1));
       
   726         aAddress += 2;
       
   727         }
       
   728     else
       
   729         {
       
   730         // argument error
       
   731         User::Leave(CSigComp::EDecompressionFailure);
       
   732         }
       
   733 
       
   734     return value;
       
   735     }
       
   736 
       
   737 // ----------------------------------------------------------------------------
       
   738 // CUdvm::DecodeAddressOperandL
       
   739 // decode address bytecode operand
       
   740 // ----------------------------------------------------------------------------
       
   741 //
       
   742 
       
   743 TUint CUdvm::DecodeAddressOperandL(TUint aPc, TUint& aAddress) const
       
   744     {
       
   745     return (DecodeMultitypeOperandL(aAddress) + aPc) & KMaxUdvmMemoryMask;
       
   746     }
       
   747 
       
   748 
       
   749 // ----------------------------------------------------------------------------
       
   750 
       
   751 TBool CUdvm::ExecuteOpcodeDecompressionFailureL(TUint& /*aPc2*/)
       
   752     {
       
   753     iCycles += 1;
       
   754     User::Leave(CSigComp::EDecompressionFailure);
       
   755     return EFalse; //not covered, never called because of above Leave().
       
   756     }
       
   757 
       
   758 TBool CUdvm::ExecuteOpcodeAndL(TUint& aPc2)
       
   759     {
       
   760     // AND ($operand_1, %operand_2)
       
   761 
       
   762     TUint op1 = DecodeReferenceOperandL(aPc2);
       
   763     TUint op2 = DecodeMultitypeOperandL(aPc2);
       
   764 
       
   765     iUdvmMemory->WriteMem16L(op1, iUdvmMemory->ReadMem16L(op1) & op2);
       
   766     iCycles += 1;
       
   767     return EFalse;
       
   768     }
       
   769 
       
   770 TBool CUdvm::ExecuteOpcodeOrL(TUint& aPc2)
       
   771     {
       
   772     // OR ($operand_1, %operand_2)
       
   773 
       
   774     TUint op1 = DecodeReferenceOperandL(aPc2);
       
   775     TUint op2 = DecodeMultitypeOperandL(aPc2);
       
   776 
       
   777     iUdvmMemory->WriteMem16L(op1, iUdvmMemory->ReadMem16L(op1) | op2);
       
   778     iCycles += 1;
       
   779     return EFalse;
       
   780     }
       
   781 
       
   782 TBool CUdvm::ExecuteOpcodeNotL(TUint& aPc2)
       
   783     {
       
   784     // NOT ($operand_1)
       
   785 
       
   786     TUint op1 = DecodeReferenceOperandL(aPc2);
       
   787 
       
   788     iUdvmMemory->WriteMem16L(op1, iUdvmMemory->ReadMem16L(op1) ^
       
   789                                               KMax16BitValueMask);
       
   790     iCycles += 1;
       
   791     return EFalse;
       
   792     }
       
   793 
       
   794 TBool CUdvm::ExecuteOpcodeLShiftL(TUint& aPc2)
       
   795     {
       
   796     // LSHIFT ($operand_1, %operand_2)
       
   797 
       
   798     TUint op1 = DecodeReferenceOperandL(aPc2);
       
   799     TUint op2 = DecodeMultitypeOperandL(aPc2);
       
   800 
       
   801     iUdvmMemory->WriteMem16L(op1, (iUdvmMemory->ReadMem16L(op1) << op2) &
       
   802                                                            KMax16BitValueMask);
       
   803     iCycles += 1;
       
   804     return EFalse;
       
   805     }
       
   806 
       
   807 TBool CUdvm::ExecuteOpcodeRShiftL(TUint& aPc2)
       
   808     {
       
   809     // RSHIFT ($operand_1, %operand_2)
       
   810 
       
   811     TUint op1 = DecodeReferenceOperandL(aPc2);
       
   812     TUint op2 = DecodeMultitypeOperandL(aPc2);
       
   813 
       
   814     iUdvmMemory->WriteMem16L(op1, (iUdvmMemory->ReadMem16L(op1) >> op2) &
       
   815                                                            KMax16BitValueMask);
       
   816     iCycles += 1;
       
   817     return EFalse;
       
   818     }
       
   819 
       
   820 TBool CUdvm::ExecuteOpcodeAddL(TUint& aPc2)
       
   821     {
       
   822     // ADD ($operand_1, %operand_2)
       
   823 
       
   824     TUint op1 = DecodeReferenceOperandL(aPc2);
       
   825     TUint op2 = DecodeMultitypeOperandL(aPc2);
       
   826 
       
   827     iUdvmMemory->WriteMem16L(op1, (iUdvmMemory->ReadMem16L(op1) + op2) &
       
   828                                                            KMax16BitValueMask);
       
   829     iCycles += 1;
       
   830     return EFalse;
       
   831     }
       
   832 
       
   833 TBool CUdvm::ExecuteOpcodeSubtractL(TUint& aPc2)
       
   834     {
       
   835     // SUBTRACT ($operand_1, %operand_2)
       
   836 
       
   837     TUint op1 = DecodeReferenceOperandL(aPc2);
       
   838     TUint op2 = DecodeMultitypeOperandL(aPc2);
       
   839 
       
   840     iUdvmMemory->WriteMem16L(op1, (iUdvmMemory->ReadMem16L(op1) - op2) &
       
   841                                                            KMax16BitValueMask);
       
   842     iCycles += 1;
       
   843     return EFalse;
       
   844     }
       
   845 
       
   846 TBool CUdvm::ExecuteOpcodeMultiplyL(TUint& aPc2)
       
   847     {
       
   848     // MULTIPLY ($operand_1, %operand_2)
       
   849 
       
   850     TUint op1 = DecodeReferenceOperandL(aPc2);
       
   851     TUint op2 = DecodeMultitypeOperandL(aPc2);
       
   852 
       
   853     iUdvmMemory->WriteMem16L(op1, (iUdvmMemory->ReadMem16L(op1) * op2) &
       
   854                                                            KMax16BitValueMask);
       
   855     iCycles += 1;
       
   856     return EFalse;
       
   857     }
       
   858 
       
   859 TBool CUdvm::ExecuteOpcodeDivideL(TUint& aPc2)
       
   860     {
       
   861     // DIVIDE ($operand_1, %operand_2)
       
   862 
       
   863     TUint op1 = DecodeReferenceOperandL(aPc2);
       
   864     TUint op2 = DecodeMultitypeOperandL(aPc2);
       
   865 
       
   866     if (op2 == 0)
       
   867         {
       
   868         User::Leave(CSigComp::EDecompressionFailure);
       
   869         }
       
   870 
       
   871     iUdvmMemory->WriteMem16L(op1, (iUdvmMemory->ReadMem16L(op1) / op2) &
       
   872                                                            KMax16BitValueMask);
       
   873     iCycles += 1;
       
   874     return EFalse;
       
   875     }
       
   876 
       
   877 TBool CUdvm::ExecuteOpcodeRemainderL(TUint& aPc2)
       
   878     {
       
   879     // REMAINDER ($operand_1, %operand_2)
       
   880 
       
   881     TUint op1 = DecodeReferenceOperandL(aPc2);
       
   882     TUint op2 = DecodeMultitypeOperandL(aPc2);
       
   883 
       
   884     if (op2 == 0)
       
   885         {
       
   886         User::Leave(CSigComp::EDecompressionFailure);
       
   887         }
       
   888 
       
   889     iUdvmMemory->WriteMem16L(op1, (iUdvmMemory->ReadMem16L(op1) % op2) &
       
   890                                                            KMax16BitValueMask);
       
   891     iCycles += 1;
       
   892     return EFalse;
       
   893     }
       
   894 
       
   895 TBool CUdvm::ExecuteOpcodeAscendingL(TUint& aPc2)
       
   896     {
       
   897     // SORT-ASCENDING (%start, %n, %k)
       
   898 
       
   899     TUint start = DecodeMultitypeOperandL(aPc2);
       
   900     TUint n = DecodeMultitypeOperandL(aPc2);
       
   901     TUint k = DecodeMultitypeOperandL(aPc2);
       
   902 
       
   903     TBool sort;
       
   904     TUint16 a;
       
   905     TUint16 b;
       
   906 
       
   907     do
       
   908         {
       
   909         sort = EFalse;
       
   910 
       
   911         for (TUint i = 0; i < (k - 1); i++)
       
   912             {
       
   913             a = iUdvmMemory->ReadMem16L(start + 2 * i);
       
   914             b = iUdvmMemory->ReadMem16L(start + 2 * (i + 1));
       
   915 
       
   916             if (a > b)
       
   917                 {
       
   918                 iUdvmMemory->WriteMem16L(start + i * 2, b);
       
   919                 iUdvmMemory->WriteMem16L(start + (i + 1) * 2, a);
       
   920                 for (TUint j = 1; j < n; j++)
       
   921                     {
       
   922                     a = iUdvmMemory->ReadMem16L(start + j * k * 2 + i * 2);
       
   923                     iUdvmMemory->WriteMem16L(start + j * k * 2 + i * 2,
       
   924                     iUdvmMemory->ReadMem16L(start + j * k * 2 + (i + 1) * 2));
       
   925                     iUdvmMemory->WriteMem16L(start + j * k * 2 + (i + 1) * 2,
       
   926                                                                             a);
       
   927                     }
       
   928                 sort = ETrue;
       
   929                 }
       
   930             }
       
   931         }
       
   932     while (sort);
       
   933 
       
   934     //cost = 1 + k * (ceiling(log2(k)) + n)
       
   935     TInt i;
       
   936     for (i = 15; i >= 0 && !(k & (1 << i));)
       
   937         {
       
   938         i--;
       
   939         }
       
   940 
       
   941     if (k & (~(1 << i)))
       
   942         {
       
   943         i++;
       
   944         }
       
   945 
       
   946     iCycles += (1 + (k * (i + n)));
       
   947     return EFalse;
       
   948     }
       
   949 
       
   950 TBool CUdvm::ExecuteOpcodeDescendingL(TUint& aPc2)
       
   951     {
       
   952     // SORT-DESCENDING (%start, %n, %k)
       
   953 
       
   954     TUint start = DecodeMultitypeOperandL(aPc2);
       
   955     TUint n = DecodeMultitypeOperandL(aPc2);
       
   956     TUint k = DecodeMultitypeOperandL(aPc2);
       
   957 
       
   958     TBool sort;
       
   959     TUint16 a;
       
   960     TUint16 b;
       
   961 
       
   962     do
       
   963         {
       
   964         sort = EFalse;
       
   965 
       
   966         for (TUint i = 0; i < (k - 1); i++)
       
   967             {
       
   968             a = iUdvmMemory->ReadMem16L(start + i * 2);
       
   969             b = iUdvmMemory->ReadMem16L(start + (i + 1) * 2);
       
   970 
       
   971             if (a < b)
       
   972                 {
       
   973                 iUdvmMemory->WriteMem16L(start + i * 2, b);
       
   974                 iUdvmMemory->WriteMem16L(start + (i + 1) * 2, a);
       
   975                 for (TUint j = 1; j < n; j++)
       
   976                     {
       
   977                     a = iUdvmMemory->ReadMem16L(start + j * k * 2 + i * 2);
       
   978                     iUdvmMemory->WriteMem16L(start + j * k * 2 + i * 2,
       
   979                     iUdvmMemory->ReadMem16L(start + j * k * 2 + (i + 1) * 2));
       
   980                     iUdvmMemory->WriteMem16L(start + j * k * 2 + (i + 1) * 2,
       
   981                                                                             a);
       
   982                     }
       
   983                 sort = ETrue;
       
   984                 }
       
   985             }
       
   986         }
       
   987     while (sort);
       
   988 
       
   989     // cost = 1 + k * (ceiling(log2(k)) + n)
       
   990     TInt i;
       
   991     for (i = 15; i >= 0 && !(k & (1 << i));)
       
   992         {
       
   993         i--;
       
   994         }
       
   995 
       
   996     if (k & (~(1 << i)))
       
   997         {
       
   998         i++;
       
   999         }
       
  1000     iCycles += 1 + k * (i + n);
       
  1001     return EFalse;
       
  1002     }
       
  1003 
       
  1004 TBool CUdvm::ExecuteOpcodeSha1L(TUint& aPc2)
       
  1005     {
       
  1006     // SHA-1 (%position, %length, %destination)
       
  1007     // NOTE: byte copying
       
  1008 
       
  1009     TUint position = DecodeMultitypeOperandL(aPc2);
       
  1010     TUint length = DecodeMultitypeOperandL(aPc2);
       
  1011     TUint destination = DecodeMultitypeOperandL(aPc2);
       
  1012 
       
  1013     iCycles += 1 + length;
       
  1014 
       
  1015     TUint bcl = iUdvmMemory->ReadMem16L(EReg_byte_copy_left);
       
  1016     TUint bcr = iUdvmMemory->ReadMem16L(EReg_byte_copy_right);
       
  1017 
       
  1018     iSHA1->Reset();
       
  1019 
       
  1020     while (length)
       
  1021         {
       
  1022         TUint nextpos = position;
       
  1023         TUint len = ByteCopyingFragmentL(nextpos,
       
  1024                                          length,
       
  1025                                          bcl,
       
  1026                                          bcr);
       
  1027 
       
  1028         if (len)
       
  1029             {
       
  1030             TPtrC8 data = TPtrC8(&iUdvmMemory->MemoryPtr()[position], len);
       
  1031             iSHA1->Hash(data);
       
  1032             }
       
  1033 
       
  1034         position = nextpos;
       
  1035         }
       
  1036 
       
  1037     TPtrC8 hash = iSHA1->Hash(KNullDesC8);
       
  1038     const TUint8* SHA1result = hash.Ptr();
       
  1039 
       
  1040     TUint respos = 0;
       
  1041     length = 20;
       
  1042 
       
  1043     while (length)
       
  1044         {
       
  1045         TUint newdest = destination;
       
  1046         TUint len = ByteCopyingFragmentL(newdest,
       
  1047                                          length,
       
  1048                                          bcl,
       
  1049                                          bcr);
       
  1050 
       
  1051         for (TUint i = 0; i < len; i++)
       
  1052             {
       
  1053             iUdvmMemory->MemoryPtr()[destination + i] = SHA1result[respos + i];
       
  1054             }
       
  1055 
       
  1056         destination = newdest;
       
  1057         respos += len;
       
  1058         }
       
  1059     return EFalse;
       
  1060     }
       
  1061 
       
  1062 TBool CUdvm::ExecuteOpcodeLoadL(TUint& aPc2)
       
  1063     {
       
  1064     // LOAD (%address, %value)
       
  1065 
       
  1066     TUint address = DecodeMultitypeOperandL(aPc2);
       
  1067     TUint value = DecodeMultitypeOperandL(aPc2);
       
  1068 
       
  1069     iUdvmMemory->WriteMem16L(address, value);
       
  1070     iCycles += 1;
       
  1071     return EFalse;
       
  1072     }
       
  1073 
       
  1074 TBool CUdvm::ExecuteOpcodeMultiloadL(TUint& aPc2)
       
  1075     {
       
  1076     // MULTILOAD (%address, #n, %value_0, ..., %value_n-1)
       
  1077 
       
  1078     TUint pc = aPc2 - 1;
       
  1079 
       
  1080     TUint address = DecodeMultitypeOperandL(aPc2);
       
  1081     TUint n = DecodeLiteralOperandL(aPc2);
       
  1082 
       
  1083     for (TUint i = 0; i < n; i++)
       
  1084         {
       
  1085         TUint value = DecodeMultitypeOperandL(aPc2);
       
  1086 
       
  1087         // check overlaping instruction location
       
  1088         if (!((address >= aPc2) || ((address + n * 2) <= pc)))
       
  1089             {
       
  1090             User::Leave(CSigComp::EDecompressionFailure);
       
  1091             }
       
  1092 
       
  1093         iUdvmMemory->WriteMem16L(address + i * 2, value);
       
  1094         }
       
  1095     iCycles += 1 + n;
       
  1096     return EFalse;
       
  1097     }
       
  1098 
       
  1099 TBool CUdvm::ExecuteOpcodePushL(TUint& aPc2)
       
  1100     {
       
  1101     // PUSH (%value)
       
  1102 
       
  1103     TUint value = DecodeMultitypeOperandL(aPc2);
       
  1104 
       
  1105     TUint sl = iUdvmMemory->ReadMem16L(EReg_stack_location);
       
  1106     TUint sf = iUdvmMemory->ReadMem16L(sl);
       
  1107 
       
  1108     iUdvmMemory->WriteMem16L((sl + 2 + sf * 2) & KMaxUdvmMemoryMask, value);
       
  1109     iUdvmMemory->WriteMem16L(sl, (sf + 1) & KMax16BitValueMask);
       
  1110     iCycles += 1;
       
  1111     return EFalse;
       
  1112     }
       
  1113 
       
  1114 TBool CUdvm::ExecuteOpcodePopL(TUint& aPc2)
       
  1115     {
       
  1116     // POP (%address)
       
  1117 
       
  1118     TUint address = DecodeMultitypeOperandL(aPc2);
       
  1119 
       
  1120     TUint sl = iUdvmMemory->ReadMem16L(EReg_stack_location);
       
  1121     TUint sf = (iUdvmMemory->ReadMem16L(sl) - 1) & KMaxUdvmMemoryMask;
       
  1122 
       
  1123     iUdvmMemory->WriteMem16L(sl, sf);
       
  1124     iUdvmMemory->WriteMem16L(address,
       
  1125                         iUdvmMemory->ReadMem16L((sl + 2 + sf * 2) &
       
  1126                                                      KMaxUdvmMemoryMask));
       
  1127     iCycles += 1;
       
  1128     return EFalse;
       
  1129     }
       
  1130 
       
  1131 TBool CUdvm::ExecuteOpcodeCopyL(TUint& aPc2)
       
  1132     {
       
  1133     // COPY (%position, %length, %destination)
       
  1134     // NOTE: byte copying
       
  1135 
       
  1136     TUint position = DecodeMultitypeOperandL(aPc2);
       
  1137     TUint length = DecodeMultitypeOperandL(aPc2);
       
  1138     TUint destination = DecodeMultitypeOperandL(aPc2);
       
  1139 
       
  1140     iCycles += 1 + length;
       
  1141 
       
  1142     TUint bcl = iUdvmMemory->ReadMem16L(EReg_byte_copy_left);
       
  1143     TUint bcr = iUdvmMemory->ReadMem16L(EReg_byte_copy_right);
       
  1144 
       
  1145     while (length)
       
  1146         {
       
  1147         iUdvmMemory->WriteMem8L(destination, iUdvmMemory->ReadMem8L(position));
       
  1148 
       
  1149         destination++;
       
  1150         destination &= KMaxUdvmMemoryMask;
       
  1151         position++;
       
  1152         position &= KMaxUdvmMemoryMask;
       
  1153 
       
  1154         length--;
       
  1155 
       
  1156         if (destination == bcr)
       
  1157             {
       
  1158             destination = bcl;
       
  1159             }
       
  1160 
       
  1161         if (position == bcr)
       
  1162             {
       
  1163             position = bcl;
       
  1164             }
       
  1165         }
       
  1166     return EFalse;
       
  1167     }
       
  1168 
       
  1169 TBool CUdvm::ExecuteOpcodeCopyLiteralL(TUint& aPc2)
       
  1170     {
       
  1171     // COPY-LITERAL (%position, %length, $destination)
       
  1172     // NOTE: byte copying
       
  1173 
       
  1174     TUint position = DecodeMultitypeOperandL(aPc2);
       
  1175     TUint length = DecodeMultitypeOperandL(aPc2);
       
  1176     TUint destination = DecodeReferenceOperandL(aPc2);
       
  1177 
       
  1178     iCycles += 1 + length;
       
  1179 
       
  1180     if (length)
       
  1181         {
       
  1182         TUint bcl = iUdvmMemory->ReadMem16L(EReg_byte_copy_left);
       
  1183         TUint bcr = iUdvmMemory->ReadMem16L(EReg_byte_copy_right);
       
  1184 
       
  1185         TUint dest = iUdvmMemory->ReadMem16L(destination);
       
  1186 
       
  1187         while (length)
       
  1188             {
       
  1189             iUdvmMemory->WriteMem8L(dest, iUdvmMemory->ReadMem8L(position));
       
  1190 
       
  1191             dest++;
       
  1192             dest &= KMaxUdvmMemoryMask;
       
  1193             position++;
       
  1194             position &= KMaxUdvmMemoryMask;
       
  1195 
       
  1196             length--;
       
  1197 
       
  1198             if (dest == bcr)
       
  1199                 {
       
  1200                 dest = bcl;
       
  1201                 }
       
  1202 
       
  1203             if (position == bcr)
       
  1204                 {
       
  1205                 position = bcl;
       
  1206                 }
       
  1207             }
       
  1208         iUdvmMemory->WriteMem16L(destination, dest);
       
  1209         }
       
  1210     return EFalse;
       
  1211     }
       
  1212 
       
  1213 TBool CUdvm::ExecuteOpcodeCopyOffsetL(TUint& aPc2)
       
  1214     {
       
  1215     // COPY-OFFSET (%offset, %length, $destination)
       
  1216     // NOTE: byte copying
       
  1217 
       
  1218     TUint offset = DecodeMultitypeOperandL(aPc2);
       
  1219     TUint length = DecodeMultitypeOperandL(aPc2);
       
  1220     TUint destination = DecodeReferenceOperandL(aPc2);
       
  1221 
       
  1222     iCycles += 1 + length;    // not 1+length+offset !!!
       
  1223 
       
  1224     if (length)
       
  1225         {
       
  1226         TUint bcl = iUdvmMemory->ReadMem16L(EReg_byte_copy_left);
       
  1227         TUint bcr = iUdvmMemory->ReadMem16L(EReg_byte_copy_right);
       
  1228 
       
  1229         TUint dest = iUdvmMemory->ReadMem16L(destination);
       
  1230 
       
  1231         TUint position = dest;
       
  1232         while (offset)
       
  1233             {
       
  1234             if (position == bcl)
       
  1235                 {
       
  1236                 position = (bcr - 1) & KMaxUdvmMemoryMask;
       
  1237                 }
       
  1238             else
       
  1239                 {
       
  1240                 position--;
       
  1241                 }
       
  1242             offset--;
       
  1243             }
       
  1244 
       
  1245         while (length)
       
  1246             {
       
  1247             iUdvmMemory->WriteMem8L(dest, iUdvmMemory->ReadMem8L(position));
       
  1248 
       
  1249             dest++;
       
  1250             dest &= KMaxUdvmMemoryMask;
       
  1251             position++;
       
  1252             position &= KMaxUdvmMemoryMask;
       
  1253 
       
  1254             length--;
       
  1255 
       
  1256             if (dest == bcr)
       
  1257                 {
       
  1258                 dest = bcl;
       
  1259                 }
       
  1260 
       
  1261             if (position == bcr)
       
  1262                 {
       
  1263                 position = bcl;
       
  1264                 }
       
  1265             }
       
  1266 
       
  1267         iUdvmMemory->WriteMem16L(destination, dest);
       
  1268         }
       
  1269     return EFalse;
       
  1270     }
       
  1271 
       
  1272 TBool CUdvm::ExecuteOpcodeMemsetL(TUint& aPc2)
       
  1273     {
       
  1274     // MEMSET (%address, %length, %start_value, %offset)
       
  1275     // NOTE: byte copying
       
  1276 
       
  1277     TUint address = DecodeMultitypeOperandL(aPc2);
       
  1278     TUint length = DecodeMultitypeOperandL(aPc2);
       
  1279     TUint value = DecodeMultitypeOperandL(aPc2);
       
  1280     TUint offset = DecodeMultitypeOperandL(aPc2);
       
  1281 
       
  1282     iCycles += 1 + length;
       
  1283 
       
  1284     if (length)
       
  1285         {
       
  1286         TUint bcl = iUdvmMemory->ReadMem16L(EReg_byte_copy_left);
       
  1287         TUint bcr = iUdvmMemory->ReadMem16L(EReg_byte_copy_right);
       
  1288 
       
  1289         while (length)
       
  1290             {
       
  1291             iUdvmMemory->WriteMem8L(address, value);
       
  1292             value = (value + offset) & KMax8BitValueMask;
       
  1293 
       
  1294             address++;
       
  1295             address &= KMaxUdvmMemoryMask;
       
  1296             length--;
       
  1297 
       
  1298             if (address == bcr)
       
  1299                 {
       
  1300                 address = bcl;
       
  1301                 }
       
  1302             }
       
  1303         }
       
  1304     return EFalse;
       
  1305     }
       
  1306 
       
  1307 TBool CUdvm::ExecuteOpcodeCompareL(TUint& aPc2)
       
  1308     {
       
  1309     /*
       
  1310     COMPARE (%value_1, %value_2, @address_1,
       
  1311              @address_2, @address_3)
       
  1312     */
       
  1313 
       
  1314     TUint pc = aPc2 - 1;
       
  1315 
       
  1316     TUint value1 = DecodeMultitypeOperandL(aPc2);
       
  1317     TUint value2 = DecodeMultitypeOperandL(aPc2);
       
  1318     TUint address1 = DecodeAddressOperandL(pc, aPc2);
       
  1319     TUint address2 = DecodeAddressOperandL(pc, aPc2);
       
  1320     TUint address3 = DecodeAddressOperandL(pc, aPc2);
       
  1321 
       
  1322     if (value1 < value2)
       
  1323         {
       
  1324         aPc2 = address1;
       
  1325         }
       
  1326     else if (value1 == value2)
       
  1327         {
       
  1328         aPc2 = address2;
       
  1329         }
       
  1330     else // if (value1 > value2)
       
  1331         {
       
  1332         aPc2 = address3;
       
  1333         }
       
  1334     iCycles += 1;
       
  1335     return EFalse;
       
  1336     }
       
  1337 
       
  1338 TBool CUdvm::ExecuteOpcodeCallL(TUint& aPc2)
       
  1339     {
       
  1340     // CALL (@address)
       
  1341 
       
  1342     TUint pc = aPc2 - 1;
       
  1343 
       
  1344     TUint address = DecodeAddressOperandL(pc, aPc2);
       
  1345 
       
  1346     TUint sl = iUdvmMemory->ReadMem16L(EReg_stack_location);
       
  1347     TUint sf = iUdvmMemory->ReadMem16L(sl);
       
  1348 
       
  1349     iUdvmMemory->WriteMem16L((sl + 2 + sf * 2) & KMaxUdvmMemoryMask, aPc2);
       
  1350     iUdvmMemory->WriteMem16L(sl, (sf + 1) & KMax16BitValueMask);
       
  1351 
       
  1352     aPc2 = address;
       
  1353     iCycles += 1;
       
  1354     return EFalse;
       
  1355     }
       
  1356 
       
  1357 TBool CUdvm::ExecuteOpcodeReturnL(TUint& aPc2)
       
  1358     {
       
  1359     // RETURN
       
  1360 
       
  1361     TUint sl = iUdvmMemory->ReadMem16L(EReg_stack_location);
       
  1362     TUint sf = (iUdvmMemory->ReadMem16L(sl) - 1) & KMaxUdvmMemoryMask;
       
  1363 
       
  1364     iUdvmMemory->WriteMem16L(sl, sf);
       
  1365     aPc2 = iUdvmMemory->ReadMem16L((sl + 2 + sf * 2) & KMaxUdvmMemoryMask);
       
  1366 
       
  1367     iCycles += 1;
       
  1368     return EFalse;
       
  1369     }
       
  1370 
       
  1371 TBool CUdvm::ExecuteOpcodeSwitchL(TUint& aPc2)
       
  1372     {
       
  1373     // SWITCH (#n, %j, @address_0, @address_1, ... , @address_n-1)
       
  1374 
       
  1375     TUint pc = aPc2 - 1;
       
  1376 
       
  1377     TUint n = DecodeLiteralOperandL(aPc2);
       
  1378     TUint j = DecodeMultitypeOperandL(aPc2);
       
  1379 
       
  1380     if (j >= n)
       
  1381         {
       
  1382         User::Leave(CSigComp::EDecompressionFailure);
       
  1383         }
       
  1384 
       
  1385     TUint address;
       
  1386     do
       
  1387         {
       
  1388         address = DecodeAddressOperandL(pc, aPc2);
       
  1389         }
       
  1390     while (j--);
       
  1391 
       
  1392     aPc2 = address;
       
  1393 
       
  1394     iCycles += 1 + n;
       
  1395     return EFalse;
       
  1396     }
       
  1397 
       
  1398 TBool CUdvm::ExecuteOpcodeCrcL(TUint& aPc2)
       
  1399     {
       
  1400     // CRC (%value, %position, %length, @address)
       
  1401     // NOTE: byte copying
       
  1402 
       
  1403     TUint pc = aPc2 - 1;
       
  1404 
       
  1405     TUint value = DecodeMultitypeOperandL(aPc2);
       
  1406     TUint position = DecodeMultitypeOperandL(aPc2);
       
  1407     TUint length = DecodeMultitypeOperandL(aPc2);
       
  1408     TUint address = DecodeAddressOperandL(pc, aPc2);
       
  1409 
       
  1410     iCycles += 1 + length;
       
  1411 
       
  1412     TUint bcl = iUdvmMemory->ReadMem16L(EReg_byte_copy_left);
       
  1413     TUint bcr = iUdvmMemory->ReadMem16L(EReg_byte_copy_right);
       
  1414 
       
  1415     TUint16 crc = Crc::KFcsInit;
       
  1416 
       
  1417     while (length)
       
  1418         {
       
  1419         TUint nextpos = position;
       
  1420         TUint len = ByteCopyingFragmentL(nextpos,
       
  1421                                          length,
       
  1422                                          bcl,
       
  1423                                          bcr);
       
  1424 
       
  1425         if (len)
       
  1426             {
       
  1427             crc = Crc::Calc(&iUdvmMemory->MemoryPtr()[position], len, crc);
       
  1428             }
       
  1429 
       
  1430         position = nextpos;
       
  1431         }
       
  1432 
       
  1433     if (crc != value)
       
  1434         {
       
  1435         aPc2 = address;
       
  1436         }
       
  1437     return EFalse;
       
  1438     }
       
  1439 
       
  1440 TBool CUdvm::ExecuteOpcodeInputBytesL(TUint& aPc2)
       
  1441     {
       
  1442     // INPUT-BYTES (%length, %destination, @address)
       
  1443     // NOTE: byte copying
       
  1444 
       
  1445     TUint pc = aPc2 - 1;
       
  1446 
       
  1447     TUint length = DecodeMultitypeOperandL(aPc2);
       
  1448     TUint destination = DecodeMultitypeOperandL(aPc2);
       
  1449     TUint address = DecodeAddressOperandL(pc, aPc2);
       
  1450 
       
  1451     iCycles += 1 + length;
       
  1452 
       
  1453     if (iLastUsedInputBit)
       
  1454         {
       
  1455         iLastUsedInputBit = 0;
       
  1456         }
       
  1457 
       
  1458     if (iInputMessageReader->Avail(length) != KErrNone)
       
  1459         {
       
  1460         aPc2 = address;
       
  1461         }
       
  1462     else
       
  1463         {
       
  1464         TUint bcl = iUdvmMemory->ReadMem16L(EReg_byte_copy_left);
       
  1465         TUint bcr = iUdvmMemory->ReadMem16L(EReg_byte_copy_right);
       
  1466 
       
  1467         while (length)
       
  1468             {
       
  1469             TUint nextdest = destination;
       
  1470             TUint len = ByteCopyingFragmentL(nextdest,
       
  1471                                              length,
       
  1472                                              bcl,
       
  1473                                              bcr);
       
  1474 
       
  1475             if (len)
       
  1476                 {
       
  1477                 TPtr8 blockPtr(iUdvmMemory->MemoryPtr() + destination, len);
       
  1478                 iInputMessageReader->ReadBlock(blockPtr);
       
  1479                 }
       
  1480 
       
  1481             destination = nextdest;
       
  1482             }
       
  1483         }
       
  1484     return EFalse;
       
  1485     }
       
  1486 
       
  1487 TBool CUdvm::ExecuteOpcodeInputBitsL(TUint& aPc2)
       
  1488     {
       
  1489     // INPUT-BITS (%length, %destination, @address)
       
  1490 
       
  1491     TUint pc = aPc2 - 1;
       
  1492 
       
  1493     TUint length = DecodeMultitypeOperandL(aPc2);
       
  1494     TUint destination = DecodeMultitypeOperandL(aPc2);
       
  1495     TUint address = DecodeAddressOperandL(pc, aPc2);
       
  1496 
       
  1497     iCycles += 1;
       
  1498 
       
  1499     if (length > 16)
       
  1500         {
       
  1501         User::Leave(CSigComp::EDecompressionFailure);
       
  1502         }
       
  1503 
       
  1504     TUint ibo = iUdvmMemory->ReadMem16L(EReg_input_bit_order);
       
  1505 
       
  1506     if (ibo & (~(EIBOFlag_P | EIBOFlag_H | EIBOFlag_F)))
       
  1507         {
       
  1508         User::Leave(CSigComp::EDecompressionFailure);
       
  1509         }
       
  1510 
       
  1511     if ((iLastIBO ^ ibo) & EIBOFlag_P)
       
  1512         {
       
  1513         // P bit changed
       
  1514         iLastUsedInputBit = 0;
       
  1515         }
       
  1516 
       
  1517     // bytes to read
       
  1518     TUint btr = (length - ((8 - iLastUsedInputBit) & 7) + 7) >> 3;
       
  1519 
       
  1520     if (iInputMessageReader->Avail(btr) != KErrNone)
       
  1521         {
       
  1522         aPc2 = address;
       
  1523         }
       
  1524     else
       
  1525         {
       
  1526         iUdvmMemory->WriteMem16L(destination,
       
  1527                                  InputMessageBitsL(length,
       
  1528                                                    ibo&EIBOFlag_P,
       
  1529                                                    ibo&EIBOFlag_F));
       
  1530         }
       
  1531     iLastIBO = ibo;
       
  1532     return EFalse;
       
  1533     }
       
  1534 
       
  1535 TBool CUdvm::ExecuteOpcodeInputHuffmanL(TUint& aPc2)
       
  1536     {
       
  1537     // INPUT-HUFFMAN (%destination, @address, #n,
       
  1538     // bits_1, %lower_bound_1,%upper_bound_1, %uncompressed_1, ...,
       
  1539     // bits_n, %lower_bound_n,%upper_bound_n, %uncompressed_n)
       
  1540 
       
  1541     TUint pc = aPc2 - 1;
       
  1542 
       
  1543     TUint destination = DecodeMultitypeOperandL(aPc2);
       
  1544     TUint address = DecodeAddressOperandL(pc, aPc2);
       
  1545     TUint n = DecodeLiteralOperandL(aPc2);
       
  1546 
       
  1547     iCycles += 1 + n;
       
  1548 
       
  1549     TUint ibo = iUdvmMemory->ReadMem16L(EReg_input_bit_order);
       
  1550 
       
  1551     if (ibo & (~(EIBOFlag_P | EIBOFlag_H | EIBOFlag_F)))
       
  1552         {
       
  1553         User::Leave(CSigComp::EDecompressionFailure);
       
  1554         }
       
  1555 
       
  1556     if ((iLastIBO ^ ibo) & EIBOFlag_P)
       
  1557         {
       
  1558         // P bit changed
       
  1559         iLastUsedInputBit = 0;
       
  1560         }
       
  1561 
       
  1562     TUint p = ibo & EIBOFlag_P;
       
  1563     TUint h = ibo & EIBOFlag_H;
       
  1564 
       
  1565     TUint val = 0;
       
  1566     TUint bits = 0;
       
  1567     TUint len;
       
  1568     TUint lower;
       
  1569     TUint upper;
       
  1570     TUint uncompressed;
       
  1571 
       
  1572     TBool quit = EFalse;
       
  1573     while (n && !quit)
       
  1574         {
       
  1575         len = DecodeMultitypeOperandL(aPc2);
       
  1576         lower = DecodeMultitypeOperandL(aPc2);
       
  1577         upper = DecodeMultitypeOperandL(aPc2);
       
  1578         uncompressed = DecodeMultitypeOperandL(aPc2);
       
  1579 
       
  1580         bits += len;
       
  1581         if (bits > 16)
       
  1582             {
       
  1583             User::Leave(CSigComp::EDecompressionFailure);
       
  1584             }
       
  1585 
       
  1586         // bytes to read
       
  1587         TUint btr = (len - ((8 - iLastUsedInputBit) & 7) + 7) >> 3;
       
  1588 
       
  1589         if (iInputMessageReader->Avail(btr) != KErrNone)
       
  1590             {
       
  1591             aPc2 = address;
       
  1592             n = 1;
       
  1593             quit = ETrue;
       
  1594             }
       
  1595 
       
  1596         if (!quit)
       
  1597             {
       
  1598             val = (val << len) | InputMessageBitsL(len, p, h);
       
  1599 
       
  1600             if ((val >= lower) && (val <= upper))
       
  1601                 {
       
  1602                 iUdvmMemory->WriteMem16L(destination,
       
  1603                             (val + uncompressed - lower) & KMax16BitValueMask);
       
  1604                 quit = ETrue;
       
  1605                 }
       
  1606             if (!quit)
       
  1607                 {
       
  1608                 n--;
       
  1609                 }
       
  1610             }
       
  1611         }
       
  1612 
       
  1613     if (n == 0)
       
  1614         {
       
  1615         User::Leave(CSigComp::EDecompressionFailure);
       
  1616         }
       
  1617 
       
  1618     n--;
       
  1619 
       
  1620     while (n)
       
  1621         {
       
  1622         len = DecodeMultitypeOperandL(aPc2);
       
  1623         lower = DecodeMultitypeOperandL(aPc2);
       
  1624         upper = DecodeMultitypeOperandL(aPc2);
       
  1625         uncompressed = DecodeMultitypeOperandL(aPc2);
       
  1626         n--;
       
  1627         }
       
  1628 
       
  1629     iLastIBO = ibo;
       
  1630     return EFalse;
       
  1631     }
       
  1632 
       
  1633 TBool CUdvm::ExecuteOpcodeStateAccessL(TUint& aPc2)
       
  1634     {
       
  1635     /*
       
  1636         STATE-ACCESS (%partial_identifier_start,
       
  1637                       %partial_identifier_length,
       
  1638                       state_begin,
       
  1639                       %state_length,
       
  1640                       %state_address, %state_instruction)
       
  1641         NOTE: byte copying
       
  1642     */
       
  1643 
       
  1644     TUint partial_identifier_start = DecodeMultitypeOperandL(aPc2);
       
  1645     TUint partial_identifier_length = DecodeMultitypeOperandL(aPc2);
       
  1646     TUint state_begin = DecodeMultitypeOperandL(aPc2);
       
  1647     TUint state_length = DecodeMultitypeOperandL(aPc2);
       
  1648     TUint state_address = DecodeMultitypeOperandL(aPc2);
       
  1649     TUint state_instruction = DecodeMultitypeOperandL(aPc2);
       
  1650 
       
  1651     if ((partial_identifier_length < KStateIdentifierMinLength) ||
       
  1652        (partial_identifier_length > KStateIdentifierMaxLength))
       
  1653         {
       
  1654         User::Leave(CSigComp::EDecompressionFailure);
       
  1655         }
       
  1656 
       
  1657     __ASSERT_ALWAYS(partial_identifier_start < iUdvmMemory->MemorySize(),
       
  1658                     User::Leave(CSigComp::EDecompressionFailure));
       
  1659 
       
  1660 
       
  1661     __ASSERT_ALWAYS(partial_identifier_start+partial_identifier_length <=
       
  1662                     iUdvmMemory->MemorySize(),
       
  1663                     User::Leave(CSigComp::EDecompressionFailure));
       
  1664 
       
  1665     TStateItem* si = iStateMgr->FindStateItem(
       
  1666                     TPtrC8(&iUdvmMemory->MemoryPtr()[partial_identifier_start],
       
  1667                     partial_identifier_length));
       
  1668 
       
  1669     if (si == NULL)
       
  1670         {
       
  1671         User::Leave(CSigComp::EDecompressionFailure);
       
  1672         }
       
  1673 
       
  1674     TestStateAccessLenL(si, partial_identifier_length);
       
  1675 
       
  1676     if (state_length == 0)
       
  1677         {
       
  1678         state_length = si->iStateLength;
       
  1679         }
       
  1680 
       
  1681     if (state_address == 0)
       
  1682         {
       
  1683         state_address = si->iStateAddress;
       
  1684         }
       
  1685 
       
  1686     if (state_instruction == 0)
       
  1687         {
       
  1688         state_instruction = si->iStateInstruction;
       
  1689         }
       
  1690 
       
  1691     if ((state_begin + state_length) > si->iStateLength)
       
  1692         {
       
  1693         User::Leave(CSigComp::EDecompressionFailure);
       
  1694         }
       
  1695 
       
  1696     iCycles += 1 + state_length;
       
  1697 
       
  1698     TUint bcl = iUdvmMemory->ReadMem16L(EReg_byte_copy_left);
       
  1699     TUint bcr = iUdvmMemory->ReadMem16L(EReg_byte_copy_right);
       
  1700 
       
  1701     while (state_length)
       
  1702         {
       
  1703         TUint nextdest = state_address;
       
  1704         TUint len = ByteCopyingFragmentL(nextdest,
       
  1705                                          state_length,
       
  1706                                          bcl,
       
  1707                                          bcr);
       
  1708 
       
  1709         if (len)
       
  1710             {
       
  1711             iUdvmMemory->CopyToMemL(state_address,
       
  1712                                     &si->iStateValue[state_begin],
       
  1713                                     len);
       
  1714             state_begin += len;
       
  1715             }
       
  1716 
       
  1717         state_address = nextdest;
       
  1718         }
       
  1719 
       
  1720     if (state_instruction)
       
  1721         {
       
  1722         aPc2 = state_instruction;
       
  1723         }
       
  1724     return EFalse;
       
  1725     }
       
  1726 
       
  1727 TBool CUdvm::ExecuteOpcodeStateCreateL(TUint& aPc2)
       
  1728     {
       
  1729     /*
       
  1730         STATE-CREATE (%state_length,
       
  1731                       %state_address,
       
  1732                       %state_instruction,
       
  1733                       %minimum_access_length,
       
  1734                       %state_retention_priority)
       
  1735     */
       
  1736 
       
  1737     if (iStateCreateRequestsNumber == KMaxStateOperations)
       
  1738         {
       
  1739         User::Leave(CSigComp::EDecompressionFailure);
       
  1740         }
       
  1741 
       
  1742     TUint state_length = DecodeMultitypeOperandL(aPc2);
       
  1743     TUint state_address = DecodeMultitypeOperandL(aPc2);
       
  1744     TUint state_instruction = DecodeMultitypeOperandL(aPc2);
       
  1745     TUint minimum_access_length = DecodeMultitypeOperandL(aPc2);
       
  1746     TUint state_retention_priority = DecodeMultitypeOperandL(aPc2);
       
  1747 
       
  1748     if ((minimum_access_length < KStateIdentifierMinLength) ||
       
  1749        (minimum_access_length > KStateIdentifierMaxLength) ||
       
  1750        (state_retention_priority == KMaxUdvmMemoryMask))
       
  1751         {
       
  1752         User::Leave(CSigComp::EDecompressionFailure);
       
  1753         }
       
  1754 
       
  1755     TUint i = iStateCreateRequestsNumber+iStateFreeRequestsNumber;
       
  1756     iStateOperationRequests[i].iOperation = EOpcode_STATE_CREATE;
       
  1757     iStateOperationRequests[i].iStateLength =
       
  1758                                static_cast<TUint16>(state_length);
       
  1759     iStateOperationRequests[i].iStateAddress =
       
  1760                                static_cast<TUint16>(state_address);
       
  1761     iStateOperationRequests[i].iStateInstruction =
       
  1762                                static_cast<TUint16>(state_instruction);
       
  1763     iStateOperationRequests[i].iMinimumAccessLength =
       
  1764                                static_cast<TUint16>(minimum_access_length);
       
  1765     iStateOperationRequests[i].iStateRetentionPriority =
       
  1766                                static_cast<TUint16>(state_retention_priority);
       
  1767     iStateOperationRequests[i].iStateValue = new (ELeave)
       
  1768                                              CArrayFixFlat<TUint8>(8);
       
  1769     iStateCreateRequestsNumber++;
       
  1770     iStateOperationRequests[i].iStateValue->ResizeL(state_length);
       
  1771 
       
  1772     iCycles += 1 + state_length;
       
  1773 
       
  1774     TUint bcl = iUdvmMemory->ReadMem16L(EReg_byte_copy_left);
       
  1775     TUint bcr = iUdvmMemory->ReadMem16L(EReg_byte_copy_right);
       
  1776 
       
  1777     TUint state_begin = 0;
       
  1778     while (state_length)
       
  1779         {
       
  1780         TUint nextdest = state_address;
       
  1781         TUint len = ByteCopyingFragmentL(nextdest,
       
  1782                                          state_length,
       
  1783                                          bcl,
       
  1784                                          bcr);
       
  1785 
       
  1786         if (len)
       
  1787             {
       
  1788             iUdvmMemory->CopyFromMemL(
       
  1789                       &iStateOperationRequests[i].iStateValue->At(state_begin),
       
  1790                       state_address,
       
  1791                       len);
       
  1792             state_begin += len;
       
  1793             }
       
  1794         state_address = nextdest;
       
  1795         }
       
  1796     return EFalse;
       
  1797     }
       
  1798 
       
  1799 TBool CUdvm::ExecuteOpcodeEndMessageL(TUint& aPc2)
       
  1800     {
       
  1801     /*
       
  1802         END-MESSAGE (%requested_feedback_location,
       
  1803                      %returned_parameters_location,
       
  1804                      %state_length, %state_address,
       
  1805                      %state_instruction,
       
  1806                      %minimum_access_length,
       
  1807                     %state_retention_priority)
       
  1808         NOTE: byte copying
       
  1809     */
       
  1810 
       
  1811     TUint requested_feedback_location = DecodeMultitypeOperandL(aPc2);
       
  1812     TUint returned_parameters_location = DecodeMultitypeOperandL(aPc2);
       
  1813     TUint state_length = DecodeMultitypeOperandL(aPc2);
       
  1814     TUint state_address = DecodeMultitypeOperandL(aPc2);
       
  1815     TUint state_instruction = DecodeMultitypeOperandL(aPc2);
       
  1816     TUint minimum_access_length = DecodeMultitypeOperandL(aPc2);
       
  1817     TUint state_retention_priority = DecodeMultitypeOperandL(aPc2);
       
  1818 
       
  1819     iCycles += 1 + state_length;
       
  1820 
       
  1821     if ((minimum_access_length >= KStateIdentifierMinLength) &&
       
  1822        (minimum_access_length <= KStateIdentifierMaxLength) &&
       
  1823        (state_retention_priority != 0xffff))
       
  1824         {
       
  1825         if (iStateCreateRequestsNumber == KMaxStateOperations)
       
  1826             {
       
  1827             User::Leave(CSigComp::EDecompressionFailure);
       
  1828             }
       
  1829 
       
  1830         TUint i = iStateCreateRequestsNumber+iStateFreeRequestsNumber;
       
  1831         iStateOperationRequests[i].iOperation = EOpcode_STATE_CREATE;
       
  1832         iStateOperationRequests[i].iStateLength =
       
  1833                                        static_cast<TUint16>(state_length);
       
  1834         iStateOperationRequests[i].iStateAddress =
       
  1835                                        static_cast<TUint16>(state_address);
       
  1836         iStateOperationRequests[i].iStateInstruction =
       
  1837                                        static_cast<TUint16>(state_instruction);
       
  1838         iStateOperationRequests[i].iMinimumAccessLength =
       
  1839                                    static_cast<TUint16>(minimum_access_length);
       
  1840         iStateOperationRequests[i].iStateRetentionPriority =
       
  1841                                 static_cast<TUint16>(state_retention_priority);
       
  1842         iStateOperationRequests[i].iStateValue = new (ELeave)
       
  1843                                                  CArrayFixFlat<TUint8>(8);
       
  1844         iStateCreateRequestsNumber++;
       
  1845         iStateOperationRequests[i].iStateValue->ResizeL(state_length);
       
  1846 
       
  1847         TUint bcl = iUdvmMemory->ReadMem16L(EReg_byte_copy_left);
       
  1848         TUint bcr = iUdvmMemory->ReadMem16L(EReg_byte_copy_right);
       
  1849 
       
  1850         TUint state_begin = 0;
       
  1851         while (state_length)
       
  1852             {
       
  1853             TUint nextdest = state_address;
       
  1854             TUint len = ByteCopyingFragmentL(nextdest,
       
  1855                                              state_length,
       
  1856                                              bcl,
       
  1857                                              bcr);
       
  1858 
       
  1859             if (len)
       
  1860                 {
       
  1861                 iUdvmMemory->CopyFromMemL(
       
  1862                       &iStateOperationRequests[i].iStateValue->At(state_begin),
       
  1863                       state_address,
       
  1864                       len);
       
  1865                 state_begin += len;
       
  1866                 }
       
  1867 
       
  1868             state_address = nextdest;
       
  1869             }
       
  1870         }
       
  1871 
       
  1872     if (requested_feedback_location)
       
  1873         {
       
  1874         TUint rfl = requested_feedback_location;
       
  1875 
       
  1876         TUint rf = iUdvmMemory->ReadMem8L(rfl);
       
  1877         rfl++;
       
  1878 
       
  1879         if (rf & ERFFlag_Q)
       
  1880             {
       
  1881             // returned feedback item
       
  1882             TUint rff = iUdvmMemory->ReadMem8L(rfl);
       
  1883             rfl++;
       
  1884 
       
  1885             if (rff & 0x80)
       
  1886                 {
       
  1887                 // long form
       
  1888                 rfl += rff & 0x7f;
       
  1889                 // check memory out of range
       
  1890                 iUdvmMemory->ReadMem8L(rfl - 1);
       
  1891                 }
       
  1892             }
       
  1893 
       
  1894         iRequestedFeedback.Set(&iUdvmMemory->MemoryPtr()
       
  1895                                   [requested_feedback_location],
       
  1896                                rfl - requested_feedback_location,
       
  1897                                rfl - requested_feedback_location);
       
  1898         }
       
  1899     else
       
  1900         {
       
  1901         iRequestedFeedback.Set(NULL, 0, 0);
       
  1902         }
       
  1903 
       
  1904     if (returned_parameters_location)
       
  1905         {
       
  1906         TUint rpl = returned_parameters_location;
       
  1907 
       
  1908         iUdvmMemory->ReadMem8L(rpl);    // cpb dms sms
       
  1909         rpl++;
       
  1910 
       
  1911         iUdvmMemory->ReadMem8L(rpl);    // version
       
  1912         rpl++;
       
  1913 
       
  1914         TBool quit = EFalse;
       
  1915         TUint psi;
       
  1916         for (; !quit; )
       
  1917             {
       
  1918             psi = iUdvmMemory->ReadMem8L(rpl);
       
  1919             rpl++;
       
  1920 
       
  1921             if ((psi < KStateIdentifierMinLength) ||
       
  1922                 (psi > KStateIdentifierMaxLength))
       
  1923                 {
       
  1924                 quit = ETrue;
       
  1925                 }
       
  1926             else
       
  1927                 {
       
  1928                 rpl += psi;
       
  1929                 }
       
  1930             }
       
  1931 
       
  1932         iReturnedParameters.Set(&iUdvmMemory->MemoryPtr()
       
  1933                                    [returned_parameters_location],
       
  1934                                 rpl - returned_parameters_location,
       
  1935                                 rpl - returned_parameters_location);
       
  1936         }
       
  1937     else
       
  1938         {
       
  1939         iReturnedParameters.Set(NULL, 0, 0);
       
  1940         }
       
  1941     return ETrue;
       
  1942     }
       
  1943 
       
  1944 TBool CUdvm::ExecuteOpcodeStateFreeL(TUint& aPc2)
       
  1945     {
       
  1946     /*
       
  1947         STATE-FREE (%partial_identifier_start,
       
  1948                     %partial_identifier_length)
       
  1949     */
       
  1950 
       
  1951     if (iStateFreeRequestsNumber == KMaxStateOperations)
       
  1952         {
       
  1953         User::Leave(CSigComp::EDecompressionFailure);
       
  1954         }
       
  1955 
       
  1956     TUint partial_identifier_start = DecodeMultitypeOperandL(aPc2);
       
  1957     TUint partial_identifier_length = DecodeMultitypeOperandL(aPc2);
       
  1958 
       
  1959     if ((partial_identifier_length < KStateIdentifierMinLength) ||
       
  1960         (partial_identifier_length > KStateIdentifierMaxLength))
       
  1961         {
       
  1962         User::Leave(CSigComp::EDecompressionFailure);
       
  1963         }
       
  1964 
       
  1965     TUint i = iStateCreateRequestsNumber+iStateFreeRequestsNumber;
       
  1966     iStateOperationRequests[i].iOperation = EOpcode_STATE_FREE;
       
  1967     iStateOperationRequests[i].iPartialIdentifierStart =
       
  1968                                static_cast<TUint16>(partial_identifier_start);
       
  1969     iStateOperationRequests[i].iPartialIdentifierLength =
       
  1970                                static_cast<TUint16>(partial_identifier_length);
       
  1971     iStateFreeRequestsNumber++;
       
  1972     iCycles += 1;
       
  1973     return EFalse;
       
  1974     }
       
  1975 
       
  1976 TBool CUdvm::ExecuteOpcodeOutputL(TUint& aPc2)
       
  1977     {
       
  1978     // OUTPUT (%output_start, %output_length)
       
  1979     // NOTE: byte copying
       
  1980 
       
  1981     TUint start = DecodeMultitypeOperandL(aPc2);
       
  1982     TUint length = DecodeMultitypeOperandL(aPc2);
       
  1983 
       
  1984     iCycles += 1 + length;
       
  1985 
       
  1986     TUint bcl = iUdvmMemory->ReadMem16L(EReg_byte_copy_left);
       
  1987     TUint bcr = iUdvmMemory->ReadMem16L(EReg_byte_copy_right);
       
  1988 
       
  1989     while (length)
       
  1990         {
       
  1991         TUint nextstart = start;
       
  1992         TUint len = ByteCopyingFragmentL(nextstart, length, bcl, bcr);
       
  1993 
       
  1994         if (len)
       
  1995             {
       
  1996             iOutputBuffer->InsertL(iOutputBuffer->Size(),
       
  1997                                    &iUdvmMemory->MemoryPtr()[start],
       
  1998                                    len);
       
  1999             }
       
  2000         start = nextstart;
       
  2001         }
       
  2002 
       
  2003     // RFC 3320, chapter 9.4.8:
       
  2004     // Decompression failure occurs if the cumulative number of bytes
       
  2005     // provided to the dispatcher exceeds 65536 bytes.
       
  2006     if (iOutputBuffer->Size() > KMaxOutputSize)
       
  2007         {
       
  2008         User::Leave(CSigComp::EDecompressionFailure);
       
  2009                 }
       
  2010 
       
  2011     return EFalse;
       
  2012     }
       
  2013 
       
  2014 
       
  2015 TBool CUdvm::ExecuteOpcodeJumpL(TUint& aPc2)
       
  2016     {
       
  2017     // JUMP (@address)
       
  2018     TUint pc = aPc2 - 1;
       
  2019     aPc2 = DecodeAddressOperandL(pc, aPc2);
       
  2020     iCycles += 1;
       
  2021     return EFalse;
       
  2022     }
       
  2023 
       
  2024 
       
  2025 // ----------------------------------------------------------------------------
       
  2026 // CUdvm::ExecuteCodeL
       
  2027 // execute UDVM code
       
  2028 // ----------------------------------------------------------------------------
       
  2029 //
       
  2030 
       
  2031 void CUdvm::ExecuteCodeL(CMessageReader* aMsgReader)
       
  2032     {
       
  2033     iInputMessageReader = aMsgReader;
       
  2034     iLastUsedInputBit = 0;
       
  2035 
       
  2036     TPtr8 retf(iReturnedFeedback);
       
  2037     DenyStateOperations();
       
  2038     iReturnedFeedback.Set(retf);
       
  2039 
       
  2040     iOutputBuffer->Reset();
       
  2041 
       
  2042     iCycles = 0;
       
  2043 
       
  2044     TUint pc = iCodeStart;
       
  2045     TBool terminated = EFalse;
       
  2046 
       
  2047     while (!terminated)
       
  2048         {
       
  2049         pc &= KMaxUdvmMemoryMask;
       
  2050         TUint8 opcode = iUdvmMemory->ReadMem8L(pc);
       
  2051         pc++;
       
  2052 
       
  2053         if (opcode >= EOpcodesNumber)
       
  2054             {
       
  2055             // unknown opcode
       
  2056             User::Leave(CSigComp::EDecompressionFailure);
       
  2057             }
       
  2058 
       
  2059         terminated = (this->*iExecuteOpcode[opcode])(pc);
       
  2060 
       
  2061         if (iCycles > iAvailableCycles)
       
  2062             {
       
  2063             User::Leave(CSigComp::EDecompressionFailure);
       
  2064             }
       
  2065         }
       
  2066     }
       
  2067 
       
  2068 
       
  2069 // ----------------------------------------------------------------------------
       
  2070 // CUdvm::AllowStateOperationsL
       
  2071 // allow for state operations
       
  2072 // ----------------------------------------------------------------------------
       
  2073 //
       
  2074 
       
  2075 TInt CUdvm::AllowStateOperationsL(CSigCompCompartment* aCompartment)
       
  2076     {
       
  2077     TInt sso = 0;
       
  2078 
       
  2079     if (iStateMgr && aCompartment)
       
  2080         {
       
  2081         TInt soNum = iStateCreateRequestsNumber + iStateFreeRequestsNumber;
       
  2082 
       
  2083         for (TInt i = 0; i < soNum; i++)
       
  2084             {
       
  2085             if (iStateOperationRequests[i].iOperation == EOpcode_STATE_CREATE)
       
  2086                 {
       
  2087                 if (iStateMgr->CreateStateL(aCompartment,
       
  2088                    iStateOperationRequests[i].iStateLength,
       
  2089                    iStateOperationRequests[i].iStateAddress,
       
  2090                    iStateOperationRequests[i].iStateInstruction,
       
  2091                    iStateOperationRequests[i].iMinimumAccessLength,
       
  2092                    iStateOperationRequests[i].iStateLength ?
       
  2093                    &iStateOperationRequests[i].iStateValue->At(0) : NULL,
       
  2094                    iStateOperationRequests[i].iStateRetentionPriority) != NULL)
       
  2095                     {
       
  2096                     sso++;
       
  2097                     }
       
  2098                 }
       
  2099 
       
  2100             if (iStateOperationRequests[i].iOperation == EOpcode_STATE_FREE)
       
  2101                 {
       
  2102                 if (iStateMgr->FreeStateL(aCompartment,
       
  2103                                          TPtrC8(
       
  2104                           &iUdvmMemory->MemoryPtr()
       
  2105                           [iStateOperationRequests[i].iPartialIdentifierStart],
       
  2106                           iStateOperationRequests[i].iPartialIdentifierLength))
       
  2107                           == KErrNone)
       
  2108                     {
       
  2109                     sso++;
       
  2110                     }
       
  2111                 }
       
  2112             }
       
  2113 
       
  2114         if (sso == soNum)
       
  2115             {
       
  2116             iStateMgr->SetReturnedFeedbackL(*aCompartment,
       
  2117                                             iReturnedFeedback);
       
  2118             iStateMgr->SetRequestedFeedbackL(*aCompartment,
       
  2119                                              iRequestedFeedback);
       
  2120             iStateMgr->SetReturnedParametersL(*aCompartment,
       
  2121                                               iReturnedParameters);
       
  2122             }
       
  2123         }
       
  2124 
       
  2125     return sso;
       
  2126     }
       
  2127 
       
  2128 
       
  2129 // ----------------------------------------------------------------------------
       
  2130 // CUdvm::DenyStateOperations
       
  2131 // deny state operations
       
  2132 // ----------------------------------------------------------------------------
       
  2133 //
       
  2134 
       
  2135 void CUdvm::DenyStateOperations()
       
  2136     {
       
  2137 
       
  2138     TUint soNum = iStateCreateRequestsNumber + iStateFreeRequestsNumber;
       
  2139 
       
  2140     for (TUint i = 0; i < soNum; i++)
       
  2141         {
       
  2142         if (iStateOperationRequests[i].iOperation == EOpcode_STATE_CREATE)
       
  2143             {
       
  2144 
       
  2145             delete iStateOperationRequests[i].iStateValue;
       
  2146             iStateOperationRequests[i].iStateValue = NULL;
       
  2147             }
       
  2148         }
       
  2149 
       
  2150     iStateCreateRequestsNumber = 0;
       
  2151     iStateFreeRequestsNumber = 0;
       
  2152 
       
  2153     iReturnedFeedback.Set(NULL, 0, 0);
       
  2154     iRequestedFeedback.Set(NULL, 0, 0);
       
  2155     iReturnedParameters.Set(NULL, 0, 0);
       
  2156     }
       
  2157 
       
  2158 
       
  2159 // ----------------------------------------------------------------------------
       
  2160 // CUdvm::CyclesConsumed
       
  2161 // get consumed cycles number
       
  2162 // ----------------------------------------------------------------------------
       
  2163 //
       
  2164 
       
  2165 #if defined(SIGCOMP_DEBUG)
       
  2166 
       
  2167 TUint CUdvm::CyclesConsumed() const
       
  2168     {
       
  2169     return iCycles;
       
  2170     }
       
  2171 
       
  2172 #endif
       
  2173 
       
  2174 //  End of File