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
6 * $Id: udvm.c 11445 2004-07-20 19:04:48Z etxrab $
\r
8 * Ethereal - Network traffic analyzer
\r
9 * By Gerald Combs <gerald@ethereal.com>
\r
10 * Copyright 1998 Gerald Combs
\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
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
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
26 * http://www.ietf.org/rfc/rfc3320.txt?number=3320
\r
27 * http://www.ietf.org/rfc/rfc3321.txt?number=3321
\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
33 #ifdef HAVE_CONFIG_H
\r
34 # include "config.h"
\r
43 #ifdef NEED_SNPRINTF_H
\r
44 # include "snprintf.h"
\r
48 #include "strutil.h"
\r
49 #include "sigcomp-udvm.h"
\r
50 #include "sigcomp_state_hdlr.h"
\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
91 static gboolean print_level_1;
\r
92 static gboolean print_level_2;
\r
93 static gboolean print_level_3;
\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
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
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
130 tvbuff_t *decomp_tvb;
\r
131 guint8 buff[UDVM_MEMORY_SIZE];
\r
133 guint8 *out_buff; /* Largest allowed size for a message is 65535 */
\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
153 guint16 byte_copy_right;
\r
154 guint16 byte_copy_left;
\r
155 guint16 input_bit_order;
\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
176 unsigned char sha1_digest_buf[20];
\r
180 /* UDVM operand variables */
\r
182 guint16 at_address;
\r
183 guint16 destination;
\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
196 guint16 at_address_1;
\r
197 guint16 at_address_2;
\r
198 guint16 at_address_3;
\r
201 guint16 lower_bound_n;
\r
202 guint16 upper_bound_n;
\r
203 guint16 uncompressed_n;
\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
215 /* Set print parameters */
\r
216 print_level_1 = FALSE;
\r
217 print_level_2 = FALSE;
\r
218 print_level_3 = FALSE;
\r
221 switch( print_flags ) {
\r
226 print_level_1 = TRUE;
\r
229 print_level_1 = TRUE;
\r
230 print_level_2 = TRUE;
\r
233 print_level_1 = TRUE;
\r
234 print_level_2 = TRUE;
\r
235 print_level_3 = TRUE;
\r
238 print_level_1 = TRUE;
\r
247 /* UDVM memory must be initialised to zero */
\r
248 while ( i < UDVM_MEMORY_SIZE ) {
\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
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
269 * : reserved : 10 - 31
\r
271 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
\r
273 * Figure 5: Initializing Useful Values in UDVM memory
\r
275 /* UDVM_memory_size */
\r
278 /* cycles_per_bit */
\r
281 /* SigComp_version */
\r
284 /* partial_state_ID_length */
\r
290 code_length = tvb_reported_length_remaining(bytecode_tvb, 0);
\r
292 cycles_per_bit = buff[2] << 8;
\r
293 cycles_per_bit = cycles_per_bit | buff[3];
\r
295 * maximum_UDVM_cycles = (8 * n + 1000) * cycles_per_bit
\r
297 maximum_UDVM_cycles = (( 8 * msg_end ) + 1000) * cycles_per_bit;
\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
302 /* Load bytecode into UDVM starting at "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
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
321 operand_address = 0;
\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
326 execute_next_instruction:
\r
328 if ( used_udvm_cycles > maximum_UDVM_cycles ){
\r
330 goto decompression_failure;
\r
332 current_instruction = buff[current_address];
\r
334 switch ( current_instruction ) {
\r
335 case SIGCOMP_INSTR_DECOMPRESSION_FAILURE:
\r
336 used_udvm_cycles++;
\r
337 if ( result_code == 0 )
\r
339 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
\r
340 "Addr: %u ## DECOMPRESSION-FAILURE(0)",
\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
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
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
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
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
378 operand_address = next_operand_address;
\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
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
395 current_address = next_operand_address;
\r
396 goto execute_next_instruction;
\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
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
414 operand_address = next_operand_address;
\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
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
431 current_address = next_operand_address;
\r
432 goto execute_next_instruction;
\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
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
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
460 current_address = next_operand_address;
\r
461 goto execute_next_instruction;
\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
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
478 operand_address = next_operand_address;
\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
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
495 current_address = next_operand_address;
\r
496 goto execute_next_instruction;
\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
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
513 operand_address = next_operand_address;
\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
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
530 current_address = next_operand_address;
\r
531 goto execute_next_instruction;
\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
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
547 operand_address = next_operand_address;
\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
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
564 current_address = next_operand_address;
\r
565 goto execute_next_instruction;
\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
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
581 operand_address = next_operand_address;
\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
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
598 current_address = next_operand_address;
\r
599 goto execute_next_instruction;
\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
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
616 operand_address = next_operand_address;
\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
624 * execute the instruction
\r
625 * MULTIPLY (m, n) := m * n (modulo 2^16)
\r
627 if ( operand_2 == 0){
\r
629 goto decompression_failure;
\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
640 current_address = next_operand_address;
\r
641 goto execute_next_instruction;
\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
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
658 operand_address = next_operand_address;
\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
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
671 if ( operand_2 == 0){
\r
673 goto decompression_failure;
\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
684 current_address = next_operand_address;
\r
685 goto execute_next_instruction;
\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
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
702 operand_address = next_operand_address;
\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
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
715 if ( operand_2 == 0){
\r
717 goto decompression_failure;
\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
728 current_address = next_operand_address;
\r
729 goto execute_next_instruction;
\r
731 case SIGCOMP_INSTR_SORT_ASCENDING: /* 11 SORT-ASCENDING (%start, %n, %k) */
\r
733 * used_udvm_cycles = 1 + k * (ceiling(log2(k)) + n)
\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
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
743 * used_udvm_cycles = 1 + k * (ceiling(log2(k)) + n)
\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
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
756 * used_udvm_cycles = 1 + k * (ceiling(log2(k)) + n)
\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
765 operand_address = current_address + 1;
\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
772 operand_address = next_operand_address;
\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
780 operand_address = next_operand_address;
\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
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
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
799 operand_address = current_address + 1;
\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
806 operand_address = next_operand_address;
\r
808 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &value);
\r
809 lsb = value & 0xff;
\r
812 buff[address] = msb;
\r
813 buff[address + 1] = lsb;
\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
821 used_udvm_cycles++;
\r
822 current_address = next_operand_address;
\r
823 goto execute_next_instruction;
\r
826 case SIGCOMP_INSTR_MULTILOAD: /* 15 MULTILOAD (%address, #n, %value_0, ..., %value_n-1) */
\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
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
837 operand_address = current_address + 1;
\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
844 operand_address = next_operand_address;
\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
852 operand_address = next_operand_address;
\r
853 used_udvm_cycles = used_udvm_cycles + n;
\r
857 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &value);
\r
858 lsb = value & 0xff;
\r
861 buff[address] = msb;
\r
862 buff[address + 1] = lsb;
\r
865 length = next_operand_address - operand_address;
\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
871 address = address + 2;
\r
872 operand_address = next_operand_address;
\r
874 current_address = next_operand_address;
\r
875 goto execute_next_instruction;
\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
885 operand_address = current_address + 1;
\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
892 used_udvm_cycles++;
\r
893 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Execution of this instruction is NOT implemented");
\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
902 operand_address = current_address + 1;
\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
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
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
920 operand_address = current_address + 1;
\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
927 operand_address = next_operand_address;
\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
935 operand_address = next_operand_address;
\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
943 current_address = next_operand_address;
\r
945 * 8.4. Byte copying
\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
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
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
966 while ( n < length ){
\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
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
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
982 k = ( k + 1 ) & 0xffff;
\r
985 used_udvm_cycles = used_udvm_cycles + 1 + length;
\r
986 goto execute_next_instruction;
\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
995 operand_address = current_address + 1;
\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
1002 operand_address = next_operand_address;
\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
1010 operand_address = next_operand_address;
\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
1019 current_address = next_operand_address;
\r
1023 * 8.4. Byte copying
\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
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
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
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
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
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
1055 k = ( k + 1 ) & 0xffff;
\r
1058 buff[result_dest] = k >> 8;
\r
1059 buff[result_dest + 1] = k & 0x00ff;
\r
1061 used_udvm_cycles = used_udvm_cycles + 1 + length;
\r
1062 goto execute_next_instruction;
\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
1071 operand_address = current_address + 1;
\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
1078 operand_address = next_operand_address;
\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
1086 operand_address = next_operand_address;
\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
1095 current_address = next_operand_address;
\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
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
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
1110 if ( (byte_copy_left + multy_offset) > ( ref_destination )){
\r
1112 position = byte_copy_right - ( multy_offset - ( ref_destination - byte_copy_left ));
\r
1114 position = ref_destination - multy_offset;
\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
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
1128 * 8.4. Byte copying
\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
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
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
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
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
1169 k = ( k + 1 ) & 0xffff;
\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
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
1185 operand_address = current_address + 1;
\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
1193 operand_address = next_operand_address;
\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
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
1208 operand_address = next_operand_address;
\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
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
1221 * Seq[n] := (start_value + n * offset) modulo 256
\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
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
1243 k = ( k + 1 ) & 0xffff;
\r
1246 used_udvm_cycles = used_udvm_cycles + 1 + length;
\r
1247 goto execute_next_instruction;
\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
1257 operand_address = current_address + 1;
\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
1265 current_address = at_address;
\r
1266 used_udvm_cycles++;
\r
1267 goto execute_next_instruction;
\r
1270 case SIGCOMP_INSTR_COMPARE: /* 23 */
\r
1271 /* COMPARE (%value_1, %value_2, @address_1, @address_2, @address_3)
\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
1278 operand_address = current_address + 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
1286 operand_address = next_operand_address;
\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
1294 operand_address = next_operand_address;
\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
1304 operand_address = next_operand_address;
\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
1315 operand_address = next_operand_address;
\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
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
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
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
1347 operand_address = current_address + 1;
\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
1356 used_udvm_cycles++;
\r
1357 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Execution of this instruction is NOT implemented");
\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
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
1371 case SIGCOMP_INSTR_SWITCH: /* 26 SWITCH (#n, %j, @address_0, @address_1, ... , @address_n-1) */
\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
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
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
1386 operand_address = current_address + 1;
\r
1388 * Number of addresses in the instruction
\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
1395 operand_address = next_operand_address;
\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
1402 operand_address = next_operand_address;
\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
1414 current_address = at_address_1;
\r
1416 operand_address = next_operand_address;
\r
1419 /* Check decompression failure */
\r
1420 if ( ( j == n ) || ( j > n )){
\r
1422 goto decompression_failure;
\r
1424 if ( current_address > UDVM_MEMORY_SIZE ){
\r
1426 goto decompression_failure;
\r
1428 used_udvm_cycles = used_udvm_cycles + 1 + n;
\r
1430 goto execute_next_instruction;
\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
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
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
1451 operand_address = next_operand_address;
\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
1459 operand_address = next_operand_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
1468 /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
\r
1469 used_udvm_cycles = used_udvm_cycles + 1 + length;
\r
1471 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Execution of this instruction is NOT implemented");
\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
1480 operand_address = current_address + 1;
\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
1487 operand_address = next_operand_address;
\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
1495 operand_address = next_operand_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
1505 /* execute the instruction TODO insert checks
\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
1519 * Figure 7: Memory addresses of the UDVM registers
\r
1521 * 8.4. Byte copying
\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
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
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
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
1545 goto execute_next_instruction;
\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
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
1557 octet = tvb_get_guint8(message_tvb, input_address);
\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
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
1571 k = ( k + 1 ) & 0xffff;
\r
1574 used_udvm_cycles = used_udvm_cycles + 1 + length;
\r
1575 current_address = next_operand_address;
\r
1576 goto execute_next_instruction;
\r
1578 case SIGCOMP_INSTR_INPUT_BITS:/* 29 INPUT-BITS (%length, %destination, @address) */
\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
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
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
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
1599 operand_address = current_address + 1;
\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
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
1614 operand_address = next_operand_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
1623 current_address = next_operand_address;
\r
1626 * Execute actual instr.
\r
1627 * The input_bit_order register contains the following three flags:
\r
1630 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
\r
1631 * | reserved |F|H|P| 68 - 69
\r
1632 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
\r
1634 input_bit_order = buff[68] << 8;
\r
1635 input_bit_order = input_bit_order | buff[69];
\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
1642 if ((input_address > ( msg_end -1)) && (remaining_bits == 0 )){
\r
1644 current_address = at_address;
\r
1645 goto execute_next_instruction;
\r
1648 if ( length > 16 ){
\r
1650 goto decompression_failure;
\r
1652 if ( input_bit_order > 7 ){
\r
1654 goto decompression_failure;
\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
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
1674 used_udvm_cycles = used_udvm_cycles + 1 + length;
\r
1675 goto execute_next_instruction;
\r
1677 case SIGCOMP_INSTR_INPUT_HUFFMAN: /* 30 */
\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
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
1688 operand_address = current_address + 1;
\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
1696 operand_address = next_operand_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
1705 operand_address = next_operand_address;
\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
1713 operand_address = next_operand_address;
\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
1719 * In all other cases, the behavior of the INPUT-HUFFMAN instruction is
\r
1722 * 1. Set j := 1 and set H := 0.
\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
1727 * 3. Set H := H * 2^bits_j + k.
\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
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
1737 * 6. Copy (H + uncompressed_j - lower_bound_j) modulo 2^16 to the
\r
1738 * memory address specified by the destination operand.
\r
1742 * The input_bit_order register contains the following three flags:
\r
1745 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
\r
1746 * | reserved |F|H|P| 68 - 69
\r
1747 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
\r
1749 * Transfer H bit to bit_order to tell decomp dispatcher which bit order to use
\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
1758 outside_huffman_boundaries = TRUE;
\r
1759 print_in_loop = print_level_1;
\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
1767 operand_address = next_operand_address;
\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
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
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
1789 operand_address = next_operand_address;
\r
1790 /* execute instruction */
\r
1791 if ( outside_huffman_boundaries ) {
\r
1793 * 3. Set H := H * 2^bits_j + k.
\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
1802 /* ldexp Returns x multiplied by 2 raised to the power of exponent.
\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
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
1817 if ( input_address > msg_end ){
\r
1818 current_address = at_address;
\r
1819 goto execute_next_instruction;
\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
1826 if ((H < lower_bound_n) || (H > upper_bound_n)){
\r
1827 outside_huffman_boundaries = TRUE;
\r
1829 outside_huffman_boundaries = FALSE;
\r
1830 print_in_loop = FALSE;
\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
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
1840 H = H + uncompressed_n - lower_bound_n;
\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
1857 if ( outside_huffman_boundaries ) {
\r
1859 goto decompression_failure;
\r
1862 current_address = next_operand_address;
\r
1863 used_udvm_cycles = used_udvm_cycles + 1 + n;
\r
1864 goto execute_next_instruction;
\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
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
1876 operand_address = current_address + 1;
\r
1879 * %partial_identifier_start
\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
1886 operand_address = next_operand_address;
\r
1889 * %partial_identifier_length
\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
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
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
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
1924 * %state_instruction
\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
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
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
1947 used_udvm_cycles = used_udvm_cycles + 1 + state_length;
\r
1948 goto execute_next_instruction;
\r
1950 case SIGCOMP_INSTR_STATE_CREATE: /* 32 */
\r
1952 * STATE-CREATE (%state_length, %state_address, %state_instruction,
\r
1953 * %minimum_access_length, %state_retention_priority)
\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
1960 operand_address = current_address + 1;
\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
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
1980 * %state_instruction
\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
1988 operand_address = next_operand_address;
\r
1990 * %minimum_access_length
\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
1998 operand_address = next_operand_address;
\r
2000 * %state_retention_priority
\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
2008 current_address = next_operand_address;
\r
2009 /* Execute the instruction
\r
2010 * TODO Implement the instruction
\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
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
2025 no_of_state_create++;
\r
2026 if ( no_of_state_create > 4 ){
\r
2028 goto decompression_failure;
\r
2030 if (( minimum_access_length < 6 ) || ( minimum_access_length > 20 )){
\r
2032 goto decompression_failure;
\r
2034 if ( state_retention_priority == 65535 ){
\r
2036 goto decompression_failure;
\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
2045 byte_copy_right = buff[66] << 8;
\r
2046 byte_copy_right = byte_copy_right | buff[67];
\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
2055 string[0]= buff[k];
\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
2062 k = ( k + 1 ) & 0xffff;
\r
2067 goto execute_next_instruction;
\r
2069 case SIGCOMP_INSTR_STATE_FREE: /* 33 */
\r
2071 * STATE-FREE (%partial_identifier_start, %partial_identifier_length)
\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
2078 operand_address = current_address + 1;
\r
2080 * %partial_identifier_start
\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
2087 operand_address = next_operand_address;
\r
2090 * %partial_identifier_length
\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
2098 current_address = next_operand_address;
\r
2100 /* Execute the instruction:
\r
2101 * TODO implement it
\r
2103 udvm_state_free(buff,p_id_start,p_id_length);
\r
2104 used_udvm_cycles++;
\r
2106 goto execute_next_instruction;
\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
2114 operand_address = current_address + 1;
\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
2123 operand_address = next_operand_address;
\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
2132 current_address = next_operand_address;
\r
2135 * Execute instruction
\r
2136 * 8.4. Byte copying
\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
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
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
2156 while ( n < output_length ){
\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
2167 out_buff[output_address] = buff[k];
\r
2168 string[0]= buff[k];
\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
2175 k = ( k + 1 ) & 0xffff;
\r
2176 output_address ++;
\r
2179 used_udvm_cycles = used_udvm_cycles + 1 + output_length;
\r
2180 goto execute_next_instruction;
\r
2182 case SIGCOMP_INSTR_END_MESSAGE: /* 35 */
\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
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
2194 operand_address = current_address + 1;
\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
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
2209 operand_address = next_operand_address;
\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
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
2229 * %state_instruction
\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
2237 operand_address = next_operand_address;
\r
2239 * %minimum_access_length
\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
2247 operand_address = next_operand_address;
\r
2250 * %state_retention_priority
\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
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
2263 goto decompression_failure;
\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
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
2272 /* Execute the instruction
\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
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
2298 k = state_address_buff[n];
\r
2299 for( x=0; x < state_length_buff[n]; x++)
\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
2306 sha1buff[8+x] = buff[k];
\r
2307 k = ( k + 1 ) & 0xffff;
\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
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
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
2333 tvb_set_free_cb( decomp_tvb, g_free );
\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
2338 proto_tree_add_text(udvm_tree, decomp_tvb, 0, -1,"SigComp message Decompressed");
\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
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
2353 decompression_failure:
\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
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
2370 * Figure 8: Bytecode for a literal (#) operand
\r
2374 decode_udvm_literal_operand(guint8 *buff,guint operand_address, guint16 *value)
\r
2379 guint offset = operand_address;
\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
2388 * 10nnnnnn nnnnnnnn N 0 - 16383
\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
2395 offset = offset + 2;
\r
2399 * 111000000 nnnnnnnn nnnnnnnn N 0 - 65535
\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
2407 offset = offset + 2;
\r
2412 * 0nnnnnnn N 0 - 127
\r
2414 operand = ( bytecode & 0x7f);
\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
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
2435 * Figure 9: Bytecode for a reference ($) operand
\r
2438 dissect_udvm_reference_operand(guint8 *buff,guint operand_address, guint16 *value,guint *result_dest)
\r
2442 guint offset = operand_address;
\r
2445 guint16 temp_data16;
\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
2453 * 10nnnnnn nnnnnnnn memory[2 * N] 0 - 65535
\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
2468 * 11000000 nnnnnnnn nnnnnnnn memory[N] 0 - 65535
\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
2482 * 0nnnnnnn memory[2 * N] 0 - 65535
\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
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
2511 decode_udvm_multitype_operand(guint8 *buff,guint operand_address, guint16 *value)
\r
2515 guint offset = operand_address;
\r
2519 guint16 temp_data16;
\r
2520 guint16 memmory_addr = 0;
\r
2522 bytecode = buff[operand_address];
\r
2523 test_bits = ( bytecode & 0xc0 ) >> 6;
\r
2524 switch (test_bits ){
\r
2527 * 00nnnnnn N 0 - 63
\r
2529 operand = buff[operand_address];
\r
2531 *g_warning("Reading 0x%x From address %u",operand,offset);
\r
2538 * 01nnnnnn memory[2 * N] 0 - 65535
\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
2547 /* Check tree most significant bits */
\r
2548 test_bits = ( bytecode & 0xe0 ) >> 5;
\r
2549 if ( test_bits == 5 ){
\r
2551 * 101nnnnn nnnnnnnn N 0 - 8191
\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
2558 offset = offset + 2;
\r
2560 test_bits = ( bytecode & 0xf0 ) >> 4;
\r
2561 if ( test_bits == 9 ){
\r
2563 * 1001nnnn nnnnnnnn N + 61440 61440 - 65535
\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
2571 offset = offset + 2;
\r
2573 test_bits = ( bytecode & 0x08 ) >> 3;
\r
2574 if ( test_bits == 1){
\r
2576 * 10001nnn 2 ^ (N + 8) 256 , ... , 32768
\r
2579 result = (guint32)pow(2,( buff[operand_address] & 0x07) + 8);
\r
2580 operand = result & 0xffff;
\r
2584 test_bits = ( bytecode & 0x0e ) >> 1;
\r
2585 if ( test_bits == 3 ){
\r
2587 * 1000 011n 2 ^ (N + 6) 64 , 128
\r
2589 result = (guint32)pow(2,( buff[operand_address] & 0x01) + 6);
\r
2590 operand = result & 0xffff;
\r
2595 * 1000 0000 nnnnnnnn nnnnnnnn N 0 - 65535
\r
2596 * 1000 0001 nnnnnnnn nnnnnnnn memory[N] 0 - 65535
\r
2599 temp_data16 = buff[operand_address + 1] << 8;
\r
2600 temp_data16 = temp_data16 | buff[operand_address + 2];
\r
2602 * g_warning("Reading 0x%x From address %u",temp_data16,operand_address);
\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
2609 *value = temp_data16;
\r
2610 offset = offset +2;
\r
2620 test_bits = ( bytecode & 0x20 ) >> 5;
\r
2621 if ( test_bits == 1 ){
\r
2623 * 111nnnnn N + 65504 65504 - 65535
\r
2625 operand = ( buff[operand_address] & 0x1f) + 65504;
\r
2630 * 110nnnnn nnnnnnnn memory[N] 0 - 65535
\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
2639 * g_warning("Reading 0x%x From address %u",temp_data16,memmory_addr);
\r
2641 offset = offset +2;
\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
2658 * operand_value = (memory_address_of_instruction + D) modulo 2^16
\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
2666 decode_udvm_address_operand(guint8 *buff,guint operand_address, guint16 *value,guint current_address)
\r
2670 guint next_opreand_address;
\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
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
2685 guint16 input_bit_order;
\r
2694 input_bit_order = buff[68] << 8;
\r
2695 input_bit_order = input_bit_order | buff[69];
\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
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
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
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
2724 * Do we hold a fraction of a byte ?
\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
2733 if ( *input_address > ( msg_end -1 ) ){
\r
2734 *result_code = 11;
\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
2743 *input_address = *input_address + 1;
\r
2745 if ( ( input_bit_order & 0x0001 ){
\r
2749 /* borrow value */
\r
2750 value = octet & 0x00ff;
\r
2751 value = value << ( 8 - (*remaining_bits));
\r
2752 *remaining_bits = *remaining_bits + 8;
\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
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
2768 value = value << ( 8 - (*remaining_bits));
\r
2769 *remaining_bits = *remaining_bits + 8;
\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
2777 *input_bits = *input_bits | value;
\r
2778 }/* Bits remain */
\r
2779 if ( ( bit_order ) == 0 ){
\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
2801 while ( i < length ){
\r
2802 value = value | (( *input_bits & 0x8000 ) >> n) ;
\r
2803 *input_bits = *input_bits << 1;
\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
2819 * Do we need one or two bytes ?
\r
2821 if ( *input_address > ( msg_end -1 ) ){
\r
2822 *result_code = 11;
\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
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
2838 if ( ( input_bit_order & 0x0001 ) == 0 ){
\r
2842 *input_bits = octet & 0xff;
\r
2843 *input_bits = *input_bits << 8;
\r
2844 *remaining_bits = 8;
\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
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
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
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
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
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
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
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
2899 if ( *input_address > ( msg_end - 1)){
\r
2900 *result_code = 11;
\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
2910 if ( ( input_bit_order & 0x0001 ) == 0 ){
\r
2914 *input_bits = *input_bits | octet;
\r
2915 *remaining_bits = 16;
\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
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
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
2935 *remaining_bits = 16;
\r
2939 if ( ( bit_order ) == 0 ){
\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
2961 while ( i < length ){
\r
2962 value = value | ( *input_bits & 0x8000 ) >> n ;
\r
2963 *input_bits = *input_bits << 1;
\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