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