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