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