Ethereal->Wireshark
[metze/wireshark/wip.git] / epan / sigcomp-udvm.c
1 /* sigcomp-udvm.c
2  * Routines making up the Universal Decompressor Virtual Machine (UDVM) used for
3  * Signaling Compression (SigComp) dissection.
4  * Copyright 2004, Anders Broman <anders.broman@ericsson.com>
5  *
6  * $Id$
7  *
8  * Wireshark - Network traffic analyzer
9  * By Gerald Combs <gerald@wireshark.org>
10  * Copyright 1998 Gerald Combs
11  *
12  * This program is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU General Public License
14  * as published by the Free Software Foundation; either version 2
15  * of the License, or (at your option) any later version.
16  * 
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  * 
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, write to the Free Software
24  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25  * References:
26  * http://www.ietf.org/rfc/rfc3320.txt?number=3320
27  * http://www.ietf.org/rfc/rfc3321.txt?number=3321
28  * Useful links :
29  * http://www.ietf.org/internet-drafts/draft-ietf-rohc-sigcomp-impl-guide-05.txt
30  * http://www.ietf.org/internet-drafts/draft-ietf-rohc-sigcomp-sip-01.txt
31  */
32
33 #ifdef HAVE_CONFIG_H
34 # include "config.h"
35 #endif
36
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <string.h>
40 #include <glib.h>
41
42 #include "packet.h"
43 #include "strutil.h"
44 #include "sigcomp-udvm.h"
45 #include "sigcomp_state_hdlr.h"
46 #include "sha1.h"
47 #include "crc16.h"
48 #include "except.h"
49
50 #define SIGCOMP_INSTR_DECOMPRESSION_FAILURE     0
51 #define SIGCOMP_INSTR_AND                       1
52 #define SIGCOMP_INSTR_OR                        2
53 #define SIGCOMP_INSTR_NOT                       3
54 #define SIGCOMP_INSTR_LSHIFT                    4
55 #define SIGCOMP_INSTR_RSHIFT                    5
56 #define SIGCOMP_INSTR_ADD                       6
57 #define SIGCOMP_INSTR_SUBTRACT                  7
58 #define SIGCOMP_INSTR_MULTIPLY                  8
59 #define SIGCOMP_INSTR_DIVIDE                    9
60 #define SIGCOMP_INSTR_REMAINDER                 10
61 #define SIGCOMP_INSTR_SORT_ASCENDING            11
62 #define SIGCOMP_INSTR_SORT_DESCENDING           12
63 #define SIGCOMP_INSTR_SHA_1                     13
64 #define SIGCOMP_INSTR_LOAD                      14
65 #define SIGCOMP_INSTR_MULTILOAD                 15
66 #define SIGCOMP_INSTR_PUSH                      16
67 #define SIGCOMP_INSTR_POP                       17
68 #define SIGCOMP_INSTR_COPY                      18
69 #define SIGCOMP_INSTR_COPY_LITERAL              19
70 #define SIGCOMP_INSTR_COPY_OFFSET               20
71 #define SIGCOMP_INSTR_MEMSET                    21
72 #define SIGCOMP_INSTR_JUMP                      22
73 #define SIGCOMP_INSTR_COMPARE                   23
74 #define SIGCOMP_INSTR_CALL                      24
75 #define SIGCOMP_INSTR_RETURN                    25
76 #define SIGCOMP_INSTR_SWITCH                    26
77 #define SIGCOMP_INSTR_CRC                       27
78 #define SIGCOMP_INSTR_INPUT_BYTES               28
79 #define SIGCOMP_INSTR_INPUT_BITS                29
80 #define SIGCOMP_INSTR_INPUT_HUFFMAN             30
81 #define SIGCOMP_INSTR_STATE_ACCESS              31
82 #define SIGCOMP_INSTR_STATE_CREATE              32
83 #define SIGCOMP_INSTR_STATE_FREE                33
84 #define SIGCOMP_INSTR_OUTPUT                    34
85 #define SIGCOMP_INSTR_END_MESSAGE               35
86
87
88 static gboolean print_level_1;
89 static gboolean print_level_2;
90 static gboolean print_level_3;
91 static gint show_instr_detail_level;
92
93 /* Internal result code values of decompression failures */
94 const value_string result_code_vals[] = {
95         { 0,    "No decompression failure" },
96         { 1,    "Partial state length less than 6 or greater than 20 bytes long" },
97         { 2,    "No state match" },
98         { 3,    "state_begin + state_length > size of state" },
99         { 4,    "Operand_2 is Zero" },
100         { 5,    "Switch statement failed j >= n" },
101         { 6,    "Atempt to jump outside of UDVM memory" },
102         { 7,    "L in input-bits > 16" },
103         { 8,    "input_bit_order > 7" },
104         { 9,    "Instruction Decompression failure encountered" },
105         {10,    "Input huffman failed j > n" },
106         {11,    "Input bits requested beyond end of message" },
107         {12,    "more than four state creation requests are made before the END-MESSAGE instruction" },
108         {13,    "state_retention_priority is 65535" },
109         {14,    "Input bytes requested beond end of message" },
110         {15,    "Maximum number of UDVM cycles reached" },
111         {16,    "UDVM stack underflow" },
112         { 255,  "This branch isn't coded yet" },
113         { 0,    NULL }
114 };
115
116 static int decode_udvm_literal_operand(guint8 *buff,guint operand_address, guint16 *value);
117 static int dissect_udvm_reference_operand(guint8 *buff,guint operand_address, guint16 *value, guint *result_dest);
118 static int decode_udvm_multitype_operand(guint8 *buff,guint operand_address,guint16 *value);
119 static int decode_udvm_address_operand(guint8 *buff,guint operand_address, guint16 *value,guint current_address);
120 static int decomp_dispatch_get_bits(tvbuff_t *message_tvb,proto_tree *udvm_tree,guint8 bit_order, 
121                         guint8 *buff,guint16 *old_input_bit_order, guint16 *remaining_bits,
122                         guint16 *input_bits, guint *input_address, guint16 length, guint16 *result_code,guint msg_end);
123
124
125 tvbuff_t*
126 decompress_sigcomp_message(tvbuff_t *bytecode_tvb, tvbuff_t *message_tvb, packet_info *pinfo,
127                                                    proto_tree *udvm_tree, gint udvm_mem_dest, 
128                                                    gint print_flags, gint hf_id,
129                                                    gint header_len,
130                                                    gint byte_code_state_len, gint byte_code_id_len,
131                                                    gint udvm_start_ip)
132 {
133         tvbuff_t        *decomp_tvb;
134         guint8          buff[UDVM_MEMORY_SIZE];
135         char            string[2];
136         guint8          *out_buff;              /* Largest allowed size for a message is 65535  */
137         guint32         i = 0;
138         guint16         n = 0;
139         guint16         m = 0;
140         guint16         x;
141         guint           k = 0;
142         guint16         H;
143         guint16         oldH;
144         guint           offset = 0;
145         guint           result_dest;
146         guint           code_length =0;
147         guint8          current_instruction;
148         guint           current_address;
149         guint           operand_address;
150         guint           input_address;
151         guint16         output_address = 0;
152         guint           next_operand_address;
153         guint8          octet;
154         guint8          msb;
155         guint8          lsb;
156         guint16         byte_copy_right;
157         guint16         byte_copy_left;
158         guint16         input_bit_order;
159         guint16         stack_location;
160         guint16         stack_fill;
161         guint16         result;
162         guint           msg_end = tvb_reported_length_remaining(message_tvb, 0);
163         guint16         result_code = 0;
164         guint16         old_input_bit_order = 0;
165         guint16         remaining_bits = 0;
166         guint16         input_bits = 0;
167         guint8          bit_order = 0;
168         gboolean        outside_huffman_boundaries = TRUE;
169         gboolean        print_in_loop = FALSE;
170         guint16         instruction_address;
171         guint8          no_of_state_create = 0;
172         guint16         state_length_buff[5];
173         guint16         state_address_buff[5];
174         guint16         state_instruction_buff[5];
175         guint16         state_minimum_access_length_buff[5];
176         guint16         state_state_retention_priority_buff[5];
177         guint32         used_udvm_cycles = 0;
178         guint           cycles_per_bit;
179         guint           maximum_UDVM_cycles;
180         guint8          *sha1buff;
181         unsigned char sha1_digest_buf[STATE_BUFFER_SIZE];
182         sha1_context ctx;
183
184
185         /* UDVM operand variables */
186         guint16 length;
187         guint16 at_address;
188         guint16 destination;
189         guint16 address;
190         guint16 value;
191         guint16 p_id_start;
192         guint16 p_id_length;
193         guint16 state_begin;
194         guint16 state_length;
195         guint16 state_address;
196         guint16 state_instruction;
197         guint16 operand_1;
198         guint16 operand_2;
199         guint16 value_1;
200         guint16 value_2;
201         guint16 at_address_1;
202         guint16 at_address_2;
203         guint16 at_address_3;
204         guint16 j;
205         guint16 bits_n;
206         guint16 lower_bound_n;
207         guint16 upper_bound_n;
208         guint16 uncompressed_n;
209         guint16 position;
210         guint16 ref_destination; /* could I have used $destination ? */
211         guint16 multy_offset;
212         guint16 output_start;
213         guint16 output_length;
214         guint16 minimum_access_length;
215         guint16 state_retention_priority;
216         guint16 requested_feedback_location;
217         guint16 returned_parameters_location;
218         guint16 start_value;
219
220
221         /* Set print parameters */
222         print_level_1 = FALSE;
223         print_level_2 = FALSE;
224         print_level_3 = FALSE;
225         show_instr_detail_level = 0;
226
227
228
229         switch( print_flags ) {
230                 case 0:
231                         break;
232
233                 case 1:
234                         print_level_1 = TRUE;
235                         show_instr_detail_level = 1;
236                         break;
237                 case 2:
238                         print_level_1 = TRUE;
239                         print_level_2 = TRUE;
240                         show_instr_detail_level = 1;
241                         break;
242                 case 3:
243                         print_level_1 = TRUE;
244                         print_level_2 = TRUE;
245                         print_level_3 = TRUE;
246                         show_instr_detail_level = 2;
247                         break;
248                 default:
249                         print_level_1 = TRUE;
250                         show_instr_detail_level = 1;
251                         break;
252         }
253
254
255
256
257
258         /* UDVM memory must be initialised to zero */
259         memset(buff, 0, UDVM_MEMORY_SIZE);
260         /* Set initial UDVM data 
261          *  The first 32 bytes of UDVM memory are then initialized to special
262          *  values as illustrated in Figure 5.
263          *
264          *                      0             7 8            15
265          *                     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
266          *                     |       UDVM_memory_size        |  0 - 1
267          *                     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
268          *                     |        cycles_per_bit         |  2 - 3
269          *                     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
270          *                     |        SigComp_version        |  4 - 5
271          *                     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
272          *                     |    partial_state_ID_length    |  6 - 7
273          *                     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
274          *                     |         state_length          |  8 - 9
275          *                     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
276          *                     |                               |
277          *                     :           reserved            :  10 - 31
278          *                     |                               |
279          *                     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
280          *
281          *            Figure 5: Initializing Useful Values in UDVM memory
282          */
283         /* UDVM_memory_size  */
284         buff[0] = (UDVM_MEMORY_SIZE >> 8) & 0x00FF;
285         buff[1] = UDVM_MEMORY_SIZE & 0x00FF;
286         /* cycles_per_bit */
287         buff[2] = 0;
288         buff[3] = 16;
289         /* SigComp_version */
290         buff[4] = 0;
291         buff[5] = 1;
292         /* partial_state_ID_length */
293         buff[6] = (byte_code_id_len >> 8) & 0x00FF;
294         buff[7] = byte_code_id_len & 0x00FF;
295         /* state_length  */
296         buff[8] = (byte_code_state_len >> 8) & 0x00FF;
297         buff[9] = byte_code_state_len & 0x00FF;
298
299         code_length = tvb_reported_length_remaining(bytecode_tvb, 0);
300
301         cycles_per_bit = buff[2] << 8;
302         cycles_per_bit = cycles_per_bit | buff[3];
303         /* 
304          * maximum_UDVM_cycles = (8 * n + 1000) * cycles_per_bit
305          */
306         maximum_UDVM_cycles = (( 8 * (header_len + msg_end) ) + 1000) * cycles_per_bit;
307
308         proto_tree_add_text(udvm_tree, bytecode_tvb, offset, 1,"maximum_UDVM_cycles(%u) = (( 8 * msg_end(%u) ) + 1000) * cycles_per_bit(%u)",maximum_UDVM_cycles,msg_end,cycles_per_bit);
309         proto_tree_add_text(udvm_tree, bytecode_tvb, offset, 1,"Message Length: %u,Byte code length: %u, Maximum UDVM cycles: %u",msg_end,code_length,maximum_UDVM_cycles);
310
311         /* Load bytecode into UDVM starting at "udvm_mem_dest" */
312         i = udvm_mem_dest;
313         if ( print_level_3 )
314                 proto_tree_add_text(udvm_tree, bytecode_tvb, offset, 1,"Load bytecode into UDVM starting at %u",i);
315         while ( code_length > offset && i < UDVM_MEMORY_SIZE ) {
316                 buff[i] = tvb_get_guint8(bytecode_tvb, offset);
317                 if ( print_level_3 )
318                         proto_tree_add_text(udvm_tree, bytecode_tvb, offset, 1,
319                                                 "              Addr: %u Instruction code(0x%0x) ", i, buff[i]);
320
321                 i++;
322                 offset++;
323
324         }
325         /* Largest allowed size for a message is 65535  */
326         out_buff = g_malloc(65535);
327         /* Start executing code */
328         current_address = udvm_start_ip;
329         input_address = 0;
330         operand_address = 0;
331         
332         proto_tree_add_text(udvm_tree, bytecode_tvb, offset, 1,"UDVM EXECUTION STARTED at Address: %u Message size %u",
333                 current_address, msg_end);
334
335 execute_next_instruction:
336
337         if ( used_udvm_cycles > maximum_UDVM_cycles ){
338                 result_code = 15;
339                 goto decompression_failure;
340         }
341         current_instruction = buff[current_address];
342
343         switch ( current_instruction ) {
344         case SIGCOMP_INSTR_DECOMPRESSION_FAILURE:
345                 used_udvm_cycles++;
346                 if ( result_code == 0 )
347                         result_code = 9;
348                 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
349                         "Addr: %u ## DECOMPRESSION-FAILURE(0)",
350                         current_address);
351                 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Wireshark UDVM diagnostic: %s.",
352                                     val_to_str(result_code, result_code_vals,"Unknown (%u)"));
353                 if ( output_address > 0 ){
354                         /* At least something got decompressed, show it */
355                         decomp_tvb = tvb_new_real_data(out_buff,output_address,output_address);
356                         /* Arrange that the allocated packet data copy be freed when the
357                          * tvbuff is freed. 
358                          */
359                         tvb_set_free_cb( decomp_tvb, g_free );
360                         /* Add the tvbuff to the list of tvbuffs to which the tvbuff we
361                          * were handed refers, so it'll get cleaned up when that tvbuff
362                          * is cleaned up. 
363                          */
364                         tvb_set_child_real_data_tvbuff(message_tvb,decomp_tvb);
365                         add_new_data_source(pinfo, decomp_tvb, "Decompressed SigComp message(Incomplete)");
366                         proto_tree_add_text(udvm_tree, decomp_tvb, 0, -1,"SigComp message Decompression failure");
367                 return decomp_tvb;
368                 }
369                 g_free(out_buff);
370                 return NULL;
371                 break;
372
373         case SIGCOMP_INSTR_AND: /* 1 AND ($operand_1, %operand_2) */
374                 used_udvm_cycles++;
375                 if (show_instr_detail_level == 2 ){
376                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
377                                 "Addr: %u ## AND(1) (operand_1, operand_2)",
378                                 current_address);
379                 }
380                 /* $operand_1*/
381                 operand_address = current_address + 1;
382                 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &operand_1, &result_dest);
383                 if (show_instr_detail_level == 2 ){
384                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u      operand_1 %u",
385                                 operand_address, operand_1);
386                 }
387                 operand_address = next_operand_address; 
388                 /* %operand_2*/
389                 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &operand_2);
390                 if (show_instr_detail_level == 2 ){
391                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u      operand_2 %u",
392                                 operand_address, operand_2);
393                 }
394                 if (show_instr_detail_level == 1)
395                 {
396                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
397                                 "Addr: %u ## AND (operand_1=%u, operand_2=%u)",
398                                 current_address, operand_1, operand_2);
399                 }
400                 /* execute the instruction */
401                 result = operand_1 & operand_2;
402                 lsb = result & 0xff;
403                 msb = result >> 8;              
404                 buff[result_dest] = msb;
405                 buff[result_dest+1] = lsb;
406                 if (print_level_1 ){
407                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"     Loading result %u at %u",
408                                 result, result_dest);
409                 }
410                 current_address = next_operand_address; 
411                 goto execute_next_instruction;
412
413                 break;
414
415         case SIGCOMP_INSTR_OR: /* 2 OR ($operand_1, %operand_2) */
416                 used_udvm_cycles++;
417                 if (show_instr_detail_level == 2 ){
418                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
419                                 "Addr: %u ## OR(2) (operand_1, operand_2)",
420                                 current_address);
421                 }
422                 /* $operand_1*/
423                 operand_address = current_address + 1;
424                 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &operand_1, &result_dest);
425                 if (show_instr_detail_level == 2 ){
426                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u      operand_1 %u",
427                                 operand_address, operand_1);
428                 }
429                 operand_address = next_operand_address; 
430                 /* %operand_2*/
431                 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &operand_2);
432                 if (show_instr_detail_level == 2 ){
433                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u      operand_2 %u",
434                                 operand_address, operand_2);
435                 }
436                 if (show_instr_detail_level == 1)
437                 {
438                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
439                                 "Addr: %u ## OR (operand_1=%u, operand_2=%u)",
440                                 current_address, operand_1, operand_2);
441                 }
442                 /* execute the instruction */
443                 result = operand_1 | operand_2;
444                 lsb = result & 0xff;
445                 msb = result >> 8;              
446                 buff[result_dest] = msb;
447                 buff[result_dest+1] = lsb;
448                 if (print_level_1 ){
449                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"     Loading result %u at %u",
450                                 result, result_dest);
451                 }
452                 current_address = next_operand_address; 
453                 goto execute_next_instruction;
454
455                 break;
456
457         case SIGCOMP_INSTR_NOT: /* 3 NOT ($operand_1) */
458                 used_udvm_cycles++;
459                 if (show_instr_detail_level == 2 ){
460                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
461                                 "Addr: %u ## NOT(3) ($operand_1)",
462                                 current_address);
463                 }
464                 /* $operand_1*/
465                 operand_address = current_address + 1;
466                 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &operand_1, &result_dest);
467                 if (show_instr_detail_level == 2 ){
468                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u      operand_1 %u",
469                                 operand_address, operand_1);
470                 }
471                 if (show_instr_detail_level == 1)
472                 {
473                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
474                                 "Addr: %u ## NOT (operand_1=%u)",
475                                 current_address, operand_1);
476                 }
477                 /* execute the instruction */
478                 result = operand_1 ^ 0xffff;
479                 lsb = result & 0xff;
480                 msb = result >> 8;              
481                 buff[result_dest] = msb;
482                 buff[result_dest+1] = lsb;
483                 if (print_level_1 ){
484                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"     Loading result %u at %u",
485                                 result, result_dest);
486                 }
487                 current_address = next_operand_address; 
488                 goto execute_next_instruction;
489                 break;
490
491         case SIGCOMP_INSTR_LSHIFT: /* 4 LSHIFT ($operand_1, %operand_2) */
492                 used_udvm_cycles++;
493                 if (show_instr_detail_level == 2 ){
494                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
495                                 "Addr: %u ## LSHIFT(4) ($operand_1, operand_2)",
496                                 current_address);
497                 }
498                 /* $operand_1*/
499                 operand_address = current_address + 1;
500                 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &operand_1, &result_dest);
501                 if (show_instr_detail_level == 2 ){
502                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u      operand_1 %u",
503                                 operand_address, operand_1);
504                 }
505                 operand_address = next_operand_address; 
506                 /* %operand_2*/
507                 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &operand_2);
508                 if (show_instr_detail_level == 2 ){
509                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u      operand_2 %u",
510                                 operand_address, operand_2);
511                 }
512                 if (show_instr_detail_level == 1)
513                 {
514                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
515                                 "Addr: %u ## LSHIFT (operand_1=%u, operand_2=%u)",
516                                 current_address, operand_1, operand_2);
517                 }
518                 /* execute the instruction */
519                 result = operand_1 << operand_2;
520                 lsb = result & 0xff;
521                 msb = result >> 8;              
522                 buff[result_dest] = msb;
523                 buff[result_dest+1] = lsb;
524                 if (print_level_1 ){
525                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"     Loading result %u at %u",
526                                 result, result_dest);
527                 }
528                 current_address = next_operand_address; 
529                 goto execute_next_instruction;
530
531                 break;
532         case SIGCOMP_INSTR_RSHIFT: /* 5 RSHIFT ($operand_1, %operand_2) */
533                 used_udvm_cycles++;
534                 if (show_instr_detail_level == 2 ){
535                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
536                                 "Addr: %u ## RSHIFT(5) (operand_1, operand_2)",
537                                 current_address);
538                 }
539                 /* $operand_1*/
540                 operand_address = current_address + 1;
541                 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &operand_1, &result_dest);
542                 if (show_instr_detail_level == 2 ){
543                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u      operand_1 %u",
544                                 operand_address, operand_1);
545                 }
546                 operand_address = next_operand_address; 
547                 /* %operand_2*/
548                 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &operand_2);
549                 if (show_instr_detail_level == 2 ){
550                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u      operand_2 %u",
551                                 operand_address, operand_2);
552                 }
553                 if (show_instr_detail_level == 1)
554                 {
555                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
556                                 "Addr: %u ## RSHIFT (operand_1=%u, operand_2=%u)",
557                                 current_address, operand_1, operand_2);
558                 }
559                 /* execute the instruction */
560                 result = operand_1 >> operand_2;
561                 lsb = result & 0xff;
562                 msb = result >> 8;              
563                 buff[result_dest] = msb;
564                 buff[result_dest+1] = lsb;
565                 if (print_level_1 ){
566                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"     Loading result %u at %u",
567                                 result, result_dest);
568                 }
569                 current_address = next_operand_address; 
570                 goto execute_next_instruction;
571                 break;
572         case SIGCOMP_INSTR_ADD: /* 6 ADD ($operand_1, %operand_2) */
573                 used_udvm_cycles++;
574                 if (show_instr_detail_level == 2 ){
575                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
576                                 "Addr: %u ## ADD(6) (operand_1, operand_2)",
577                                 current_address);
578                 }
579                 /* $operand_1*/
580                 operand_address = current_address + 1;
581                 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &operand_1, &result_dest);
582                 if (show_instr_detail_level == 2 ){
583                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u      operand_1 %u",
584                                 operand_address, operand_1);
585                 }
586                 operand_address = next_operand_address; 
587                 /* %operand_2*/
588                 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &operand_2);
589                 if (show_instr_detail_level == 2 ){
590                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u      operand_2 %u",
591                                 operand_address, operand_2);
592                 }
593                 if (show_instr_detail_level == 1)
594                 {
595                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
596                                 "Addr: %u ## ADD (operand_1=%u, operand_2=%u)",
597                                 current_address, operand_1, operand_2);
598                 }
599                 /* execute the instruction */
600                 result = operand_1 + operand_2;
601                 lsb = result & 0xff;
602                 msb = result >> 8;              
603                 buff[result_dest] = msb;
604                 buff[result_dest+1] = lsb;
605                 if (print_level_1 ){
606                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"               Loading result %u at %u",
607                                 result, result_dest);
608                 }
609                 current_address = next_operand_address; 
610                 goto execute_next_instruction;
611
612         case SIGCOMP_INSTR_SUBTRACT: /* 7 SUBTRACT ($operand_1, %operand_2) */
613                 used_udvm_cycles++;
614                 if (show_instr_detail_level == 2 ){
615                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
616                                 "Addr: %u ## SUBTRACT(7) (operand_1, operand_2)",
617                                 current_address);
618                 }
619                 /* $operand_1*/
620                 operand_address = current_address + 1;
621                 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &operand_1, &result_dest);
622                 if (show_instr_detail_level == 2 ){
623                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u      operand_1 %u",
624                                 operand_address, operand_1);
625                 }
626                 operand_address = next_operand_address; 
627                 /* %operand_2*/
628                 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &operand_2);
629                 if (show_instr_detail_level == 2 ){
630                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u      operand_2 %u",
631                                 operand_address, operand_2);
632                 }
633                 if (show_instr_detail_level == 1)
634                 {
635                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
636                                 "Addr: %u ## SUBTRACT (operand_1=%u, operand_2=%u)",
637                                 current_address, operand_1, operand_2);
638                 }
639                 /* execute the instruction */
640                 result = operand_1 - operand_2;
641                 lsb = result & 0xff;
642                 msb = result >> 8;              
643                 buff[result_dest] = msb;
644                 buff[result_dest+1] = lsb;
645                 if (print_level_1 ){
646                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"               Loading result %u at %u",
647                                 result, result_dest);
648                 }
649                 current_address = next_operand_address; 
650                 goto execute_next_instruction;
651                 break;
652
653         case SIGCOMP_INSTR_MULTIPLY: /* 8 MULTIPLY ($operand_1, %operand_2) */
654                 used_udvm_cycles++;
655                 if (show_instr_detail_level == 2 ){
656                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
657                                 "Addr: %u ##MULTIPLY(8) (operand_1, operand_2)",
658                                 current_address);
659                 }
660                 /* $operand_1*/
661                 operand_address = current_address + 1;
662                 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &operand_1, &result_dest);
663                 if (show_instr_detail_level == 2 ){
664                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u      operand_1 %u",
665                                 operand_address, operand_1);
666                 }
667                 operand_address = next_operand_address; 
668                 /* %operand_2*/
669                 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &operand_2);
670                 if (show_instr_detail_level == 2 ){
671                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u      operand_2 %u",
672                                 operand_address, operand_2);
673                 }
674                 if (show_instr_detail_level == 1)
675                 {
676                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
677                                 "Addr: %u ## MULTIPLY (operand_1=%u, operand_2=%u)",
678                                 current_address, operand_1, operand_2);
679                 }
680                 /* 
681                  * execute the instruction
682                  * MULTIPLY (m, n)  := m * n (modulo 2^16)
683                  */
684                 if ( operand_2 == 0){
685                         result_code = 4;
686                         goto decompression_failure;
687                 }
688                 result = operand_1 * operand_2;
689                 lsb = result & 0xff;
690                 msb = result >> 8;              
691                 buff[result_dest] = msb;
692                 buff[result_dest+1] = lsb;
693                 if (print_level_1 ){
694                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"     Loading result %u at %u",
695                                 result, result_dest);
696                 }
697                 current_address = next_operand_address; 
698                 goto execute_next_instruction;
699                 break;
700
701         case SIGCOMP_INSTR_DIVIDE: /* 9 DIVIDE ($operand_1, %operand_2) */
702                 used_udvm_cycles++;
703                 if (show_instr_detail_level == 2 ){
704                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
705                                 "Addr: %u ## DIVIDE(9) (operand_1, operand_2)",
706                                 current_address);
707                 }
708                 /* $operand_1*/
709                 operand_address = current_address + 1;
710                 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &operand_1, &result_dest);
711                 if (show_instr_detail_level == 2 ){
712                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u      operand_1 %u",
713                                 operand_address, operand_1);
714                 }
715                 operand_address = next_operand_address; 
716                 /* %operand_2*/
717                 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &operand_2);
718                 if (show_instr_detail_level == 2 ){
719                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u      operand_2 %u",
720                                 operand_address, operand_2);
721                 }
722                 if (show_instr_detail_level == 1)
723                 {
724                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
725                                 "Addr: %u ## DIVIDE (operand_1=%u, operand_2=%u)",
726                                 current_address, operand_1, operand_2);
727                 }
728                 /* 
729                  * execute the instruction
730                  * DIVIDE (m, n)    := floor(m / n)
731                  * Decompression failure occurs if a DIVIDE or REMAINDER instruction
732                  * encounters an operand_2 that is zero.
733                  */
734                 if ( operand_2 == 0){
735                         result_code = 4;
736                         goto decompression_failure;
737                 }
738                 result = operand_1 / operand_2;
739                 lsb = result & 0xff;
740                 msb = result >> 8;              
741                 buff[result_dest] = msb;
742                 buff[result_dest+1] = lsb;
743                 if (print_level_1 ){
744                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"     Loading result %u at %u",
745                                 result, result_dest);
746                 }
747                 current_address = next_operand_address; 
748                 goto execute_next_instruction;
749                 break;
750
751         case SIGCOMP_INSTR_REMAINDER: /* 10 REMAINDER ($operand_1, %operand_2) */
752                 used_udvm_cycles++;
753                 if (show_instr_detail_level == 2 ){
754                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
755                                 "Addr: %u ## REMAINDER(10) (operand_1, operand_2)",
756                                 current_address);
757                 }
758                 /* $operand_1*/
759                 operand_address = current_address + 1;
760                 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &operand_1, &result_dest);
761                 if (show_instr_detail_level == 2 ){
762                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u      operand_1 %u",
763                                 operand_address, operand_1);
764                 }
765                 operand_address = next_operand_address; 
766                 /* %operand_2*/
767                 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &operand_2);
768                 if (show_instr_detail_level == 2 ){
769                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u      operand_2 %u",
770                                 operand_address, operand_2);
771                 }
772                 if (show_instr_detail_level == 1)
773                 {
774                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
775                                 "Addr: %u ## REMAINDER (operand_1=%u, operand_2=%u)",
776                                 current_address, operand_1, operand_2);
777                 }
778                 /* 
779                  * execute the instruction
780                  * REMAINDER (m, n) := m - n * floor(m / n)
781                  * Decompression failure occurs if a DIVIDE or REMAINDER instruction
782                  * encounters an operand_2 that is zero.
783                  */
784                 if ( operand_2 == 0){
785                         result_code = 4;
786                         goto decompression_failure;
787                 }
788                 result = operand_1 - operand_2 * (operand_1 / operand_2);
789                 lsb = result & 0xff;
790                 msb = result >> 8;              
791                 buff[result_dest] = msb;
792                 buff[result_dest+1] = lsb;
793                 if (print_level_1 ){
794                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"     Loading result %u at %u",
795                                 result, result_dest);
796                 }
797                 current_address = next_operand_address; 
798                 goto execute_next_instruction;
799                 break;
800         case SIGCOMP_INSTR_SORT_ASCENDING: /* 11 SORT-ASCENDING (%start, %n, %k) */
801                 /*
802                  *      used_udvm_cycles =  1 + k * (ceiling(log2(k)) + n)
803                  */
804                 if (print_level_1 ){
805                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
806                                 "Addr: %u ## SORT-ASCENDING(11) (start, n, k))",
807                                 current_address);
808                 }
809                 operand_address = current_address + 1;
810                 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Execution of this instruction is NOT implemented");
811                 /*
812                  *      used_udvm_cycles =  1 + k * (ceiling(log2(k)) + n)
813                  */
814                 break;
815
816         case SIGCOMP_INSTR_SORT_DESCENDING: /* 12 SORT-DESCENDING (%start, %n, %k) */
817                 if (print_level_1 ){
818                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
819                                 "Addr: %u ## SORT-DESCENDING(12) (start, n, k))",
820                                 current_address);
821                 }
822                 operand_address = current_address + 1;
823                 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Execution of this instruction is NOT implemented");
824                 /*
825                  *      used_udvm_cycles =  1 + k * (ceiling(log2(k)) + n)
826                  */
827                 break;
828         case SIGCOMP_INSTR_SHA_1: /* 13 SHA-1 (%position, %length, %destination) */
829                 if (print_level_1 ){
830                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
831                                 "Addr: %u ## SHA-1(13) (position, length, destination)",
832                                 current_address);
833                 }
834                 operand_address = current_address + 1;
835                 /* %position */
836                 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &position);
837                 if (print_level_1 ){
838                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u      position %u",
839                                 operand_address, position);
840                 }
841                 operand_address = next_operand_address; 
842
843                 /* %length */
844                 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &length);
845                 if (print_level_1 ){
846                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u      Length %u",
847                                 operand_address, length);
848                 }
849                 operand_address = next_operand_address;
850
851                 /* $destination */
852                 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &ref_destination, &result_dest);
853                 if (print_level_1 ){
854                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u      $destination %u",
855                                 operand_address, ref_destination);
856                 }
857                 current_address = next_operand_address; 
858                 used_udvm_cycles = used_udvm_cycles + 1 + length;
859
860                 n = 0;
861                 k = position;
862                 byte_copy_right = buff[66] << 8;
863                 byte_copy_right = byte_copy_right | buff[67];
864                 byte_copy_left = buff[64] << 8;
865                 byte_copy_left = byte_copy_left | buff[65];
866
867                 if (print_level_2 ){
868                         proto_tree_add_text(udvm_tree, message_tvb, 0, -1,
869                                         "byte_copy_right = %u", byte_copy_right);
870                 }
871
872                 sha1_starts( &ctx );
873
874                 while (n<length) {
875                         guint16 handle_now = length;
876
877                         if ( k < byte_copy_right && byte_copy_right <= k + (length-n) ){
878                                 handle_now = byte_copy_right - position;
879                         }
880
881                         if (k + handle_now >= UDVM_MEMORY_SIZE)
882                                 goto decompression_failure;
883                         sha1_update( &ctx, &buff[k], handle_now );
884
885                         k = ( k + handle_now ) & 0xffff;
886                         n = ( n + handle_now ) & 0xffff;
887
888                         if ( k >= byte_copy_right ) {
889                                 k = byte_copy_left;
890                         }
891                 }
892
893                 sha1_finish( &ctx, sha1_digest_buf );
894
895                 k = ref_destination; 
896
897                 for ( n=0; n< STATE_BUFFER_SIZE; n++ ) {
898
899                         buff[k] = sha1_digest_buf[n];
900
901                         k = ( k + 1 ) & 0xffff;
902                         n++;
903
904                         if ( k == byte_copy_right ){
905                                 k = byte_copy_left;
906                         }
907                 }
908
909                 if (print_level_2 ){
910                         proto_tree_add_text(udvm_tree, message_tvb, 0, -1,
911                                         "Calculated SHA-1: %s",
912                                         bytes_to_str(sha1_digest_buf, STATE_BUFFER_SIZE));
913                 }
914
915                 current_address = next_operand_address;
916                 goto execute_next_instruction;
917                 break;
918
919         case SIGCOMP_INSTR_LOAD: /* 14 LOAD (%address, %value) */
920                 if (show_instr_detail_level == 2 ){
921                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
922                                 "Addr: %u ## LOAD(14) (%%address, %%value)",
923                                 current_address);
924                 }
925                 operand_address = current_address + 1;
926                 /* %address */
927                 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &address);
928                 if (show_instr_detail_level == 2 ){
929                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u      Address %u",
930                                 operand_address, address);
931                 }
932                 operand_address = next_operand_address; 
933                 /* %value */
934                 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &value);
935                 if (show_instr_detail_level == 1)
936                 {
937                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
938                                 "Addr: %u ## LOAD (%%address=%u, %%value=%u)",
939                                 current_address, address, value);
940                 }
941                 lsb = value & 0xff;
942                 msb = value >> 8;
943
944                 buff[address] = msb;
945                 buff[address + 1] = lsb;
946
947                 if (print_level_1 ){
948                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u      Value %u",
949                                 operand_address, value);
950                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"     Loading bytes at %u Value %u 0x%x",
951                                         address, value, value);
952                 }
953                 used_udvm_cycles++;
954                 current_address = next_operand_address;
955                 goto execute_next_instruction;
956                 break;
957
958         case SIGCOMP_INSTR_MULTILOAD: /* 15 MULTILOAD (%address, #n, %value_0, ..., %value_n-1) */
959                 /* RFC 3320:
960                  * The MULTILOAD instruction sets a contiguous block of 2-byte words in
961                  * the UDVM memory to specified values.
962                  * Hmm what if the value to load only takes one byte ? Chose to always load two bytes.
963                  */
964                 if (show_instr_detail_level == 2 ){
965                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
966                                 "Addr: %u ## MULTILOAD(15) (%%address, #n, value_0, ..., value_n-1)",
967                                 current_address);
968                 }
969                 operand_address = current_address + 1;
970                 /* %address */
971                 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &address);
972                 if (show_instr_detail_level == 2 ){
973                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u      Address %u",
974                                 operand_address, address);
975                 }
976                 operand_address = next_operand_address; 
977
978                 /* #n */
979                 next_operand_address = decode_udvm_literal_operand(buff,operand_address, &n);
980                 if (show_instr_detail_level == 2 ){
981                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u      n %u",
982                                 operand_address, n);
983                 }
984                 if (show_instr_detail_level == 1)
985                 {
986                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
987                                 "Addr: %u ## MULTILOAD (%%address=%u, #n=%u, value_0, ..., value_%d)",
988                                 current_address, address, n, n-1);
989                 }
990                 operand_address = next_operand_address; 
991                 used_udvm_cycles = used_udvm_cycles + 1 + n;
992                 while ( n > 0) {
993                         n = n - 1;
994                         /* %value */
995                         next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &value);
996                         lsb = value & 0xff;
997                         msb = value >> 8;
998
999                         if (address >= UDVM_MEMORY_SIZE - 1)
1000                                 goto decompression_failure;
1001
1002                         buff[address] = msb;
1003                         buff[address + 1] = lsb;
1004                         /* debug
1005                         */
1006                         length = next_operand_address - operand_address;
1007
1008                         if (print_level_1 ){
1009                                 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1, "Addr: %u      Value %5u      - Loading bytes at %5u Value %5u 0x%x",
1010                                 operand_address, value, address, value, value);
1011                         }
1012                         address = address + 2;
1013                         operand_address = next_operand_address; 
1014                 }
1015                 current_address = next_operand_address;
1016                 goto execute_next_instruction;
1017
1018                 break;
1019                          
1020         case SIGCOMP_INSTR_PUSH: /* 16 PUSH (%value) */
1021                 if (show_instr_detail_level == 2){
1022                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1023                                 "Addr: %u ## PUSH(16) (value)",
1024                                 current_address);
1025                 }
1026                 operand_address = current_address + 1;
1027                 /* %value */
1028                 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &value);
1029                 if (show_instr_detail_level == 2){
1030                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u      Value %u",
1031                                 operand_address, value);
1032                 }
1033                 if (show_instr_detail_level == 1)
1034                 {
1035                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1036                                 "Addr: %u ## PUSH (value=%u)",
1037                                 current_address, value);
1038                 }
1039                 current_address = next_operand_address; 
1040
1041                 /* Push the value address onto the stack */ 
1042                 stack_location = (buff[70] << 8) | buff[71];
1043                 stack_fill = (buff[stack_location] << 8) 
1044                            | buff[(stack_location+1) & 0xFFFF];
1045                 address = (stack_location + stack_fill * 2 + 2) & 0xFFFF;
1046
1047                 if (address >= UDVM_MEMORY_SIZE - 1)
1048                         goto decompression_failure;
1049
1050                 buff[address] = (value >> 8) & 0x00FF;
1051                 buff[(address+1) & 0xFFFF] = value & 0x00FF;
1052
1053                 if (stack_location >= UDVM_MEMORY_SIZE - 1)
1054                         goto decompression_failure;
1055                 
1056                 stack_fill = (stack_fill + 1) & 0xFFFF;
1057                 buff[stack_location] = (stack_fill >> 8) & 0x00FF;
1058                 buff[(stack_location+1) & 0xFFFF] = stack_fill & 0x00FF;
1059
1060                 used_udvm_cycles++;
1061                 goto execute_next_instruction;
1062
1063                 break;
1064
1065         case SIGCOMP_INSTR_POP: /* 17 POP (%address) */
1066                 if (show_instr_detail_level == 2){
1067                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1068                                 "Addr: %u ## POP(16) (value)",
1069                                 current_address);
1070                 }
1071                 operand_address = current_address + 1;
1072                 /* %value */
1073                 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &destination);
1074                 if (show_instr_detail_level == 2){
1075                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u      Value %u",
1076                                 operand_address, destination);
1077                 }
1078                 if (show_instr_detail_level == 1)
1079                 {
1080                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1081                                 "Addr: %u ## POP (address=%u)",
1082                                 current_address, destination);
1083                 }
1084                 current_address = next_operand_address; 
1085
1086                 /* Pop value from the top of the stack */ 
1087                 stack_location = (buff[70] << 8) | buff[71];
1088                 stack_fill = (buff[stack_location] << 8) 
1089                            | buff[(stack_location+1) & 0xFFFF];
1090                 if (stack_fill == 0)
1091                 {
1092                     result_code = 16;
1093                     goto decompression_failure;
1094                 }
1095
1096                 if (stack_location >= UDVM_MEMORY_SIZE - 1)
1097                         goto decompression_failure;
1098
1099                 stack_fill = (stack_fill - 1) & 0xFFFF;
1100                 buff[stack_location] = (stack_fill >> 8) & 0x00FF;
1101                 buff[(stack_location+1) & 0xFFFF] = stack_fill & 0x00FF;
1102
1103                 address = (stack_location + stack_fill * 2 + 2) & 0xFFFF;
1104
1105                 if (address >= UDVM_MEMORY_SIZE - 1)
1106                         goto decompression_failure;
1107
1108                 value = (buff[address] << 8) 
1109                            | buff[(address+1) & 0xFFFF];
1110
1111                 /* ... and store the popped value. */
1112                 if (destination >= UDVM_MEMORY_SIZE - 1)
1113                         goto decompression_failure;
1114                 buff[destination] = (value >> 8) & 0x00FF;
1115                 buff[(destination+1) & 0xFFFF] = value & 0x00FF;
1116
1117                 used_udvm_cycles++;
1118                 goto execute_next_instruction;
1119
1120                 break;
1121
1122         case SIGCOMP_INSTR_COPY: /* 18 COPY (%position, %length, %destination) */
1123                 if (show_instr_detail_level == 2 ){
1124                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1125                                 "Addr: %u ## COPY(18) (position, length, destination)",
1126                                 current_address);
1127                 }
1128                 operand_address = current_address + 1;
1129                 /* %position */
1130                 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &position);
1131                 if (show_instr_detail_level == 2 ){
1132                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u      position %u",
1133                                 operand_address, position);
1134                 }
1135                 operand_address = next_operand_address; 
1136
1137                 /* %length */
1138                 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &length);
1139                 if (show_instr_detail_level == 2 ){
1140                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u      Length %u",
1141                                 operand_address, length);
1142                 }
1143                 operand_address = next_operand_address;
1144
1145                 /* %destination */
1146                 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &destination);
1147                 if (show_instr_detail_level == 2 ){
1148                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u      Destination %u",
1149                                 operand_address, destination);
1150                 }
1151                 if (show_instr_detail_level == 1)
1152                 {
1153                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1154                                 "Addr: %u ## COPY (position=%u, length=%u, destination=%u)",
1155                                 current_address, position, length, destination);
1156                 }
1157                 current_address = next_operand_address;
1158                 /*
1159                  * 8.4.  Byte copying
1160                  * :
1161                  * The string of bytes is copied in ascending order of memory address,
1162                  * respecting the bounds set by byte_copy_left and byte_copy_right.
1163                  * More precisely, if a byte is copied from/to Address m then the next
1164                  * byte is copied from/to Address n where n is calculated as follows:
1165                  *
1166                  * Set k := m + 1 (modulo 2^16)
1167                  * If k = byte_copy_right then set n := byte_copy_left, else set n := k
1168                  *
1169                  */ 
1170
1171                 n = 0;
1172                 k = destination; 
1173                 byte_copy_right = buff[66] << 8;
1174                 byte_copy_right = byte_copy_right | buff[67];
1175                 byte_copy_left = buff[64] << 8;
1176                 byte_copy_left = byte_copy_left | buff[65];
1177                 if (print_level_2 ){
1178                         proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
1179                                                 "               byte_copy_right = %u", byte_copy_right);
1180                 }
1181
1182                 while ( n < length ){
1183                         buff[k] = buff[position];
1184                         if (print_level_2 ){
1185                                 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
1186                                         "               Copying value: %u (0x%x) to Addr: %u",
1187                                         buff[position], buff[position], k);
1188                         }
1189                         position = ( position + 1 ) & 0xffff;
1190                         k = ( k + 1 ) & 0xffff;
1191                         n++;
1192
1193                         /*
1194                          * Check for circular buffer wrapping after the positions are
1195                          * incremented. If either started at BCR then they should continue
1196                          * to increment beyond BCR.
1197                          */
1198                         if ( k == byte_copy_right ){
1199                                 k = byte_copy_left;
1200                         }
1201                         if ( position == byte_copy_right ){
1202                                 position = byte_copy_left;
1203                         }
1204                 }
1205                 used_udvm_cycles = used_udvm_cycles + 1 + length;
1206                 goto execute_next_instruction;
1207                 break;
1208
1209         case SIGCOMP_INSTR_COPY_LITERAL: /* 19 COPY-LITERAL (%position, %length, $destination) */
1210                 if (show_instr_detail_level == 2 ){
1211                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1212                                 "Addr: %u ## COPY-LITERAL(19) (position, length, $destination)",
1213                                 current_address);
1214                 }
1215                 operand_address = current_address + 1;
1216                 /* %position */
1217                 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &position);
1218                 if (show_instr_detail_level == 2 ){
1219                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u      position %u",
1220                                 operand_address, position);
1221                 }
1222                 operand_address = next_operand_address; 
1223
1224                 /* %length */
1225                 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &length);
1226                 if (show_instr_detail_level == 2 ){
1227                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u      Length %u",
1228                                 operand_address, length);
1229                 }
1230                 operand_address = next_operand_address;
1231
1232
1233                 /* $destination */
1234                 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &ref_destination, &result_dest);
1235                 if (show_instr_detail_level == 2 ){
1236                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u      destination %u",
1237                                 operand_address, ref_destination);
1238                 }
1239                 if (show_instr_detail_level == 1)
1240                 {
1241                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1242                                 "Addr: %u ## COPY-LITERAL (position=%u, length=%u, $destination=%u)",
1243                                 current_address, position, length, destination);
1244                 }
1245                 current_address = next_operand_address; 
1246
1247
1248                 /*
1249                  * 8.4.  Byte copying
1250                  * :
1251                  * The string of bytes is copied in ascending order of memory address,
1252                  * respecting the bounds set by byte_copy_left and byte_copy_right.
1253                  * More precisely, if a byte is copied from/to Address m then the next
1254                  * byte is copied from/to Address n where n is calculated as follows:
1255                  *
1256                  * Set k := m + 1 (modulo 2^16)
1257                  * If k = byte_copy_right then set n := byte_copy_left, else set n := k
1258                  *
1259                  */ 
1260
1261                 n = 0;
1262                 k = ref_destination; 
1263                 byte_copy_right = buff[66] << 8;
1264                 byte_copy_right = byte_copy_right | buff[67];
1265                 byte_copy_left = buff[64] << 8;
1266                 byte_copy_left = byte_copy_left | buff[65];
1267                 if (print_level_2 ){
1268                         proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
1269                                         "               byte_copy_right = %u", byte_copy_right);
1270                 }
1271                 while ( n < length ){
1272
1273                         buff[k] = buff[position];
1274                         if (print_level_2 ){
1275                                 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
1276                                         "               Copying value: %u (0x%x) to Addr: %u", 
1277                                         buff[position], buff[position], k);
1278                         }
1279                         position = ( position + 1 ) & 0xffff;
1280                         k = ( k + 1 ) & 0xffff;
1281                         n++;
1282
1283                         /*
1284                          * Check for circular buffer wrapping after the positions are
1285                          * incremented. It is important that k cannot be left set
1286                          * to BCR. Also, if either started at BCR then they should continue
1287                          * to increment beyond BCR.
1288                          */
1289                         if ( k == byte_copy_right ){
1290                                 k = byte_copy_left;
1291                         }
1292                         if ( position == byte_copy_right ){
1293                                 position = byte_copy_left;
1294                         }
1295                 }
1296                 buff[result_dest] = k >> 8;
1297                 buff[result_dest + 1] = k & 0x00ff;
1298
1299                 used_udvm_cycles = used_udvm_cycles + 1 + length;
1300                 goto execute_next_instruction;
1301                 break;
1302  
1303         case SIGCOMP_INSTR_COPY_OFFSET: /* 20 COPY-OFFSET (%offset, %length, $destination) */
1304                 if (show_instr_detail_level == 2 ){
1305                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1306                                 "Addr: %u ## COPY-OFFSET(20) (offset, length, $destination)",
1307                                 current_address);
1308                 }
1309                 operand_address = current_address + 1;
1310                 /* %offset */
1311                 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &multy_offset);
1312                 if (show_instr_detail_level == 2 ){
1313                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u      offset %u",
1314                                 operand_address, multy_offset);
1315                 }
1316                 operand_address = next_operand_address; 
1317
1318                 /* %length */
1319                 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &length);
1320                 if (show_instr_detail_level == 2 ){
1321                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u      Length %u",
1322                                 operand_address, length);
1323                 }
1324                 operand_address = next_operand_address;
1325
1326
1327                 /* $destination */
1328                 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &ref_destination, &result_dest);
1329                 if (show_instr_detail_level == 2 ){
1330                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u      $destination %u",
1331                                 operand_address, ref_destination);
1332                 }
1333
1334                 if (show_instr_detail_level == 1)
1335                 {
1336                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1337                                 "Addr: %u ## COPY-OFFSET (offset=%u, length=%u, $destination=%u)",
1338                                 current_address, multy_offset, length, result_dest);
1339                 }
1340                 current_address = next_operand_address; 
1341
1342                 /* Execute the instruction:
1343                  * To derive the value of the position operand, starting at the memory
1344                  * address specified by destination, the UDVM counts backwards a total
1345                  * of offset memory addresses.
1346                  * 
1347                  * If the memory address specified in byte_copy_left is reached, the
1348                  * next memory address is taken to be (byte_copy_right - 1) modulo 2^16.
1349                  */
1350                 byte_copy_left = buff[64] << 8;
1351                 byte_copy_left = byte_copy_left | buff[65];
1352                 byte_copy_right = buff[66] << 8;
1353                 byte_copy_right = byte_copy_right | buff[67];
1354
1355                 /*
1356                  * In order to work out the position, simple arithmetic is tricky
1357                  * to apply because there some nasty corner cases. A simple loop
1358                  * is inefficient but the logic is simple.
1359                  *
1360                  * FUTURE: This could be optimised.
1361                  */
1362                 for (position = ref_destination, i = 0; i < multy_offset; i++)
1363                 {
1364                         if ( position == byte_copy_left )
1365                         {
1366                                 position = (byte_copy_right - 1) & 0xffff;
1367                         }
1368                         else
1369                         {
1370                                 position = (position - 1) & 0xffff;
1371                         }
1372                 }
1373
1374                 if (print_level_2 ){
1375                         proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
1376                                         "               byte_copy_left = %u byte_copy_right = %u position= %u",
1377                                         byte_copy_left, byte_copy_right, position);
1378                         }
1379                 /* The COPY-OFFSET instruction then behaves as a COPY-LITERAL
1380                  * instruction, taking the value of the position operand to be the last
1381                  * memory address reached in the above step.
1382                  */
1383
1384                 /*
1385                  * 8.4.  Byte copying
1386                  * :
1387                  * The string of bytes is copied in ascending order of memory address,
1388                  * respecting the bounds set by byte_copy_left and byte_copy_right.
1389                  * More precisely, if a byte is copied from/to Address m then the next
1390                  * byte is copied from/to Address n where n is calculated as follows:
1391                  *
1392                  * Set k := m + 1 (modulo 2^16)
1393                  * If k = byte_copy_right then set n := byte_copy_left, else set n := k
1394                  *
1395                  */ 
1396
1397                 n = 0;
1398                 k = ref_destination; 
1399                 if (print_level_2 ){
1400                         proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
1401                                         "               byte_copy_left = %u byte_copy_right = %u", byte_copy_left, byte_copy_right);
1402                 }
1403                 while ( n < length ){
1404                         buff[k] = buff[position];
1405                         if (print_level_2 ){
1406                                 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
1407                                         "               Copying value: %5u (0x%x) from Addr: %u to Addr: %u",
1408                                         buff[position], buff[position],(position), k);
1409                         }
1410                         n++;
1411                         k = ( k + 1 ) & 0xffff;
1412                         position = ( position + 1 ) & 0xffff;
1413
1414                         /*
1415                          * Check for circular buffer wrapping after the positions are
1416                          * incremented. It is important that k cannot be left set
1417                          * to BCR. Also, if either started at BCR then they should continue
1418                          * to increment beyond BCR.
1419                          */
1420                         if ( k == byte_copy_right ){
1421                                 k = byte_copy_left;
1422                         }
1423                         if ( position == byte_copy_right ){
1424                                 position = byte_copy_left;
1425                         }
1426                 }
1427                 buff[result_dest] = k >> 8;
1428                 buff[result_dest + 1] = k & 0x00ff;
1429                 used_udvm_cycles = used_udvm_cycles + 1 + length;
1430                 goto execute_next_instruction;
1431
1432                 break;
1433         case SIGCOMP_INSTR_MEMSET: /* 21 MEMSET (%address, %length, %start_value, %offset) */
1434                 if (show_instr_detail_level == 2 ){
1435                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1436                                 "Addr: %u ## MEMSET(21) (address, length, start_value, offset)",
1437                                 current_address);
1438                 }
1439                 operand_address = current_address + 1;
1440
1441                 /* %address */
1442                 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &address);
1443                 if (show_instr_detail_level == 2 ){
1444                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u      Address %u",
1445                                 operand_address, address);
1446                 }
1447                 operand_address = next_operand_address; 
1448
1449                 /*  %length, */
1450                 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &length);
1451                 if (show_instr_detail_level == 2 ){
1452                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u      Length %u",
1453                                 operand_address, length);
1454                 }
1455                 operand_address = next_operand_address;
1456                 /* %start_value */
1457                 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &start_value);
1458                 if (show_instr_detail_level == 2 ){
1459                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u      start_value %u",
1460                                 operand_address, start_value);
1461                 }
1462                 operand_address = next_operand_address; 
1463
1464                 /* %offset */
1465                 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &multy_offset);
1466                 if (show_instr_detail_level == 2 ){
1467                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u      offset %u",
1468                                 operand_address, multy_offset);
1469                 }
1470                 if (show_instr_detail_level == 1)
1471                 {
1472                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1473                                 "Addr: %u ## MEMSET (address=%u, length=%u, start_value=%u, offset=%u)",
1474                                 current_address, address, length, start_value, multy_offset);
1475                 }
1476                 current_address = next_operand_address; 
1477                 /* exetute the instruction
1478                  * The sequence of values used by the MEMSET instruction is specified by
1479                  * the following formula:
1480                  * 
1481                  * Seq[n] := (start_value + n * offset) modulo 256
1482                  */
1483                 n = 0;
1484                 k = address; 
1485                 byte_copy_right = buff[66] << 8;
1486                 byte_copy_right = byte_copy_right | buff[67];
1487                 byte_copy_left = buff[64] << 8;
1488                 byte_copy_left = byte_copy_left | buff[65];
1489                 if (print_level_2 ){
1490                         proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
1491                                         "               byte_copy_left = %u byte_copy_right = %u", byte_copy_left, byte_copy_right);
1492                 }
1493                 while ( n < length ){
1494                         if ( k == byte_copy_right ){
1495                                 k = byte_copy_left;
1496                         }
1497                         buff[k] = (start_value + ( n * multy_offset)) & 0xff;
1498                         if (print_level_2 ){
1499                                 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
1500                                         "     Storing value: %u (0x%x) at Addr: %u",
1501                                         buff[k], buff[k], k);
1502                         }
1503                         k = ( k + 1 ) & 0xffff;
1504                         n++;
1505                 }/* end while */
1506                 used_udvm_cycles = used_udvm_cycles + 1 + length;
1507                 goto execute_next_instruction;
1508                 break;
1509
1510
1511         case SIGCOMP_INSTR_JUMP: /* 22 JUMP (@address) */
1512                 if (show_instr_detail_level == 2 ){
1513                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1514                                 "Addr: %u ## JUMP(22) (@address)",
1515                                 current_address);
1516                 }
1517                 operand_address = current_address + 1;
1518                 /* @address */
1519                  /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
1520                 next_operand_address = decode_udvm_address_operand(buff,operand_address, &at_address, current_address);
1521                 if (show_instr_detail_level == 2 ){
1522                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u      @Address %u",
1523                                 operand_address, at_address);
1524                 }
1525                 if (show_instr_detail_level == 1)
1526                 {
1527                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1528                                 "Addr: %u ## JUMP (@address=%u)",
1529                                 current_address, at_address);
1530                 }
1531                 current_address = at_address;
1532                 used_udvm_cycles++;
1533                 goto execute_next_instruction;
1534                 break;
1535
1536         case SIGCOMP_INSTR_COMPARE: /* 23 */
1537                 /* COMPARE (%value_1, %value_2, @address_1, @address_2, @address_3)
1538                  */
1539                 if (show_instr_detail_level == 2 ){
1540                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1541                                 "Addr: %u ## COMPARE(23) (value_1, value_2, @address_1, @address_2, @address_3)",
1542                                 current_address);
1543                 }
1544                 operand_address = current_address + 1;
1545
1546                 /* %value_1 */
1547                 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &value_1);
1548                 if (show_instr_detail_level == 2 ){
1549                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u      Value %u",
1550                                         operand_address, value_1);
1551                 }
1552                 operand_address = next_operand_address;
1553
1554                 /* %value_2 */
1555                 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &value_2);
1556                 if (show_instr_detail_level == 2 ){
1557                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u      Value %u",
1558                                         operand_address, value_2);
1559                 }
1560                 operand_address = next_operand_address;
1561
1562                 /* @address_1 */
1563                  /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
1564                 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &at_address_1);
1565                 at_address_1 = ( current_address + at_address_1) & 0xffff;
1566                 if (show_instr_detail_level == 2 ){
1567                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u      @Address %u",
1568                                 operand_address, at_address_1);
1569                 }
1570                 operand_address = next_operand_address;
1571
1572
1573                 /* @address_2 */
1574                  /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
1575                 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &at_address_2);
1576                 at_address_2 = ( current_address + at_address_2) & 0xffff;
1577                 if (show_instr_detail_level == 2 ){
1578                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u      @Address %u",
1579                                 operand_address, at_address_2);
1580                 }
1581                 operand_address = next_operand_address;
1582
1583                 /* @address_3 */
1584                  /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
1585                 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &at_address_3);
1586                 at_address_3 = ( current_address + at_address_3) & 0xffff;
1587                 if (show_instr_detail_level == 2 ){
1588                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u      @Address %u",
1589                                 operand_address, at_address_3);
1590                 }
1591                 if (show_instr_detail_level == 1)
1592                 {
1593                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1594                                 "Addr: %u ## COMPARE (value_1=%u, value_2=%u, @address_1=%u, @address_2=%u, @address_3=%u)",
1595                                 current_address, value_1, value_2, at_address_1, at_address_2, at_address_3);
1596                 }
1597                 /* execute the instruction
1598                  * If value_1 < value_2 then the UDVM continues instruction execution at
1599                  * the memory address specified by address 1. If value_1 = value_2 then
1600                  * it jumps to the address specified by address_2. If value_1 > value_2
1601                  * then it jumps to the address specified by address_3.
1602                  */
1603                 if ( value_1 < value_2 )
1604                         current_address = at_address_1;
1605                 if ( value_1 == value_2 )
1606                         current_address = at_address_2;
1607                 if ( value_1 > value_2 )
1608                         current_address = at_address_3;
1609                 used_udvm_cycles++;
1610                 goto execute_next_instruction;
1611                 break;
1612
1613         case SIGCOMP_INSTR_CALL: /* 24 CALL (@address) (PUSH addr )*/
1614                 if (show_instr_detail_level == 2){
1615                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1616                                 "Addr: %u ## CALL(24) (@address) (PUSH addr )",
1617                                 current_address);
1618                 }
1619                 operand_address = current_address + 1;
1620                 /* @address */
1621                 next_operand_address = decode_udvm_address_operand(buff,operand_address, &at_address, current_address);
1622                 if (show_instr_detail_level == 2 ){
1623                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u      @Address %u",
1624                                 operand_address, at_address);
1625                 }
1626                 if (show_instr_detail_level == 1)
1627                 {
1628                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1629                                 "Addr: %u ## CALL (@address=%u)",
1630                                 current_address, at_address);
1631                 }
1632                 current_address = next_operand_address; 
1633
1634                 /* Push the current address onto the stack */ 
1635                 stack_location = (buff[70] << 8) | buff[71];
1636                 stack_fill = (buff[stack_location] << 8) 
1637                            | buff[(stack_location+1) & 0xFFFF];
1638                 address = (stack_location + stack_fill * 2 + 2) & 0xFFFF;
1639                 if (address >= UDVM_MEMORY_SIZE - 1)
1640                         goto decompression_failure;
1641                 buff[address] = (current_address >> 8) & 0x00FF;
1642                 buff[(address+1) & 0xFFFF] = current_address & 0x00FF;
1643                 
1644                 stack_fill = (stack_fill + 1) & 0xFFFF;
1645                 if (stack_location >= UDVM_MEMORY_SIZE - 1)
1646                         goto decompression_failure;
1647                 buff[stack_location] = (stack_fill >> 8) & 0x00FF;
1648                 buff[(stack_location+1) & 0xFFFF] = stack_fill & 0x00FF;
1649
1650                 /* ... and jump to the destination address */
1651                 current_address = at_address;
1652
1653                 used_udvm_cycles++;
1654                 goto execute_next_instruction;
1655
1656                 break;
1657
1658         case SIGCOMP_INSTR_RETURN: /* 25 POP and return */
1659                 if (print_level_1 || show_instr_detail_level == 1){
1660                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1661                                 "Addr: %u ## POP(25) and return",
1662                                 current_address);
1663                 }
1664
1665                 /* Pop value from the top of the stack */ 
1666                 stack_location = (buff[70] << 8) | buff[71];
1667                 stack_fill = (buff[stack_location] << 8) 
1668                            | buff[(stack_location+1) & 0xFFFF];
1669                 if (stack_fill == 0)
1670                 {
1671                     result_code = 16;
1672                     goto decompression_failure;
1673                 }
1674
1675                 stack_fill = (stack_fill - 1) & 0xFFFF;
1676                 if (stack_location >= UDVM_MEMORY_SIZE - 1)
1677                         goto decompression_failure;
1678                 buff[stack_location] = (stack_fill >> 8) & 0x00FF;
1679                 buff[(stack_location+1) & 0xFFFF] = stack_fill & 0x00FF;
1680
1681                 address = (stack_location + stack_fill * 2 + 2) & 0xFFFF;
1682                 at_address = (buff[address] << 8) 
1683                            | buff[(address+1) & 0xFFFF];
1684
1685                 /* ... and set the PC to the popped value */
1686                 current_address = at_address;
1687
1688                 used_udvm_cycles++;
1689                 goto execute_next_instruction;
1690
1691                 break;
1692
1693         case SIGCOMP_INSTR_SWITCH: /* 26 SWITCH (#n, %j, @address_0, @address_1, ... , @address_n-1) */
1694                 /*
1695                  * When a SWITCH instruction is encountered the UDVM reads the value of
1696                  * j. It then continues instruction execution at the address specified
1697                  * by address j.
1698                  * 
1699                  * Decompression failure occurs if j specifies a value of n or more, or
1700                  * if the address lies beyond the overall UDVM memory size.
1701                  */
1702                 instruction_address = current_address;
1703                 if (print_level_1 ){
1704                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1705                                 "Addr: %u ## SWITCH (#n, j, @address_0, @address_1, ... , @address_n-1))",
1706                                 current_address);
1707                 }
1708                 operand_address = current_address + 1;
1709                 /* #n 
1710                  * Number of addresses in the instruction
1711                  */
1712                 next_operand_address = decode_udvm_literal_operand(buff,operand_address, &n);
1713                 if (print_level_1 ){
1714                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u      n %u",
1715                                 operand_address, n);
1716                 }
1717                 operand_address = next_operand_address; 
1718                 /* %j */
1719                 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &j);
1720                 if (print_level_1 ){
1721                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u      j %u",
1722                                         operand_address, j);
1723                 }
1724                 operand_address = next_operand_address;
1725                 m = 0;
1726                 while ( m < n ){
1727                         /* @address_n-1 */
1728                         /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
1729                         next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &at_address_1);
1730                         at_address_1 = ( instruction_address + at_address_1) & 0xffff;
1731                         if (print_level_1 ){
1732                                 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u      @Address %u",
1733                                         operand_address, at_address_1);
1734                         }
1735                         if ( j == m ){
1736                                 current_address = at_address_1;
1737                         }
1738                         operand_address = next_operand_address;
1739                         m++;
1740                 }
1741                 /* Check decompression failure */
1742                 if ( ( j == n ) || ( j > n )){
1743                         result_code = 5;
1744                         goto decompression_failure;
1745                 }
1746                 if ( current_address > UDVM_MEMORY_SIZE ){
1747                         result_code = 6;
1748                         goto decompression_failure;
1749                 }
1750                 used_udvm_cycles = used_udvm_cycles + 1 + n;
1751
1752                 goto execute_next_instruction;
1753
1754                 break;
1755         case SIGCOMP_INSTR_CRC: /* 27 CRC (%value, %position, %length, @address) */
1756                 if (print_level_1 ){
1757                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1758                                 "Addr: %u ## CRC (value, position, length, @address)",
1759                                 current_address);
1760                 }
1761
1762                 operand_address = current_address + 1;
1763
1764                 /* %value */
1765                 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &value);
1766                 if (print_level_1 ){
1767                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u      Value %u",
1768                                 operand_address, value);
1769                 }
1770                 operand_address = next_operand_address; 
1771
1772                 /* %position */
1773                 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &position);
1774                 if (print_level_1 ){
1775                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u      position %u",
1776                                 operand_address, position);
1777                 }
1778                 operand_address = next_operand_address; 
1779
1780                 /* %length */
1781                 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &length);
1782                 if (print_level_1 ){
1783                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u      Length %u",
1784                                 operand_address, length);
1785                 }
1786                 operand_address = next_operand_address;
1787
1788                 /* @address */
1789                 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &at_address);
1790                 at_address = ( current_address + at_address) & 0xffff;
1791                 if (print_level_1 ){
1792                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u      @Address %u",
1793                                 operand_address, at_address);
1794                 }
1795                  /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
1796                 used_udvm_cycles = used_udvm_cycles + 1 + length;
1797                 
1798                 n = 0;
1799                 k = position;
1800                 byte_copy_right = buff[66] << 8;
1801                 byte_copy_right = byte_copy_right | buff[67];
1802                 byte_copy_left = buff[64] << 8;
1803                 byte_copy_left = byte_copy_left | buff[65];
1804                 result = 0;
1805
1806                 if (print_level_2 ){
1807                         proto_tree_add_text(udvm_tree, message_tvb, 0, -1,
1808                                         "byte_copy_right = %u", byte_copy_right);
1809                 }
1810
1811                 while (n<length) {
1812
1813                         guint16 handle_now = length - n;
1814
1815                         if ( k < byte_copy_right && byte_copy_right <= k + (length-n) ){
1816                                 handle_now = byte_copy_right - k;
1817                         }
1818
1819                         if (k + handle_now >= UDVM_MEMORY_SIZE)
1820                                 goto decompression_failure;
1821                         result = crc16_ccitt_seed(&buff[k], handle_now, (guint16) (result ^ 0xffff));
1822
1823                         k = ( k + handle_now ) & 0xffff;
1824                         n = ( n + handle_now ) & 0xffff;
1825
1826                         if ( k >= byte_copy_right ) {
1827                                 k = byte_copy_left;
1828                         }
1829                 }
1830
1831                 result = result ^ 0xffff;
1832
1833                 if (print_level_1 ){
1834                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1, "Calculated CRC %u", result);
1835                 }
1836                 if (result != value){
1837                         current_address = at_address;
1838                 }
1839                 else {
1840                         current_address = next_operand_address;
1841                 }
1842                 goto execute_next_instruction;
1843                 break;
1844
1845
1846         case SIGCOMP_INSTR_INPUT_BYTES: /* 28 INPUT-BYTES (%length, %destination, @address) */
1847                 if (show_instr_detail_level == 2 ){
1848                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1849                                 "Addr: %u ## INPUT-BYTES(28) length, destination, @address)",
1850                                 current_address);
1851                 }
1852                 operand_address = current_address + 1;
1853                 /* %length */
1854                 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &length);
1855                 if (show_instr_detail_level == 2 ){
1856                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u      Length %u",
1857                                 operand_address, length);
1858                 }
1859                 operand_address = next_operand_address;
1860
1861                 /* %destination */
1862                 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &destination);
1863                 if (show_instr_detail_level == 2 ){
1864                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u      Destination %u",
1865                                 operand_address, destination);
1866                 }
1867                 operand_address = next_operand_address;
1868
1869                 /* @address */
1870                  /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
1871                 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &at_address);
1872                 at_address = ( current_address + at_address) & 0xffff;
1873                 if (show_instr_detail_level == 2 ){
1874                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u      @Address %u",
1875                                 operand_address, at_address);
1876                 }
1877                 if (show_instr_detail_level == 1)
1878                 {
1879                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1880                                 "Addr: %u ## INPUT-BYTES length=%u, destination=%u, @address=%u)",
1881                                 current_address, length, destination, at_address);
1882                 }
1883                 /* execute the instruction TODO insert checks 
1884                  * RFC 3320 :
1885                  *
1886                  *    0             7 8            15
1887                  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1888                  *   |        byte_copy_left         |  64 - 65
1889                  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1890                  *   |        byte_copy_right        |  66 - 67
1891                  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1892                  *   |        input_bit_order        |  68 - 69
1893                  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1894                  *   |        stack_location         |  70 - 71
1895                  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1896                  * 
1897                  * Figure 7: Memory addresses of the UDVM registers
1898                  * :
1899                  * 8.4.  Byte copying
1900                  * :
1901                  * The string of bytes is copied in ascending order of memory address,
1902                  * respecting the bounds set by byte_copy_left and byte_copy_right.
1903                  * More precisely, if a byte is copied from/to Address m then the next
1904                  * byte is copied from/to Address n where n is calculated as follows:
1905                  *
1906                  * Set k := m + 1 (modulo 2^16)
1907                  * If k = byte_copy_right then set n := byte_copy_left, else set n := k
1908                  *
1909                  */ 
1910
1911                 n = 0;
1912                 k = destination; 
1913                 byte_copy_right = buff[66] << 8;
1914                 byte_copy_right = byte_copy_right | buff[67];
1915                 byte_copy_left = buff[64] << 8;
1916                 byte_copy_left = byte_copy_left | buff[65];
1917                 if (print_level_1 ){
1918                         proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
1919                                         "               byte_copy_right = %u", byte_copy_right);
1920                 }
1921                 /* clear out remaining bits if any */
1922                 remaining_bits = 0;
1923                 input_bits=0;
1924                 /* operand_address used as dummy */
1925                 while ( n < length ){
1926                         if (input_address > ( msg_end - 1)){
1927                                 current_address = at_address;
1928                                 result_code = 14;
1929                                 goto execute_next_instruction;
1930                         }
1931
1932                         if ( k == byte_copy_right ){
1933                                 k = byte_copy_left;
1934                         }
1935                         octet = tvb_get_guint8(message_tvb, input_address);
1936                         buff[k] = octet;
1937                         if (print_level_1 ){
1938                                 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
1939                                         "               Loading value: %u (0x%x) at Addr: %u", octet, octet, k);
1940                         }
1941                         input_address++;
1942                         /*
1943                          * If the instruction requests data that lies beyond the end of the
1944                          * SigComp message, no data is returned.  Instead the UDVM moves program
1945                          * execution to the address specified by the address operand.
1946                          */
1947
1948                         
1949                         k = ( k + 1 ) & 0xffff;
1950                         n++;
1951                 }
1952                 used_udvm_cycles = used_udvm_cycles + 1 + length;
1953                 current_address = next_operand_address;
1954                 goto execute_next_instruction;
1955                 break;
1956         case SIGCOMP_INSTR_INPUT_BITS:/* 29   INPUT-BITS (%length, %destination, @address) */
1957                 /*
1958                  * The length operand indicates the requested number of bits.
1959                  * Decompression failure occurs if this operand does not lie between 0
1960                  * and 16 inclusive.
1961                  * 
1962                  * The destination operand specifies the memory address to which the
1963                  * compressed data should be copied.  Note that the requested bits are
1964                  * interpreted as a 2-byte integer ranging from 0 to 2^length - 1, as
1965                  * explained in Section 8.2.
1966                  *
1967                  * If the instruction requests data that lies beyond the end of the
1968                  * SigComp message, no data is returned.  Instead the UDVM moves program
1969                  * execution to the address specified by the address operand.
1970                  */
1971
1972                 if (show_instr_detail_level == 2 ){
1973                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1974                                 "Addr: %u ## INPUT-BITS(29) (length, destination, @address)",
1975                                 current_address);
1976                 }
1977                 operand_address = current_address + 1;
1978
1979                 /* %length */
1980                 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &length);
1981                 if (show_instr_detail_level == 2 ){
1982                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u      length %u",
1983                                 operand_address, length);
1984                 }
1985                 operand_address = next_operand_address;
1986                 /* %destination */
1987                 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &destination);
1988                 if (show_instr_detail_level == 2 ){
1989                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u      Destination %u",
1990                                 operand_address, destination);
1991                 }
1992                 operand_address = next_operand_address;
1993
1994                 /* @address */
1995                  /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
1996                 next_operand_address = decode_udvm_address_operand(buff,operand_address, &at_address, current_address);
1997                 if (show_instr_detail_level == 2 ){
1998                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u      @Address %u",
1999                                 operand_address, at_address);
2000                 }
2001                 if (show_instr_detail_level == 1)
2002                 {
2003                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2004                                 "Addr: %u ## INPUT-BITS length=%u, destination=%u, @address=%u)",
2005                                 current_address, length, destination, at_address);
2006                 }
2007                 current_address = next_operand_address;
2008
2009                 /*
2010                  * Execute actual instr.
2011                  * The input_bit_order register contains the following three flags:
2012                  * 
2013                  *            0             7 8            15
2014                  *           +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2015                  *           |         reserved        |F|H|P|  68 - 69
2016                  *           +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2017                  */
2018                 input_bit_order = buff[68] << 8;
2019                 input_bit_order = input_bit_order | buff[69];
2020                 /*
2021                  * If the instruction requests data that lies beyond the end of the
2022                  * SigComp message, no data is returned.  Instead the UDVM moves program
2023                  * execution to the address specified by the address operand.
2024                  */
2025
2026                 if ( length > 16 ){
2027                         result_code = 7;
2028                         goto decompression_failure;
2029                 }
2030                 if ( input_bit_order > 7 ){
2031                         result_code = 8;
2032                         goto decompression_failure;
2033                 }
2034
2035                 /* 
2036                  * Transfer F bit to bit_order to tell decomp dispatcher which bit order to use 
2037                  */
2038                 bit_order = ( input_bit_order & 0x0004 ) >> 2;
2039                 value = decomp_dispatch_get_bits( message_tvb, udvm_tree, bit_order, 
2040                                 buff, &old_input_bit_order, &remaining_bits,
2041                                 &input_bits, &input_address, length, &result_code, msg_end);
2042                 if ( result_code == 11 ){
2043                         used_udvm_cycles = used_udvm_cycles + 1;
2044                         current_address = at_address;
2045                         goto execute_next_instruction;
2046                 }
2047                 msb = value >> 8;
2048                 lsb = value & 0x00ff;
2049                 if (destination >= UDVM_MEMORY_SIZE - 1)
2050                         goto decompression_failure;
2051                 buff[destination] = msb;
2052                 buff[destination + 1]=lsb;
2053                 if (print_level_1 ){
2054                         proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
2055                         "               Loading value: %u (0x%x) at Addr: %u, remaining_bits: %u", value, value, destination, remaining_bits);
2056                 }
2057
2058                 used_udvm_cycles = used_udvm_cycles + 1;
2059                 goto execute_next_instruction;
2060                 break;
2061         case SIGCOMP_INSTR_INPUT_HUFFMAN: /* 30 */
2062                 /*
2063                  * INPUT-HUFFMAN (%destination, @address, #n, %bits_1, %lower_bound_1,
2064                  *  %upper_bound_1, %uncompressed_1, ... , %bits_n, %lower_bound_n,
2065                  *  %upper_bound_n, %uncompressed_n)
2066                  */
2067                 if (show_instr_detail_level == 2 ){
2068                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2069                                 "Addr: %u ## INPUT-HUFFMAN (destination, @address, #n, bits_1, lower_bound_1,upper_bound_1, uncompressed_1, ... , bits_n, lower_bound_n,upper_bound_n, uncompressed_n)",
2070                                 current_address);
2071                 }
2072                 operand_address = current_address + 1;
2073
2074                 /* %destination */
2075                 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &destination);
2076                 if (show_instr_detail_level == 2 ){
2077                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u      Destination %u",
2078                                 operand_address, destination);
2079                 }
2080                 operand_address = next_operand_address;
2081
2082                 /* @address */
2083                  /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
2084                 next_operand_address = decode_udvm_address_operand(buff,operand_address, &at_address, current_address);
2085                 if (show_instr_detail_level == 2 ){
2086                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u      @Address %u",
2087                                 operand_address, at_address);
2088                 }
2089                 operand_address = next_operand_address;
2090
2091                 /* #n */
2092                 next_operand_address = decode_udvm_literal_operand(buff,operand_address, &n);
2093                 if (show_instr_detail_level == 2 ){
2094                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u      n %u",
2095                                 operand_address, n);
2096                 }
2097                 operand_address = next_operand_address; 
2098                 if (show_instr_detail_level == 1)
2099                 {
2100                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2101                                 "Addr: %u ## INPUT-HUFFMAN (destination=%u, @address=%u, #n=%u, bits_1, lower_1,upper_1, unc_1, ... , bits_%d, lower_%d,upper_%d, unc_%d)",
2102                                 current_address, destination, at_address, n, n, n, n, n);
2103                 }
2104
2105                 used_udvm_cycles = used_udvm_cycles + 1 + n;
2106
2107                 /*
2108                  * Note that if n = 0 then the INPUT-HUFFMAN instruction is ignored and
2109                  * program execution resumes at the following instruction.
2110                  * Decompression failure occurs if (bits_1 + ... + bits_n) > 16.
2111                  * 
2112                  * In all other cases, the behavior of the INPUT-HUFFMAN instruction is
2113                  * defined below:
2114                  * 
2115                  * 1. Set j := 1 and set H := 0.
2116                  * 
2117                  * 2. Request bits_j compressed bits.  Interpret the returned bits as an
2118                  * integer k from 0 to 2^bits_j - 1, as explained in Section 8.2.
2119                  * 
2120                  * 3. Set H := H * 2^bits_j + k.
2121                  * 
2122                  * 4. If data is requested that lies beyond the end of the SigComp
2123                  * message, terminate the INPUT-HUFFMAN instruction and move program
2124                  * execution to the memory address specified by the address operand.
2125                  * 
2126                  * 5. If (H < lower_bound_j) or (H > upper_bound_j) then set j := j + 1.
2127                  * Then go back to Step 2, unless j > n in which case decompression
2128                  * failure occurs.
2129                  * 
2130                  * 6. Copy (H + uncompressed_j - lower_bound_j) modulo 2^16 to the
2131                  * memory address specified by the destination operand.
2132                  * 
2133                  */
2134                 /*
2135                  * The input_bit_order register contains the following three flags:
2136                  * 
2137                  *            0             7 8            15
2138                  *           +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2139                  *           |         reserved        |F|H|P|  68 - 69
2140                  *           +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2141                  *
2142                  * Transfer H bit to bit_order to tell decomp dispatcher which bit order to use 
2143                  */
2144                 input_bit_order = buff[68] << 8;
2145                 input_bit_order = input_bit_order | buff[69];
2146                 bit_order = ( input_bit_order & 0x0002 ) >> 1;
2147
2148                 j = 1;
2149                 H = 0;
2150                 m = n;
2151                 outside_huffman_boundaries = TRUE;
2152                 print_in_loop = print_level_3;
2153                 while ( m > 0 ){
2154                         /* %bits_n */
2155                         next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &bits_n);
2156                         if (print_in_loop ){
2157                                 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u      bits_n %u",
2158                                         operand_address, bits_n);
2159                         }
2160                         operand_address = next_operand_address; 
2161
2162                         /* %lower_bound_n */
2163                         next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &lower_bound_n);
2164                         if (print_in_loop ){
2165                                 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u      lower_bound_n %u",
2166                                         operand_address, lower_bound_n);
2167                         }
2168                         operand_address = next_operand_address; 
2169                         /* %upper_bound_n */
2170                         next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &upper_bound_n);
2171                         if (print_in_loop ){
2172                                 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u      upper_bound_n %u",
2173                                         operand_address, upper_bound_n);
2174                         }
2175                         operand_address = next_operand_address; 
2176                         /* %uncompressed_n */
2177                         next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &uncompressed_n);
2178                         if (print_in_loop ){
2179                                 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u      uncompressed_n %u",
2180                                         operand_address, uncompressed_n);
2181                         }
2182                         operand_address = next_operand_address;
2183                         /* execute instruction */
2184                         if ( outside_huffman_boundaries ) {
2185                                 /*
2186                                  * 2. Request bits_j compressed bits.  Interpret the returned bits as an
2187                                  *    integer k from 0 to 2^bits_j - 1, as explained in Section 8.2.
2188                                  */
2189                                 k = decomp_dispatch_get_bits( message_tvb, udvm_tree, bit_order, 
2190                                                 buff, &old_input_bit_order, &remaining_bits,
2191                                                 &input_bits, &input_address, bits_n, &result_code, msg_end);
2192                                 if ( result_code == 11 ){
2193                                         /*
2194                                         * 4. If data is requested that lies beyond the end of the SigComp
2195                                         * message, terminate the INPUT-HUFFMAN instruction and move program
2196                                         * execution to the memory address specified by the address operand.
2197                                         */
2198                                         current_address = at_address;
2199                                         goto execute_next_instruction;
2200                                 }
2201
2202                                 /* 
2203                                  * 3. Set H := H * 2^bits_j + k.
2204                                  * [In practice is a shift+OR operation.]
2205                                  */
2206                                 oldH = H;
2207                                 H = (H << bits_n) | k;
2208                                 if (print_level_3 ){
2209                                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"               Set H(%u) := H(%u) * 2^bits_j(%u) + k(%u)",
2210                                                  H ,oldH, 1<<bits_n,k);
2211                                 }
2212
2213                                 /*
2214                                  * 5. If (H < lower_bound_j) or (H > upper_bound_j) then set j := j + 1.
2215                                  * Then go back to Step 2, unless j > n in which case decompression
2216                                  * failure occurs.
2217                                  */
2218                                 if ((H < lower_bound_n) || (H > upper_bound_n)){
2219                                         outside_huffman_boundaries = TRUE;
2220                                 }else{
2221                                         outside_huffman_boundaries = FALSE;
2222                                         print_in_loop = FALSE;
2223                                         /*
2224                                          * 6. Copy (H + uncompressed_j - lower_bound_j) modulo 2^16 to the
2225                                          * memory address specified by the destination operand.
2226                                          */
2227                                         if (print_level_2 ){
2228                                                 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2229                                                         "               H(%u) = H(%u) + uncompressed_n(%u) - lower_bound_n(%u)",
2230                                                 (H + uncompressed_n - lower_bound_n ),H, uncompressed_n, lower_bound_n);
2231                                         }
2232                                         H = H + uncompressed_n - lower_bound_n;
2233                                         msb = H >> 8;
2234                                         lsb = H & 0x00ff;
2235                                         if (destination >= UDVM_MEMORY_SIZE - 1)
2236                                                 goto decompression_failure;
2237                                         buff[destination] = msb;
2238                                         buff[destination + 1]=lsb;
2239                                         if (print_level_1 ){
2240                                                 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
2241                                         "               Loading H: %u (0x%x) at Addr: %u,j = %u remaining_bits: %u", 
2242                                                 H, H, destination,( n - m + 1 ), remaining_bits);
2243                                         }
2244                                         
2245                                 }
2246
2247
2248                         }
2249                         m = m - 1;
2250                 }
2251                 if ( outside_huffman_boundaries ) {
2252                         result_code = 10;
2253                         goto decompression_failure;
2254                 }
2255
2256                 current_address = next_operand_address;
2257                 goto execute_next_instruction;
2258                 break;
2259
2260         case SIGCOMP_INSTR_STATE_ACCESS: /* 31 */
2261                 /*   STATE-ACCESS (%partial_identifier_start, %partial_identifier_length,
2262                  * %state_begin, %state_length, %state_address, %state_instruction)
2263                  */
2264                 if (show_instr_detail_level == 2 ){
2265                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2266                                 "Addr: %u ## STATE-ACCESS(31) (partial_identifier_start, partial_identifier_length,state_begin, state_length, state_address, state_instruction)",
2267                                 current_address);
2268                 }
2269                 operand_address = current_address + 1;
2270
2271                 /* 
2272                  * %partial_identifier_start
2273                  */
2274                 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &p_id_start);
2275                 if (show_instr_detail_level == 2 ){
2276                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u       partial_identifier_start %u",
2277                                 operand_address, p_id_start);
2278                 }
2279                 operand_address = next_operand_address;
2280
2281                 /*
2282                  * %partial_identifier_length
2283                  */
2284                 operand_address = next_operand_address;
2285                 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &p_id_length);
2286                 if (show_instr_detail_level == 2 ){
2287                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u       partial_identifier_length %u",
2288                                 operand_address, p_id_length);
2289                 }
2290                 /*
2291                  * %state_begin
2292                  */
2293                 operand_address = next_operand_address;
2294                 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_begin);
2295                 if (show_instr_detail_level == 2 ){
2296                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u       state_begin %u",
2297                                 operand_address, state_begin);
2298                 }
2299                 /*
2300                  * %state_length
2301                  */
2302                 operand_address = next_operand_address;
2303                 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_length);
2304                 if (show_instr_detail_level == 2 ){
2305                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u       state_length %u",
2306                                 operand_address, state_length);
2307                 }
2308                 /*
2309                  * %state_address
2310                  */
2311                 operand_address = next_operand_address;
2312                 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_address);
2313                 if (show_instr_detail_level == 2 ){
2314                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u       state_address %u",
2315                                 operand_address, state_address);
2316                 }
2317                 /*
2318                  * %state_instruction
2319                  */
2320                 operand_address = next_operand_address;
2321                 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_instruction);
2322                 if (show_instr_detail_level == 2 ){
2323                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u       state_instruction %u",
2324                                 operand_address, state_instruction);
2325                 }
2326                 if (show_instr_detail_level == 1)
2327                 {
2328                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2329                                 "Addr: %u ## STATE-ACCESS(31) (partial_identifier_start=%u, partial_identifier_length=%u,state_begin=%u, state_length=%u, state_address=%u, state_instruction=%u)",
2330                                 current_address, p_id_start, p_id_length, state_begin, state_length, state_address, state_instruction);
2331                 }
2332                 current_address = next_operand_address;
2333                 byte_copy_right = buff[66] << 8;
2334                 byte_copy_right = byte_copy_right | buff[67];
2335                 byte_copy_left = buff[64] << 8;
2336                 byte_copy_left = byte_copy_left | buff[65];
2337                 if (print_level_2 ){
2338                         proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
2339                                         "               byte_copy_right = %u, byte_copy_left = %u", byte_copy_right,byte_copy_left);
2340                 }
2341
2342                 result_code = udvm_state_access(message_tvb, udvm_tree, buff, p_id_start, p_id_length, state_begin, &state_length, 
2343                         &state_address, &state_instruction, hf_id);
2344                 if ( result_code != 0 ){
2345                         goto decompression_failure; 
2346                 }
2347                 used_udvm_cycles = used_udvm_cycles + 1 + state_length;
2348                 goto execute_next_instruction;
2349                 break;
2350         case SIGCOMP_INSTR_STATE_CREATE: /* 32 */
2351                 /*
2352                  * STATE-CREATE (%state_length, %state_address, %state_instruction,
2353                  * %minimum_access_length, %state_retention_priority)
2354                  */
2355                 if (show_instr_detail_level == 2 ){
2356                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2357                                 "Addr: %u ## STATE-CREATE(32) (state_length, state_address, state_instruction,minimum_access_length, state_retention_priority)",
2358                                 current_address);
2359                 }
2360                 operand_address = current_address + 1;
2361
2362                 /*
2363                  * %state_length
2364                  */
2365                 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_length);
2366                 if (show_instr_detail_level == 2 ){
2367                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u       state_length %u",
2368                                 operand_address, state_length);
2369                 }
2370                 /*
2371                  * %state_address
2372                  */
2373                 operand_address = next_operand_address;
2374                 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_address);
2375                 if (show_instr_detail_level == 2 ){
2376                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u       state_address %u",
2377                                 operand_address, state_address);
2378                 }
2379                 /*
2380                  * %state_instruction
2381                  */
2382                 operand_address = next_operand_address;
2383                 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_instruction);
2384                 if (show_instr_detail_level == 2 ){
2385                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u       state_instruction %u",
2386                                 operand_address, state_instruction);
2387                 }
2388                 operand_address = next_operand_address;
2389                 /*
2390                  * %minimum_access_length
2391                  */
2392                 operand_address = next_operand_address;
2393                 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &minimum_access_length);
2394                 if (show_instr_detail_level == 2 ){
2395                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u       minimum_access_length %u",
2396                                 operand_address, minimum_access_length);
2397                 }
2398                 operand_address = next_operand_address;
2399                 /*
2400                  * %state_retention_priority
2401                  */
2402                 operand_address = next_operand_address;
2403                 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_retention_priority);
2404                 if (show_instr_detail_level == 2 ){
2405                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u       state_retention_priority %u",
2406                                 operand_address, state_retention_priority);
2407                 }
2408                 if (show_instr_detail_level == 1)
2409                 {
2410                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2411                                 "Addr: %u ## STATE-CREATE(32) (state_length=%u, state_address=%u, state_instruction=%u,minimum_access_length=%u, state_retention_priority=%u)",
2412                                 current_address, state_length, state_address, state_instruction,minimum_access_length, state_retention_priority);
2413                 }
2414                 current_address = next_operand_address;
2415                 /* Execute the instruction
2416                  * TODO Implement the instruction
2417                  * RFC3320:
2418                  *    Note that the new state item cannot be created until a valid
2419                  *    compartment identifier has been returned by the application.
2420                  *    Consequently, when a STATE-CREATE instruction is encountered the UDVM
2421                  *    simply buffers the five supplied operands until the END-MESSAGE
2422                  *    instruction is reached.  The steps taken at this point are described
2423                  *    in Section 9.4.9.
2424                  *
2425                  *   Decompression failure MUST occur if more than four state creation
2426                  *   requests are made before the END-MESSAGE instruction is encountered.
2427                  *   Decompression failure also occurs if the minimum_access_length does
2428                  *   not lie between 6 and 20 inclusive, or if the
2429                  *   state_retention_priority is 65535.
2430                  */
2431                 no_of_state_create++;
2432                 if ( no_of_state_create > 4 ){
2433                         result_code = 12;
2434                         goto decompression_failure; 
2435                 }
2436                 if (( minimum_access_length < 6 ) || ( minimum_access_length > STATE_BUFFER_SIZE )){
2437                         result_code = 1;
2438                         goto decompression_failure; 
2439                 }
2440                 if ( state_retention_priority == 65535 ){
2441                         result_code = 13;
2442                         goto decompression_failure; 
2443                 }
2444                 state_length_buff[no_of_state_create] = state_length;
2445                 state_address_buff[no_of_state_create] = state_address;
2446                 state_instruction_buff[no_of_state_create] = state_instruction;
2447                 state_minimum_access_length_buff[no_of_state_create] = minimum_access_length;
2448                 state_state_retention_priority_buff[no_of_state_create] = state_retention_priority;
2449                 used_udvm_cycles = used_udvm_cycles + 1 + state_length;
2450                 /* Debug */
2451                 byte_copy_right = buff[66] << 8;
2452                 byte_copy_right = byte_copy_right | buff[67];
2453                 byte_copy_left = buff[64] << 8;
2454                 byte_copy_left = byte_copy_left | buff[65];
2455                 n = 0;
2456                 k = state_address;
2457                 while ( n < state_length ){
2458                         if ( k == byte_copy_right ){
2459                                 k = byte_copy_left;
2460                         }
2461                         string[0]= buff[k];
2462                         string[1]= '\0';
2463                         if (print_level_3 ){
2464                                 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2465                                         "               Addr: %5u State value: %u (0x%x) ASCII(%s)",
2466                                         k,buff[k],buff[k],format_text(string, 1));
2467                         }
2468                         k = ( k + 1 ) & 0xffff;
2469                         n++;
2470                 }
2471                 /* End debug */
2472
2473                 goto execute_next_instruction;
2474                 break;
2475         case SIGCOMP_INSTR_STATE_FREE: /* 33 */
2476                 /*
2477                  * STATE-FREE (%partial_identifier_start, %partial_identifier_length)
2478                  */
2479                 if (show_instr_detail_level == 2 ){
2480                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2481                                 "Addr: %u ## STATE-FREE (partial_identifier_start, partial_identifier_length)",
2482                                 current_address);
2483                 }
2484                 operand_address = current_address + 1;
2485                 /* 
2486                  * %partial_identifier_start
2487                  */
2488                 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &p_id_start);
2489                 if (show_instr_detail_level == 2 ){
2490                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u       partial_identifier_start %u",
2491                                 operand_address, p_id_start);
2492                 }
2493                 operand_address = next_operand_address;
2494
2495                 /*
2496                  * %partial_identifier_length
2497                  */
2498                 operand_address = next_operand_address;
2499                 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &p_id_length);
2500                 if (show_instr_detail_level == 2 ){
2501                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u       partial_identifier_length %u",
2502                                 operand_address, p_id_length);
2503                 }
2504                 if (show_instr_detail_level == 1)
2505                 {
2506                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2507                                 "Addr: %u ## STATE-FREE (partial_identifier_start=%u, partial_identifier_length=%u)",
2508                                 current_address, p_id_start, p_id_length);
2509                 }
2510                 current_address = next_operand_address;
2511
2512                 /* Execute the instruction:
2513                  * TODO implement it
2514                  */
2515                 udvm_state_free(buff,p_id_start,p_id_length);
2516                 used_udvm_cycles++;
2517
2518                 goto execute_next_instruction;
2519                 break;
2520         case SIGCOMP_INSTR_OUTPUT: /* 34 OUTPUT (%output_start, %output_length) */
2521                 if (show_instr_detail_level == 2 ){
2522                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2523                                 "Addr: %u ## OUTPUT(34) (output_start, output_length)",
2524                                 current_address);
2525                 }
2526                 operand_address = current_address + 1;
2527                 /* 
2528                  * %output_start
2529                  */
2530                 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &output_start);
2531                 if (show_instr_detail_level == 2 ){
2532                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u      output_start %u",
2533                                 operand_address, output_start);
2534                 }
2535                 operand_address = next_operand_address;
2536                 /* 
2537                  * %output_length
2538                  */
2539                 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &output_length);
2540                 if (show_instr_detail_level == 2 ){
2541                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u      output_length %u",
2542                                 operand_address, output_length);
2543                 }
2544                 if (show_instr_detail_level == 1)
2545                 {
2546                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2547                                 "Addr: %u ## OUTPUT (output_start=%u, output_length=%u)",
2548                                 current_address, output_start, output_length);
2549                 }
2550                 current_address = next_operand_address;
2551
2552                 /* 
2553                  * Execute instruction 
2554                  * 8.4.  Byte copying
2555                  * :
2556                  * The string of bytes is copied in ascending order of memory address,
2557                  * respecting the bounds set by byte_copy_left and byte_copy_right.
2558                  * More precisely, if a byte is copied from/to Address m then the next
2559                  * byte is copied from/to Address n where n is calculated as follows:
2560                  *
2561                  * Set k := m + 1 (modulo 2^16)
2562                  * If k = byte_copy_right then set n := byte_copy_left, else set n := k
2563                  *
2564                  */ 
2565
2566                 n = 0;
2567                 k = output_start; 
2568                 byte_copy_right = buff[66] << 8;
2569                 byte_copy_right = byte_copy_right | buff[67];
2570                 byte_copy_left = buff[64] << 8;
2571                 byte_copy_left = byte_copy_left | buff[65];
2572                 if (print_level_3 ){
2573                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2574                                         "               byte_copy_right = %u", byte_copy_right);
2575                 }
2576                 while ( n < output_length ){
2577
2578                         if ( k == byte_copy_right ){
2579                                 k = byte_copy_left;
2580                         }
2581                         out_buff[output_address] = buff[k];
2582                         string[0]= buff[k];
2583                         string[1]= '\0';
2584                         if (print_level_3 ){
2585                                 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2586                                         "               Output value: %u (0x%x) ASCII(%s) from Addr: %u ,output to dispatcher position %u",
2587                                         buff[k],buff[k],format_text(string,1), k,output_address);
2588                         }
2589                         k = ( k + 1 ) & 0xffff;
2590                         output_address ++;
2591                         n++;
2592                 }
2593                 used_udvm_cycles = used_udvm_cycles + 1 + output_length;
2594                 goto execute_next_instruction;
2595                 break;
2596         case SIGCOMP_INSTR_END_MESSAGE: /* 35 */
2597                 /*
2598                  * END-MESSAGE (%requested_feedback_location,
2599                  * %returned_parameters_location, %state_length, %state_address,
2600                  * %state_instruction, %minimum_access_length,
2601                  * %state_retention_priority)
2602                  */
2603                 if (show_instr_detail_level == 2 ){
2604                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2605                                 "Addr: %u ## END-MESSAGE (requested_feedback_location,state_instruction, minimum_access_length,state_retention_priority)",
2606                                 current_address);
2607                 }
2608                 operand_address = current_address + 1;
2609
2610                 /* %requested_feedback_location */
2611                 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &requested_feedback_location);
2612                 if (show_instr_detail_level == 2 ){
2613                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u      requested_feedback_location %u",
2614                                 operand_address, requested_feedback_location);
2615                 }
2616                 operand_address = next_operand_address;
2617                 /* returned_parameters_location */
2618                 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &returned_parameters_location);
2619                 if (show_instr_detail_level == 2 ){
2620                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u      returned_parameters_location %u",
2621                                 operand_address, returned_parameters_location);
2622                 }
2623                 operand_address = next_operand_address;
2624                 /*
2625                  * %state_length
2626                  */
2627                 operand_address = next_operand_address;
2628                 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_length);
2629                 if (show_instr_detail_level == 2 ){
2630                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u      state_length %u",
2631                                 operand_address, state_length);
2632                 }
2633                 /*
2634                  * %state_address
2635                  */
2636                 operand_address = next_operand_address;
2637                 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_address);
2638                 if (show_instr_detail_level == 2 ){
2639                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u      state_address %u",
2640                                 operand_address, state_address);
2641                 }
2642                 /*
2643                  * %state_instruction
2644                  */
2645                 operand_address = next_operand_address;
2646                 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_instruction);
2647                 if (show_instr_detail_level == 2 ){
2648                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u      state_instruction %u",
2649                                 operand_address, state_instruction);
2650                 }
2651
2652                 /*
2653                  * %minimum_access_length
2654                  */
2655                 operand_address = next_operand_address;
2656                 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &minimum_access_length);
2657                 if (show_instr_detail_level == 2 ){
2658                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u      minimum_access_length %u",
2659                                 operand_address, minimum_access_length);
2660                 }
2661
2662                 /*
2663                  * %state_retention_priority
2664                  */
2665                 operand_address = next_operand_address;
2666                 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_retention_priority);
2667                 if (show_instr_detail_level == 2 ){
2668                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u      state_retention_priority %u",
2669                                 operand_address, state_retention_priority);
2670                 }
2671                 if (show_instr_detail_level == 1)
2672                 {
2673                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2674                                 "Addr: %u ## END-MESSAGE (requested_feedback_location=%u, returned_parameters_location=%u, state_length=%u, state_address=%u, state_instruction=%u, minimum_access_length=%u, state_retention_priority=%u)",
2675                                 current_address, requested_feedback_location, returned_parameters_location, state_length, state_address, state_instruction, minimum_access_length,state_retention_priority);
2676                 }
2677                 current_address = next_operand_address;
2678                 /* TODO: This isn't currently totaly correct as END_INSTRUCTION might not create state */
2679                 no_of_state_create++;
2680                 if ( no_of_state_create > 4 ){
2681                         result_code = 12;
2682                         goto decompression_failure; 
2683                 }
2684                 state_length_buff[no_of_state_create] = state_length;
2685                 state_address_buff[no_of_state_create] = state_address;
2686                 state_instruction_buff[no_of_state_create] = state_instruction;
2687                 /* Not used ? */
2688                 state_minimum_access_length_buff[no_of_state_create] = minimum_access_length;
2689                 state_state_retention_priority_buff[no_of_state_create] = state_retention_priority;
2690                 
2691                 /* Execute the instruction
2692                  */
2693                 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"no_of_state_create %u",no_of_state_create);
2694                 if ( no_of_state_create != 0 ){
2695                         memset(sha1_digest_buf, 0, STATE_BUFFER_SIZE);
2696                         n = 1;
2697                         byte_copy_right = buff[66] << 8;
2698                         byte_copy_right = byte_copy_right | buff[67];
2699                         byte_copy_left = buff[64] << 8;
2700                         byte_copy_left = byte_copy_left | buff[65];
2701                         while ( n < no_of_state_create + 1 ){
2702                                 sha1buff = g_malloc(state_length_buff[n]+8);
2703                                 sha1buff[0] = state_length_buff[n] >> 8;
2704                                 sha1buff[1] = state_length_buff[n] & 0xff;
2705                                 sha1buff[2] = state_address_buff[n] >> 8;
2706                                 sha1buff[3] = state_address_buff[n] & 0xff;
2707                                 sha1buff[4] = state_instruction_buff[n] >> 8;
2708                                 sha1buff[5] = state_instruction_buff[n] & 0xff; 
2709                                 sha1buff[6] = state_minimum_access_length_buff[n] >> 8;
2710                                 sha1buff[7] = state_minimum_access_length_buff[n] & 0xff;
2711                                 if (print_level_3 ){
2712                                         for( x=0; x < 8; x++){
2713                                                 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"sha1buff %u 0x%x",
2714                                                         x,sha1buff[x]);
2715                                         }
2716                                 }
2717                                 k = state_address_buff[n];
2718                                 for( x=0; x < state_length_buff[n]; x++)
2719                                         {
2720                                         if ( k == byte_copy_right ){
2721                                                 k = byte_copy_left;
2722                                         }
2723                                         sha1buff[8+x] = buff[k];
2724                                         k = ( k + 1 ) & 0xffff;
2725                                         }
2726
2727                                 sha1_starts( &ctx );
2728                                 sha1_update( &ctx, (guint8 *) sha1buff, state_length_buff[n] + 8);
2729                                 sha1_finish( &ctx, sha1_digest_buf );
2730                                 if (print_level_3 ){
2731                                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"SHA1 digest %s",bytes_to_str(sha1_digest_buf, STATE_BUFFER_SIZE));
2732
2733                                 }
2734                                 udvm_state_create(sha1buff, sha1_digest_buf, state_minimum_access_length_buff[n]);
2735                                 proto_tree_add_text(udvm_tree,bytecode_tvb, 0, -1,"### Creating state ###");
2736                                 proto_tree_add_string(udvm_tree,hf_id, bytecode_tvb, 0, 0, bytes_to_str(sha1_digest_buf, state_minimum_access_length_buff[n]));
2737
2738                                 n++;
2739
2740                         }
2741                 }
2742
2743
2744
2745                 /* At least something got decompressed, show it */
2746                 decomp_tvb = tvb_new_real_data(out_buff,output_address,output_address);
2747                 /* Arrange that the allocated packet data copy be freed when the
2748                  * tvbuff is freed. 
2749                  */
2750                 tvb_set_free_cb( decomp_tvb, g_free );
2751
2752                 tvb_set_child_real_data_tvbuff(message_tvb,decomp_tvb);
2753                 add_new_data_source(pinfo, decomp_tvb, "Decompressed SigComp message");
2754                 /*
2755                 proto_tree_add_text(udvm_tree, decomp_tvb, 0, -1,"SigComp message Decompressed");
2756                 */      
2757                 used_udvm_cycles = used_udvm_cycles + 1 + state_length;
2758                 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"maximum_UDVM_cycles %u used_udvm_cycles %u",
2759                         maximum_UDVM_cycles, used_udvm_cycles);
2760                 return decomp_tvb;
2761                 break;
2762
2763         default:
2764             proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," ### Addr %u Invalid instruction: %u (0x%x)",
2765                         current_address,current_instruction,current_instruction);
2766                 break;
2767                 }
2768                 g_free(out_buff);
2769                 return NULL;
2770 decompression_failure:
2771                 
2772                 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"DECOMPRESSION FAILURE: %s",
2773                                     val_to_str(result_code, result_code_vals,"Unknown (%u)"));
2774                 THROW(ReportedBoundsError);
2775                 g_free(out_buff);
2776                 return NULL;
2777
2778 }
2779         
2780  /*  The simplest operand type is the literal (#), which encodes a
2781   * constant integer from 0 to 65535 inclusive.  A literal operand may
2782   * require between 1 and 3 bytes depending on its value.
2783   * Bytecode:                       Operand value:      Range:
2784   * 0nnnnnnn                        N                   0 - 127
2785   * 10nnnnnn nnnnnnnn               N                   0 - 16383
2786   * 11000000 nnnnnnnn nnnnnnnn      N                   0 - 65535
2787   *
2788   *            Figure 8: Bytecode for a literal (#) operand
2789   *
2790   */
2791 static int
2792 decode_udvm_literal_operand(guint8 *buff,guint operand_address, guint16 *value) 
2793 {
2794         guint   bytecode;
2795         guint16 operand;
2796         guint   test_bits;
2797         guint   offset = operand_address;
2798         guint8  temp_data;
2799
2800         bytecode = buff[operand_address];
2801         test_bits = bytecode >> 7;
2802         if (test_bits == 1){
2803                 test_bits = bytecode >> 6;
2804                 if (test_bits == 2){
2805                         /*
2806                          * 10nnnnnn nnnnnnnn               N                   0 - 16383
2807                          */
2808                         temp_data = buff[operand_address] & 0x1f;
2809                         operand = temp_data << 8;
2810                         temp_data = buff[operand_address + 1];
2811                         operand = operand | temp_data;
2812                         *value = operand;
2813                         offset = offset + 2;
2814
2815                 }else{
2816                         /*
2817                          * 111000000 nnnnnnnn nnnnnnnn      N                   0 - 65535
2818                          */
2819                         offset ++;
2820                         temp_data = buff[operand_address] & 0x1f;
2821                         operand = temp_data << 8;
2822                         temp_data = buff[operand_address + 1];
2823                         operand = operand | temp_data;
2824                         *value = operand;
2825                         offset = offset + 2;
2826
2827                 }
2828         }else{
2829                 /*
2830                  * 0nnnnnnn                        N                   0 - 127
2831                  */
2832                 operand = ( bytecode & 0x7f);
2833                 *value = operand;
2834                 offset ++;
2835         }
2836
2837         return offset;
2838
2839 }
2840
2841 /*
2842  * The second operand type is the reference ($), which is always used to
2843  * access a 2-byte value located elsewhere in the UDVM memory.  The
2844  * bytecode for a reference operand is decoded to be a constant integer
2845  * from 0 to 65535 inclusive, which is interpreted as the memory address
2846  * containing the actual value of the operand.
2847  * Bytecode:                       Operand value:      Range:
2848  *
2849  * 0nnnnnnn                        memory[2 * N]       0 - 65535
2850  * 10nnnnnn nnnnnnnn               memory[2 * N]       0 - 65535
2851  * 11000000 nnnnnnnn nnnnnnnn      memory[N]           0 - 65535
2852  *
2853  *            Figure 9: Bytecode for a reference ($) operand
2854  */
2855 static int
2856 dissect_udvm_reference_operand(guint8 *buff,guint operand_address, guint16 *value,guint *result_dest) 
2857 {
2858         guint bytecode;
2859         guint16 operand;
2860         guint   offset = operand_address;
2861         guint test_bits;
2862         guint8  temp_data;
2863         guint16 temp_data16;
2864
2865         bytecode = buff[operand_address];
2866         test_bits = bytecode >> 7;
2867         if (test_bits == 1){
2868                 test_bits = bytecode >> 6;
2869                 if (test_bits == 2){
2870                         /*
2871                          * 10nnnnnn nnnnnnnn               memory[2 * N]       0 - 65535
2872                          */
2873                         temp_data = buff[operand_address] & 0x3f;
2874                         operand = temp_data << 8;
2875                         temp_data = buff[operand_address + 1];
2876                         operand = operand | temp_data;
2877                         operand = (operand * 2);
2878                         *result_dest = operand;
2879                         temp_data16 = buff[operand] << 8;
2880                         temp_data16 = temp_data16 | buff[operand+1];
2881                         *value = temp_data16;
2882                         offset = offset + 2;
2883
2884                 }else{
2885                         /*
2886                          * 11000000 nnnnnnnn nnnnnnnn      memory[N]           0 - 65535
2887                          */
2888                         operand_address++;
2889                         operand = buff[operand_address] << 8;
2890                         operand = operand | buff[operand_address + 1];
2891                         *result_dest = operand;
2892                         temp_data16 = buff[operand] << 8;
2893                         temp_data16 = temp_data16 | buff[operand+1];
2894                         *value = temp_data16;
2895                         offset = offset + 3;
2896
2897                 }
2898         }else{
2899                 /*
2900                  * 0nnnnnnn                        memory[2 * N]       0 - 65535
2901                  */
2902                 operand = ( bytecode & 0x7f);
2903                 operand = (operand * 2);
2904                 *result_dest = operand;
2905                 temp_data16 = buff[operand] << 8;
2906                 temp_data16 = temp_data16 | buff[operand+1];
2907                 *value = temp_data16;
2908                 offset ++;
2909         }
2910
2911         if (offset >= UDVM_MEMORY_SIZE || *result_dest >= UDVM_MEMORY_SIZE - 1 )
2912                 THROW(ReportedBoundsError);
2913
2914         return offset;
2915 }
2916
2917         /* RFC3320
2918          * Figure 10: Bytecode for a multitype (%) operand
2919          * Bytecode:                       Operand value:      Range:               HEX val
2920          * 00nnnnnn                        N                   0 - 63                           0x00
2921          * 01nnnnnn                        memory[2 * N]       0 - 65535                        0x40
2922          * 1000011n                        2 ^ (N + 6)        64 , 128                          0x86    
2923          * 10001nnn                        2 ^ (N + 8)    256 , ... , 32768                     0x88
2924          * 111nnnnn                        N + 65504       65504 - 65535                        0xe0
2925          * 1001nnnn nnnnnnnn               N + 61440       61440 - 65535                        0x90
2926          * 101nnnnn nnnnnnnn               N                   0 - 8191                         0xa0
2927          * 110nnnnn nnnnnnnn               memory[N]           0 - 65535                        0xc0
2928          * 10000000 nnnnnnnn nnnnnnnn      N                   0 - 65535                        0x80
2929          * 10000001 nnnnnnnn nnnnnnnn      memory[N]           0 - 65535                        0x81
2930          */
2931 static int
2932 decode_udvm_multitype_operand(guint8 *buff,guint operand_address, guint16 *value)
2933 {
2934         guint test_bits;
2935         guint bytecode;
2936         guint offset = operand_address;
2937         guint16 operand;
2938         guint32 result;
2939         guint8 temp_data;
2940         guint16 temp_data16;
2941         guint16 memmory_addr = 0;
2942
2943         bytecode = buff[operand_address];
2944         test_bits = ( bytecode & 0xc0 ) >> 6;
2945         switch (test_bits ){
2946         case 0:
2947                 /*  
2948                  * 00nnnnnn                        N                   0 - 63
2949                  */
2950                 operand =  buff[operand_address];
2951                 /* debug
2952                  *g_warning("Reading 0x%x From address %u",operand,offset);
2953                  */
2954                 *value = operand;
2955                 offset ++;
2956                 break;
2957         case 1:
2958                 /*  
2959                  * 01nnnnnn                        memory[2 * N]       0 - 65535
2960                  */
2961                 memmory_addr = ( bytecode & 0x3f) * 2;
2962                 temp_data16 = buff[memmory_addr] << 8;
2963                 temp_data16 = temp_data16 | buff[memmory_addr+1];
2964                 *value = temp_data16;
2965                 offset ++;
2966                 break;
2967         case 2:
2968                 /* Check tree most significant bits */
2969                 test_bits = ( bytecode & 0xe0 ) >> 5;
2970                 if ( test_bits == 5 ){
2971                 /*
2972                  * 101nnnnn nnnnnnnn               N                   0 - 8191
2973                  */
2974                         temp_data = buff[operand_address] & 0x1f;
2975                         operand = temp_data << 8;
2976                         temp_data = buff[operand_address + 1];
2977                         operand = operand | temp_data;
2978                         *value = operand;
2979                         offset = offset + 2;
2980                 }else{
2981                         test_bits = ( bytecode & 0xf0 ) >> 4;
2982                         if ( test_bits == 9 ){
2983                 /*
2984                  * 1001nnnn nnnnnnnn               N + 61440       61440 - 65535
2985                  */
2986                                 temp_data = buff[operand_address] & 0x0f;
2987                                 operand = temp_data << 8;
2988                                 temp_data = buff[operand_address + 1];
2989                                 operand = operand | temp_data;
2990                                 operand = operand + 61440;
2991                                 *value = operand;
2992                                 offset = offset + 2;
2993                         }else{
2994                                 test_bits = ( bytecode & 0x08 ) >> 3;
2995                                 if ( test_bits == 1){
2996                 /*
2997                  * 10001nnn                        2 ^ (N + 8)    256 , ... , 32768
2998                  */
2999
3000                                         result = 1 << ((buff[operand_address] & 0x07) + 8);
3001                                         operand = result & 0xffff;
3002                                         *value = operand;
3003                                         offset ++;
3004                                 }else{
3005                                         test_bits = ( bytecode & 0x0e ) >> 1;
3006                                         if ( test_bits == 3 ){
3007                                                 /*
3008                                                  * 1000 011n                        2 ^ (N + 6)        64 , 128
3009                                                  */
3010                                                 result = 1 << ((buff[operand_address] & 0x01) + 6);
3011                                                 operand = result & 0xffff;
3012                                                 *value = operand;
3013                                                 offset ++;
3014                                         }else{
3015                                         /*
3016                                          * 1000 0000 nnnnnnnn nnnnnnnn      N                   0 - 65535
3017                                          * 1000 0001 nnnnnnnn nnnnnnnn      memory[N]           0 - 65535
3018                                          */
3019                                                 offset ++;
3020                                                 temp_data16 = buff[operand_address + 1] << 8;
3021                                                 temp_data16 = temp_data16 | buff[operand_address + 2];
3022                                                 /*  debug
3023                                                  * g_warning("Reading 0x%x From address %u",temp_data16,operand_address);
3024                                                  */
3025                                                 if ( (bytecode & 0x01) == 1 ){
3026                                                         memmory_addr = temp_data16;
3027                                                         temp_data16 = buff[memmory_addr] << 8;
3028                                                         temp_data16 = temp_data16 | buff[memmory_addr+1];
3029                                                 }
3030                                                 *value = temp_data16;
3031                                                 offset = offset +2;
3032                                         }
3033
3034
3035                                 }
3036                         }
3037                 }
3038                 break;
3039
3040         case 3:
3041                 test_bits = ( bytecode & 0x20 ) >> 5;
3042                 if ( test_bits == 1 ){
3043                 /*
3044                  * 111nnnnn                        N + 65504       65504 - 65535
3045                  */
3046                         operand = ( buff[operand_address] & 0x1f) + 65504;
3047                         *value = operand;
3048                         offset ++;
3049                 }else{
3050                 /*
3051                  * 110nnnnn nnnnnnnn               memory[N]           0 - 65535
3052                  */
3053                         memmory_addr = buff[operand_address] & 0x1f;
3054                         memmory_addr = memmory_addr << 8;
3055                         memmory_addr = memmory_addr | buff[operand_address + 1];
3056                         temp_data16 = buff[memmory_addr] << 8;
3057                         temp_data16 = temp_data16 | buff[memmory_addr+1];
3058                         *value = temp_data16;
3059                         /*  debug 
3060                          * g_warning("Reading 0x%x From address %u",temp_data16,memmory_addr);
3061                          */
3062                         offset = offset +2;
3063                 }
3064                         
3065         default :
3066                 break;
3067         }
3068         return offset;
3069 }
3070         /*
3071          *
3072          * The fourth operand type is the address (@).  This operand is decoded
3073          * as a multitype operand followed by a further step: the memory address
3074          * of the UDVM instruction containing the address operand is added to
3075          * obtain the correct operand value.  So if the operand value from
3076          * Figure 10 is D then the actual operand value of an address is
3077          * calculated as follows:
3078          *
3079          * operand_value = (memory_address_of_instruction + D) modulo 2^16
3080          *
3081          * Address operands are always used in instructions that control program
3082          * flow, because they ensure that the UDVM bytecode is position-
3083          * independent code (i.e., it will run independently of where it is
3084          * placed in the UDVM memory).
3085          */
3086 static int
3087 decode_udvm_address_operand(guint8 *buff,guint operand_address, guint16 *value,guint current_address)
3088 {
3089         guint32 result;
3090         guint16 value1;
3091         guint next_opreand_address;
3092
3093         next_opreand_address = decode_udvm_multitype_operand(buff, operand_address, &value1);
3094         result = value1 & 0xffff;
3095         result = result + current_address;
3096         *value = result & 0xffff;
3097         return next_opreand_address;
3098 }
3099
3100
3101 /*
3102  * This is a lookup table used to reverse the bits in a byte.
3103  */
3104 static guint8 reverse [] = {
3105     0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0,
3106     0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0,
3107     0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8,
3108     0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8,
3109     0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4,
3110     0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4,
3111     0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC,
3112     0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC,
3113     0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2,
3114     0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2,
3115     0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA,
3116     0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA,
3117     0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6,
3118     0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6,
3119     0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE,
3120     0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE,
3121     0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1,
3122     0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1,
3123     0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9,
3124     0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9,
3125     0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5,
3126     0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5,
3127     0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED,
3128     0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD,
3129     0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3,
3130     0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3,
3131     0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB,
3132     0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB,
3133     0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7,
3134     0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7,
3135     0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF,
3136     0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF
3137 };
3138
3139
3140 static int
3141 decomp_dispatch_get_bits(
3142                 tvbuff_t *message_tvb,
3143                 proto_tree *udvm_tree,
3144                 guint8 bit_order, 
3145                 guint8 *buff,
3146                 guint16 *old_input_bit_order, 
3147                 guint16 *remaining_bits,
3148                 guint16 *input_bits, 
3149                 guint *input_address, 
3150                 guint16 length, 
3151                 guint16 *result_code,
3152                 guint msg_end)
3153 {
3154         guint16 input_bit_order;
3155         guint16 bits_still_required = length;
3156         guint16 value = 0;
3157         guint8  octet;
3158         gint    extra_bytes_available = msg_end - *input_address;
3159         gint    p_bit;
3160         gint    prev_p_bit = *old_input_bit_order & 0x0001;
3161         gint    bits_to_use = 0;
3162
3163
3164         input_bit_order = buff[68] << 8;
3165         input_bit_order = input_bit_order | buff[69];
3166         *result_code = 0;
3167         p_bit = (input_bit_order & 0x0001) != 0;
3168
3169         /*
3170          * Discard any spare bits.
3171          * Note: We take care to avoid remaining_bits having the value of 8.
3172          */
3173         if (prev_p_bit != p_bit)
3174         {
3175                 *remaining_bits = 0;
3176                 *old_input_bit_order = input_bit_order;
3177         }
3178
3179         /*
3180          * Check we can suppy the required number of bits now, before we alter
3181          * the input buffer's state.
3182          */
3183         if (*remaining_bits + extra_bytes_available * 8 < length)
3184         {
3185                 *result_code = 11;
3186                 return 0xfbad;
3187         }
3188
3189         /* Note: This is never called with length > 16, so the following loop 
3190         *       never loops more than three time. */
3191         while (bits_still_required > 0)
3192         {
3193                 /* 
3194                  * We only put anything into input_bits if we know we will remove
3195                  * at least one bit. That ensures we can simply discard the spare
3196                  * bits if the P-bit changes.
3197                  */
3198                 if (*remaining_bits == 0)
3199                 {
3200                         octet = tvb_get_guint8(message_tvb, *input_address);
3201                         if (print_level_1 ){
3202                                 proto_tree_add_text(udvm_tree, message_tvb, *input_address , 1,
3203                                                 "               Geting value: %u (0x%x) From Addr: %u", octet, octet, *input_address);
3204                         }
3205                         *input_address = *input_address + 1;
3206
3207                         if (p_bit != 0)
3208                         {
3209                                 octet = reverse[octet];
3210                         }
3211                         *input_bits = octet;
3212                         *remaining_bits = 8;
3213                 }
3214
3215                 /* Add some more bits to the accumulated value. */
3216                 bits_to_use = bits_still_required < *remaining_bits ? bits_still_required : *remaining_bits;
3217                 bits_still_required -= bits_to_use;
3218
3219                 *input_bits <<= bits_to_use;           /* Shift bits into MSByte */
3220                 value = (value << bits_to_use)         /* Then add to the accumulated value */
3221                         | ((*input_bits >> 8) & 0xFF);
3222                 *remaining_bits -= bits_to_use;            
3223                 *input_bits &= 0x00FF;                 /* Leave just the remaining bits */
3224         }
3225
3226         if (bit_order != 0)
3227         {
3228                 /* Bit reverse the entire word. */
3229                 guint16 lsb = reverse[(value >> 8) & 0xFF];
3230                 guint16 msb = reverse[value & 0xFF];
3231
3232                 value = ((msb << 8) | lsb) >> (16 - length);
3233         }
3234
3235         return value;
3236 }
3237
3238
3239 /* end udvm */
3240