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