2 * Routines making up the Universal Decompressor Virtual Machine (UDVM) used for
3 * Signaling Compression (SigComp) dissection.
4 * Copyright 2004, Anders Broman <anders.broman@ericsson.com>
8 * Ethereal - Network traffic analyzer
9 * By Gerald Combs <gerald@ethereal.com>
10 * Copyright 1998 Gerald Combs
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
26 * http://www.ietf.org/rfc/rfc3320.txt?number=3320
27 * http://www.ietf.org/rfc/rfc3321.txt?number=3321
29 * http://www.ietf.org/internet-drafts/draft-ietf-rohc-sigcomp-impl-guide-05.txt
30 * http://www.ietf.org/internet-drafts/draft-ietf-rohc-sigcomp-sip-01.txt
44 #include "sigcomp-udvm.h"
45 #include "sigcomp_state_hdlr.h"
49 #define SIGCOMP_INSTR_DECOMPRESSION_FAILURE 0
50 #define SIGCOMP_INSTR_AND 1
51 #define SIGCOMP_INSTR_OR 2
52 #define SIGCOMP_INSTR_NOT 3
53 #define SIGCOMP_INSTR_LSHIFT 4
54 #define SIGCOMP_INSTR_RSHIFT 5
55 #define SIGCOMP_INSTR_ADD 6
56 #define SIGCOMP_INSTR_SUBTRACT 7
57 #define SIGCOMP_INSTR_MULTIPLY 8
58 #define SIGCOMP_INSTR_DIVIDE 9
59 #define SIGCOMP_INSTR_REMAINDER 10
60 #define SIGCOMP_INSTR_SORT_ASCENDING 11
61 #define SIGCOMP_INSTR_SORT_DESCENDING 12
62 #define SIGCOMP_INSTR_SHA_1 13
63 #define SIGCOMP_INSTR_LOAD 14
64 #define SIGCOMP_INSTR_MULTILOAD 15
65 #define SIGCOMP_INSTR_PUSH 16
66 #define SIGCOMP_INSTR_POP 17
67 #define SIGCOMP_INSTR_COPY 18
68 #define SIGCOMP_INSTR_COPY_LITERAL 19
69 #define SIGCOMP_INSTR_COPY_OFFSET 20
70 #define SIGCOMP_INSTR_MEMSET 21
71 #define SIGCOMP_INSTR_JUMP 22
72 #define SIGCOMP_INSTR_COMPARE 23
73 #define SIGCOMP_INSTR_CALL 24
74 #define SIGCOMP_INSTR_RETURN 25
75 #define SIGCOMP_INSTR_SWITCH 26
76 #define SIGCOMP_INSTR_CRC 27
77 #define SIGCOMP_INSTR_INPUT_BYTES 28
78 #define SIGCOMP_INSTR_INPUT_BITS 29
79 #define SIGCOMP_INSTR_INPUT_HUFFMAN 30
80 #define SIGCOMP_INSTR_STATE_ACCESS 31
81 #define SIGCOMP_INSTR_STATE_CREATE 32
82 #define SIGCOMP_INSTR_STATE_FREE 33
83 #define SIGCOMP_INSTR_OUTPUT 34
84 #define SIGCOMP_INSTR_END_MESSAGE 35
87 static gboolean print_level_1;
88 static gboolean print_level_2;
89 static gboolean print_level_3;
90 static gint show_instr_detail_level;
92 /* Internal result code values of decompression failures */
93 const value_string result_code_vals[] = {
94 { 0, "No decomprssion failure" },
95 { 1, "Partial state length less than 6 or greater than 20 bytes long" },
96 { 2, "No state match" },
97 { 3, "state_begin + state_length > size of state" },
98 { 4, "Operand_2 is Zero" },
99 { 5, "Switch statement failed j >= n" },
100 { 6, "Atempt to jump outside of UDVM memory" },
101 { 7, "L in input-bits > 16" },
102 { 8, "input_bit_order > 7" },
103 { 9, "Instruction Decompression failure encountered" },
104 {10, "Input huffman failed j > n" },
105 {11, "Input bits requested beyond end of message" },
106 {12, "more than four state creation requests are made before the END-MESSAGE instruction" },
107 {13, "state_retention_priority is 65535" },
108 {14, "Input bytes requested beond end of message" },
109 {15, "Maximum number of UDVM cycles reached" },
110 {16, "UDVM stack underflow" },
111 { 255, "This branch isn't coded yet" },
115 static int decode_udvm_literal_operand(guint8 *buff,guint operand_address, guint16 *value);
116 static int dissect_udvm_reference_operand(guint8 *buff,guint operand_address, guint16 *value, guint *result_dest);
117 static int decode_udvm_multitype_operand(guint8 *buff,guint operand_address,guint16 *value);
118 static int decode_udvm_address_operand(guint8 *buff,guint operand_address, guint16 *value,guint current_address);
119 static int decomp_dispatch_get_bits(tvbuff_t *message_tvb,proto_tree *udvm_tree,guint8 bit_order,
120 guint8 *buff,guint16 *old_input_bit_order, guint16 *remaining_bits,
121 guint16 *input_bits, guint *input_address, guint16 length, guint16 *result_code,guint msg_end);
125 decompress_sigcomp_message(tvbuff_t *bytecode_tvb, tvbuff_t *message_tvb, packet_info *pinfo,
126 proto_tree *udvm_tree, gint udvm_mem_dest,
127 gint print_flags, gint hf_id,
129 gint byte_code_state_len, gint byte_code_id_len,
132 tvbuff_t *decomp_tvb;
133 guint8 buff[UDVM_MEMORY_SIZE];
134 char string[2],*strp;
135 guint8 *out_buff; /* Largest allowed size for a message is 65535 */
145 guint code_length =0;
146 guint8 current_instruction;
147 guint current_address;
148 guint operand_address;
150 guint16 output_address = 0;
151 guint next_operand_address;
155 guint16 byte_copy_right;
156 guint16 byte_copy_left;
157 guint16 input_bit_order;
158 guint16 stack_location;
161 guint msg_end = tvb_reported_length_remaining(message_tvb, 0);
162 guint16 result_code = 0;
163 guint16 old_input_bit_order = 0;
164 guint16 remaining_bits = 0;
165 guint16 input_bits = 0;
166 guint8 bit_order = 0;
167 gboolean outside_huffman_boundaries = TRUE;
168 gboolean print_in_loop = FALSE;
169 guint16 instruction_address;
170 guint8 no_of_state_create = 0;
171 guint16 state_length_buff[5];
172 guint16 state_address_buff[5];
173 guint16 state_instruction_buff[5];
174 guint16 state_minimum_access_length_buff[5];
175 guint16 state_state_retention_priority_buff[5];
176 guint32 used_udvm_cycles = 0;
177 guint cycles_per_bit;
178 guint maximum_UDVM_cycles;
180 unsigned char sha1_digest_buf[20];
184 /* UDVM operand variables */
193 guint16 state_length;
194 guint16 state_address;
195 guint16 state_instruction;
200 guint16 at_address_1;
201 guint16 at_address_2;
202 guint16 at_address_3;
205 guint16 lower_bound_n;
206 guint16 upper_bound_n;
207 guint16 uncompressed_n;
209 guint16 ref_destination; /* could I have used $destination ? */
210 guint16 multy_offset;
211 guint16 output_start;
212 guint16 output_length;
213 guint16 minimum_access_length;
214 guint16 state_retention_priority;
215 guint16 requested_feedback_location;
216 guint16 returned_parameters_location;
220 /* Set print parameters */
221 print_level_1 = FALSE;
222 print_level_2 = FALSE;
223 print_level_3 = FALSE;
224 show_instr_detail_level = 0;
228 switch( print_flags ) {
233 print_level_1 = TRUE;
234 show_instr_detail_level = 1;
237 print_level_1 = TRUE;
238 print_level_2 = TRUE;
239 show_instr_detail_level = 1;
242 print_level_1 = TRUE;
243 print_level_2 = TRUE;
244 print_level_3 = TRUE;
245 show_instr_detail_level = 2;
248 print_level_1 = TRUE;
249 show_instr_detail_level = 1;
257 /* UDVM memory must be initialised to zero */
258 while ( i < UDVM_MEMORY_SIZE ) {
262 /* Set initial UDVM data
263 * The first 32 bytes of UDVM memory are then initialized to special
264 * values as illustrated in Figure 5.
267 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
268 * | UDVM_memory_size | 0 - 1
269 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
270 * | cycles_per_bit | 2 - 3
271 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
272 * | SigComp_version | 4 - 5
273 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
274 * | partial_state_ID_length | 6 - 7
275 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
276 * | state_length | 8 - 9
277 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
279 * : reserved : 10 - 31
281 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
283 * Figure 5: Initializing Useful Values in UDVM memory
285 /* UDVM_memory_size */
286 buff[0] = (UDVM_MEMORY_SIZE >> 8) & 0x00FF;
287 buff[1] = UDVM_MEMORY_SIZE & 0x00FF;
291 /* SigComp_version */
294 /* partial_state_ID_length */
295 buff[6] = (byte_code_id_len >> 8) & 0x00FF;
296 buff[7] = byte_code_id_len & 0x00FF;
298 buff[8] = (byte_code_state_len >> 8) & 0x00FF;
299 buff[9] = byte_code_state_len & 0x00FF;
301 code_length = tvb_reported_length_remaining(bytecode_tvb, 0);
303 cycles_per_bit = buff[2] << 8;
304 cycles_per_bit = cycles_per_bit | buff[3];
306 * maximum_UDVM_cycles = (8 * n + 1000) * cycles_per_bit
308 maximum_UDVM_cycles = (( 8 * (header_len + msg_end) ) + 1000) * cycles_per_bit;
310 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);
311 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);
313 /* Load bytecode into UDVM starting at "udvm_mem_dest" */
316 proto_tree_add_text(udvm_tree, bytecode_tvb, offset, 1,"Load bytecode into UDVM starting at %u",i);
317 while ( code_length > offset ) {
318 buff[i] = tvb_get_guint8(bytecode_tvb, offset);
320 proto_tree_add_text(udvm_tree, bytecode_tvb, offset, 1,
321 " Addr: %u Instruction code(0x%0x) ", i, buff[i]);
327 /* Largest allowed size for a message is 65535 */
328 out_buff = g_malloc(65535);
329 /* Start executing code */
330 current_address = udvm_start_ip;
334 proto_tree_add_text(udvm_tree, bytecode_tvb, offset, 1,"UDVM EXECUTION STARTED at Address: %u Message size %u",
335 current_address, msg_end);
337 execute_next_instruction:
339 if ( used_udvm_cycles > maximum_UDVM_cycles ){
341 goto decompression_failure;
343 current_instruction = buff[current_address];
345 switch ( current_instruction ) {
346 case SIGCOMP_INSTR_DECOMPRESSION_FAILURE:
348 if ( result_code == 0 )
350 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
351 "Addr: %u ## DECOMPRESSION-FAILURE(0)",
353 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Ethereal UDVM diagnostic: %s.",
354 val_to_str(result_code, result_code_vals,"Unknown (%u)"));
355 if ( output_address > 0 ){
356 /* At least something got decompressed, show it */
357 decomp_tvb = tvb_new_real_data(out_buff,output_address,output_address);
358 /* Arrange that the allocated packet data copy be freed when the
361 tvb_set_free_cb( decomp_tvb, g_free );
362 /* Add the tvbuff to the list of tvbuffs to which the tvbuff we
363 * were handed refers, so it'll get cleaned up when that tvbuff
366 tvb_set_child_real_data_tvbuff(message_tvb,decomp_tvb);
367 add_new_data_source(pinfo, decomp_tvb, "Decompressed SigComp message(Incomplete)");
368 proto_tree_add_text(udvm_tree, decomp_tvb, 0, -1,"SigComp message Decompression failure");
375 case SIGCOMP_INSTR_AND: /* 1 AND ($operand_1, %operand_2) */
377 if (show_instr_detail_level == 2 ){
378 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
379 "Addr: %u ## AND(1) (operand_1, operand_2)",
383 operand_address = current_address + 1;
384 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &operand_1, &result_dest);
385 if (show_instr_detail_level == 2 ){
386 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_1 %u",
387 operand_address, operand_1);
389 operand_address = next_operand_address;
391 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &operand_2);
392 if (show_instr_detail_level == 2 ){
393 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_2 %u",
394 operand_address, operand_2);
396 if (show_instr_detail_level == 1)
398 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
399 "Addr: %u ## AND (operand_1=%u, operand_2=%u)",
400 current_address, operand_1, operand_2);
402 /* execute the instruction */
403 result = operand_1 & operand_2;
406 buff[result_dest] = msb;
407 buff[result_dest+1] = lsb;
409 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," Loading result %u at %u",
410 result, result_dest);
412 current_address = next_operand_address;
413 goto execute_next_instruction;
417 case SIGCOMP_INSTR_OR: /* 2 OR ($operand_1, %operand_2) */
419 if (show_instr_detail_level == 2 ){
420 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
421 "Addr: %u ## OR(2) (operand_1, operand_2)",
425 operand_address = current_address + 1;
426 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &operand_1, &result_dest);
427 if (show_instr_detail_level == 2 ){
428 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_1 %u",
429 operand_address, operand_1);
431 operand_address = next_operand_address;
433 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &operand_2);
434 if (show_instr_detail_level == 2 ){
435 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_2 %u",
436 operand_address, operand_2);
438 if (show_instr_detail_level == 1)
440 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
441 "Addr: %u ## OR (operand_1=%u, operand_2=%u)",
442 current_address, operand_1, operand_2);
444 /* execute the instruction */
445 result = operand_1 | operand_2;
448 buff[result_dest] = msb;
449 buff[result_dest+1] = lsb;
451 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," Loading result %u at %u",
452 result, result_dest);
454 current_address = next_operand_address;
455 goto execute_next_instruction;
459 case SIGCOMP_INSTR_NOT: /* 3 NOT ($operand_1) */
461 if (show_instr_detail_level == 2 ){
462 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
463 "Addr: %u ## NOT(3) ($operand_1)",
467 operand_address = current_address + 1;
468 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &operand_1, &result_dest);
469 if (show_instr_detail_level == 2 ){
470 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_1 %u",
471 operand_address, operand_1);
473 if (show_instr_detail_level == 1)
475 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
476 "Addr: %u ## NOT (operand_1=%u)",
477 current_address, operand_1);
479 /* execute the instruction */
480 result = operand_1 ^ 0xffff;
483 buff[result_dest] = msb;
484 buff[result_dest+1] = lsb;
486 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," Loading result %u at %u",
487 result, result_dest);
489 current_address = next_operand_address;
490 goto execute_next_instruction;
493 case SIGCOMP_INSTR_LSHIFT: /* 4 LSHIFT ($operand_1, %operand_2) */
495 if (show_instr_detail_level == 2 ){
496 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
497 "Addr: %u ## LSHIFT(4) ($operand_1, operand_2)",
501 operand_address = current_address + 1;
502 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &operand_1, &result_dest);
503 if (show_instr_detail_level == 2 ){
504 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_1 %u",
505 operand_address, operand_1);
507 operand_address = next_operand_address;
509 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &operand_2);
510 if (show_instr_detail_level == 2 ){
511 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_2 %u",
512 operand_address, operand_2);
514 if (show_instr_detail_level == 1)
516 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
517 "Addr: %u ## LSHIFT (operand_1=%u, operand_2=%u)",
518 current_address, operand_1, operand_2);
520 /* execute the instruction */
521 result = operand_1 << operand_2;
524 buff[result_dest] = msb;
525 buff[result_dest+1] = lsb;
527 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," Loading result %u at %u",
528 result, result_dest);
530 current_address = next_operand_address;
531 goto execute_next_instruction;
534 case SIGCOMP_INSTR_RSHIFT: /* 5 RSHIFT ($operand_1, %operand_2) */
536 if (show_instr_detail_level == 2 ){
537 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
538 "Addr: %u ## RSHIFT(5) (operand_1, operand_2)",
542 operand_address = current_address + 1;
543 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &operand_1, &result_dest);
544 if (show_instr_detail_level == 2 ){
545 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_1 %u",
546 operand_address, operand_1);
548 operand_address = next_operand_address;
550 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &operand_2);
551 if (show_instr_detail_level == 2 ){
552 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_2 %u",
553 operand_address, operand_2);
555 if (show_instr_detail_level == 1)
557 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
558 "Addr: %u ## RSHIFT (operand_1=%u, operand_2=%u)",
559 current_address, operand_1, operand_2);
561 /* execute the instruction */
562 result = operand_1 >> operand_2;
565 buff[result_dest] = msb;
566 buff[result_dest+1] = lsb;
568 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," Loading result %u at %u",
569 result, result_dest);
571 current_address = next_operand_address;
572 goto execute_next_instruction;
574 case SIGCOMP_INSTR_ADD: /* 6 ADD ($operand_1, %operand_2) */
576 if (show_instr_detail_level == 2 ){
577 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
578 "Addr: %u ## ADD(6) (operand_1, operand_2)",
582 operand_address = current_address + 1;
583 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &operand_1, &result_dest);
584 if (show_instr_detail_level == 2 ){
585 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_1 %u",
586 operand_address, operand_1);
588 operand_address = next_operand_address;
590 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &operand_2);
591 if (show_instr_detail_level == 2 ){
592 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_2 %u",
593 operand_address, operand_2);
595 if (show_instr_detail_level == 1)
597 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
598 "Addr: %u ## ADD (operand_1=%u, operand_2=%u)",
599 current_address, operand_1, operand_2);
601 /* execute the instruction */
602 result = operand_1 + operand_2;
605 buff[result_dest] = msb;
606 buff[result_dest+1] = lsb;
608 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," Loading result %u at %u",
609 result, result_dest);
611 current_address = next_operand_address;
612 goto execute_next_instruction;
614 case SIGCOMP_INSTR_SUBTRACT: /* 7 SUBTRACT ($operand_1, %operand_2) */
616 if (show_instr_detail_level == 2 ){
617 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
618 "Addr: %u ## SUBTRACT(7) (operand_1, operand_2)",
622 operand_address = current_address + 1;
623 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &operand_1, &result_dest);
624 if (show_instr_detail_level == 2 ){
625 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_1 %u",
626 operand_address, operand_1);
628 operand_address = next_operand_address;
630 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &operand_2);
631 if (show_instr_detail_level == 2 ){
632 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_2 %u",
633 operand_address, operand_2);
635 if (show_instr_detail_level == 1)
637 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
638 "Addr: %u ## SUBTRACT (operand_1=%u, operand_2=%u)",
639 current_address, operand_1, operand_2);
641 /* execute the instruction */
642 result = operand_1 - operand_2;
645 buff[result_dest] = msb;
646 buff[result_dest+1] = lsb;
648 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," Loading result %u at %u",
649 result, result_dest);
651 current_address = next_operand_address;
652 goto execute_next_instruction;
655 case SIGCOMP_INSTR_MULTIPLY: /* 8 MULTIPLY ($operand_1, %operand_2) */
657 if (show_instr_detail_level == 2 ){
658 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
659 "Addr: %u ##MULTIPLY(8) (operand_1, operand_2)",
663 operand_address = current_address + 1;
664 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &operand_1, &result_dest);
665 if (show_instr_detail_level == 2 ){
666 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_1 %u",
667 operand_address, operand_1);
669 operand_address = next_operand_address;
671 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &operand_2);
672 if (show_instr_detail_level == 2 ){
673 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_2 %u",
674 operand_address, operand_2);
676 if (show_instr_detail_level == 1)
678 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
679 "Addr: %u ## MULTIPLY (operand_1=%u, operand_2=%u)",
680 current_address, operand_1, operand_2);
683 * execute the instruction
684 * MULTIPLY (m, n) := m * n (modulo 2^16)
686 if ( operand_2 == 0){
688 goto decompression_failure;
690 result = operand_1 * operand_2;
693 buff[result_dest] = msb;
694 buff[result_dest+1] = lsb;
696 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," Loading result %u at %u",
697 result, result_dest);
699 current_address = next_operand_address;
700 goto execute_next_instruction;
703 case SIGCOMP_INSTR_DIVIDE: /* 9 DIVIDE ($operand_1, %operand_2) */
705 if (show_instr_detail_level == 2 ){
706 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
707 "Addr: %u ## DIVIDE(9) (operand_1, operand_2)",
711 operand_address = current_address + 1;
712 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &operand_1, &result_dest);
713 if (show_instr_detail_level == 2 ){
714 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_1 %u",
715 operand_address, operand_1);
717 operand_address = next_operand_address;
719 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &operand_2);
720 if (show_instr_detail_level == 2 ){
721 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_2 %u",
722 operand_address, operand_2);
724 if (show_instr_detail_level == 1)
726 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
727 "Addr: %u ## DIVIDE (operand_1=%u, operand_2=%u)",
728 current_address, operand_1, operand_2);
731 * execute the instruction
732 * DIVIDE (m, n) := floor(m / n)
733 * Decompression failure occurs if a DIVIDE or REMAINDER instruction
734 * encounters an operand_2 that is zero.
736 if ( operand_2 == 0){
738 goto decompression_failure;
740 result = operand_1 / operand_2;
743 buff[result_dest] = msb;
744 buff[result_dest+1] = lsb;
746 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," Loading result %u at %u",
747 result, result_dest);
749 current_address = next_operand_address;
750 goto execute_next_instruction;
753 case SIGCOMP_INSTR_REMAINDER: /* 10 REMAINDER ($operand_1, %operand_2) */
755 if (show_instr_detail_level == 2 ){
756 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
757 "Addr: %u ## REMAINDER(10) (operand_1, operand_2)",
761 operand_address = current_address + 1;
762 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &operand_1, &result_dest);
763 if (show_instr_detail_level == 2 ){
764 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_1 %u",
765 operand_address, operand_1);
767 operand_address = next_operand_address;
769 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &operand_2);
770 if (show_instr_detail_level == 2 ){
771 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_2 %u",
772 operand_address, operand_2);
774 if (show_instr_detail_level == 1)
776 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
777 "Addr: %u ## REMAINDER (operand_1=%u, operand_2=%u)",
778 current_address, operand_1, operand_2);
781 * execute the instruction
782 * REMAINDER (m, n) := m - n * floor(m / n)
783 * Decompression failure occurs if a DIVIDE or REMAINDER instruction
784 * encounters an operand_2 that is zero.
786 if ( operand_2 == 0){
788 goto decompression_failure;
790 result = operand_1 - operand_2 * (operand_1 / operand_2);
793 buff[result_dest] = msb;
794 buff[result_dest+1] = lsb;
796 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," Loading result %u at %u",
797 result, result_dest);
799 current_address = next_operand_address;
800 goto execute_next_instruction;
802 case SIGCOMP_INSTR_SORT_ASCENDING: /* 11 SORT-ASCENDING (%start, %n, %k) */
804 * used_udvm_cycles = 1 + k * (ceiling(log2(k)) + n)
807 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
808 "Addr: %u ## SORT-ASCENDING(11) (start, n, k))",
811 operand_address = current_address + 1;
812 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Execution of this instruction is NOT implemented");
814 * used_udvm_cycles = 1 + k * (ceiling(log2(k)) + n)
818 case SIGCOMP_INSTR_SORT_DESCENDING: /* 12 SORT-DESCENDING (%start, %n, %k) */
820 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
821 "Addr: %u ## SORT-DESCENDING(12) (start, n, k))",
824 operand_address = current_address + 1;
825 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Execution of this instruction is NOT implemented");
827 * used_udvm_cycles = 1 + k * (ceiling(log2(k)) + n)
830 case SIGCOMP_INSTR_SHA_1: /* 13 SHA-1 (%position, %length, %destination) */
832 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
833 "Addr: %u ## SHA-1(13) (position, length, destination)",
836 operand_address = current_address + 1;
838 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &position);
840 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u position %u",
841 operand_address, position);
843 operand_address = next_operand_address;
846 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &length);
848 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Length %u",
849 operand_address, length);
851 operand_address = next_operand_address;
854 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &ref_destination, &result_dest);
856 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u $destination %u",
857 operand_address, ref_destination);
859 current_address = next_operand_address;
860 used_udvm_cycles = used_udvm_cycles + 1 + length;
864 byte_copy_right = buff[66] << 8;
865 byte_copy_right = byte_copy_right | buff[67];
866 byte_copy_left = buff[64] << 8;
867 byte_copy_left = byte_copy_left | buff[65];
870 proto_tree_add_text(udvm_tree, message_tvb, 0, -1,
871 "byte_copy_right = %u", byte_copy_right);
877 guint16 handle_now = length;
879 if ( k < byte_copy_right && byte_copy_right <= k + (length-n) ){
880 handle_now = byte_copy_right - position;
883 sha1_update( &ctx, &buff[k], handle_now );
885 k = ( k + handle_now ) & 0xffff;
886 n = ( n + handle_now ) & 0xffff;
888 if ( k >= byte_copy_right ) {
893 sha1_finish( &ctx, sha1_digest_buf );
897 for ( n=0; n<20; n++ ) {
899 buff[k] = sha1_digest_buf[n];
901 k = ( k + 1 ) & 0xffff;
904 if ( k == byte_copy_right ){
910 proto_tree_add_text(udvm_tree, message_tvb, 0, -1,
911 "Calculated SHA-1: %s",
912 bytes_to_str(sha1_digest_buf, 20));
915 current_address = next_operand_address;
916 goto execute_next_instruction;
919 case SIGCOMP_INSTR_LOAD: /* 14 LOAD (%address, %value) */
920 if (show_instr_detail_level == 2 ){
921 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
922 "Addr: %u ## LOAD(14) (%%address, %%value)",
925 operand_address = current_address + 1;
927 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &address);
928 if (show_instr_detail_level == 2 ){
929 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Address %u",
930 operand_address, address);
932 operand_address = next_operand_address;
934 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &value);
935 if (show_instr_detail_level == 1)
937 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
938 "Addr: %u ## LOAD (%%address=%u, %%value=%u)",
939 current_address, address, value);
945 buff[address + 1] = lsb;
948 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Value %u",
949 operand_address, value);
950 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," Loading bytes at %u Value %u 0x%x",
951 address, value, value);
954 current_address = next_operand_address;
955 goto execute_next_instruction;
958 case SIGCOMP_INSTR_MULTILOAD: /* 15 MULTILOAD (%address, #n, %value_0, ..., %value_n-1) */
960 * The MULTILOAD instruction sets a contiguous block of 2-byte words in
961 * the UDVM memory to specified values.
962 * Hmm what if the value to load only takes one byte ? Chose to always load two bytes.
964 if (show_instr_detail_level == 2 ){
965 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
966 "Addr: %u ## MULTILOAD(15) (%%address, #n, value_0, ..., value_n-1)",
969 operand_address = current_address + 1;
971 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &address);
972 if (show_instr_detail_level == 2 ){
973 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Address %u",
974 operand_address, address);
976 operand_address = next_operand_address;
979 next_operand_address = decode_udvm_literal_operand(buff,operand_address, &n);
980 if (show_instr_detail_level == 2 ){
981 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u n %u",
984 if (show_instr_detail_level == 1)
986 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
987 "Addr: %u ## MULTILOAD (%%address=%u, #n=%u, value_0, ..., value_%d)",
988 current_address, address, n, n-1);
990 operand_address = next_operand_address;
991 used_udvm_cycles = used_udvm_cycles + 1 + n;
995 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &value);
1000 buff[address + 1] = lsb;
1003 length = next_operand_address - operand_address;
1005 if (print_level_1 ){
1006 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1, "Addr: %u Value %5u - Loading bytes at %5u Value %5u 0x%x",
1007 operand_address, value, address, value, value);
1009 address = address + 2;
1010 operand_address = next_operand_address;
1012 current_address = next_operand_address;
1013 goto execute_next_instruction;
1017 case SIGCOMP_INSTR_PUSH: /* 16 PUSH (%value) */
1018 if (show_instr_detail_level == 2){
1019 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1020 "Addr: %u ## PUSH(16) (value)",
1023 operand_address = current_address + 1;
1025 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &value);
1026 if (show_instr_detail_level == 2){
1027 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Value %u",
1028 operand_address, value);
1030 if (show_instr_detail_level == 1)
1032 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1033 "Addr: %u ## PUSH (value=%u)",
1034 current_address, value);
1036 current_address = next_operand_address;
1038 /* Push the value address onto the stack */
1039 stack_location = (buff[70] << 8) | buff[71];
1040 stack_fill = (buff[stack_location] << 8)
1041 | buff[(stack_location+1) & 0xFFFF];
1042 address = (stack_location + stack_fill * 2 + 2) & 0xFFFF;
1044 buff[address] = (value >> 8) & 0x00FF;
1045 buff[(address+1) & 0xFFFF] = value & 0x00FF;
1047 stack_fill = (stack_fill + 1) & 0xFFFF;
1048 buff[stack_location] = (stack_fill >> 8) & 0x00FF;
1049 buff[(stack_location+1) & 0xFFFF] = stack_fill & 0x00FF;
1052 goto execute_next_instruction;
1056 case SIGCOMP_INSTR_POP: /* 17 POP (%address) */
1057 if (show_instr_detail_level == 2){
1058 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1059 "Addr: %u ## POP(16) (value)",
1062 operand_address = current_address + 1;
1064 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &destination);
1065 if (show_instr_detail_level == 2){
1066 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Value %u",
1067 operand_address, destination);
1069 if (show_instr_detail_level == 1)
1071 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1072 "Addr: %u ## POP (address=%u)",
1073 current_address, destination);
1075 current_address = next_operand_address;
1077 /* Pop value from the top of the stack */
1078 stack_location = (buff[70] << 8) | buff[71];
1079 stack_fill = (buff[stack_location] << 8)
1080 | buff[(stack_location+1) & 0xFFFF];
1081 if (stack_fill == 0)
1084 goto decompression_failure;
1087 stack_fill = (stack_fill - 1) & 0xFFFF;
1088 buff[stack_location] = (stack_fill >> 8) & 0x00FF;
1089 buff[(stack_location+1) & 0xFFFF] = stack_fill & 0x00FF;
1091 address = (stack_location + stack_fill * 2 + 2) & 0xFFFF;
1092 value = (buff[address] << 8)
1093 | buff[(address+1) & 0xFFFF];
1095 /* ... and store the popped value. */
1096 buff[destination] = (value >> 8) & 0x00FF;
1097 buff[(destination+1) & 0xFFFF] = value & 0x00FF;
1100 goto execute_next_instruction;
1104 case SIGCOMP_INSTR_COPY: /* 18 COPY (%position, %length, %destination) */
1105 if (show_instr_detail_level == 2 ){
1106 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1107 "Addr: %u ## COPY(18) (position, length, destination)",
1110 operand_address = current_address + 1;
1112 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &position);
1113 if (show_instr_detail_level == 2 ){
1114 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u position %u",
1115 operand_address, position);
1117 operand_address = next_operand_address;
1120 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &length);
1121 if (show_instr_detail_level == 2 ){
1122 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Length %u",
1123 operand_address, length);
1125 operand_address = next_operand_address;
1128 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &destination);
1129 if (show_instr_detail_level == 2 ){
1130 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Destination %u",
1131 operand_address, destination);
1133 if (show_instr_detail_level == 1)
1135 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1136 "Addr: %u ## COPY (position=%u, length=%u, destination=%u)",
1137 current_address, position, length, destination);
1139 current_address = next_operand_address;
1143 * The string of bytes is copied in ascending order of memory address,
1144 * respecting the bounds set by byte_copy_left and byte_copy_right.
1145 * More precisely, if a byte is copied from/to Address m then the next
1146 * byte is copied from/to Address n where n is calculated as follows:
1148 * Set k := m + 1 (modulo 2^16)
1149 * If k = byte_copy_right then set n := byte_copy_left, else set n := k
1155 byte_copy_right = buff[66] << 8;
1156 byte_copy_right = byte_copy_right | buff[67];
1157 byte_copy_left = buff[64] << 8;
1158 byte_copy_left = byte_copy_left | buff[65];
1159 if (print_level_2 ){
1160 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
1161 " byte_copy_right = %u", byte_copy_right);
1164 while ( n < length ){
1165 buff[k] = buff[position];
1166 if (print_level_2 ){
1167 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
1168 " Copying value: %u (0x%x) to Addr: %u",
1169 buff[position], buff[position], k);
1171 position = ( position + 1 ) & 0xffff;
1172 k = ( k + 1 ) & 0xffff;
1176 * Check for circular buffer wrapping after the positions are
1177 * incremented. If either started at BCR then they should continue
1178 * to increment beyond BCR.
1180 if ( k == byte_copy_right ){
1183 if ( position == byte_copy_right ){
1184 position = byte_copy_left;
1187 used_udvm_cycles = used_udvm_cycles + 1 + length;
1188 goto execute_next_instruction;
1191 case SIGCOMP_INSTR_COPY_LITERAL: /* 19 COPY-LITERAL (%position, %length, $destination) */
1192 if (show_instr_detail_level == 2 ){
1193 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1194 "Addr: %u ## COPY-LITERAL(19) (position, length, $destination)",
1197 operand_address = current_address + 1;
1199 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &position);
1200 if (show_instr_detail_level == 2 ){
1201 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u position %u",
1202 operand_address, position);
1204 operand_address = next_operand_address;
1207 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &length);
1208 if (show_instr_detail_level == 2 ){
1209 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Length %u",
1210 operand_address, length);
1212 operand_address = next_operand_address;
1216 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &ref_destination, &result_dest);
1217 if (show_instr_detail_level == 2 ){
1218 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u destination %u",
1219 operand_address, ref_destination);
1221 if (show_instr_detail_level == 1)
1223 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1224 "Addr: %u ## COPY-LITERAL (position=%u, length=%u, $destination=%u)",
1225 current_address, position, length, destination);
1227 current_address = next_operand_address;
1233 * The string of bytes is copied in ascending order of memory address,
1234 * respecting the bounds set by byte_copy_left and byte_copy_right.
1235 * More precisely, if a byte is copied from/to Address m then the next
1236 * byte is copied from/to Address n where n is calculated as follows:
1238 * Set k := m + 1 (modulo 2^16)
1239 * If k = byte_copy_right then set n := byte_copy_left, else set n := k
1244 k = ref_destination;
1245 byte_copy_right = buff[66] << 8;
1246 byte_copy_right = byte_copy_right | buff[67];
1247 byte_copy_left = buff[64] << 8;
1248 byte_copy_left = byte_copy_left | buff[65];
1249 if (print_level_2 ){
1250 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
1251 " byte_copy_right = %u", byte_copy_right);
1253 while ( n < length ){
1255 buff[k] = buff[position];
1256 if (print_level_2 ){
1257 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
1258 " Copying value: %u (0x%x) to Addr: %u",
1259 buff[position], buff[position], k);
1261 position = ( position + 1 ) & 0xffff;
1262 k = ( k + 1 ) & 0xffff;
1266 * Check for circular buffer wrapping after the positions are
1267 * incremented. It is important that k cannot be left set
1268 * to BCR. Also, if either started at BCR then they should continue
1269 * to increment beyond BCR.
1271 if ( k == byte_copy_right ){
1274 if ( position == byte_copy_right ){
1275 position = byte_copy_left;
1278 buff[result_dest] = k >> 8;
1279 buff[result_dest + 1] = k & 0x00ff;
1281 used_udvm_cycles = used_udvm_cycles + 1 + length;
1282 goto execute_next_instruction;
1285 case SIGCOMP_INSTR_COPY_OFFSET: /* 20 COPY-OFFSET (%offset, %length, $destination) */
1286 if (show_instr_detail_level == 2 ){
1287 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1288 "Addr: %u ## COPY-OFFSET(20) (offset, length, $destination)",
1291 operand_address = current_address + 1;
1293 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &multy_offset);
1294 if (show_instr_detail_level == 2 ){
1295 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u offset %u",
1296 operand_address, multy_offset);
1298 operand_address = next_operand_address;
1301 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &length);
1302 if (show_instr_detail_level == 2 ){
1303 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Length %u",
1304 operand_address, length);
1306 operand_address = next_operand_address;
1310 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &ref_destination, &result_dest);
1311 if (show_instr_detail_level == 2 ){
1312 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u $destination %u",
1313 operand_address, ref_destination);
1316 if (show_instr_detail_level == 1)
1318 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1319 "Addr: %u ## COPY-OFFSET (offset=%u, length=%u, $destination=%u)",
1320 current_address, multy_offset, length, result_dest);
1322 current_address = next_operand_address;
1324 /* Execute the instruction:
1325 * To derive the value of the position operand, starting at the memory
1326 * address specified by destination, the UDVM counts backwards a total
1327 * of offset memory addresses.
1329 * If the memory address specified in byte_copy_left is reached, the
1330 * next memory address is taken to be (byte_copy_right - 1) modulo 2^16.
1332 byte_copy_left = buff[64] << 8;
1333 byte_copy_left = byte_copy_left | buff[65];
1334 byte_copy_right = buff[66] << 8;
1335 byte_copy_right = byte_copy_right | buff[67];
1338 * In order to work out the position, simple arithmetic is tricky
1339 * to apply because there some nasty corner cases. A simple loop
1340 * is inefficient but the logic is simple.
1342 * FUTURE: This could be optimised.
1344 for (position = ref_destination, i = 0; i < multy_offset; i++)
1346 if ( position == byte_copy_left )
1348 position = (byte_copy_right - 1) & 0xffff;
1352 position = (position - 1) & 0xffff;
1356 if (print_level_2 ){
1357 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
1358 " byte_copy_left = %u byte_copy_right = %u position= %u",
1359 byte_copy_left, byte_copy_right, position);
1361 /* The COPY-OFFSET instruction then behaves as a COPY-LITERAL
1362 * instruction, taking the value of the position operand to be the last
1363 * memory address reached in the above step.
1369 * The string of bytes is copied in ascending order of memory address,
1370 * respecting the bounds set by byte_copy_left and byte_copy_right.
1371 * More precisely, if a byte is copied from/to Address m then the next
1372 * byte is copied from/to Address n where n is calculated as follows:
1374 * Set k := m + 1 (modulo 2^16)
1375 * If k = byte_copy_right then set n := byte_copy_left, else set n := k
1380 k = ref_destination;
1381 if (print_level_2 ){
1382 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
1383 " byte_copy_left = %u byte_copy_right = %u", byte_copy_left, byte_copy_right);
1385 while ( n < length ){
1386 buff[k] = buff[position];
1387 if (print_level_2 ){
1388 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
1389 " Copying value: %5u (0x%x) from Addr: %u to Addr: %u",
1390 buff[position], buff[position],(position), k);
1393 k = ( k + 1 ) & 0xffff;
1394 position = ( position + 1 ) & 0xffff;
1397 * Check for circular buffer wrapping after the positions are
1398 * incremented. It is important that k cannot be left set
1399 * to BCR. Also, if either started at BCR then they should continue
1400 * to increment beyond BCR.
1402 if ( k == byte_copy_right ){
1405 if ( position == byte_copy_right ){
1406 position = byte_copy_left;
1409 buff[result_dest] = k >> 8;
1410 buff[result_dest + 1] = k & 0x00ff;
1411 used_udvm_cycles = used_udvm_cycles + 1 + length;
1412 goto execute_next_instruction;
1415 case SIGCOMP_INSTR_MEMSET: /* 21 MEMSET (%address, %length, %start_value, %offset) */
1416 if (show_instr_detail_level == 2 ){
1417 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1418 "Addr: %u ## MEMSET(21) (address, length, start_value, offset)",
1421 operand_address = current_address + 1;
1424 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &address);
1425 if (show_instr_detail_level == 2 ){
1426 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Address %u",
1427 operand_address, address);
1429 operand_address = next_operand_address;
1432 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &length);
1433 if (show_instr_detail_level == 2 ){
1434 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Length %u",
1435 operand_address, length);
1437 operand_address = next_operand_address;
1439 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &start_value);
1440 if (show_instr_detail_level == 2 ){
1441 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u start_value %u",
1442 operand_address, start_value);
1444 operand_address = next_operand_address;
1447 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &multy_offset);
1448 if (show_instr_detail_level == 2 ){
1449 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u offset %u",
1450 operand_address, multy_offset);
1452 if (show_instr_detail_level == 1)
1454 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1455 "Addr: %u ## MEMSET (address=%u, length=%u, start_value=%u, offset=%u)",
1456 current_address, address, length, start_value, multy_offset);
1458 current_address = next_operand_address;
1459 /* exetute the instruction
1460 * The sequence of values used by the MEMSET instruction is specified by
1461 * the following formula:
1463 * Seq[n] := (start_value + n * offset) modulo 256
1467 byte_copy_right = buff[66] << 8;
1468 byte_copy_right = byte_copy_right | buff[67];
1469 byte_copy_left = buff[64] << 8;
1470 byte_copy_left = byte_copy_left | buff[65];
1471 if (print_level_2 ){
1472 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
1473 " byte_copy_left = %u byte_copy_right = %u", byte_copy_left, byte_copy_right);
1475 while ( n < length ){
1476 if ( k == byte_copy_right ){
1479 buff[k] = (start_value + ( n * multy_offset)) & 0xff;
1480 if (print_level_2 ){
1481 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
1482 " Storing value: %u (0x%x) at Addr: %u",
1483 buff[k], buff[k], k);
1485 k = ( k + 1 ) & 0xffff;
1488 used_udvm_cycles = used_udvm_cycles + 1 + length;
1489 goto execute_next_instruction;
1493 case SIGCOMP_INSTR_JUMP: /* 22 JUMP (@address) */
1494 if (show_instr_detail_level == 2 ){
1495 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1496 "Addr: %u ## JUMP(22) (@address)",
1499 operand_address = current_address + 1;
1501 /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
1502 next_operand_address = decode_udvm_address_operand(buff,operand_address, &at_address, current_address);
1503 if (show_instr_detail_level == 2 ){
1504 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u @Address %u",
1505 operand_address, at_address);
1507 if (show_instr_detail_level == 1)
1509 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1510 "Addr: %u ## JUMP (@address=%u)",
1511 current_address, at_address);
1513 current_address = at_address;
1515 goto execute_next_instruction;
1518 case SIGCOMP_INSTR_COMPARE: /* 23 */
1519 /* COMPARE (%value_1, %value_2, @address_1, @address_2, @address_3)
1521 if (show_instr_detail_level == 2 ){
1522 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1523 "Addr: %u ## COMPARE(23) (value_1, value_2, @address_1, @address_2, @address_3)",
1526 operand_address = current_address + 1;
1529 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &value_1);
1530 if (show_instr_detail_level == 2 ){
1531 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Value %u",
1532 operand_address, value_1);
1534 operand_address = next_operand_address;
1537 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &value_2);
1538 if (show_instr_detail_level == 2 ){
1539 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Value %u",
1540 operand_address, value_2);
1542 operand_address = next_operand_address;
1545 /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
1546 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &at_address_1);
1547 at_address_1 = ( current_address + at_address_1) & 0xffff;
1548 if (show_instr_detail_level == 2 ){
1549 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u @Address %u",
1550 operand_address, at_address_1);
1552 operand_address = next_operand_address;
1556 /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
1557 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &at_address_2);
1558 at_address_2 = ( current_address + at_address_2) & 0xffff;
1559 if (show_instr_detail_level == 2 ){
1560 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u @Address %u",
1561 operand_address, at_address_2);
1563 operand_address = next_operand_address;
1566 /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
1567 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &at_address_3);
1568 at_address_3 = ( current_address + at_address_3) & 0xffff;
1569 if (show_instr_detail_level == 2 ){
1570 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u @Address %u",
1571 operand_address, at_address_3);
1573 if (show_instr_detail_level == 1)
1575 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1576 "Addr: %u ## COMPARE (value_1=%u, value_2=%u, @address_1=%u, @address_2=%u, @address_3=%u)",
1577 current_address, value_1, value_2, at_address_1, at_address_2, at_address_3);
1579 /* execute the instruction
1580 * If value_1 < value_2 then the UDVM continues instruction execution at
1581 * the memory address specified by address 1. If value_1 = value_2 then
1582 * it jumps to the address specified by address_2. If value_1 > value_2
1583 * then it jumps to the address specified by address_3.
1585 if ( value_1 < value_2 )
1586 current_address = at_address_1;
1587 if ( value_1 == value_2 )
1588 current_address = at_address_2;
1589 if ( value_1 > value_2 )
1590 current_address = at_address_3;
1592 goto execute_next_instruction;
1595 case SIGCOMP_INSTR_CALL: /* 24 CALL (@address) (PUSH addr )*/
1596 if (show_instr_detail_level == 2){
1597 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1598 "Addr: %u ## CALL(24) (@address) (PUSH addr )",
1601 operand_address = current_address + 1;
1603 next_operand_address = decode_udvm_address_operand(buff,operand_address, &at_address, current_address);
1604 if (show_instr_detail_level == 2 ){
1605 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u @Address %u",
1606 operand_address, at_address);
1608 if (show_instr_detail_level == 1)
1610 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1611 "Addr: %u ## CALL (@address=%u)",
1612 current_address, at_address);
1614 current_address = next_operand_address;
1616 /* Push the current address onto the stack */
1617 stack_location = (buff[70] << 8) | buff[71];
1618 stack_fill = (buff[stack_location] << 8)
1619 | buff[(stack_location+1) & 0xFFFF];
1620 address = (stack_location + stack_fill * 2 + 2) & 0xFFFF;
1621 buff[address] = (current_address >> 8) & 0x00FF;
1622 buff[(address+1) & 0xFFFF] = current_address & 0x00FF;
1624 stack_fill = (stack_fill + 1) & 0xFFFF;
1625 buff[stack_location] = (stack_fill >> 8) & 0x00FF;
1626 buff[(stack_location+1) & 0xFFFF] = stack_fill & 0x00FF;
1628 /* ... and jump to the destination address */
1629 current_address = at_address;
1632 goto execute_next_instruction;
1636 case SIGCOMP_INSTR_RETURN: /* 25 POP and return */
1637 if (print_level_1 || show_instr_detail_level == 1){
1638 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1639 "Addr: %u ## POP(25) and return",
1643 /* Pop value from the top of the stack */
1644 stack_location = (buff[70] << 8) | buff[71];
1645 stack_fill = (buff[stack_location] << 8)
1646 | buff[(stack_location+1) & 0xFFFF];
1647 if (stack_fill == 0)
1650 goto decompression_failure;
1653 stack_fill = (stack_fill - 1) & 0xFFFF;
1654 buff[stack_location] = (stack_fill >> 8) & 0x00FF;
1655 buff[(stack_location+1) & 0xFFFF] = stack_fill & 0x00FF;
1657 address = (stack_location + stack_fill * 2 + 2) & 0xFFFF;
1658 at_address = (buff[address] << 8)
1659 | buff[(address+1) & 0xFFFF];
1661 /* ... and set the PC to the popped value */
1662 current_address = at_address;
1665 goto execute_next_instruction;
1669 case SIGCOMP_INSTR_SWITCH: /* 26 SWITCH (#n, %j, @address_0, @address_1, ... , @address_n-1) */
1671 * When a SWITCH instruction is encountered the UDVM reads the value of
1672 * j. It then continues instruction execution at the address specified
1675 * Decompression failure occurs if j specifies a value of n or more, or
1676 * if the address lies beyond the overall UDVM memory size.
1678 instruction_address = current_address;
1679 if (print_level_1 ){
1680 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1681 "Addr: %u ## SWITCH (#n, j, @address_0, @address_1, ... , @address_n-1))",
1684 operand_address = current_address + 1;
1686 * Number of addresses in the instruction
1688 next_operand_address = decode_udvm_literal_operand(buff,operand_address, &n);
1689 if (print_level_1 ){
1690 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u n %u",
1691 operand_address, n);
1693 operand_address = next_operand_address;
1695 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &j);
1696 if (print_level_1 ){
1697 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u j %u",
1698 operand_address, j);
1700 operand_address = next_operand_address;
1704 /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
1705 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &at_address_1);
1706 at_address_1 = ( instruction_address + at_address_1) & 0xffff;
1707 if (print_level_1 ){
1708 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u @Address %u",
1709 operand_address, at_address_1);
1712 current_address = at_address_1;
1714 operand_address = next_operand_address;
1717 /* Check decompression failure */
1718 if ( ( j == n ) || ( j > n )){
1720 goto decompression_failure;
1722 if ( current_address > UDVM_MEMORY_SIZE ){
1724 goto decompression_failure;
1726 used_udvm_cycles = used_udvm_cycles + 1 + n;
1728 goto execute_next_instruction;
1731 case SIGCOMP_INSTR_CRC: /* 27 CRC (%value, %position, %length, @address) */
1732 if (print_level_1 ){
1733 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1734 "Addr: %u ## CRC (value, position, length, @address)",
1738 operand_address = current_address + 1;
1741 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &value);
1742 if (print_level_1 ){
1743 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Value %u",
1744 operand_address, value);
1746 operand_address = next_operand_address;
1749 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &position);
1750 if (print_level_1 ){
1751 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u position %u",
1752 operand_address, position);
1754 operand_address = next_operand_address;
1757 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &length);
1758 if (print_level_1 ){
1759 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Length %u",
1760 operand_address, length);
1762 operand_address = next_operand_address;
1765 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &at_address);
1766 at_address = ( current_address + at_address) & 0xffff;
1767 if (print_level_1 ){
1768 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u @Address %u",
1769 operand_address, at_address);
1771 /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
1772 used_udvm_cycles = used_udvm_cycles + 1 + length;
1776 byte_copy_right = buff[66] << 8;
1777 byte_copy_right = byte_copy_right | buff[67];
1778 byte_copy_left = buff[64] << 8;
1779 byte_copy_left = byte_copy_left | buff[65];
1782 if (print_level_2 ){
1783 proto_tree_add_text(udvm_tree, message_tvb, 0, -1,
1784 "byte_copy_right = %u", byte_copy_right);
1789 guint16 handle_now = length - n;
1791 if ( k < byte_copy_right && byte_copy_right <= k + (length-n) ){
1792 handle_now = byte_copy_right - k;
1795 result = crc16_ccitt_seed(&buff[k], handle_now, result ^ 0xffff);
1797 k = ( k + handle_now ) & 0xffff;
1798 n = ( n + handle_now ) & 0xffff;
1800 if ( k >= byte_copy_right ) {
1805 result = result ^ 0xffff;
1807 if (print_level_1 ){
1808 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1, "Calculated CRC %u", result);
1810 if (result != value){
1811 current_address = at_address;
1814 current_address = next_operand_address;
1816 goto execute_next_instruction;
1820 case SIGCOMP_INSTR_INPUT_BYTES: /* 28 INPUT-BYTES (%length, %destination, @address) */
1821 if (show_instr_detail_level == 2 ){
1822 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1823 "Addr: %u ## INPUT-BYTES(28) length, destination, @address)",
1826 operand_address = current_address + 1;
1828 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &length);
1829 if (show_instr_detail_level == 2 ){
1830 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Length %u",
1831 operand_address, length);
1833 operand_address = next_operand_address;
1836 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &destination);
1837 if (show_instr_detail_level == 2 ){
1838 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Destination %u",
1839 operand_address, destination);
1841 operand_address = next_operand_address;
1844 /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
1845 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &at_address);
1846 at_address = ( current_address + at_address) & 0xffff;
1847 if (show_instr_detail_level == 2 ){
1848 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u @Address %u",
1849 operand_address, at_address);
1851 if (show_instr_detail_level == 1)
1853 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1854 "Addr: %u ## INPUT-BYTES length=%u, destination=%u, @address=%u)",
1855 current_address, length, destination, at_address);
1857 /* execute the instruction TODO insert checks
1861 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1862 * | byte_copy_left | 64 - 65
1863 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1864 * | byte_copy_right | 66 - 67
1865 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1866 * | input_bit_order | 68 - 69
1867 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1868 * | stack_location | 70 - 71
1869 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1871 * Figure 7: Memory addresses of the UDVM registers
1875 * The string of bytes is copied in ascending order of memory address,
1876 * respecting the bounds set by byte_copy_left and byte_copy_right.
1877 * More precisely, if a byte is copied from/to Address m then the next
1878 * byte is copied from/to Address n where n is calculated as follows:
1880 * Set k := m + 1 (modulo 2^16)
1881 * If k = byte_copy_right then set n := byte_copy_left, else set n := k
1887 byte_copy_right = buff[66] << 8;
1888 byte_copy_right = byte_copy_right | buff[67];
1889 byte_copy_left = buff[64] << 8;
1890 byte_copy_left = byte_copy_left | buff[65];
1891 if (print_level_1 ){
1892 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
1893 " byte_copy_right = %u", byte_copy_right);
1895 /* clear out remaining bits if any */
1898 /* operand_address used as dummy */
1899 while ( n < length ){
1900 if (input_address > ( msg_end - 1)){
1901 current_address = at_address;
1903 goto execute_next_instruction;
1906 if ( k == byte_copy_right ){
1909 octet = tvb_get_guint8(message_tvb, input_address);
1911 if (print_level_1 ){
1912 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
1913 " Loading value: %u (0x%x) at Addr: %u", octet, octet, k);
1917 * If the instruction requests data that lies beyond the end of the
1918 * SigComp message, no data is returned. Instead the UDVM moves program
1919 * execution to the address specified by the address operand.
1923 k = ( k + 1 ) & 0xffff;
1926 used_udvm_cycles = used_udvm_cycles + 1 + length;
1927 current_address = next_operand_address;
1928 goto execute_next_instruction;
1930 case SIGCOMP_INSTR_INPUT_BITS:/* 29 INPUT-BITS (%length, %destination, @address) */
1932 * The length operand indicates the requested number of bits.
1933 * Decompression failure occurs if this operand does not lie between 0
1936 * The destination operand specifies the memory address to which the
1937 * compressed data should be copied. Note that the requested bits are
1938 * interpreted as a 2-byte integer ranging from 0 to 2^length - 1, as
1939 * explained in Section 8.2.
1941 * If the instruction requests data that lies beyond the end of the
1942 * SigComp message, no data is returned. Instead the UDVM moves program
1943 * execution to the address specified by the address operand.
1946 if (show_instr_detail_level == 2 ){
1947 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1948 "Addr: %u ## INPUT-BITS(29) (length, destination, @address)",
1951 operand_address = current_address + 1;
1954 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &length);
1955 if (show_instr_detail_level == 2 ){
1956 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u length %u",
1957 operand_address, length);
1959 operand_address = next_operand_address;
1961 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &destination);
1962 if (show_instr_detail_level == 2 ){
1963 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Destination %u",
1964 operand_address, destination);
1966 operand_address = next_operand_address;
1969 /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
1970 next_operand_address = decode_udvm_address_operand(buff,operand_address, &at_address, current_address);
1971 if (show_instr_detail_level == 2 ){
1972 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u @Address %u",
1973 operand_address, at_address);
1975 if (show_instr_detail_level == 1)
1977 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1978 "Addr: %u ## INPUT-BITS length=%u, destination=%u, @address=%u)",
1979 current_address, length, destination, at_address);
1981 current_address = next_operand_address;
1984 * Execute actual instr.
1985 * The input_bit_order register contains the following three flags:
1988 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1989 * | reserved |F|H|P| 68 - 69
1990 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1992 input_bit_order = buff[68] << 8;
1993 input_bit_order = input_bit_order | buff[69];
1995 * If the instruction requests data that lies beyond the end of the
1996 * SigComp message, no data is returned. Instead the UDVM moves program
1997 * execution to the address specified by the address operand.
2002 goto decompression_failure;
2004 if ( input_bit_order > 7 ){
2006 goto decompression_failure;
2010 * Transfer F bit to bit_order to tell decomp dispatcher which bit order to use
2012 bit_order = ( input_bit_order & 0x0004 ) >> 2;
2013 value = decomp_dispatch_get_bits( message_tvb, udvm_tree, bit_order,
2014 buff, &old_input_bit_order, &remaining_bits,
2015 &input_bits, &input_address, length, &result_code, msg_end);
2016 if ( result_code == 11 ){
2017 used_udvm_cycles = used_udvm_cycles + 1;
2018 current_address = at_address;
2019 goto execute_next_instruction;
2022 lsb = value & 0x00ff;
2023 buff[destination] = msb;
2024 buff[destination + 1]=lsb;
2025 if (print_level_1 ){
2026 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
2027 " Loading value: %u (0x%x) at Addr: %u, remaining_bits: %u", value, value, destination, remaining_bits);
2030 used_udvm_cycles = used_udvm_cycles + 1;
2031 goto execute_next_instruction;
2033 case SIGCOMP_INSTR_INPUT_HUFFMAN: /* 30 */
2035 * INPUT-HUFFMAN (%destination, @address, #n, %bits_1, %lower_bound_1,
2036 * %upper_bound_1, %uncompressed_1, ... , %bits_n, %lower_bound_n,
2037 * %upper_bound_n, %uncompressed_n)
2039 if (show_instr_detail_level == 2 ){
2040 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2041 "Addr: %u ## INPUT-HUFFMAN (destination, @address, #n, bits_1, lower_bound_1,upper_bound_1, uncompressed_1, ... , bits_n, lower_bound_n,upper_bound_n, uncompressed_n)",
2044 operand_address = current_address + 1;
2047 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &destination);
2048 if (show_instr_detail_level == 2 ){
2049 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Destination %u",
2050 operand_address, destination);
2052 operand_address = next_operand_address;
2055 /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
2056 next_operand_address = decode_udvm_address_operand(buff,operand_address, &at_address, current_address);
2057 if (show_instr_detail_level == 2 ){
2058 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u @Address %u",
2059 operand_address, at_address);
2061 operand_address = next_operand_address;
2064 next_operand_address = decode_udvm_literal_operand(buff,operand_address, &n);
2065 if (show_instr_detail_level == 2 ){
2066 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u n %u",
2067 operand_address, n);
2069 operand_address = next_operand_address;
2070 if (show_instr_detail_level == 1)
2072 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2073 "Addr: %u ## INPUT-HUFFMAN (destination=%u, @address=%u, #n=%u, bits_1, lower_1,upper_1, unc_1, ... , bits_%d, lower_%d,upper_%d, unc_%d)",
2074 current_address, destination, at_address, n, n, n, n, n);
2077 used_udvm_cycles = used_udvm_cycles + 1 + n;
2080 * Note that if n = 0 then the INPUT-HUFFMAN instruction is ignored and
2081 * program execution resumes at the following instruction.
2082 * Decompression failure occurs if (bits_1 + ... + bits_n) > 16.
2084 * In all other cases, the behavior of the INPUT-HUFFMAN instruction is
2087 * 1. Set j := 1 and set H := 0.
2089 * 2. Request bits_j compressed bits. Interpret the returned bits as an
2090 * integer k from 0 to 2^bits_j - 1, as explained in Section 8.2.
2092 * 3. Set H := H * 2^bits_j + k.
2094 * 4. If data is requested that lies beyond the end of the SigComp
2095 * message, terminate the INPUT-HUFFMAN instruction and move program
2096 * execution to the memory address specified by the address operand.
2098 * 5. If (H < lower_bound_j) or (H > upper_bound_j) then set j := j + 1.
2099 * Then go back to Step 2, unless j > n in which case decompression
2102 * 6. Copy (H + uncompressed_j - lower_bound_j) modulo 2^16 to the
2103 * memory address specified by the destination operand.
2107 * The input_bit_order register contains the following three flags:
2110 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2111 * | reserved |F|H|P| 68 - 69
2112 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2114 * Transfer H bit to bit_order to tell decomp dispatcher which bit order to use
2116 input_bit_order = buff[68] << 8;
2117 input_bit_order = input_bit_order | buff[69];
2118 bit_order = ( input_bit_order & 0x0002 ) >> 1;
2123 outside_huffman_boundaries = TRUE;
2124 print_in_loop = print_level_3;
2127 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &bits_n);
2128 if (print_in_loop ){
2129 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u bits_n %u",
2130 operand_address, bits_n);
2132 operand_address = next_operand_address;
2134 /* %lower_bound_n */
2135 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &lower_bound_n);
2136 if (print_in_loop ){
2137 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u lower_bound_n %u",
2138 operand_address, lower_bound_n);
2140 operand_address = next_operand_address;
2141 /* %upper_bound_n */
2142 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &upper_bound_n);
2143 if (print_in_loop ){
2144 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u upper_bound_n %u",
2145 operand_address, upper_bound_n);
2147 operand_address = next_operand_address;
2148 /* %uncompressed_n */
2149 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &uncompressed_n);
2150 if (print_in_loop ){
2151 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u uncompressed_n %u",
2152 operand_address, uncompressed_n);
2154 operand_address = next_operand_address;
2155 /* execute instruction */
2156 if ( outside_huffman_boundaries ) {
2158 * 2. Request bits_j compressed bits. Interpret the returned bits as an
2159 * integer k from 0 to 2^bits_j - 1, as explained in Section 8.2.
2161 k = decomp_dispatch_get_bits( message_tvb, udvm_tree, bit_order,
2162 buff, &old_input_bit_order, &remaining_bits,
2163 &input_bits, &input_address, bits_n, &result_code, msg_end);
2164 if ( result_code == 11 ){
2166 * 4. If data is requested that lies beyond the end of the SigComp
2167 * message, terminate the INPUT-HUFFMAN instruction and move program
2168 * execution to the memory address specified by the address operand.
2170 current_address = at_address;
2171 goto execute_next_instruction;
2175 * 3. Set H := H * 2^bits_j + k.
2176 * [In practice is a shift+OR operation.]
2179 H = (H << bits_n) | k;
2180 if (print_level_3 ){
2181 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," Set H(%u) := H(%u) * 2^bits_j(%u) + k(%u)",
2182 H ,oldH, 1<<bits_n,k);
2186 * 5. If (H < lower_bound_j) or (H > upper_bound_j) then set j := j + 1.
2187 * Then go back to Step 2, unless j > n in which case decompression
2190 if ((H < lower_bound_n) || (H > upper_bound_n)){
2191 outside_huffman_boundaries = TRUE;
2193 outside_huffman_boundaries = FALSE;
2194 print_in_loop = FALSE;
2196 * 6. Copy (H + uncompressed_j - lower_bound_j) modulo 2^16 to the
2197 * memory address specified by the destination operand.
2199 if (print_level_2 ){
2200 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2201 " H(%u) = H(%u) + uncompressed_n(%u) - lower_bound_n(%u)",
2202 (H + uncompressed_n - lower_bound_n ),H, uncompressed_n, lower_bound_n);
2204 H = H + uncompressed_n - lower_bound_n;
2207 buff[destination] = msb;
2208 buff[destination + 1]=lsb;
2209 if (print_level_1 ){
2210 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
2211 " Loading H: %u (0x%x) at Addr: %u,j = %u remaining_bits: %u",
2212 H, H, destination,( n - m + 1 ), remaining_bits);
2221 if ( outside_huffman_boundaries ) {
2223 goto decompression_failure;
2226 current_address = next_operand_address;
2227 goto execute_next_instruction;
2230 case SIGCOMP_INSTR_STATE_ACCESS: /* 31 */
2231 /* STATE-ACCESS (%partial_identifier_start, %partial_identifier_length,
2232 * %state_begin, %state_length, %state_address, %state_instruction)
2234 if (show_instr_detail_level == 2 ){
2235 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2236 "Addr: %u ## STATE-ACCESS(31) (partial_identifier_start, partial_identifier_length,state_begin, state_length, state_address, state_instruction)",
2239 operand_address = current_address + 1;
2242 * %partial_identifier_start
2244 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &p_id_start);
2245 if (show_instr_detail_level == 2 ){
2246 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u partial_identifier_start %u",
2247 operand_address, p_id_start);
2249 operand_address = next_operand_address;
2252 * %partial_identifier_length
2254 operand_address = next_operand_address;
2255 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &p_id_length);
2256 if (show_instr_detail_level == 2 ){
2257 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u partial_identifier_length %u",
2258 operand_address, p_id_length);
2263 operand_address = next_operand_address;
2264 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_begin);
2265 if (show_instr_detail_level == 2 ){
2266 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_begin %u",
2267 operand_address, state_begin);
2272 operand_address = next_operand_address;
2273 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_length);
2274 if (show_instr_detail_level == 2 ){
2275 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_length %u",
2276 operand_address, state_length);
2281 operand_address = next_operand_address;
2282 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_address);
2283 if (show_instr_detail_level == 2 ){
2284 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_address %u",
2285 operand_address, state_address);
2288 * %state_instruction
2290 operand_address = next_operand_address;
2291 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_instruction);
2292 if (show_instr_detail_level == 2 ){
2293 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_instruction %u",
2294 operand_address, state_instruction);
2296 if (show_instr_detail_level == 1)
2298 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2299 "Addr: %u ## STATE-ACCESS(31) (partial_identifier_start=%u, partial_identifier_length=%u,state_begin=%u, state_length=%u, state_address=%u, state_instruction=%u)",
2300 current_address, p_id_start, p_id_length, state_begin, state_length, state_address, state_instruction);
2302 current_address = next_operand_address;
2303 byte_copy_right = buff[66] << 8;
2304 byte_copy_right = byte_copy_right | buff[67];
2305 byte_copy_left = buff[64] << 8;
2306 byte_copy_left = byte_copy_left | buff[65];
2307 if (print_level_2 ){
2308 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
2309 " byte_copy_right = %u, byte_copy_left = %u", byte_copy_right,byte_copy_left);
2312 result_code = udvm_state_access(message_tvb, udvm_tree, buff, p_id_start, p_id_length, state_begin, &state_length,
2313 &state_address, &state_instruction, hf_id);
2314 if ( result_code != 0 ){
2315 goto decompression_failure;
2317 used_udvm_cycles = used_udvm_cycles + 1 + state_length;
2318 goto execute_next_instruction;
2320 case SIGCOMP_INSTR_STATE_CREATE: /* 32 */
2322 * STATE-CREATE (%state_length, %state_address, %state_instruction,
2323 * %minimum_access_length, %state_retention_priority)
2325 if (show_instr_detail_level == 2 ){
2326 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2327 "Addr: %u ## STATE-CREATE(32) (state_length, state_address, state_instruction,minimum_access_length, state_retention_priority)",
2330 operand_address = current_address + 1;
2335 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_length);
2336 if (show_instr_detail_level == 2 ){
2337 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_length %u",
2338 operand_address, state_length);
2343 operand_address = next_operand_address;
2344 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_address);
2345 if (show_instr_detail_level == 2 ){
2346 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_address %u",
2347 operand_address, state_address);
2350 * %state_instruction
2352 operand_address = next_operand_address;
2353 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_instruction);
2354 if (show_instr_detail_level == 2 ){
2355 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_instruction %u",
2356 operand_address, state_instruction);
2358 operand_address = next_operand_address;
2360 * %minimum_access_length
2362 operand_address = next_operand_address;
2363 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &minimum_access_length);
2364 if (show_instr_detail_level == 2 ){
2365 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u minimum_access_length %u",
2366 operand_address, minimum_access_length);
2368 operand_address = next_operand_address;
2370 * %state_retention_priority
2372 operand_address = next_operand_address;
2373 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_retention_priority);
2374 if (show_instr_detail_level == 2 ){
2375 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_retention_priority %u",
2376 operand_address, state_retention_priority);
2378 if (show_instr_detail_level == 1)
2380 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2381 "Addr: %u ## STATE-CREATE(32) (state_length=%u, state_address=%u, state_instruction=%u,minimum_access_length=%u, state_retention_priority=%u)",
2382 current_address, state_length, state_address, state_instruction,minimum_access_length, state_retention_priority);
2384 current_address = next_operand_address;
2385 /* Execute the instruction
2386 * TODO Implement the instruction
2388 * Note that the new state item cannot be created until a valid
2389 * compartment identifier has been returned by the application.
2390 * Consequently, when a STATE-CREATE instruction is encountered the UDVM
2391 * simply buffers the five supplied operands until the END-MESSAGE
2392 * instruction is reached. The steps taken at this point are described
2395 * Decompression failure MUST occur if more than four state creation
2396 * requests are made before the END-MESSAGE instruction is encountered.
2397 * Decompression failure also occurs if the minimum_access_length does
2398 * not lie between 6 and 20 inclusive, or if the
2399 * state_retention_priority is 65535.
2401 no_of_state_create++;
2402 if ( no_of_state_create > 4 ){
2404 goto decompression_failure;
2406 if (( minimum_access_length < 6 ) || ( minimum_access_length > 20 )){
2408 goto decompression_failure;
2410 if ( state_retention_priority == 65535 ){
2412 goto decompression_failure;
2414 state_length_buff[no_of_state_create] = state_length;
2415 state_address_buff[no_of_state_create] = state_address;
2416 state_instruction_buff[no_of_state_create] = state_instruction;
2417 state_minimum_access_length_buff[no_of_state_create] = minimum_access_length;
2418 state_state_retention_priority_buff[no_of_state_create] = state_retention_priority;
2419 used_udvm_cycles = used_udvm_cycles + 1 + state_length;
2421 byte_copy_right = buff[66] << 8;
2422 byte_copy_right = byte_copy_right | buff[67];
2423 byte_copy_left = buff[64] << 8;
2424 byte_copy_left = byte_copy_left | buff[65];
2427 while ( n < state_length ){
2428 if ( k == byte_copy_right ){
2433 if (print_level_3 ){
2434 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2435 " Addr: %5u State value: %u (0x%x) ASCII(%s)",
2436 k,buff[k],buff[k],string);
2438 k = ( k + 1 ) & 0xffff;
2443 goto execute_next_instruction;
2445 case SIGCOMP_INSTR_STATE_FREE: /* 33 */
2447 * STATE-FREE (%partial_identifier_start, %partial_identifier_length)
2449 if (show_instr_detail_level == 2 ){
2450 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2451 "Addr: %u ## STATE-FREE (partial_identifier_start, partial_identifier_length)",
2454 operand_address = current_address + 1;
2456 * %partial_identifier_start
2458 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &p_id_start);
2459 if (show_instr_detail_level == 2 ){
2460 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u partial_identifier_start %u",
2461 operand_address, p_id_start);
2463 operand_address = next_operand_address;
2466 * %partial_identifier_length
2468 operand_address = next_operand_address;
2469 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &p_id_length);
2470 if (show_instr_detail_level == 2 ){
2471 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u partial_identifier_length %u",
2472 operand_address, p_id_length);
2474 if (show_instr_detail_level == 1)
2476 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2477 "Addr: %u ## STATE-FREE (partial_identifier_start=%u, partial_identifier_length=%u)",
2478 current_address, p_id_start, p_id_length);
2480 current_address = next_operand_address;
2482 /* Execute the instruction:
2485 udvm_state_free(buff,p_id_start,p_id_length);
2488 goto execute_next_instruction;
2490 case SIGCOMP_INSTR_OUTPUT: /* 34 OUTPUT (%output_start, %output_length) */
2491 if (show_instr_detail_level == 2 ){
2492 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2493 "Addr: %u ## OUTPUT(34) (output_start, output_length)",
2496 operand_address = current_address + 1;
2500 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &output_start);
2501 if (show_instr_detail_level == 2 ){
2502 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u output_start %u",
2503 operand_address, output_start);
2505 operand_address = next_operand_address;
2509 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &output_length);
2510 if (show_instr_detail_level == 2 ){
2511 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u output_length %u",
2512 operand_address, output_length);
2514 if (show_instr_detail_level == 1)
2516 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2517 "Addr: %u ## OUTPUT (output_start=%u, output_length=%u)",
2518 current_address, output_start, output_length);
2520 current_address = next_operand_address;
2523 * Execute instruction
2526 * The string of bytes is copied in ascending order of memory address,
2527 * respecting the bounds set by byte_copy_left and byte_copy_right.
2528 * More precisely, if a byte is copied from/to Address m then the next
2529 * byte is copied from/to Address n where n is calculated as follows:
2531 * Set k := m + 1 (modulo 2^16)
2532 * If k = byte_copy_right then set n := byte_copy_left, else set n := k
2538 byte_copy_right = buff[66] << 8;
2539 byte_copy_right = byte_copy_right | buff[67];
2540 byte_copy_left = buff[64] << 8;
2541 byte_copy_left = byte_copy_left | buff[65];
2542 if (print_level_3 ){
2543 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2544 " byte_copy_right = %u", byte_copy_right);
2546 while ( n < output_length ){
2548 if ( k == byte_copy_right ){
2551 out_buff[output_address] = buff[k];
2555 if (print_level_3 ){
2556 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2557 " Output value: %u (0x%x) ASCII(%s) from Addr: %u ,output to dispatcher position %u",
2558 buff[k],buff[k],format_text(strp,1), k,output_address);
2560 k = ( k + 1 ) & 0xffff;
2564 used_udvm_cycles = used_udvm_cycles + 1 + output_length;
2565 goto execute_next_instruction;
2567 case SIGCOMP_INSTR_END_MESSAGE: /* 35 */
2569 * END-MESSAGE (%requested_feedback_location,
2570 * %returned_parameters_location, %state_length, %state_address,
2571 * %state_instruction, %minimum_access_length,
2572 * %state_retention_priority)
2574 if (show_instr_detail_level == 2 ){
2575 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2576 "Addr: %u ## END-MESSAGE (requested_feedback_location,state_instruction, minimum_access_length,state_retention_priority)",
2579 operand_address = current_address + 1;
2581 /* %requested_feedback_location */
2582 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &requested_feedback_location);
2583 if (show_instr_detail_level == 2 ){
2584 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u requested_feedback_location %u",
2585 operand_address, requested_feedback_location);
2587 operand_address = next_operand_address;
2588 /* returned_parameters_location */
2589 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &returned_parameters_location);
2590 if (show_instr_detail_level == 2 ){
2591 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u returned_parameters_location %u",
2592 operand_address, returned_parameters_location);
2594 operand_address = next_operand_address;
2598 operand_address = next_operand_address;
2599 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_length);
2600 if (show_instr_detail_level == 2 ){
2601 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_length %u",
2602 operand_address, state_length);
2607 operand_address = next_operand_address;
2608 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_address);
2609 if (show_instr_detail_level == 2 ){
2610 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_address %u",
2611 operand_address, state_address);
2614 * %state_instruction
2616 operand_address = next_operand_address;
2617 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_instruction);
2618 if (show_instr_detail_level == 2 ){
2619 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_instruction %u",
2620 operand_address, state_instruction);
2624 * %minimum_access_length
2626 operand_address = next_operand_address;
2627 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &minimum_access_length);
2628 if (show_instr_detail_level == 2 ){
2629 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u minimum_access_length %u",
2630 operand_address, minimum_access_length);
2634 * %state_retention_priority
2636 operand_address = next_operand_address;
2637 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_retention_priority);
2638 if (show_instr_detail_level == 2 ){
2639 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_retention_priority %u",
2640 operand_address, state_retention_priority);
2642 if (show_instr_detail_level == 1)
2644 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2645 "Addr: %u ## END-MESSAGE (requested_feedback_location=%u, returned_parameters_location=%u, state_length=%u, state_address=%u, state_instruction=%u, minimum_access_length=%u, state_retention_priority=%u)",
2646 current_address, requested_feedback_location, returned_parameters_location, state_length, state_address, state_instruction, minimum_access_length,state_retention_priority);
2648 current_address = next_operand_address;
2649 /* TODO: This isn't currently totaly correct as END_INSTRUCTION might not create state */
2650 no_of_state_create++;
2651 if ( no_of_state_create > 4 ){
2653 goto decompression_failure;
2655 state_length_buff[no_of_state_create] = state_length;
2656 state_address_buff[no_of_state_create] = state_address;
2657 state_instruction_buff[no_of_state_create] = state_instruction;
2659 state_minimum_access_length_buff[no_of_state_create] = minimum_access_length;
2660 state_state_retention_priority_buff[no_of_state_create] = state_retention_priority;
2662 /* Execute the instruction
2664 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"no_of_state_create %u",no_of_state_create);
2665 if ( no_of_state_create != 0 ){
2666 for( x=0; x < 20; x++){
2667 sha1_digest_buf[x]=0;
2670 byte_copy_right = buff[66] << 8;
2671 byte_copy_right = byte_copy_right | buff[67];
2672 byte_copy_left = buff[64] << 8;
2673 byte_copy_left = byte_copy_left | buff[65];
2674 while ( n < no_of_state_create + 1 ){
2675 sha1buff = g_malloc(state_length_buff[n]+8);
2676 sha1buff[0] = state_length_buff[n] >> 8;
2677 sha1buff[1] = state_length_buff[n] & 0xff;
2678 sha1buff[2] = state_address_buff[n] >> 8;
2679 sha1buff[3] = state_address_buff[n] & 0xff;
2680 sha1buff[4] = state_instruction_buff[n] >> 8;
2681 sha1buff[5] = state_instruction_buff[n] & 0xff;
2682 sha1buff[6] = state_minimum_access_length_buff[n] >> 8;
2683 sha1buff[7] = state_minimum_access_length_buff[n] & 0xff;
2684 if (print_level_3 ){
2685 for( x=0; x < 8; x++){
2686 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"sha1buff %u 0x%x",
2690 k = state_address_buff[n];
2691 for( x=0; x < state_length_buff[n]; x++)
2693 if ( k == byte_copy_right ){
2696 sha1buff[8+x] = buff[k];
2697 k = ( k + 1 ) & 0xffff;
2700 sha1_starts( &ctx );
2701 sha1_update( &ctx, (guint8 *) sha1buff, state_length_buff[n] + 8);
2702 sha1_finish( &ctx, sha1_digest_buf );
2703 if (print_level_3 ){
2704 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"SHA1 digest %s",bytes_to_str(sha1_digest_buf, 20));
2707 udvm_state_create(sha1buff, sha1_digest_buf, state_minimum_access_length_buff[n]);
2708 proto_tree_add_text(udvm_tree,bytecode_tvb, 0, -1,"### Creating state ###");
2709 proto_tree_add_string(udvm_tree,hf_id, bytecode_tvb, 0, 0, bytes_to_str(sha1_digest_buf, state_minimum_access_length_buff[n]));
2718 /* At least something got decompressed, show it */
2719 decomp_tvb = tvb_new_real_data(out_buff,output_address,output_address);
2720 /* Arrange that the allocated packet data copy be freed when the
2723 tvb_set_free_cb( decomp_tvb, g_free );
2725 tvb_set_child_real_data_tvbuff(message_tvb,decomp_tvb);
2726 add_new_data_source(pinfo, decomp_tvb, "Decompressed SigComp message");
2728 proto_tree_add_text(udvm_tree, decomp_tvb, 0, -1,"SigComp message Decompressed");
2730 used_udvm_cycles = used_udvm_cycles + 1 + state_length;
2731 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"maximum_UDVM_cycles %u used_udvm_cycles %u",
2732 maximum_UDVM_cycles, used_udvm_cycles);
2737 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," ### Addr %u Invalid instruction: %u (0x%x)",
2738 current_address,current_instruction,current_instruction);
2743 decompression_failure:
2745 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"DECOMPRESSION FAILURE: %s",
2746 val_to_str(result_code, result_code_vals,"Unknown (%u)"));
2752 /* The simplest operand type is the literal (#), which encodes a
2753 * constant integer from 0 to 65535 inclusive. A literal operand may
2754 * require between 1 and 3 bytes depending on its value.
2755 * Bytecode: Operand value: Range:
2756 * 0nnnnnnn N 0 - 127
2757 * 10nnnnnn nnnnnnnn N 0 - 16383
2758 * 11000000 nnnnnnnn nnnnnnnn N 0 - 65535
2760 * Figure 8: Bytecode for a literal (#) operand
2764 decode_udvm_literal_operand(guint8 *buff,guint operand_address, guint16 *value)
2769 guint offset = operand_address;
2772 bytecode = buff[operand_address];
2773 test_bits = bytecode >> 7;
2774 if (test_bits == 1){
2775 test_bits = bytecode >> 6;
2776 if (test_bits == 2){
2778 * 10nnnnnn nnnnnnnn N 0 - 16383
2780 temp_data = buff[operand_address] & 0x1f;
2781 operand = temp_data << 8;
2782 temp_data = buff[operand_address + 1];
2783 operand = operand | temp_data;
2785 offset = offset + 2;
2789 * 111000000 nnnnnnnn nnnnnnnn N 0 - 65535
2792 temp_data = buff[operand_address] & 0x1f;
2793 operand = temp_data << 8;
2794 temp_data = buff[operand_address + 1];
2795 operand = operand | temp_data;
2797 offset = offset + 2;
2802 * 0nnnnnnn N 0 - 127
2804 operand = ( bytecode & 0x7f);
2814 * The second operand type is the reference ($), which is always used to
2815 * access a 2-byte value located elsewhere in the UDVM memory. The
2816 * bytecode for a reference operand is decoded to be a constant integer
2817 * from 0 to 65535 inclusive, which is interpreted as the memory address
2818 * containing the actual value of the operand.
2819 * Bytecode: Operand value: Range:
2821 * 0nnnnnnn memory[2 * N] 0 - 65535
2822 * 10nnnnnn nnnnnnnn memory[2 * N] 0 - 65535
2823 * 11000000 nnnnnnnn nnnnnnnn memory[N] 0 - 65535
2825 * Figure 9: Bytecode for a reference ($) operand
2828 dissect_udvm_reference_operand(guint8 *buff,guint operand_address, guint16 *value,guint *result_dest)
2832 guint offset = operand_address;
2835 guint16 temp_data16;
2837 bytecode = buff[operand_address];
2838 test_bits = bytecode >> 7;
2839 if (test_bits == 1){
2840 test_bits = bytecode >> 6;
2841 if (test_bits == 2){
2843 * 10nnnnnn nnnnnnnn memory[2 * N] 0 - 65535
2845 temp_data = buff[operand_address] & 0x3f;
2846 operand = temp_data << 8;
2847 temp_data = buff[operand_address + 1];
2848 operand = operand | temp_data;
2849 operand = (operand * 2);
2850 *result_dest = operand;
2851 temp_data16 = buff[operand] << 8;
2852 temp_data16 = temp_data16 | buff[operand+1];
2853 *value = temp_data16;
2854 offset = offset + 2;
2858 * 11000000 nnnnnnnn nnnnnnnn memory[N] 0 - 65535
2861 operand = buff[operand_address] << 8;
2862 operand = operand | buff[operand_address + 1];
2863 *result_dest = operand;
2864 temp_data16 = buff[operand] << 8;
2865 temp_data16 = temp_data16 | buff[operand+1];
2866 *value = temp_data16;
2867 offset = offset + 3;
2872 * 0nnnnnnn memory[2 * N] 0 - 65535
2874 operand = ( bytecode & 0x7f);
2875 operand = (operand * 2);
2876 *result_dest = operand;
2877 temp_data16 = buff[operand] << 8;
2878 temp_data16 = temp_data16 | buff[operand+1];
2879 *value = temp_data16;
2887 * Figure 10: Bytecode for a multitype (%) operand
2888 * Bytecode: Operand value: Range: HEX val
2889 * 00nnnnnn N 0 - 63 0x00
2890 * 01nnnnnn memory[2 * N] 0 - 65535 0x40
2891 * 1000011n 2 ^ (N + 6) 64 , 128 0x86
2892 * 10001nnn 2 ^ (N + 8) 256 , ... , 32768 0x88
2893 * 111nnnnn N + 65504 65504 - 65535 0xe0
2894 * 1001nnnn nnnnnnnn N + 61440 61440 - 65535 0x90
2895 * 101nnnnn nnnnnnnn N 0 - 8191 0xa0
2896 * 110nnnnn nnnnnnnn memory[N] 0 - 65535 0xc0
2897 * 10000000 nnnnnnnn nnnnnnnn N 0 - 65535 0x80
2898 * 10000001 nnnnnnnn nnnnnnnn memory[N] 0 - 65535 0x81
2901 decode_udvm_multitype_operand(guint8 *buff,guint operand_address, guint16 *value)
2905 guint offset = operand_address;
2909 guint16 temp_data16;
2910 guint16 memmory_addr = 0;
2912 bytecode = buff[operand_address];
2913 test_bits = ( bytecode & 0xc0 ) >> 6;
2914 switch (test_bits ){
2919 operand = buff[operand_address];
2921 *g_warning("Reading 0x%x From address %u",operand,offset);
2928 * 01nnnnnn memory[2 * N] 0 - 65535
2930 memmory_addr = ( bytecode & 0x3f) * 2;
2931 temp_data16 = buff[memmory_addr] << 8;
2932 temp_data16 = temp_data16 | buff[memmory_addr+1];
2933 *value = temp_data16;
2937 /* Check tree most significant bits */
2938 test_bits = ( bytecode & 0xe0 ) >> 5;
2939 if ( test_bits == 5 ){
2941 * 101nnnnn nnnnnnnn N 0 - 8191
2943 temp_data = buff[operand_address] & 0x1f;
2944 operand = temp_data << 8;
2945 temp_data = buff[operand_address + 1];
2946 operand = operand | temp_data;
2948 offset = offset + 2;
2950 test_bits = ( bytecode & 0xf0 ) >> 4;
2951 if ( test_bits == 9 ){
2953 * 1001nnnn nnnnnnnn N + 61440 61440 - 65535
2955 temp_data = buff[operand_address] & 0x0f;
2956 operand = temp_data << 8;
2957 temp_data = buff[operand_address + 1];
2958 operand = operand | temp_data;
2959 operand = operand + 61440;
2961 offset = offset + 2;
2963 test_bits = ( bytecode & 0x08 ) >> 3;
2964 if ( test_bits == 1){
2966 * 10001nnn 2 ^ (N + 8) 256 , ... , 32768
2969 result = 1 << ((buff[operand_address] & 0x07) + 8);
2970 operand = result & 0xffff;
2974 test_bits = ( bytecode & 0x0e ) >> 1;
2975 if ( test_bits == 3 ){
2977 * 1000 011n 2 ^ (N + 6) 64 , 128
2979 result = 1 << ((buff[operand_address] & 0x01) + 6);
2980 operand = result & 0xffff;
2985 * 1000 0000 nnnnnnnn nnnnnnnn N 0 - 65535
2986 * 1000 0001 nnnnnnnn nnnnnnnn memory[N] 0 - 65535
2989 temp_data16 = buff[operand_address + 1] << 8;
2990 temp_data16 = temp_data16 | buff[operand_address + 2];
2992 * g_warning("Reading 0x%x From address %u",temp_data16,operand_address);
2994 if ( (bytecode & 0x01) == 1 ){
2995 memmory_addr = temp_data16;
2996 temp_data16 = buff[memmory_addr] << 8;
2997 temp_data16 = temp_data16 | buff[memmory_addr+1];
2999 *value = temp_data16;
3010 test_bits = ( bytecode & 0x20 ) >> 5;
3011 if ( test_bits == 1 ){
3013 * 111nnnnn N + 65504 65504 - 65535
3015 operand = ( buff[operand_address] & 0x1f) + 65504;
3020 * 110nnnnn nnnnnnnn memory[N] 0 - 65535
3022 memmory_addr = buff[operand_address] & 0x1f;
3023 memmory_addr = memmory_addr << 8;
3024 memmory_addr = memmory_addr | buff[operand_address + 1];
3025 temp_data16 = buff[memmory_addr] << 8;
3026 temp_data16 = temp_data16 | buff[memmory_addr+1];
3027 *value = temp_data16;
3029 * g_warning("Reading 0x%x From address %u",temp_data16,memmory_addr);
3041 * The fourth operand type is the address (@). This operand is decoded
3042 * as a multitype operand followed by a further step: the memory address
3043 * of the UDVM instruction containing the address operand is added to
3044 * obtain the correct operand value. So if the operand value from
3045 * Figure 10 is D then the actual operand value of an address is
3046 * calculated as follows:
3048 * operand_value = (memory_address_of_instruction + D) modulo 2^16
3050 * Address operands are always used in instructions that control program
3051 * flow, because they ensure that the UDVM bytecode is position-
3052 * independent code (i.e., it will run independently of where it is
3053 * placed in the UDVM memory).
3056 decode_udvm_address_operand(guint8 *buff,guint operand_address, guint16 *value,guint current_address)
3060 guint next_opreand_address;
3062 next_opreand_address = decode_udvm_multitype_operand(buff, operand_address, &value1);
3063 result = value1 & 0xffff;
3064 result = result + current_address;
3065 *value = result & 0xffff;
3066 return next_opreand_address;
3071 * This is a lookup table used to reverse the bits in a byte.
3073 static guint8 reverse [] = {
3074 0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0,
3075 0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0,
3076 0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8,
3077 0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8,
3078 0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4,
3079 0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4,
3080 0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC,
3081 0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC,
3082 0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2,
3083 0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2,
3084 0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA,
3085 0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA,
3086 0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6,
3087 0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6,
3088 0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE,
3089 0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE,
3090 0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1,
3091 0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1,
3092 0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9,
3093 0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9,
3094 0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5,
3095 0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5,
3096 0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED,
3097 0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD,
3098 0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3,
3099 0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3,
3100 0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB,
3101 0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB,
3102 0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7,
3103 0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7,
3104 0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF,
3105 0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF
3110 decomp_dispatch_get_bits(
3111 tvbuff_t *message_tvb,
3112 proto_tree *udvm_tree,
3115 guint16 *old_input_bit_order,
3116 guint16 *remaining_bits,
3117 guint16 *input_bits,
3118 guint *input_address,
3120 guint16 *result_code,
3123 guint16 input_bit_order;
3124 guint16 bits_still_required = length;
3127 gint extra_bytes_available = msg_end - *input_address;
3129 gint prev_p_bit = *old_input_bit_order & 0x0001;
3130 gint bits_to_use = 0;
3133 input_bit_order = buff[68] << 8;
3134 input_bit_order = input_bit_order | buff[69];
3136 p_bit = (input_bit_order & 0x0001) != 0;
3139 * Discard any spare bits.
3140 * Note: We take care to avoid remaining_bits having the value of 8.
3142 if (prev_p_bit != p_bit)
3144 *remaining_bits = 0;
3145 *old_input_bit_order = input_bit_order;
3149 * Check we can suppy the required number of bits now, before we alter
3150 * the input buffer's state.
3152 if (*remaining_bits + extra_bytes_available * 8 < length)
3158 /* Note: This is never called with length > 16, so the following loop
3159 * never loops more than three time. */
3160 while (bits_still_required > 0)
3163 * We only put anything into input_bits if we know we will remove
3164 * at least one bit. That ensures we can simply discard the spare
3165 * bits if the P-bit changes.
3167 if (*remaining_bits == 0)
3169 octet = tvb_get_guint8(message_tvb, *input_address);
3170 if (print_level_1 ){
3171 proto_tree_add_text(udvm_tree, message_tvb, *input_address , 1,
3172 " Geting value: %u (0x%x) From Addr: %u", octet, octet, *input_address);
3174 *input_address = *input_address + 1;
3178 octet = reverse[octet];
3180 *input_bits = octet;
3181 *remaining_bits = 8;
3184 /* Add some more bits to the accumulated value. */
3185 bits_to_use = bits_still_required < *remaining_bits ? bits_still_required : *remaining_bits;
3186 bits_still_required -= bits_to_use;
3188 *input_bits <<= bits_to_use; /* Shift bits into MSByte */
3189 value = (value << bits_to_use) /* Then add to the accumulated value */
3190 | ((*input_bits >> 8) & 0xFF);
3191 *remaining_bits -= bits_to_use;
3192 *input_bits &= 0x00FF; /* Leave just the remaining bits */
3197 /* Bit reverse the entire word. */
3198 guint16 lsb = reverse[(value >> 8) & 0xFF];
3199 guint16 msb = reverse[value & 0xFF];
3201 value = ((msb << 8) | lsb) >> (16 - length);