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