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