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