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