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