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