Move prototype of bytes_to_str, bytes_to_str_punct to correct header.
[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 <epan/emem.h>
41
42 #include <wsutil/sha1.h>
43 #include <wsutil/crc16.h>
44
45 #include "packet.h"
46 #include "strutil.h"
47 #include "to_str.h"
48 #include "sigcomp-udvm.h"
49 #include "sigcomp_state_hdlr.h"
50 #include "except.h"
51
52 #define SIGCOMP_INSTR_DECOMPRESSION_FAILURE     0
53 #define SIGCOMP_INSTR_AND                       1
54 #define SIGCOMP_INSTR_OR                        2
55 #define SIGCOMP_INSTR_NOT                       3
56 #define SIGCOMP_INSTR_LSHIFT                    4
57 #define SIGCOMP_INSTR_RSHIFT                    5
58 #define SIGCOMP_INSTR_ADD                       6
59 #define SIGCOMP_INSTR_SUBTRACT                  7
60 #define SIGCOMP_INSTR_MULTIPLY                  8
61 #define SIGCOMP_INSTR_DIVIDE                    9
62 #define SIGCOMP_INSTR_REMAINDER                 10
63 #define SIGCOMP_INSTR_SORT_ASCENDING            11
64 #define SIGCOMP_INSTR_SORT_DESCENDING           12
65 #define SIGCOMP_INSTR_SHA_1                     13
66 #define SIGCOMP_INSTR_LOAD                      14
67 #define SIGCOMP_INSTR_MULTILOAD                 15
68 #define SIGCOMP_INSTR_PUSH                      16
69 #define SIGCOMP_INSTR_POP                       17
70 #define SIGCOMP_INSTR_COPY                      18
71 #define SIGCOMP_INSTR_COPY_LITERAL              19
72 #define SIGCOMP_INSTR_COPY_OFFSET               20
73 #define SIGCOMP_INSTR_MEMSET                    21
74 #define SIGCOMP_INSTR_JUMP                      22
75 #define SIGCOMP_INSTR_COMPARE                   23
76 #define SIGCOMP_INSTR_CALL                      24
77 #define SIGCOMP_INSTR_RETURN                    25
78 #define SIGCOMP_INSTR_SWITCH                    26
79 #define SIGCOMP_INSTR_CRC                       27
80 #define SIGCOMP_INSTR_INPUT_BYTES               28
81 #define SIGCOMP_INSTR_INPUT_BITS                29
82 #define SIGCOMP_INSTR_INPUT_HUFFMAN             30
83 #define SIGCOMP_INSTR_STATE_ACCESS              31
84 #define SIGCOMP_INSTR_STATE_CREATE              32
85 #define SIGCOMP_INSTR_STATE_FREE                33
86 #define SIGCOMP_INSTR_OUTPUT                    34
87 #define SIGCOMP_INSTR_END_MESSAGE               35
88
89
90 static gboolean print_level_1;
91 static gboolean print_level_2;
92 static gboolean print_level_3;
93 static gint show_instr_detail_level;
94
95 /* Internal result code values of decompression failures */
96 const value_string result_code_vals[] = {
97         { 0,    "No decompression failure" },
98         { 1,    "Partial state length less than 6 or greater than 20 bytes long" },
99         { 2,    "No state match" },
100         { 3,    "state_begin + state_length > size of state" },
101         { 4,    "Operand_2 is Zero" },
102         { 5,    "Switch statement failed j >= n" },
103         { 6,    "Attempt to jump outside of UDVM memory" },
104         { 7,    "L in input-bits > 16" },
105         { 8,    "input_bit_order > 7" },
106         { 9,    "Instruction Decompression failure encountered" },
107         {10,    "Input huffman failed j > n" },
108         {11,    "Input bits requested beyond end of message" },
109         {12,    "more than four state creation requests are made before the END-MESSAGE instruction" },
110         {13,    "state_retention_priority is 65535" },
111         {14,    "Input bytes requested beyond end of message" },
112         {15,    "Maximum number of UDVM cycles reached" },
113         {16,    "UDVM stack underflow" },
114         { 255,  "This branch isn't coded yet" },
115         { 0,    NULL }
116 };
117
118 static int decode_udvm_literal_operand(guint8 *buff,guint operand_address, guint16 *value);
119 static int dissect_udvm_reference_operand(guint8 *buff,guint operand_address, guint16 *value, guint *result_dest);
120 static int decode_udvm_multitype_operand(guint8 *buff,guint operand_address,guint16 *value);
121 static int decode_udvm_address_operand(guint8 *buff,guint operand_address, guint16 *value,guint current_address);
122 static int decomp_dispatch_get_bits(tvbuff_t *message_tvb,proto_tree *udvm_tree,guint8 bit_order,
123                         guint8 *buff,guint16 *old_input_bit_order, guint16 *remaining_bits,
124                         guint16 *input_bits, guint *input_address, guint16 length, guint16 *result_code,guint msg_end);
125
126
127 tvbuff_t*
128 decompress_sigcomp_message(tvbuff_t *bytecode_tvb, tvbuff_t *message_tvb, packet_info *pinfo,
129                                                    proto_tree *udvm_tree, gint udvm_mem_dest,
130                                                    gint print_flags, gint hf_id,
131                                                    gint header_len,
132                                                    gint byte_code_state_len, gint byte_code_id_len,
133                                                    gint udvm_start_ip)
134 {
135         tvbuff_t        *decomp_tvb;
136         /* UDVM memory must be initialised to zero */
137         guint8          *buff = (guint8 *)ep_alloc0(UDVM_MEMORY_SIZE);
138         char            string[2];
139         guint8          *out_buff;              /* Largest allowed size for a message is UDVM_MEMORY_SIZE = 65536 */
140         guint32         i = 0;
141         guint16         n = 0;
142         guint16         m = 0;
143         guint16         x;
144         guint           k = 0;
145         guint16         H;
146         guint16         oldH;
147         guint           offset = 0;
148         guint           result_dest;
149         guint           code_length =0;
150         guint8          current_instruction;
151         guint           current_address;
152         guint           operand_address;
153         guint           input_address;
154         guint16         output_address = 0;
155         guint           next_operand_address;
156         guint8          octet;
157         guint8          msb;
158         guint8          lsb;
159         guint16         byte_copy_right;
160         guint16         byte_copy_left;
161         guint16         input_bit_order;
162         guint16         stack_location;
163         guint16         stack_fill;
164         guint16         result;
165         guint           msg_end = tvb_reported_length_remaining(message_tvb, 0);
166         guint16         result_code = 0;
167         guint16         old_input_bit_order = 0;
168         guint16         remaining_bits = 0;
169         guint16         input_bits = 0;
170         guint8          bit_order = 0;
171         gboolean        outside_huffman_boundaries = TRUE;
172         gboolean        print_in_loop = FALSE;
173         guint16         instruction_address;
174         guint8          no_of_state_create = 0;
175         guint16         state_length_buff[5];
176         guint16         state_address_buff[5];
177         guint16         state_instruction_buff[5];
178         guint16         state_minimum_access_length_buff[5];
179         /* guint16              state_state_retention_priority_buff[5]; */
180         guint32         used_udvm_cycles = 0;
181         guint           cycles_per_bit;
182         guint           maximum_UDVM_cycles;
183         guint8          *sha1buff;
184         unsigned char sha1_digest_buf[STATE_BUFFER_SIZE];
185         sha1_context ctx;
186
187
188         /* UDVM operand variables */
189         guint16 length;
190         guint16 at_address;
191         guint16 destination;
192         guint16 addr;
193         guint16 value;
194         guint16 p_id_start;
195         guint16 p_id_length;
196         guint16 state_begin;
197         guint16 state_length;
198         guint16 state_address;
199         guint16 state_instruction;
200         guint16 operand_1;
201         guint16 operand_2;
202         guint16 value_1;
203         guint16 value_2;
204         guint16 at_address_1;
205         guint16 at_address_2;
206         guint16 at_address_3;
207         guint16 j;
208         guint16 bits_n;
209         guint16 lower_bound_n;
210         guint16 upper_bound_n;
211         guint16 uncompressed_n;
212         guint16 position;
213         guint16 ref_destination; /* could I have used $destination ? */
214         guint16 multy_offset;
215         guint16 output_start;
216         guint16 output_length;
217         guint16 minimum_access_length;
218         guint16 state_retention_priority;
219         guint16 requested_feedback_location;
220         guint16 returned_parameters_location;
221         guint16 start_value;
222
223
224         /* Set print parameters */
225         print_level_1 = FALSE;
226         print_level_2 = FALSE;
227         print_level_3 = FALSE;
228         show_instr_detail_level = 0;
229
230
231
232         switch( print_flags ) {
233                 case 0:
234                         break;
235
236                 case 1:
237                         print_level_1 = TRUE;
238                         show_instr_detail_level = 1;
239                         break;
240                 case 2:
241                         print_level_1 = TRUE;
242                         print_level_2 = TRUE;
243                         show_instr_detail_level = 1;
244                         break;
245                 case 3:
246                         print_level_1 = TRUE;
247                         print_level_2 = TRUE;
248                         print_level_3 = TRUE;
249                         show_instr_detail_level = 2;
250                         break;
251                 default:
252                         print_level_1 = TRUE;
253                         show_instr_detail_level = 1;
254                         break;
255         }
256
257         /* Set initial UDVM data
258          *  The first 32 bytes of UDVM memory are then initialized to special
259          *  values as illustrated in Figure 5.
260          *
261          *                      0             7 8            15
262          *                     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
263          *                     |       UDVM_memory_size        |  0 - 1
264          *                     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
265          *                     |        cycles_per_bit         |  2 - 3
266          *                     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
267          *                     |        SigComp_version        |  4 - 5
268          *                     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
269          *                     |    partial_state_ID_length    |  6 - 7
270          *                     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
271          *                     |         state_length          |  8 - 9
272          *                     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
273          *                     |                               |
274          *                     :           reserved            :  10 - 31
275          *                     |                               |
276          *                     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
277          *
278          *            Figure 5: Initializing Useful Values in UDVM memory
279          */
280         /* UDVM_memory_size  */
281         buff[0] = (UDVM_MEMORY_SIZE >> 8) & 0x00FF;
282         buff[1] = UDVM_MEMORY_SIZE & 0x00FF;
283         /* cycles_per_bit */
284         buff[2] = 0;
285         buff[3] = 16;
286         /* SigComp_version */
287         buff[4] = 0;
288         buff[5] = 1;
289         /* partial_state_ID_length */
290         buff[6] = (byte_code_id_len >> 8) & 0x00FF;
291         buff[7] = byte_code_id_len & 0x00FF;
292         /* state_length  */
293         buff[8] = (byte_code_state_len >> 8) & 0x00FF;
294         buff[9] = byte_code_state_len & 0x00FF;
295
296         code_length = tvb_reported_length_remaining(bytecode_tvb, 0);
297
298         cycles_per_bit = buff[2] << 8;
299         cycles_per_bit = cycles_per_bit | buff[3];
300         /*
301          * maximum_UDVM_cycles = (8 * n + 1000) * cycles_per_bit
302          */
303         maximum_UDVM_cycles = (( 8 * (header_len + msg_end) ) + 1000) * cycles_per_bit;
304
305         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);
306         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);
307
308         /* Load bytecode into UDVM starting at "udvm_mem_dest" */
309         i = udvm_mem_dest;
310         if ( print_level_3 )
311                 proto_tree_add_text(udvm_tree, bytecode_tvb, offset, 1,"Load bytecode into UDVM starting at %u",i);
312         while ( code_length > offset && i < UDVM_MEMORY_SIZE ) {
313                 buff[i] = tvb_get_guint8(bytecode_tvb, offset);
314                 if ( print_level_3 )
315                         proto_tree_add_text(udvm_tree, bytecode_tvb, offset, 1,
316                                                 "              Addr: %u Instruction code(0x%0x) ", i, buff[i]);
317
318                 i++;
319                 offset++;
320
321         }
322         /* Largest allowed size for a message is UDVM_MEMORY_SIZE = 65536  */
323         out_buff = (guint8 *)g_malloc(UDVM_MEMORY_SIZE);
324         /* Start executing code */
325         current_address = udvm_start_ip;
326         input_address = 0;
327
328         proto_tree_add_text(udvm_tree, bytecode_tvb, offset, 1,"UDVM EXECUTION STARTED at Address: %u Message size %u",
329                 current_address, msg_end);
330
331 execute_next_instruction:
332
333         if ( used_udvm_cycles > maximum_UDVM_cycles ){
334                 result_code = 15;
335                 goto decompression_failure;
336         }
337         used_udvm_cycles++;
338         current_instruction = buff[current_address & 0xffff];
339
340         switch ( current_instruction ) {
341         case SIGCOMP_INSTR_DECOMPRESSION_FAILURE:
342                 if ( result_code == 0 )
343                         result_code = 9;
344                 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
345                         "Addr: %u ## DECOMPRESSION-FAILURE(0)",
346                         current_address);
347                 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Wireshark UDVM diagnostic: %s.",
348                                     val_to_str(result_code, result_code_vals,"Unknown (%u)"));
349                 if ( output_address > 0 ){
350                         /* At least something got decompressed, show it */
351                         decomp_tvb = tvb_new_child_real_data(message_tvb, out_buff,output_address,output_address);
352                         /* Arrange that the allocated packet data copy be freed when the
353                          * tvbuff is freed.
354                          */
355                         tvb_set_free_cb( decomp_tvb, g_free );
356                         /* Add the tvbuff to the list of tvbuffs to which the tvbuff we
357                          * were handed refers, so it'll get cleaned up when that tvbuff
358                          * is cleaned up.
359                          */
360                         add_new_data_source(pinfo, decomp_tvb, "Decompressed SigComp message(Incomplete)");
361                         proto_tree_add_text(udvm_tree, decomp_tvb, 0, -1,"SigComp message Decompression failure");
362                 return decomp_tvb;
363                 }
364                 g_free(out_buff);
365                 return NULL;
366                 break;
367
368         case SIGCOMP_INSTR_AND: /* 1 AND ($operand_1, %operand_2) */
369                 if (show_instr_detail_level == 2 ){
370                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
371                                 "Addr: %u ## AND(1) (operand_1, operand_2)",
372                                 current_address);
373                 }
374                 /* $operand_1*/
375                 operand_address = current_address + 1;
376                 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &operand_1, &result_dest);
377                 if (show_instr_detail_level == 2 ){
378                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u      operand_1 %u",
379                                 operand_address, operand_1);
380                 }
381                 operand_address = next_operand_address;
382                 /* %operand_2*/
383                 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &operand_2);
384                 if (show_instr_detail_level == 2 ){
385                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u      operand_2 %u",
386                                 operand_address, operand_2);
387                 }
388                 if (show_instr_detail_level == 1)
389                 {
390                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
391                                 "Addr: %u ## AND (operand_1=%u, operand_2=%u)",
392                                 current_address, operand_1, operand_2);
393                 }
394                 /* execute the instruction */
395                 result = operand_1 & operand_2;
396                 lsb = result & 0xff;
397                 msb = result >> 8;
398                 buff[result_dest] = msb;
399                 buff[(result_dest+1) & 0xffff] = lsb;
400                 if (print_level_1 ){
401                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"     Loading result %u at %u",
402                                 result, result_dest);
403                 }
404                 current_address = next_operand_address;
405                 goto execute_next_instruction;
406
407                 break;
408
409         case SIGCOMP_INSTR_OR: /* 2 OR ($operand_1, %operand_2) */
410                 if (show_instr_detail_level == 2 ){
411                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
412                                 "Addr: %u ## OR(2) (operand_1, operand_2)",
413                                 current_address);
414                 }
415                 /* $operand_1*/
416                 operand_address = current_address + 1;
417                 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &operand_1, &result_dest);
418                 if (show_instr_detail_level == 2 ){
419                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u      operand_1 %u",
420                                 operand_address, operand_1);
421                 }
422                 operand_address = next_operand_address;
423                 /* %operand_2*/
424                 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &operand_2);
425                 if (show_instr_detail_level == 2 ){
426                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u      operand_2 %u",
427                                 operand_address, operand_2);
428                 }
429                 if (show_instr_detail_level == 1)
430                 {
431                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
432                                 "Addr: %u ## OR (operand_1=%u, operand_2=%u)",
433                                 current_address, operand_1, operand_2);
434                 }
435                 /* execute the instruction */
436                 result = operand_1 | operand_2;
437                 lsb = result & 0xff;
438                 msb = result >> 8;
439                 buff[result_dest] = msb;
440                 buff[(result_dest+1) & 0xffff] = lsb;
441                 if (print_level_1 ){
442                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"     Loading result %u at %u",
443                                 result, result_dest);
444                 }
445                 current_address = next_operand_address;
446                 goto execute_next_instruction;
447
448                 break;
449
450         case SIGCOMP_INSTR_NOT: /* 3 NOT ($operand_1) */
451                 if (show_instr_detail_level == 2 ){
452                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
453                                 "Addr: %u ## NOT(3) ($operand_1)",
454                                 current_address);
455                 }
456                 /* $operand_1*/
457                 operand_address = current_address + 1;
458                 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &operand_1, &result_dest);
459                 if (show_instr_detail_level == 2 ){
460                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u      operand_1 %u",
461                                 operand_address, operand_1);
462                 }
463                 if (show_instr_detail_level == 1)
464                 {
465                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
466                                 "Addr: %u ## NOT (operand_1=%u)",
467                                 current_address, operand_1);
468                 }
469                 /* execute the instruction */
470                 result = operand_1 ^ 0xffff;
471                 lsb = result & 0xff;
472                 msb = result >> 8;
473                 buff[result_dest] = msb;
474                 buff[(result_dest+1) & 0xffff] = lsb;
475                 if (print_level_1 ){
476                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"     Loading result %u at %u",
477                                 result, result_dest);
478                 }
479                 current_address = next_operand_address;
480                 goto execute_next_instruction;
481                 break;
482
483         case SIGCOMP_INSTR_LSHIFT: /* 4 LSHIFT ($operand_1, %operand_2) */
484                 if (show_instr_detail_level == 2 ){
485                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
486                                 "Addr: %u ## LSHIFT(4) ($operand_1, operand_2)",
487                                 current_address);
488                 }
489                 /* $operand_1*/
490                 operand_address = current_address + 1;
491                 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &operand_1, &result_dest);
492                 if (show_instr_detail_level == 2 ){
493                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u      operand_1 %u",
494                                 operand_address, operand_1);
495                 }
496                 operand_address = next_operand_address;
497                 /* %operand_2*/
498                 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &operand_2);
499                 if (show_instr_detail_level == 2 ){
500                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u      operand_2 %u",
501                                 operand_address, operand_2);
502                 }
503                 if (show_instr_detail_level == 1)
504                 {
505                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
506                                 "Addr: %u ## LSHIFT (operand_1=%u, operand_2=%u)",
507                                 current_address, operand_1, operand_2);
508                 }
509                 /* execute the instruction */
510                 result = operand_1 << operand_2;
511                 lsb = result & 0xff;
512                 msb = result >> 8;
513                 buff[result_dest] = msb;
514                 buff[(result_dest+1) & 0xffff] = lsb;
515                 if (print_level_1 ){
516                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"     Loading result %u at %u",
517                                 result, result_dest);
518                 }
519                 current_address = next_operand_address;
520                 goto execute_next_instruction;
521
522                 break;
523         case SIGCOMP_INSTR_RSHIFT: /* 5 RSHIFT ($operand_1, %operand_2) */
524                 if (show_instr_detail_level == 2 ){
525                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
526                                 "Addr: %u ## RSHIFT(5) (operand_1, operand_2)",
527                                 current_address);
528                 }
529                 /* $operand_1*/
530                 operand_address = current_address + 1;
531                 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &operand_1, &result_dest);
532                 if (show_instr_detail_level == 2 ){
533                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u      operand_1 %u",
534                                 operand_address, operand_1);
535                 }
536                 operand_address = next_operand_address;
537                 /* %operand_2*/
538                 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &operand_2);
539                 if (show_instr_detail_level == 2 ){
540                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u      operand_2 %u",
541                                 operand_address, operand_2);
542                 }
543                 if (show_instr_detail_level == 1)
544                 {
545                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
546                                 "Addr: %u ## RSHIFT (operand_1=%u, operand_2=%u)",
547                                 current_address, operand_1, operand_2);
548                 }
549                 /* execute the instruction */
550                 result = operand_1 >> operand_2;
551                 lsb = result & 0xff;
552                 msb = result >> 8;
553                 buff[result_dest] = msb;
554                 buff[(result_dest+1) & 0xffff] = lsb;
555                 if (print_level_1 ){
556                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"     Loading result %u at %u",
557                                 result, result_dest);
558                 }
559                 current_address = next_operand_address;
560                 goto execute_next_instruction;
561                 break;
562         case SIGCOMP_INSTR_ADD: /* 6 ADD ($operand_1, %operand_2) */
563                 if (show_instr_detail_level == 2 ){
564                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
565                                 "Addr: %u ## ADD(6) (operand_1, operand_2)",
566                                 current_address);
567                 }
568                 /* $operand_1*/
569                 operand_address = current_address + 1;
570                 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &operand_1, &result_dest);
571                 if (show_instr_detail_level == 2 ){
572                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u      operand_1 %u",
573                                 operand_address, operand_1);
574                 }
575                 operand_address = next_operand_address;
576                 /* %operand_2*/
577                 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &operand_2);
578                 if (show_instr_detail_level == 2 ){
579                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u      operand_2 %u",
580                                 operand_address, operand_2);
581                 }
582                 if (show_instr_detail_level == 1)
583                 {
584                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
585                                 "Addr: %u ## ADD (operand_1=%u, operand_2=%u)",
586                                 current_address, operand_1, operand_2);
587                 }
588                 /* execute the instruction */
589                 result = operand_1 + operand_2;
590                 lsb = result & 0xff;
591                 msb = result >> 8;
592                 buff[result_dest] = msb;
593                 buff[(result_dest+1) & 0xffff] = lsb;
594                 if (print_level_1 ){
595                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"               Loading result %u at %u",
596                                 result, result_dest);
597                 }
598                 current_address = next_operand_address;
599                 goto execute_next_instruction;
600
601         case SIGCOMP_INSTR_SUBTRACT: /* 7 SUBTRACT ($operand_1, %operand_2) */
602                 if (show_instr_detail_level == 2 ){
603                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
604                                 "Addr: %u ## SUBTRACT(7) (operand_1, operand_2)",
605                                 current_address);
606                 }
607                 /* $operand_1*/
608                 operand_address = current_address + 1;
609                 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &operand_1, &result_dest);
610                 if (show_instr_detail_level == 2 ){
611                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u      operand_1 %u",
612                                 operand_address, operand_1);
613                 }
614                 operand_address = next_operand_address;
615                 /* %operand_2*/
616                 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &operand_2);
617                 if (show_instr_detail_level == 2 ){
618                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u      operand_2 %u",
619                                 operand_address, operand_2);
620                 }
621                 if (show_instr_detail_level == 1)
622                 {
623                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
624                                 "Addr: %u ## SUBTRACT (operand_1=%u, operand_2=%u)",
625                                 current_address, operand_1, operand_2);
626                 }
627                 /* execute the instruction */
628                 result = operand_1 - operand_2;
629                 lsb = result & 0xff;
630                 msb = result >> 8;
631                 buff[result_dest] = msb;
632                 buff[(result_dest+1) & 0xffff] = lsb;
633                 if (print_level_1 ){
634                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"               Loading result %u at %u",
635                                 result, result_dest);
636                 }
637                 current_address = next_operand_address;
638                 goto execute_next_instruction;
639                 break;
640
641         case SIGCOMP_INSTR_MULTIPLY: /* 8 MULTIPLY ($operand_1, %operand_2) */
642                 if (show_instr_detail_level == 2 ){
643                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
644                                 "Addr: %u ##MULTIPLY(8) (operand_1, operand_2)",
645                                 current_address);
646                 }
647                 /* $operand_1*/
648                 operand_address = current_address + 1;
649                 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &operand_1, &result_dest);
650                 if (show_instr_detail_level == 2 ){
651                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u      operand_1 %u",
652                                 operand_address, operand_1);
653                 }
654                 operand_address = next_operand_address;
655                 /* %operand_2*/
656                 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &operand_2);
657                 if (show_instr_detail_level == 2 ){
658                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u      operand_2 %u",
659                                 operand_address, operand_2);
660                 }
661                 if (show_instr_detail_level == 1)
662                 {
663                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
664                                 "Addr: %u ## MULTIPLY (operand_1=%u, operand_2=%u)",
665                                 current_address, operand_1, operand_2);
666                 }
667                 /*
668                  * execute the instruction
669                  * MULTIPLY (m, n)  := m * n (modulo 2^16)
670                  */
671                 if ( operand_2 == 0){
672                         result_code = 4;
673                         goto decompression_failure;
674                 }
675                 result = operand_1 * operand_2;
676                 lsb = result & 0xff;
677                 msb = result >> 8;
678                 buff[result_dest] = msb;
679                 buff[(result_dest+1) & 0xffff] = lsb;
680                 if (print_level_1 ){
681                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"     Loading result %u at %u",
682                                 result, result_dest);
683                 }
684                 current_address = next_operand_address;
685                 goto execute_next_instruction;
686                 break;
687
688         case SIGCOMP_INSTR_DIVIDE: /* 9 DIVIDE ($operand_1, %operand_2) */
689                 if (show_instr_detail_level == 2 ){
690                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
691                                 "Addr: %u ## DIVIDE(9) (operand_1, operand_2)",
692                                 current_address);
693                 }
694                 /* $operand_1*/
695                 operand_address = current_address + 1;
696                 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &operand_1, &result_dest);
697                 if (show_instr_detail_level == 2 ){
698                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u      operand_1 %u",
699                                 operand_address, operand_1);
700                 }
701                 operand_address = next_operand_address;
702                 /* %operand_2*/
703                 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &operand_2);
704                 if (show_instr_detail_level == 2 ){
705                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u      operand_2 %u",
706                                 operand_address, operand_2);
707                 }
708                 if (show_instr_detail_level == 1)
709                 {
710                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
711                                 "Addr: %u ## DIVIDE (operand_1=%u, operand_2=%u)",
712                                 current_address, operand_1, operand_2);
713                 }
714                 /*
715                  * execute the instruction
716                  * DIVIDE (m, n)    := floor(m / n)
717                  * Decompression failure occurs if a DIVIDE or REMAINDER instruction
718                  * encounters an operand_2 that is zero.
719                  */
720                 if ( operand_2 == 0){
721                         result_code = 4;
722                         goto decompression_failure;
723                 }
724                 result = operand_1 / operand_2;
725                 lsb = result & 0xff;
726                 msb = result >> 8;
727                 buff[result_dest] = msb;
728                 buff[(result_dest+1) & 0xffff] = lsb;
729                 if (print_level_1 ){
730                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"     Loading result %u at %u",
731                                 result, result_dest);
732                 }
733                 current_address = next_operand_address;
734                 goto execute_next_instruction;
735                 break;
736
737         case SIGCOMP_INSTR_REMAINDER: /* 10 REMAINDER ($operand_1, %operand_2) */
738                 if (show_instr_detail_level == 2 ){
739                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
740                                 "Addr: %u ## REMAINDER(10) (operand_1, operand_2)",
741                                 current_address);
742                 }
743                 /* $operand_1*/
744                 operand_address = current_address + 1;
745                 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &operand_1, &result_dest);
746                 if (show_instr_detail_level == 2 ){
747                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u      operand_1 %u",
748                                 operand_address, operand_1);
749                 }
750                 operand_address = next_operand_address;
751                 /* %operand_2*/
752                 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &operand_2);
753                 if (show_instr_detail_level == 2 ){
754                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u      operand_2 %u",
755                                 operand_address, operand_2);
756                 }
757                 if (show_instr_detail_level == 1)
758                 {
759                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
760                                 "Addr: %u ## REMAINDER (operand_1=%u, operand_2=%u)",
761                                 current_address, operand_1, operand_2);
762                 }
763                 /*
764                  * execute the instruction
765                  * REMAINDER (m, n) := m - n * floor(m / n)
766                  * Decompression failure occurs if a DIVIDE or REMAINDER instruction
767                  * encounters an operand_2 that is zero.
768                  */
769                 if ( operand_2 == 0){
770                         result_code = 4;
771                         goto decompression_failure;
772                 }
773                 result = operand_1 - operand_2 * (operand_1 / operand_2);
774                 lsb = result & 0xff;
775                 msb = result >> 8;
776                 buff[result_dest] = msb;
777                 buff[(result_dest+1) & 0xffff] = lsb;
778                 if (print_level_1 ){
779                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"     Loading result %u at %u",
780                                 result, result_dest);
781                 }
782                 current_address = next_operand_address;
783                 goto execute_next_instruction;
784                 break;
785         case SIGCOMP_INSTR_SORT_ASCENDING: /* 11 SORT-ASCENDING (%start, %n, %k) */
786                 /*
787                  *      used_udvm_cycles =  1 + k * (ceiling(log2(k)) + n)
788                  */
789                 if (print_level_1 ){
790                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
791                                 "Addr: %u ## SORT-ASCENDING(11) (start, n, k))",
792                                 current_address);
793                 }
794                 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Execution of this instruction is NOT implemented");
795                 /*
796                  *      used_udvm_cycles =  1 + k * (ceiling(log2(k)) + n)
797                  */
798                 break;
799
800         case SIGCOMP_INSTR_SORT_DESCENDING: /* 12 SORT-DESCENDING (%start, %n, %k) */
801                 if (print_level_1 ){
802                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
803                                 "Addr: %u ## SORT-DESCENDING(12) (start, n, k))",
804                                 current_address);
805                 }
806                 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Execution of this instruction is NOT implemented");
807                 /*
808                  *      used_udvm_cycles =  1 + k * (ceiling(log2(k)) + n)
809                  */
810                 break;
811         case SIGCOMP_INSTR_SHA_1: /* 13 SHA-1 (%position, %length, %destination) */
812                 if (print_level_1 ){
813                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
814                                 "Addr: %u ## SHA-1(13) (position, length, destination)",
815                                 current_address);
816                 }
817                 operand_address = current_address + 1;
818                 /* %position */
819                 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &position);
820                 if (print_level_1 ){
821                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u      position %u",
822                                 operand_address, position);
823                 }
824                 operand_address = next_operand_address;
825
826                 /* %length */
827                 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &length);
828                 if (print_level_1 ){
829                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u      Length %u",
830                                 operand_address, length);
831                 }
832                 operand_address = next_operand_address;
833
834                 /* $destination */
835                 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &ref_destination, &result_dest);
836                 if (print_level_1 ){
837                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u      $destination %u",
838                                 operand_address, ref_destination);
839                 }
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                 /* TODO: This isn't currently totaly correct as END_INSTRUCTION might not create state */
2645                 no_of_state_create++;
2646                 if ( no_of_state_create > 4 ){
2647                         result_code = 12;
2648                         goto decompression_failure;
2649                 }
2650                 state_length_buff[no_of_state_create] = state_length;
2651                 state_address_buff[no_of_state_create] = state_address;
2652                 state_instruction_buff[no_of_state_create] = state_instruction;
2653                 /* Not used ? */
2654                 state_minimum_access_length_buff[no_of_state_create] = minimum_access_length;
2655                 /* state_state_retention_priority_buff[no_of_state_create] = state_retention_priority; */
2656
2657                 /* Execute the instruction
2658                  */
2659                 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"no_of_state_create %u",no_of_state_create);
2660                 if ( no_of_state_create != 0 ){
2661                         memset(sha1_digest_buf, 0, STATE_BUFFER_SIZE);
2662                         n = 1;
2663                         byte_copy_right = buff[66] << 8;
2664                         byte_copy_right = byte_copy_right | buff[67];
2665                         byte_copy_left = buff[64] << 8;
2666                         byte_copy_left = byte_copy_left | buff[65];
2667                         while ( n < no_of_state_create + 1 ){
2668                                 sha1buff = (guint8 *)g_malloc(state_length_buff[n]+8);
2669                                 sha1buff[0] = state_length_buff[n] >> 8;
2670                                 sha1buff[1] = state_length_buff[n] & 0xff;
2671                                 sha1buff[2] = state_address_buff[n] >> 8;
2672                                 sha1buff[3] = state_address_buff[n] & 0xff;
2673                                 sha1buff[4] = state_instruction_buff[n] >> 8;
2674                                 sha1buff[5] = state_instruction_buff[n] & 0xff;
2675                                 sha1buff[6] = state_minimum_access_length_buff[n] >> 8;
2676                                 sha1buff[7] = state_minimum_access_length_buff[n] & 0xff;
2677                                 if (print_level_3 ){
2678                                         for( x=0; x < 8; x++){
2679                                                 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"sha1buff %u 0x%x",
2680                                                         x,sha1buff[x]);
2681                                         }
2682                                 }
2683                                 k = state_address_buff[n];
2684                                 for( x=0; x < state_length_buff[n]; x++)
2685                                         {
2686                                         if ( k == byte_copy_right ){
2687                                                 k = byte_copy_left;
2688                                         }
2689                                         sha1buff[8+x] = buff[k];
2690                                         k = ( k + 1 ) & 0xffff;
2691                                         }
2692
2693                                 sha1_starts( &ctx );
2694                                 sha1_update( &ctx, (guint8 *) sha1buff, state_length_buff[n] + 8);
2695                                 sha1_finish( &ctx, sha1_digest_buf );
2696                                 if (print_level_3 ){
2697                                         proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"SHA1 digest %s",bytes_to_str(sha1_digest_buf, STATE_BUFFER_SIZE));
2698
2699                                 }
2700 /* begin partial state-id change cco@iptel.org */
2701 #if 0
2702                                 udvm_state_create(sha1buff, sha1_digest_buf, state_minimum_access_length_buff[n]);
2703 #endif
2704                                 udvm_state_create(sha1buff, sha1_digest_buf, STATE_MIN_ACCESS_LEN);
2705 /* end partial state-id change cco@iptel.org */
2706                                 proto_tree_add_text(udvm_tree,bytecode_tvb, 0, -1,"### Creating state ###");
2707                                 proto_tree_add_string(udvm_tree,hf_id, bytecode_tvb, 0, 0, bytes_to_str(sha1_digest_buf, state_minimum_access_length_buff[n]));
2708
2709                                 n++;
2710
2711                         }
2712                 }
2713
2714
2715
2716                 /* At least something got decompressed, show it */
2717                 decomp_tvb = tvb_new_child_real_data(message_tvb, out_buff,output_address,output_address);
2718                 /* Arrange that the allocated packet data copy be freed when the
2719                  * tvbuff is freed.
2720                  */
2721                 tvb_set_free_cb( decomp_tvb, g_free );
2722
2723                 add_new_data_source(pinfo, decomp_tvb, "Decompressed SigComp message");
2724                 /*
2725                 proto_tree_add_text(udvm_tree, decomp_tvb, 0, -1,"SigComp message Decompressed");
2726                 */
2727                 used_udvm_cycles = used_udvm_cycles + state_length;
2728                 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"maximum_UDVM_cycles %u used_udvm_cycles %u",
2729                         maximum_UDVM_cycles, used_udvm_cycles);
2730                 return decomp_tvb;
2731                 break;
2732
2733         default:
2734             proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," ### Addr %u Invalid instruction: %u (0x%x)",
2735                         current_address,current_instruction,current_instruction);
2736                 break;
2737                 }
2738                 g_free(out_buff);
2739                 return NULL;
2740 decompression_failure:
2741
2742                 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"DECOMPRESSION FAILURE: %s",
2743                                     val_to_str(result_code, result_code_vals,"Unknown (%u)"));
2744                 THROW(ReportedBoundsError);
2745                 g_free(out_buff);
2746                 return NULL;
2747
2748 }
2749
2750  /*  The simplest operand type is the literal (#), which encodes a
2751   * constant integer from 0 to 65535 inclusive.  A literal operand may
2752   * require between 1 and 3 bytes depending on its value.
2753   * Bytecode:                       Operand value:      Range:
2754   * 0nnnnnnn                        N                   0 - 127
2755   * 10nnnnnn nnnnnnnn               N                   0 - 16383
2756   * 11000000 nnnnnnnn nnnnnnnn      N                   0 - 65535
2757   *
2758   *            Figure 8: Bytecode for a literal (#) operand
2759   *
2760   */
2761 static int
2762 decode_udvm_literal_operand(guint8 *buff,guint operand_address, guint16 *value)
2763 {
2764         guint   bytecode;
2765         guint16 operand;
2766         guint   test_bits;
2767         guint   offset = operand_address;
2768         guint8  temp_data;
2769
2770         bytecode = buff[operand_address];
2771         test_bits = bytecode >> 7;
2772         if (test_bits == 1){
2773                 test_bits = bytecode >> 6;
2774                 if (test_bits == 2){
2775                         /*
2776                          * 10nnnnnn nnnnnnnn               N                   0 - 16383
2777                          */
2778                         temp_data = buff[operand_address] & 0x1f;
2779                         operand = temp_data << 8;
2780                         temp_data = buff[(operand_address + 1) & 0xffff];
2781                         operand = operand | temp_data;
2782                         *value = operand;
2783                         offset = offset + 2;
2784
2785                 }else{
2786                         /*
2787                          * 111000000 nnnnnnnn nnnnnnnn      N                   0 - 65535
2788                          */
2789                         offset ++;
2790                         temp_data = buff[operand_address] & 0x1f;
2791                         operand = temp_data << 8;
2792                         temp_data = buff[(operand_address + 1) & 0xffff];
2793                         operand = operand | temp_data;
2794                         *value = operand;
2795                         offset = offset + 2;
2796
2797                 }
2798         }else{
2799                 /*
2800                  * 0nnnnnnn                        N                   0 - 127
2801                  */
2802                 operand = ( bytecode & 0x7f);
2803                 *value = operand;
2804                 offset ++;
2805         }
2806
2807         return offset;
2808
2809 }
2810
2811 /*
2812  * The second operand type is the reference ($), which is always used to
2813  * access a 2-byte value located elsewhere in the UDVM memory.  The
2814  * bytecode for a reference operand is decoded to be a constant integer
2815  * from 0 to 65535 inclusive, which is interpreted as the memory address
2816  * containing the actual value of the operand.
2817  * Bytecode:                       Operand value:      Range:
2818  *
2819  * 0nnnnnnn                        memory[2 * N]       0 - 65535
2820  * 10nnnnnn nnnnnnnn               memory[2 * N]       0 - 65535
2821  * 11000000 nnnnnnnn nnnnnnnn      memory[N]           0 - 65535
2822  *
2823  *            Figure 9: Bytecode for a reference ($) operand
2824  */
2825 static int
2826 dissect_udvm_reference_operand(guint8 *buff,guint operand_address, guint16 *value,guint *result_dest)
2827 {
2828         guint bytecode;
2829         guint16 operand;
2830         guint   offset = operand_address;
2831         guint test_bits;
2832         guint8  temp_data;
2833         guint16 temp_data16;
2834
2835         bytecode = buff[operand_address];
2836         test_bits = bytecode >> 7;
2837         if (test_bits == 1){
2838                 test_bits = bytecode >> 6;
2839                 if (test_bits == 2){
2840                         /*
2841                          * 10nnnnnn nnnnnnnn               memory[2 * N]       0 - 65535
2842                          */
2843                         temp_data = buff[operand_address] & 0x3f;
2844                         operand = temp_data << 8;
2845                         temp_data = buff[(operand_address + 1) & 0xffff];
2846                         operand = operand | temp_data;
2847                         operand = (operand * 2);
2848                         *result_dest = operand;
2849                         temp_data16 = buff[operand] << 8;
2850                         temp_data16 = temp_data16 | buff[(operand+1) & 0xffff];
2851                         *value = temp_data16;
2852                         offset = offset + 2;
2853
2854                 }else{
2855                         /*
2856                          * 11000000 nnnnnnnn nnnnnnnn      memory[N]           0 - 65535
2857                          */
2858                         operand_address++;
2859                         operand = buff[operand_address] << 8;
2860                         operand = operand | buff[(operand_address + 1) & 0xffff];
2861                         *result_dest = operand;
2862                         temp_data16 = buff[operand] << 8;
2863                         temp_data16 = temp_data16 | buff[(operand+1) & 0xffff];
2864                         *value = temp_data16;
2865                         offset = offset + 3;
2866
2867                 }
2868         }else{
2869                 /*
2870                  * 0nnnnnnn                        memory[2 * N]       0 - 65535
2871                  */
2872                 operand = ( bytecode & 0x7f);
2873                 operand = (operand * 2);
2874                 *result_dest = operand;
2875                 temp_data16 = buff[operand] << 8;
2876                 temp_data16 = temp_data16 | buff[(operand+1) & 0xffff];
2877                 *value = temp_data16;
2878                 offset ++;
2879         }
2880
2881         if (offset >= UDVM_MEMORY_SIZE || *result_dest >= UDVM_MEMORY_SIZE - 1 )
2882                 THROW(ReportedBoundsError);
2883
2884         return offset;
2885 }
2886
2887         /* RFC3320
2888          * Figure 10: Bytecode for a multitype (%) operand
2889          * Bytecode:                       Operand value:      Range:               HEX val
2890          * 00nnnnnn                        N                   0 - 63                           0x00
2891          * 01nnnnnn                        memory[2 * N]       0 - 65535                        0x40
2892          * 1000011n                        2 ^ (N + 6)        64 , 128                          0x86
2893          * 10001nnn                        2 ^ (N + 8)    256 , ... , 32768                     0x88
2894          * 111nnnnn                        N + 65504       65504 - 65535                        0xe0
2895          * 1001nnnn nnnnnnnn               N + 61440       61440 - 65535                        0x90
2896          * 101nnnnn nnnnnnnn               N                   0 - 8191                         0xa0
2897          * 110nnnnn nnnnnnnn               memory[N]           0 - 65535                        0xc0
2898          * 10000000 nnnnnnnn nnnnnnnn      N                   0 - 65535                        0x80
2899          * 10000001 nnnnnnnn nnnnnnnn      memory[N]           0 - 65535                        0x81
2900          */
2901 static int
2902 decode_udvm_multitype_operand(guint8 *buff,guint operand_address, guint16 *value)
2903 {
2904         guint test_bits;
2905         guint bytecode;
2906         guint offset = operand_address;
2907         guint16 operand;
2908         guint32 result;
2909         guint8 temp_data;
2910         guint16 temp_data16;
2911         guint16 memmory_addr = 0;
2912
2913 *value = 0;
2914
2915         bytecode = buff[operand_address];
2916         test_bits = ( bytecode & 0xc0 ) >> 6;
2917         switch (test_bits ){
2918         case 0:
2919                 /*
2920                  * 00nnnnnn                        N                   0 - 63
2921                  */
2922                 operand =  buff[operand_address];
2923                 /* debug
2924                  *g_warning("Reading 0x%x From address %u",operand,offset);
2925                  */
2926                 *value = operand;
2927                 offset ++;
2928                 break;
2929         case 1:
2930                 /*
2931                  * 01nnnnnn                        memory[2 * N]       0 - 65535
2932                  */
2933                 memmory_addr = ( bytecode & 0x3f) * 2;
2934                 temp_data16 = buff[memmory_addr] << 8;
2935                 temp_data16 = temp_data16 | buff[(memmory_addr+1) & 0xffff];
2936                 *value = temp_data16;
2937                 offset ++;
2938                 break;
2939         case 2:
2940                 /* Check tree most significant bits */
2941                 test_bits = ( bytecode & 0xe0 ) >> 5;
2942                 if ( test_bits == 5 ){
2943                 /*
2944                  * 101nnnnn nnnnnnnn               N                   0 - 8191
2945                  */
2946                         temp_data = buff[operand_address] & 0x1f;
2947                         operand = temp_data << 8;
2948                         temp_data = buff[(operand_address + 1) & 0xffff];
2949                         operand = operand | temp_data;
2950                         *value = operand;
2951                         offset = offset + 2;
2952                 }else{
2953                         test_bits = ( bytecode & 0xf0 ) >> 4;
2954                         if ( test_bits == 9 ){
2955                 /*
2956                  * 1001nnnn nnnnnnnn               N + 61440       61440 - 65535
2957                  */
2958                                 temp_data = buff[operand_address] & 0x0f;
2959                                 operand = temp_data << 8;
2960                                 temp_data = buff[(operand_address + 1) & 0xffff];
2961                                 operand = operand | temp_data;
2962                                 operand = operand + 61440;
2963                                 *value = operand;
2964                                 offset = offset + 2;
2965                         }else{
2966                                 test_bits = ( bytecode & 0x08 ) >> 3;
2967                                 if ( test_bits == 1){
2968                 /*
2969                  * 10001nnn                        2 ^ (N + 8)    256 , ... , 32768
2970                  */
2971
2972                                         result = 1 << ((buff[operand_address] & 0x07) + 8);
2973                                         operand = result & 0xffff;
2974                                         *value = operand;
2975                                         offset ++;
2976                                 }else{
2977                                         test_bits = ( bytecode & 0x0e ) >> 1;
2978                                         if ( test_bits == 3 ){
2979                                                 /*
2980                                                  * 1000 011n                        2 ^ (N + 6)        64 , 128
2981                                                  */
2982                                                 result = 1 << ((buff[operand_address] & 0x01) + 6);
2983                                                 operand = result & 0xffff;
2984                                                 *value = operand;
2985                                                 offset ++;
2986                                         }else{
2987                                         /*
2988                                          * 1000 0000 nnnnnnnn nnnnnnnn      N                   0 - 65535
2989                                          * 1000 0001 nnnnnnnn nnnnnnnn      memory[N]           0 - 65535
2990                                          */
2991                                                 offset ++;
2992                                                 temp_data16 = buff[(operand_address + 1) & 0xffff] << 8;
2993                                                 temp_data16 = temp_data16 | buff[(operand_address + 2) & 0xffff];
2994                                                 /*  debug
2995                                                  * g_warning("Reading 0x%x From address %u",temp_data16,operand_address);
2996                                                  */
2997                                                 if ( (bytecode & 0x01) == 1 ){
2998                                                         memmory_addr = temp_data16;
2999                                                         temp_data16 = buff[memmory_addr] << 8;
3000                                                         temp_data16 = temp_data16 | buff[(memmory_addr+1) & 0xffff];
3001                                                 }
3002                                                 *value = temp_data16;
3003                                                 offset = offset +2;
3004                                         }
3005
3006
3007                                 }
3008                         }
3009                 }
3010                 break;
3011
3012         case 3:
3013                 test_bits = ( bytecode & 0x20 ) >> 5;
3014                 if ( test_bits == 1 ){
3015                 /*
3016                  * 111nnnnn                        N + 65504       65504 - 65535
3017                  */
3018                         operand = ( buff[operand_address] & 0x1f) + 65504;
3019                         *value = operand;
3020                         offset ++;
3021                 }else{
3022                 /*
3023                  * 110nnnnn nnnnnnnn               memory[N]           0 - 65535
3024                  */
3025                         memmory_addr = buff[operand_address] & 0x1f;
3026                         memmory_addr = memmory_addr << 8;
3027                         memmory_addr = memmory_addr | buff[(operand_address + 1) & 0xffff];
3028                         temp_data16 = buff[memmory_addr] << 8;
3029                         temp_data16 = temp_data16 | buff[(memmory_addr+1) & 0xffff];
3030                         *value = temp_data16;
3031                         /*  debug
3032                          * g_warning("Reading 0x%x From address %u",temp_data16,memmory_addr);
3033                          */
3034                         offset = offset +2;
3035                 }
3036
3037         default :
3038                 break;
3039         }
3040         return offset;
3041 }
3042         /*
3043          *
3044          * The fourth operand type is the address (@).  This operand is decoded
3045          * as a multitype operand followed by a further step: the memory address
3046          * of the UDVM instruction containing the address operand is added to
3047          * obtain the correct operand value.  So if the operand value from
3048          * Figure 10 is D then the actual operand value of an address is
3049          * calculated as follows:
3050          *
3051          * operand_value = (memory_address_of_instruction + D) modulo 2^16
3052          *
3053          * Address operands are always used in instructions that control program
3054          * flow, because they ensure that the UDVM bytecode is position-
3055          * independent code (i.e., it will run independently of where it is
3056          * placed in the UDVM memory).
3057          */
3058 static int
3059 decode_udvm_address_operand(guint8 *buff,guint operand_address, guint16 *value,guint current_address)
3060 {
3061         guint32 result;
3062         guint16 value1;
3063         guint next_opreand_address;
3064
3065         next_opreand_address = decode_udvm_multitype_operand(buff, operand_address, &value1);
3066         result = value1 & 0xffff;
3067         result = result + current_address;
3068         *value = result & 0xffff;
3069         return next_opreand_address;
3070 }
3071
3072
3073 /*
3074  * This is a lookup table used to reverse the bits in a byte.
3075  */
3076 static guint8 reverse [] = {
3077     0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0,
3078     0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0,
3079     0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8,
3080     0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8,
3081     0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4,
3082     0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4,
3083     0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC,
3084     0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC,
3085     0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2,
3086     0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2,
3087     0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA,
3088     0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA,
3089     0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6,
3090     0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6,
3091     0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE,
3092     0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE,
3093     0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1,
3094     0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1,
3095     0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9,
3096     0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9,
3097     0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5,
3098     0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5,
3099     0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED,
3100     0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD,
3101     0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3,
3102     0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3,
3103     0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB,
3104     0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB,
3105     0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7,
3106     0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7,
3107     0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF,
3108     0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF
3109 };
3110
3111
3112 static int
3113 decomp_dispatch_get_bits(
3114                 tvbuff_t *message_tvb,
3115                 proto_tree *udvm_tree,
3116                 guint8 bit_order,
3117                 guint8 *buff,
3118                 guint16 *old_input_bit_order,
3119                 guint16 *remaining_bits,
3120                 guint16 *input_bits,
3121                 guint *input_address,
3122                 guint16 length,
3123                 guint16 *result_code,
3124                 guint msg_end)
3125 {
3126         guint16 input_bit_order;
3127         guint16 bits_still_required = length;
3128         guint16 value = 0;
3129         guint8  octet;
3130         gint    extra_bytes_available = msg_end - *input_address;
3131         gint    p_bit;
3132         gint    prev_p_bit = *old_input_bit_order & 0x0001;
3133         gint    bits_to_use = 0;
3134
3135
3136         input_bit_order = buff[68] << 8;
3137         input_bit_order = input_bit_order | buff[69];
3138         *result_code = 0;
3139         p_bit = (input_bit_order & 0x0001) != 0;
3140
3141         /*
3142          * Discard any spare bits.
3143          * Note: We take care to avoid remaining_bits having the value of 8.
3144          */
3145         if (prev_p_bit != p_bit)
3146         {
3147                 *remaining_bits = 0;
3148                 *old_input_bit_order = input_bit_order;
3149         }
3150
3151         /*
3152          * Check we can suppy the required number of bits now, before we alter
3153          * the input buffer's state.
3154          */
3155         if (*remaining_bits + extra_bytes_available * 8 < length)
3156         {
3157                 *result_code = 11;
3158                 return 0xfbad;
3159         }
3160
3161         /* Note: This is never called with length > 16, so the following loop
3162         *       never loops more than three time. */
3163         while (bits_still_required > 0)
3164         {
3165                 /*
3166                  * We only put anything into input_bits if we know we will remove
3167                  * at least one bit. That ensures we can simply discard the spare
3168                  * bits if the P-bit changes.
3169                  */
3170                 if (*remaining_bits == 0)
3171                 {
3172                         octet = tvb_get_guint8(message_tvb, *input_address);
3173                         if (print_level_1 ){
3174                                 proto_tree_add_text(udvm_tree, message_tvb, *input_address , 1,
3175                                                 "               Getting value: %u (0x%x) From Addr: %u", octet, octet, *input_address);
3176                         }
3177                         *input_address = *input_address + 1;
3178
3179                         if (p_bit != 0)
3180                         {
3181                                 octet = reverse[octet];
3182                         }
3183                         *input_bits = octet;
3184                         *remaining_bits = 8;
3185                 }
3186
3187                 /* Add some more bits to the accumulated value. */
3188                 bits_to_use = bits_still_required < *remaining_bits ? bits_still_required : *remaining_bits;
3189                 bits_still_required -= bits_to_use;
3190
3191                 *input_bits <<= bits_to_use;           /* Shift bits into MSByte */
3192                 value = (value << bits_to_use)         /* Then add to the accumulated value */
3193                         | ((*input_bits >> 8) & 0xFF);
3194                 *remaining_bits -= bits_to_use;
3195                 *input_bits &= 0x00FF;                 /* Leave just the remaining bits */
3196         }
3197
3198         if (bit_order != 0)
3199         {
3200                 /* Bit reverse the entire word. */
3201                 guint16 lsb = reverse[(value >> 8) & 0xFF];
3202                 guint16 msb = reverse[value & 0xFF];
3203
3204                 value = ((msb << 8) | lsb) >> (16 - length);
3205         }
3206
3207         return value;
3208 }
3209
3210
3211 /* end udvm */
3212