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