|
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 |