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[STATE_BUFFER_SIZE];
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 memset(buff, 0, UDVM_MEMORY_SIZE);
259 /* Set initial UDVM data
260 * The first 32 bytes of UDVM memory are then initialized to special
261 * values as illustrated in Figure 5.
264 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
265 * | UDVM_memory_size | 0 - 1
266 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
267 * | cycles_per_bit | 2 - 3
268 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
269 * | SigComp_version | 4 - 5
270 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
271 * | partial_state_ID_length | 6 - 7
272 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
273 * | state_length | 8 - 9
274 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
276 * : reserved : 10 - 31
278 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
280 * Figure 5: Initializing Useful Values in UDVM memory
282 /* UDVM_memory_size */
283 buff[0] = (UDVM_MEMORY_SIZE >> 8) & 0x00FF;
284 buff[1] = UDVM_MEMORY_SIZE & 0x00FF;
288 /* SigComp_version */
291 /* partial_state_ID_length */
292 buff[6] = (byte_code_id_len >> 8) & 0x00FF;
293 buff[7] = byte_code_id_len & 0x00FF;
295 buff[8] = (byte_code_state_len >> 8) & 0x00FF;
296 buff[9] = byte_code_state_len & 0x00FF;
298 code_length = tvb_reported_length_remaining(bytecode_tvb, 0);
300 cycles_per_bit = buff[2] << 8;
301 cycles_per_bit = cycles_per_bit | buff[3];
303 * maximum_UDVM_cycles = (8 * n + 1000) * cycles_per_bit
305 maximum_UDVM_cycles = (( 8 * (header_len + msg_end) ) + 1000) * cycles_per_bit;
307 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);
308 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);
310 /* Load bytecode into UDVM starting at "udvm_mem_dest" */
313 proto_tree_add_text(udvm_tree, bytecode_tvb, offset, 1,"Load bytecode into UDVM starting at %u",i);
314 while ( code_length > offset ) {
315 buff[i] = tvb_get_guint8(bytecode_tvb, offset);
317 proto_tree_add_text(udvm_tree, bytecode_tvb, offset, 1,
318 " Addr: %u Instruction code(0x%0x) ", i, buff[i]);
324 /* Largest allowed size for a message is 65535 */
325 out_buff = g_malloc(65535);
326 /* Start executing code */
327 current_address = udvm_start_ip;
331 proto_tree_add_text(udvm_tree, bytecode_tvb, offset, 1,"UDVM EXECUTION STARTED at Address: %u Message size %u",
332 current_address, msg_end);
334 execute_next_instruction:
336 if ( used_udvm_cycles > maximum_UDVM_cycles ){
338 goto decompression_failure;
340 current_instruction = buff[current_address];
342 switch ( current_instruction ) {
343 case SIGCOMP_INSTR_DECOMPRESSION_FAILURE:
345 if ( result_code == 0 )
347 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
348 "Addr: %u ## DECOMPRESSION-FAILURE(0)",
350 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Ethereal UDVM diagnostic: %s.",
351 val_to_str(result_code, result_code_vals,"Unknown (%u)"));
352 if ( output_address > 0 ){
353 /* At least something got decompressed, show it */
354 decomp_tvb = tvb_new_real_data(out_buff,output_address,output_address);
355 /* Arrange that the allocated packet data copy be freed when the
358 tvb_set_free_cb( decomp_tvb, g_free );
359 /* Add the tvbuff to the list of tvbuffs to which the tvbuff we
360 * were handed refers, so it'll get cleaned up when that tvbuff
363 tvb_set_child_real_data_tvbuff(message_tvb,decomp_tvb);
364 add_new_data_source(pinfo, decomp_tvb, "Decompressed SigComp message(Incomplete)");
365 proto_tree_add_text(udvm_tree, decomp_tvb, 0, -1,"SigComp message Decompression failure");
372 case SIGCOMP_INSTR_AND: /* 1 AND ($operand_1, %operand_2) */
374 if (show_instr_detail_level == 2 ){
375 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
376 "Addr: %u ## AND(1) (operand_1, operand_2)",
380 operand_address = current_address + 1;
381 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &operand_1, &result_dest);
382 if (show_instr_detail_level == 2 ){
383 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_1 %u",
384 operand_address, operand_1);
386 operand_address = next_operand_address;
388 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &operand_2);
389 if (show_instr_detail_level == 2 ){
390 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_2 %u",
391 operand_address, operand_2);
393 if (show_instr_detail_level == 1)
395 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
396 "Addr: %u ## AND (operand_1=%u, operand_2=%u)",
397 current_address, operand_1, operand_2);
399 /* execute the instruction */
400 result = operand_1 & operand_2;
403 buff[result_dest] = msb;
404 buff[result_dest+1] = lsb;
406 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," Loading result %u at %u",
407 result, result_dest);
409 current_address = next_operand_address;
410 goto execute_next_instruction;
414 case SIGCOMP_INSTR_OR: /* 2 OR ($operand_1, %operand_2) */
416 if (show_instr_detail_level == 2 ){
417 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
418 "Addr: %u ## OR(2) (operand_1, operand_2)",
422 operand_address = current_address + 1;
423 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &operand_1, &result_dest);
424 if (show_instr_detail_level == 2 ){
425 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_1 %u",
426 operand_address, operand_1);
428 operand_address = next_operand_address;
430 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &operand_2);
431 if (show_instr_detail_level == 2 ){
432 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_2 %u",
433 operand_address, operand_2);
435 if (show_instr_detail_level == 1)
437 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
438 "Addr: %u ## OR (operand_1=%u, operand_2=%u)",
439 current_address, operand_1, operand_2);
441 /* execute the instruction */
442 result = operand_1 | operand_2;
445 buff[result_dest] = msb;
446 buff[result_dest+1] = lsb;
448 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," Loading result %u at %u",
449 result, result_dest);
451 current_address = next_operand_address;
452 goto execute_next_instruction;
456 case SIGCOMP_INSTR_NOT: /* 3 NOT ($operand_1) */
458 if (show_instr_detail_level == 2 ){
459 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
460 "Addr: %u ## NOT(3) ($operand_1)",
464 operand_address = current_address + 1;
465 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &operand_1, &result_dest);
466 if (show_instr_detail_level == 2 ){
467 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_1 %u",
468 operand_address, operand_1);
470 if (show_instr_detail_level == 1)
472 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
473 "Addr: %u ## NOT (operand_1=%u)",
474 current_address, operand_1);
476 /* execute the instruction */
477 result = operand_1 ^ 0xffff;
480 buff[result_dest] = msb;
481 buff[result_dest+1] = lsb;
483 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," Loading result %u at %u",
484 result, result_dest);
486 current_address = next_operand_address;
487 goto execute_next_instruction;
490 case SIGCOMP_INSTR_LSHIFT: /* 4 LSHIFT ($operand_1, %operand_2) */
492 if (show_instr_detail_level == 2 ){
493 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
494 "Addr: %u ## LSHIFT(4) ($operand_1, operand_2)",
498 operand_address = current_address + 1;
499 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &operand_1, &result_dest);
500 if (show_instr_detail_level == 2 ){
501 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_1 %u",
502 operand_address, operand_1);
504 operand_address = next_operand_address;
506 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &operand_2);
507 if (show_instr_detail_level == 2 ){
508 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_2 %u",
509 operand_address, operand_2);
511 if (show_instr_detail_level == 1)
513 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
514 "Addr: %u ## LSHIFT (operand_1=%u, operand_2=%u)",
515 current_address, operand_1, operand_2);
517 /* execute the instruction */
518 result = operand_1 << operand_2;
521 buff[result_dest] = msb;
522 buff[result_dest+1] = lsb;
524 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," Loading result %u at %u",
525 result, result_dest);
527 current_address = next_operand_address;
528 goto execute_next_instruction;
531 case SIGCOMP_INSTR_RSHIFT: /* 5 RSHIFT ($operand_1, %operand_2) */
533 if (show_instr_detail_level == 2 ){
534 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
535 "Addr: %u ## RSHIFT(5) (operand_1, operand_2)",
539 operand_address = current_address + 1;
540 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &operand_1, &result_dest);
541 if (show_instr_detail_level == 2 ){
542 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_1 %u",
543 operand_address, operand_1);
545 operand_address = next_operand_address;
547 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &operand_2);
548 if (show_instr_detail_level == 2 ){
549 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_2 %u",
550 operand_address, operand_2);
552 if (show_instr_detail_level == 1)
554 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
555 "Addr: %u ## RSHIFT (operand_1=%u, operand_2=%u)",
556 current_address, operand_1, operand_2);
558 /* execute the instruction */
559 result = operand_1 >> operand_2;
562 buff[result_dest] = msb;
563 buff[result_dest+1] = lsb;
565 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," Loading result %u at %u",
566 result, result_dest);
568 current_address = next_operand_address;
569 goto execute_next_instruction;
571 case SIGCOMP_INSTR_ADD: /* 6 ADD ($operand_1, %operand_2) */
573 if (show_instr_detail_level == 2 ){
574 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
575 "Addr: %u ## ADD(6) (operand_1, operand_2)",
579 operand_address = current_address + 1;
580 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &operand_1, &result_dest);
581 if (show_instr_detail_level == 2 ){
582 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_1 %u",
583 operand_address, operand_1);
585 operand_address = next_operand_address;
587 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &operand_2);
588 if (show_instr_detail_level == 2 ){
589 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_2 %u",
590 operand_address, operand_2);
592 if (show_instr_detail_level == 1)
594 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
595 "Addr: %u ## ADD (operand_1=%u, operand_2=%u)",
596 current_address, operand_1, operand_2);
598 /* execute the instruction */
599 result = operand_1 + operand_2;
602 buff[result_dest] = msb;
603 buff[result_dest+1] = lsb;
605 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," Loading result %u at %u",
606 result, result_dest);
608 current_address = next_operand_address;
609 goto execute_next_instruction;
611 case SIGCOMP_INSTR_SUBTRACT: /* 7 SUBTRACT ($operand_1, %operand_2) */
613 if (show_instr_detail_level == 2 ){
614 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
615 "Addr: %u ## SUBTRACT(7) (operand_1, operand_2)",
619 operand_address = current_address + 1;
620 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &operand_1, &result_dest);
621 if (show_instr_detail_level == 2 ){
622 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_1 %u",
623 operand_address, operand_1);
625 operand_address = next_operand_address;
627 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &operand_2);
628 if (show_instr_detail_level == 2 ){
629 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_2 %u",
630 operand_address, operand_2);
632 if (show_instr_detail_level == 1)
634 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
635 "Addr: %u ## SUBTRACT (operand_1=%u, operand_2=%u)",
636 current_address, operand_1, operand_2);
638 /* execute the instruction */
639 result = operand_1 - operand_2;
642 buff[result_dest] = msb;
643 buff[result_dest+1] = lsb;
645 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," Loading result %u at %u",
646 result, result_dest);
648 current_address = next_operand_address;
649 goto execute_next_instruction;
652 case SIGCOMP_INSTR_MULTIPLY: /* 8 MULTIPLY ($operand_1, %operand_2) */
654 if (show_instr_detail_level == 2 ){
655 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
656 "Addr: %u ##MULTIPLY(8) (operand_1, operand_2)",
660 operand_address = current_address + 1;
661 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &operand_1, &result_dest);
662 if (show_instr_detail_level == 2 ){
663 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_1 %u",
664 operand_address, operand_1);
666 operand_address = next_operand_address;
668 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &operand_2);
669 if (show_instr_detail_level == 2 ){
670 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_2 %u",
671 operand_address, operand_2);
673 if (show_instr_detail_level == 1)
675 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
676 "Addr: %u ## MULTIPLY (operand_1=%u, operand_2=%u)",
677 current_address, operand_1, operand_2);
680 * execute the instruction
681 * MULTIPLY (m, n) := m * n (modulo 2^16)
683 if ( operand_2 == 0){
685 goto decompression_failure;
687 result = operand_1 * operand_2;
690 buff[result_dest] = msb;
691 buff[result_dest+1] = lsb;
693 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," Loading result %u at %u",
694 result, result_dest);
696 current_address = next_operand_address;
697 goto execute_next_instruction;
700 case SIGCOMP_INSTR_DIVIDE: /* 9 DIVIDE ($operand_1, %operand_2) */
702 if (show_instr_detail_level == 2 ){
703 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
704 "Addr: %u ## DIVIDE(9) (operand_1, operand_2)",
708 operand_address = current_address + 1;
709 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &operand_1, &result_dest);
710 if (show_instr_detail_level == 2 ){
711 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_1 %u",
712 operand_address, operand_1);
714 operand_address = next_operand_address;
716 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &operand_2);
717 if (show_instr_detail_level == 2 ){
718 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_2 %u",
719 operand_address, operand_2);
721 if (show_instr_detail_level == 1)
723 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
724 "Addr: %u ## DIVIDE (operand_1=%u, operand_2=%u)",
725 current_address, operand_1, operand_2);
728 * execute the instruction
729 * DIVIDE (m, n) := floor(m / n)
730 * Decompression failure occurs if a DIVIDE or REMAINDER instruction
731 * encounters an operand_2 that is zero.
733 if ( operand_2 == 0){
735 goto decompression_failure;
737 result = operand_1 / operand_2;
740 buff[result_dest] = msb;
741 buff[result_dest+1] = lsb;
743 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," Loading result %u at %u",
744 result, result_dest);
746 current_address = next_operand_address;
747 goto execute_next_instruction;
750 case SIGCOMP_INSTR_REMAINDER: /* 10 REMAINDER ($operand_1, %operand_2) */
752 if (show_instr_detail_level == 2 ){
753 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
754 "Addr: %u ## REMAINDER(10) (operand_1, operand_2)",
758 operand_address = current_address + 1;
759 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &operand_1, &result_dest);
760 if (show_instr_detail_level == 2 ){
761 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_1 %u",
762 operand_address, operand_1);
764 operand_address = next_operand_address;
766 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &operand_2);
767 if (show_instr_detail_level == 2 ){
768 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_2 %u",
769 operand_address, operand_2);
771 if (show_instr_detail_level == 1)
773 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
774 "Addr: %u ## REMAINDER (operand_1=%u, operand_2=%u)",
775 current_address, operand_1, operand_2);
778 * execute the instruction
779 * REMAINDER (m, n) := m - n * floor(m / n)
780 * Decompression failure occurs if a DIVIDE or REMAINDER instruction
781 * encounters an operand_2 that is zero.
783 if ( operand_2 == 0){
785 goto decompression_failure;
787 result = operand_1 - operand_2 * (operand_1 / operand_2);
790 buff[result_dest] = msb;
791 buff[result_dest+1] = lsb;
793 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," Loading result %u at %u",
794 result, result_dest);
796 current_address = next_operand_address;
797 goto execute_next_instruction;
799 case SIGCOMP_INSTR_SORT_ASCENDING: /* 11 SORT-ASCENDING (%start, %n, %k) */
801 * used_udvm_cycles = 1 + k * (ceiling(log2(k)) + n)
804 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
805 "Addr: %u ## SORT-ASCENDING(11) (start, n, k))",
808 operand_address = current_address + 1;
809 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Execution of this instruction is NOT implemented");
811 * used_udvm_cycles = 1 + k * (ceiling(log2(k)) + n)
815 case SIGCOMP_INSTR_SORT_DESCENDING: /* 12 SORT-DESCENDING (%start, %n, %k) */
817 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
818 "Addr: %u ## SORT-DESCENDING(12) (start, n, k))",
821 operand_address = current_address + 1;
822 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Execution of this instruction is NOT implemented");
824 * used_udvm_cycles = 1 + k * (ceiling(log2(k)) + n)
827 case SIGCOMP_INSTR_SHA_1: /* 13 SHA-1 (%position, %length, %destination) */
829 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
830 "Addr: %u ## SHA-1(13) (position, length, destination)",
833 operand_address = current_address + 1;
835 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &position);
837 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u position %u",
838 operand_address, position);
840 operand_address = next_operand_address;
843 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &length);
845 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Length %u",
846 operand_address, length);
848 operand_address = next_operand_address;
851 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &ref_destination, &result_dest);
853 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u $destination %u",
854 operand_address, ref_destination);
856 current_address = next_operand_address;
857 used_udvm_cycles = used_udvm_cycles + 1 + length;
861 byte_copy_right = buff[66] << 8;
862 byte_copy_right = byte_copy_right | buff[67];
863 byte_copy_left = buff[64] << 8;
864 byte_copy_left = byte_copy_left | buff[65];
867 proto_tree_add_text(udvm_tree, message_tvb, 0, -1,
868 "byte_copy_right = %u", byte_copy_right);
874 guint16 handle_now = length;
876 if ( k < byte_copy_right && byte_copy_right <= k + (length-n) ){
877 handle_now = byte_copy_right - position;
880 sha1_update( &ctx, &buff[k], handle_now );
882 k = ( k + handle_now ) & 0xffff;
883 n = ( n + handle_now ) & 0xffff;
885 if ( k >= byte_copy_right ) {
890 sha1_finish( &ctx, sha1_digest_buf );
894 for ( n=0; n< STATE_BUFFER_SIZE; n++ ) {
896 buff[k] = sha1_digest_buf[n];
898 k = ( k + 1 ) & 0xffff;
901 if ( k == byte_copy_right ){
907 proto_tree_add_text(udvm_tree, message_tvb, 0, -1,
908 "Calculated SHA-1: %s",
909 bytes_to_str(sha1_digest_buf, STATE_BUFFER_SIZE));
912 current_address = next_operand_address;
913 goto execute_next_instruction;
916 case SIGCOMP_INSTR_LOAD: /* 14 LOAD (%address, %value) */
917 if (show_instr_detail_level == 2 ){
918 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
919 "Addr: %u ## LOAD(14) (%%address, %%value)",
922 operand_address = current_address + 1;
924 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &address);
925 if (show_instr_detail_level == 2 ){
926 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Address %u",
927 operand_address, address);
929 operand_address = next_operand_address;
931 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &value);
932 if (show_instr_detail_level == 1)
934 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
935 "Addr: %u ## LOAD (%%address=%u, %%value=%u)",
936 current_address, address, value);
942 buff[address + 1] = lsb;
945 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Value %u",
946 operand_address, value);
947 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," Loading bytes at %u Value %u 0x%x",
948 address, value, value);
951 current_address = next_operand_address;
952 goto execute_next_instruction;
955 case SIGCOMP_INSTR_MULTILOAD: /* 15 MULTILOAD (%address, #n, %value_0, ..., %value_n-1) */
957 * The MULTILOAD instruction sets a contiguous block of 2-byte words in
958 * the UDVM memory to specified values.
959 * Hmm what if the value to load only takes one byte ? Chose to always load two bytes.
961 if (show_instr_detail_level == 2 ){
962 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
963 "Addr: %u ## MULTILOAD(15) (%%address, #n, value_0, ..., value_n-1)",
966 operand_address = current_address + 1;
968 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &address);
969 if (show_instr_detail_level == 2 ){
970 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Address %u",
971 operand_address, address);
973 operand_address = next_operand_address;
976 next_operand_address = decode_udvm_literal_operand(buff,operand_address, &n);
977 if (show_instr_detail_level == 2 ){
978 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u n %u",
981 if (show_instr_detail_level == 1)
983 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
984 "Addr: %u ## MULTILOAD (%%address=%u, #n=%u, value_0, ..., value_%d)",
985 current_address, address, n, n-1);
987 operand_address = next_operand_address;
988 used_udvm_cycles = used_udvm_cycles + 1 + n;
992 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &value);
997 buff[address + 1] = lsb;
1000 length = next_operand_address - operand_address;
1002 if (print_level_1 ){
1003 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1, "Addr: %u Value %5u - Loading bytes at %5u Value %5u 0x%x",
1004 operand_address, value, address, value, value);
1006 address = address + 2;
1007 operand_address = next_operand_address;
1009 current_address = next_operand_address;
1010 goto execute_next_instruction;
1014 case SIGCOMP_INSTR_PUSH: /* 16 PUSH (%value) */
1015 if (show_instr_detail_level == 2){
1016 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1017 "Addr: %u ## PUSH(16) (value)",
1020 operand_address = current_address + 1;
1022 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &value);
1023 if (show_instr_detail_level == 2){
1024 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Value %u",
1025 operand_address, value);
1027 if (show_instr_detail_level == 1)
1029 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1030 "Addr: %u ## PUSH (value=%u)",
1031 current_address, value);
1033 current_address = next_operand_address;
1035 /* Push the value address onto the stack */
1036 stack_location = (buff[70] << 8) | buff[71];
1037 stack_fill = (buff[stack_location] << 8)
1038 | buff[(stack_location+1) & 0xFFFF];
1039 address = (stack_location + stack_fill * 2 + 2) & 0xFFFF;
1041 buff[address] = (value >> 8) & 0x00FF;
1042 buff[(address+1) & 0xFFFF] = value & 0x00FF;
1044 stack_fill = (stack_fill + 1) & 0xFFFF;
1045 buff[stack_location] = (stack_fill >> 8) & 0x00FF;
1046 buff[(stack_location+1) & 0xFFFF] = stack_fill & 0x00FF;
1049 goto execute_next_instruction;
1053 case SIGCOMP_INSTR_POP: /* 17 POP (%address) */
1054 if (show_instr_detail_level == 2){
1055 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1056 "Addr: %u ## POP(16) (value)",
1059 operand_address = current_address + 1;
1061 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &destination);
1062 if (show_instr_detail_level == 2){
1063 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Value %u",
1064 operand_address, destination);
1066 if (show_instr_detail_level == 1)
1068 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1069 "Addr: %u ## POP (address=%u)",
1070 current_address, destination);
1072 current_address = next_operand_address;
1074 /* Pop value from the top of the stack */
1075 stack_location = (buff[70] << 8) | buff[71];
1076 stack_fill = (buff[stack_location] << 8)
1077 | buff[(stack_location+1) & 0xFFFF];
1078 if (stack_fill == 0)
1081 goto decompression_failure;
1084 stack_fill = (stack_fill - 1) & 0xFFFF;
1085 buff[stack_location] = (stack_fill >> 8) & 0x00FF;
1086 buff[(stack_location+1) & 0xFFFF] = stack_fill & 0x00FF;
1088 address = (stack_location + stack_fill * 2 + 2) & 0xFFFF;
1089 value = (buff[address] << 8)
1090 | buff[(address+1) & 0xFFFF];
1092 /* ... and store the popped value. */
1093 buff[destination] = (value >> 8) & 0x00FF;
1094 buff[(destination+1) & 0xFFFF] = value & 0x00FF;
1097 goto execute_next_instruction;
1101 case SIGCOMP_INSTR_COPY: /* 18 COPY (%position, %length, %destination) */
1102 if (show_instr_detail_level == 2 ){
1103 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1104 "Addr: %u ## COPY(18) (position, length, destination)",
1107 operand_address = current_address + 1;
1109 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &position);
1110 if (show_instr_detail_level == 2 ){
1111 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u position %u",
1112 operand_address, position);
1114 operand_address = next_operand_address;
1117 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &length);
1118 if (show_instr_detail_level == 2 ){
1119 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Length %u",
1120 operand_address, length);
1122 operand_address = next_operand_address;
1125 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &destination);
1126 if (show_instr_detail_level == 2 ){
1127 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Destination %u",
1128 operand_address, destination);
1130 if (show_instr_detail_level == 1)
1132 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1133 "Addr: %u ## COPY (position=%u, length=%u, destination=%u)",
1134 current_address, position, length, destination);
1136 current_address = next_operand_address;
1140 * The string of bytes is copied in ascending order of memory address,
1141 * respecting the bounds set by byte_copy_left and byte_copy_right.
1142 * More precisely, if a byte is copied from/to Address m then the next
1143 * byte is copied from/to Address n where n is calculated as follows:
1145 * Set k := m + 1 (modulo 2^16)
1146 * If k = byte_copy_right then set n := byte_copy_left, else set n := k
1152 byte_copy_right = buff[66] << 8;
1153 byte_copy_right = byte_copy_right | buff[67];
1154 byte_copy_left = buff[64] << 8;
1155 byte_copy_left = byte_copy_left | buff[65];
1156 if (print_level_2 ){
1157 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
1158 " byte_copy_right = %u", byte_copy_right);
1161 while ( n < length ){
1162 buff[k] = buff[position];
1163 if (print_level_2 ){
1164 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
1165 " Copying value: %u (0x%x) to Addr: %u",
1166 buff[position], buff[position], k);
1168 position = ( position + 1 ) & 0xffff;
1169 k = ( k + 1 ) & 0xffff;
1173 * Check for circular buffer wrapping after the positions are
1174 * incremented. If either started at BCR then they should continue
1175 * to increment beyond BCR.
1177 if ( k == byte_copy_right ){
1180 if ( position == byte_copy_right ){
1181 position = byte_copy_left;
1184 used_udvm_cycles = used_udvm_cycles + 1 + length;
1185 goto execute_next_instruction;
1188 case SIGCOMP_INSTR_COPY_LITERAL: /* 19 COPY-LITERAL (%position, %length, $destination) */
1189 if (show_instr_detail_level == 2 ){
1190 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1191 "Addr: %u ## COPY-LITERAL(19) (position, length, $destination)",
1194 operand_address = current_address + 1;
1196 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &position);
1197 if (show_instr_detail_level == 2 ){
1198 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u position %u",
1199 operand_address, position);
1201 operand_address = next_operand_address;
1204 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &length);
1205 if (show_instr_detail_level == 2 ){
1206 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Length %u",
1207 operand_address, length);
1209 operand_address = next_operand_address;
1213 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &ref_destination, &result_dest);
1214 if (show_instr_detail_level == 2 ){
1215 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u destination %u",
1216 operand_address, ref_destination);
1218 if (show_instr_detail_level == 1)
1220 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1221 "Addr: %u ## COPY-LITERAL (position=%u, length=%u, $destination=%u)",
1222 current_address, position, length, destination);
1224 current_address = next_operand_address;
1230 * The string of bytes is copied in ascending order of memory address,
1231 * respecting the bounds set by byte_copy_left and byte_copy_right.
1232 * More precisely, if a byte is copied from/to Address m then the next
1233 * byte is copied from/to Address n where n is calculated as follows:
1235 * Set k := m + 1 (modulo 2^16)
1236 * If k = byte_copy_right then set n := byte_copy_left, else set n := k
1241 k = ref_destination;
1242 byte_copy_right = buff[66] << 8;
1243 byte_copy_right = byte_copy_right | buff[67];
1244 byte_copy_left = buff[64] << 8;
1245 byte_copy_left = byte_copy_left | buff[65];
1246 if (print_level_2 ){
1247 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
1248 " byte_copy_right = %u", byte_copy_right);
1250 while ( n < length ){
1252 buff[k] = buff[position];
1253 if (print_level_2 ){
1254 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
1255 " Copying value: %u (0x%x) to Addr: %u",
1256 buff[position], buff[position], k);
1258 position = ( position + 1 ) & 0xffff;
1259 k = ( k + 1 ) & 0xffff;
1263 * Check for circular buffer wrapping after the positions are
1264 * incremented. It is important that k cannot be left set
1265 * to BCR. Also, if either started at BCR then they should continue
1266 * to increment beyond BCR.
1268 if ( k == byte_copy_right ){
1271 if ( position == byte_copy_right ){
1272 position = byte_copy_left;
1275 buff[result_dest] = k >> 8;
1276 buff[result_dest + 1] = k & 0x00ff;
1278 used_udvm_cycles = used_udvm_cycles + 1 + length;
1279 goto execute_next_instruction;
1282 case SIGCOMP_INSTR_COPY_OFFSET: /* 20 COPY-OFFSET (%offset, %length, $destination) */
1283 if (show_instr_detail_level == 2 ){
1284 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1285 "Addr: %u ## COPY-OFFSET(20) (offset, length, $destination)",
1288 operand_address = current_address + 1;
1290 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &multy_offset);
1291 if (show_instr_detail_level == 2 ){
1292 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u offset %u",
1293 operand_address, multy_offset);
1295 operand_address = next_operand_address;
1298 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &length);
1299 if (show_instr_detail_level == 2 ){
1300 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Length %u",
1301 operand_address, length);
1303 operand_address = next_operand_address;
1307 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &ref_destination, &result_dest);
1308 if (show_instr_detail_level == 2 ){
1309 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u $destination %u",
1310 operand_address, ref_destination);
1313 if (show_instr_detail_level == 1)
1315 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1316 "Addr: %u ## COPY-OFFSET (offset=%u, length=%u, $destination=%u)",
1317 current_address, multy_offset, length, result_dest);
1319 current_address = next_operand_address;
1321 /* Execute the instruction:
1322 * To derive the value of the position operand, starting at the memory
1323 * address specified by destination, the UDVM counts backwards a total
1324 * of offset memory addresses.
1326 * If the memory address specified in byte_copy_left is reached, the
1327 * next memory address is taken to be (byte_copy_right - 1) modulo 2^16.
1329 byte_copy_left = buff[64] << 8;
1330 byte_copy_left = byte_copy_left | buff[65];
1331 byte_copy_right = buff[66] << 8;
1332 byte_copy_right = byte_copy_right | buff[67];
1335 * In order to work out the position, simple arithmetic is tricky
1336 * to apply because there some nasty corner cases. A simple loop
1337 * is inefficient but the logic is simple.
1339 * FUTURE: This could be optimised.
1341 for (position = ref_destination, i = 0; i < multy_offset; i++)
1343 if ( position == byte_copy_left )
1345 position = (byte_copy_right - 1) & 0xffff;
1349 position = (position - 1) & 0xffff;
1353 if (print_level_2 ){
1354 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
1355 " byte_copy_left = %u byte_copy_right = %u position= %u",
1356 byte_copy_left, byte_copy_right, position);
1358 /* The COPY-OFFSET instruction then behaves as a COPY-LITERAL
1359 * instruction, taking the value of the position operand to be the last
1360 * memory address reached in the above step.
1366 * The string of bytes is copied in ascending order of memory address,
1367 * respecting the bounds set by byte_copy_left and byte_copy_right.
1368 * More precisely, if a byte is copied from/to Address m then the next
1369 * byte is copied from/to Address n where n is calculated as follows:
1371 * Set k := m + 1 (modulo 2^16)
1372 * If k = byte_copy_right then set n := byte_copy_left, else set n := k
1377 k = ref_destination;
1378 if (print_level_2 ){
1379 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
1380 " byte_copy_left = %u byte_copy_right = %u", byte_copy_left, byte_copy_right);
1382 while ( n < length ){
1383 buff[k] = buff[position];
1384 if (print_level_2 ){
1385 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
1386 " Copying value: %5u (0x%x) from Addr: %u to Addr: %u",
1387 buff[position], buff[position],(position), k);
1390 k = ( k + 1 ) & 0xffff;
1391 position = ( position + 1 ) & 0xffff;
1394 * Check for circular buffer wrapping after the positions are
1395 * incremented. It is important that k cannot be left set
1396 * to BCR. Also, if either started at BCR then they should continue
1397 * to increment beyond BCR.
1399 if ( k == byte_copy_right ){
1402 if ( position == byte_copy_right ){
1403 position = byte_copy_left;
1406 buff[result_dest] = k >> 8;
1407 buff[result_dest + 1] = k & 0x00ff;
1408 used_udvm_cycles = used_udvm_cycles + 1 + length;
1409 goto execute_next_instruction;
1412 case SIGCOMP_INSTR_MEMSET: /* 21 MEMSET (%address, %length, %start_value, %offset) */
1413 if (show_instr_detail_level == 2 ){
1414 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1415 "Addr: %u ## MEMSET(21) (address, length, start_value, offset)",
1418 operand_address = current_address + 1;
1421 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &address);
1422 if (show_instr_detail_level == 2 ){
1423 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Address %u",
1424 operand_address, address);
1426 operand_address = next_operand_address;
1429 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &length);
1430 if (show_instr_detail_level == 2 ){
1431 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Length %u",
1432 operand_address, length);
1434 operand_address = next_operand_address;
1436 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &start_value);
1437 if (show_instr_detail_level == 2 ){
1438 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u start_value %u",
1439 operand_address, start_value);
1441 operand_address = next_operand_address;
1444 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &multy_offset);
1445 if (show_instr_detail_level == 2 ){
1446 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u offset %u",
1447 operand_address, multy_offset);
1449 if (show_instr_detail_level == 1)
1451 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1452 "Addr: %u ## MEMSET (address=%u, length=%u, start_value=%u, offset=%u)",
1453 current_address, address, length, start_value, multy_offset);
1455 current_address = next_operand_address;
1456 /* exetute the instruction
1457 * The sequence of values used by the MEMSET instruction is specified by
1458 * the following formula:
1460 * Seq[n] := (start_value + n * offset) modulo 256
1464 byte_copy_right = buff[66] << 8;
1465 byte_copy_right = byte_copy_right | buff[67];
1466 byte_copy_left = buff[64] << 8;
1467 byte_copy_left = byte_copy_left | buff[65];
1468 if (print_level_2 ){
1469 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
1470 " byte_copy_left = %u byte_copy_right = %u", byte_copy_left, byte_copy_right);
1472 while ( n < length ){
1473 if ( k == byte_copy_right ){
1476 buff[k] = (start_value + ( n * multy_offset)) & 0xff;
1477 if (print_level_2 ){
1478 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
1479 " Storing value: %u (0x%x) at Addr: %u",
1480 buff[k], buff[k], k);
1482 k = ( k + 1 ) & 0xffff;
1485 used_udvm_cycles = used_udvm_cycles + 1 + length;
1486 goto execute_next_instruction;
1490 case SIGCOMP_INSTR_JUMP: /* 22 JUMP (@address) */
1491 if (show_instr_detail_level == 2 ){
1492 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1493 "Addr: %u ## JUMP(22) (@address)",
1496 operand_address = current_address + 1;
1498 /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
1499 next_operand_address = decode_udvm_address_operand(buff,operand_address, &at_address, current_address);
1500 if (show_instr_detail_level == 2 ){
1501 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u @Address %u",
1502 operand_address, at_address);
1504 if (show_instr_detail_level == 1)
1506 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1507 "Addr: %u ## JUMP (@address=%u)",
1508 current_address, at_address);
1510 current_address = at_address;
1512 goto execute_next_instruction;
1515 case SIGCOMP_INSTR_COMPARE: /* 23 */
1516 /* COMPARE (%value_1, %value_2, @address_1, @address_2, @address_3)
1518 if (show_instr_detail_level == 2 ){
1519 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1520 "Addr: %u ## COMPARE(23) (value_1, value_2, @address_1, @address_2, @address_3)",
1523 operand_address = current_address + 1;
1526 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &value_1);
1527 if (show_instr_detail_level == 2 ){
1528 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Value %u",
1529 operand_address, value_1);
1531 operand_address = next_operand_address;
1534 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &value_2);
1535 if (show_instr_detail_level == 2 ){
1536 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Value %u",
1537 operand_address, value_2);
1539 operand_address = next_operand_address;
1542 /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
1543 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &at_address_1);
1544 at_address_1 = ( current_address + at_address_1) & 0xffff;
1545 if (show_instr_detail_level == 2 ){
1546 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u @Address %u",
1547 operand_address, at_address_1);
1549 operand_address = next_operand_address;
1553 /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
1554 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &at_address_2);
1555 at_address_2 = ( current_address + at_address_2) & 0xffff;
1556 if (show_instr_detail_level == 2 ){
1557 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u @Address %u",
1558 operand_address, at_address_2);
1560 operand_address = next_operand_address;
1563 /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
1564 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &at_address_3);
1565 at_address_3 = ( current_address + at_address_3) & 0xffff;
1566 if (show_instr_detail_level == 2 ){
1567 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u @Address %u",
1568 operand_address, at_address_3);
1570 if (show_instr_detail_level == 1)
1572 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1573 "Addr: %u ## COMPARE (value_1=%u, value_2=%u, @address_1=%u, @address_2=%u, @address_3=%u)",
1574 current_address, value_1, value_2, at_address_1, at_address_2, at_address_3);
1576 /* execute the instruction
1577 * If value_1 < value_2 then the UDVM continues instruction execution at
1578 * the memory address specified by address 1. If value_1 = value_2 then
1579 * it jumps to the address specified by address_2. If value_1 > value_2
1580 * then it jumps to the address specified by address_3.
1582 if ( value_1 < value_2 )
1583 current_address = at_address_1;
1584 if ( value_1 == value_2 )
1585 current_address = at_address_2;
1586 if ( value_1 > value_2 )
1587 current_address = at_address_3;
1589 goto execute_next_instruction;
1592 case SIGCOMP_INSTR_CALL: /* 24 CALL (@address) (PUSH addr )*/
1593 if (show_instr_detail_level == 2){
1594 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1595 "Addr: %u ## CALL(24) (@address) (PUSH addr )",
1598 operand_address = current_address + 1;
1600 next_operand_address = decode_udvm_address_operand(buff,operand_address, &at_address, current_address);
1601 if (show_instr_detail_level == 2 ){
1602 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u @Address %u",
1603 operand_address, at_address);
1605 if (show_instr_detail_level == 1)
1607 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1608 "Addr: %u ## CALL (@address=%u)",
1609 current_address, at_address);
1611 current_address = next_operand_address;
1613 /* Push the current address onto the stack */
1614 stack_location = (buff[70] << 8) | buff[71];
1615 stack_fill = (buff[stack_location] << 8)
1616 | buff[(stack_location+1) & 0xFFFF];
1617 address = (stack_location + stack_fill * 2 + 2) & 0xFFFF;
1618 buff[address] = (current_address >> 8) & 0x00FF;
1619 buff[(address+1) & 0xFFFF] = current_address & 0x00FF;
1621 stack_fill = (stack_fill + 1) & 0xFFFF;
1622 buff[stack_location] = (stack_fill >> 8) & 0x00FF;
1623 buff[(stack_location+1) & 0xFFFF] = stack_fill & 0x00FF;
1625 /* ... and jump to the destination address */
1626 current_address = at_address;
1629 goto execute_next_instruction;
1633 case SIGCOMP_INSTR_RETURN: /* 25 POP and return */
1634 if (print_level_1 || show_instr_detail_level == 1){
1635 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1636 "Addr: %u ## POP(25) and return",
1640 /* Pop value from the top of the stack */
1641 stack_location = (buff[70] << 8) | buff[71];
1642 stack_fill = (buff[stack_location] << 8)
1643 | buff[(stack_location+1) & 0xFFFF];
1644 if (stack_fill == 0)
1647 goto decompression_failure;
1650 stack_fill = (stack_fill - 1) & 0xFFFF;
1651 buff[stack_location] = (stack_fill >> 8) & 0x00FF;
1652 buff[(stack_location+1) & 0xFFFF] = stack_fill & 0x00FF;
1654 address = (stack_location + stack_fill * 2 + 2) & 0xFFFF;
1655 at_address = (buff[address] << 8)
1656 | buff[(address+1) & 0xFFFF];
1658 /* ... and set the PC to the popped value */
1659 current_address = at_address;
1662 goto execute_next_instruction;
1666 case SIGCOMP_INSTR_SWITCH: /* 26 SWITCH (#n, %j, @address_0, @address_1, ... , @address_n-1) */
1668 * When a SWITCH instruction is encountered the UDVM reads the value of
1669 * j. It then continues instruction execution at the address specified
1672 * Decompression failure occurs if j specifies a value of n or more, or
1673 * if the address lies beyond the overall UDVM memory size.
1675 instruction_address = current_address;
1676 if (print_level_1 ){
1677 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1678 "Addr: %u ## SWITCH (#n, j, @address_0, @address_1, ... , @address_n-1))",
1681 operand_address = current_address + 1;
1683 * Number of addresses in the instruction
1685 next_operand_address = decode_udvm_literal_operand(buff,operand_address, &n);
1686 if (print_level_1 ){
1687 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u n %u",
1688 operand_address, n);
1690 operand_address = next_operand_address;
1692 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &j);
1693 if (print_level_1 ){
1694 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u j %u",
1695 operand_address, j);
1697 operand_address = next_operand_address;
1701 /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
1702 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &at_address_1);
1703 at_address_1 = ( instruction_address + at_address_1) & 0xffff;
1704 if (print_level_1 ){
1705 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u @Address %u",
1706 operand_address, at_address_1);
1709 current_address = at_address_1;
1711 operand_address = next_operand_address;
1714 /* Check decompression failure */
1715 if ( ( j == n ) || ( j > n )){
1717 goto decompression_failure;
1719 if ( current_address > UDVM_MEMORY_SIZE ){
1721 goto decompression_failure;
1723 used_udvm_cycles = used_udvm_cycles + 1 + n;
1725 goto execute_next_instruction;
1728 case SIGCOMP_INSTR_CRC: /* 27 CRC (%value, %position, %length, @address) */
1729 if (print_level_1 ){
1730 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1731 "Addr: %u ## CRC (value, position, length, @address)",
1735 operand_address = current_address + 1;
1738 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &value);
1739 if (print_level_1 ){
1740 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Value %u",
1741 operand_address, value);
1743 operand_address = next_operand_address;
1746 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &position);
1747 if (print_level_1 ){
1748 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u position %u",
1749 operand_address, position);
1751 operand_address = next_operand_address;
1754 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &length);
1755 if (print_level_1 ){
1756 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Length %u",
1757 operand_address, length);
1759 operand_address = next_operand_address;
1762 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &at_address);
1763 at_address = ( current_address + at_address) & 0xffff;
1764 if (print_level_1 ){
1765 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u @Address %u",
1766 operand_address, at_address);
1768 /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
1769 used_udvm_cycles = used_udvm_cycles + 1 + length;
1773 byte_copy_right = buff[66] << 8;
1774 byte_copy_right = byte_copy_right | buff[67];
1775 byte_copy_left = buff[64] << 8;
1776 byte_copy_left = byte_copy_left | buff[65];
1779 if (print_level_2 ){
1780 proto_tree_add_text(udvm_tree, message_tvb, 0, -1,
1781 "byte_copy_right = %u", byte_copy_right);
1786 guint16 handle_now = length - n;
1788 if ( k < byte_copy_right && byte_copy_right <= k + (length-n) ){
1789 handle_now = byte_copy_right - k;
1792 result = crc16_ccitt_seed(&buff[k], handle_now, result ^ 0xffff);
1794 k = ( k + handle_now ) & 0xffff;
1795 n = ( n + handle_now ) & 0xffff;
1797 if ( k >= byte_copy_right ) {
1802 result = result ^ 0xffff;
1804 if (print_level_1 ){
1805 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1, "Calculated CRC %u", result);
1807 if (result != value){
1808 current_address = at_address;
1811 current_address = next_operand_address;
1813 goto execute_next_instruction;
1817 case SIGCOMP_INSTR_INPUT_BYTES: /* 28 INPUT-BYTES (%length, %destination, @address) */
1818 if (show_instr_detail_level == 2 ){
1819 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1820 "Addr: %u ## INPUT-BYTES(28) length, destination, @address)",
1823 operand_address = current_address + 1;
1825 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &length);
1826 if (show_instr_detail_level == 2 ){
1827 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Length %u",
1828 operand_address, length);
1830 operand_address = next_operand_address;
1833 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &destination);
1834 if (show_instr_detail_level == 2 ){
1835 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Destination %u",
1836 operand_address, destination);
1838 operand_address = next_operand_address;
1841 /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
1842 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &at_address);
1843 at_address = ( current_address + at_address) & 0xffff;
1844 if (show_instr_detail_level == 2 ){
1845 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u @Address %u",
1846 operand_address, at_address);
1848 if (show_instr_detail_level == 1)
1850 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1851 "Addr: %u ## INPUT-BYTES length=%u, destination=%u, @address=%u)",
1852 current_address, length, destination, at_address);
1854 /* execute the instruction TODO insert checks
1858 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1859 * | byte_copy_left | 64 - 65
1860 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1861 * | byte_copy_right | 66 - 67
1862 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1863 * | input_bit_order | 68 - 69
1864 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1865 * | stack_location | 70 - 71
1866 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1868 * Figure 7: Memory addresses of the UDVM registers
1872 * The string of bytes is copied in ascending order of memory address,
1873 * respecting the bounds set by byte_copy_left and byte_copy_right.
1874 * More precisely, if a byte is copied from/to Address m then the next
1875 * byte is copied from/to Address n where n is calculated as follows:
1877 * Set k := m + 1 (modulo 2^16)
1878 * If k = byte_copy_right then set n := byte_copy_left, else set n := k
1884 byte_copy_right = buff[66] << 8;
1885 byte_copy_right = byte_copy_right | buff[67];
1886 byte_copy_left = buff[64] << 8;
1887 byte_copy_left = byte_copy_left | buff[65];
1888 if (print_level_1 ){
1889 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
1890 " byte_copy_right = %u", byte_copy_right);
1892 /* clear out remaining bits if any */
1895 /* operand_address used as dummy */
1896 while ( n < length ){
1897 if (input_address > ( msg_end - 1)){
1898 current_address = at_address;
1900 goto execute_next_instruction;
1903 if ( k == byte_copy_right ){
1906 octet = tvb_get_guint8(message_tvb, input_address);
1908 if (print_level_1 ){
1909 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
1910 " Loading value: %u (0x%x) at Addr: %u", octet, octet, k);
1914 * If the instruction requests data that lies beyond the end of the
1915 * SigComp message, no data is returned. Instead the UDVM moves program
1916 * execution to the address specified by the address operand.
1920 k = ( k + 1 ) & 0xffff;
1923 used_udvm_cycles = used_udvm_cycles + 1 + length;
1924 current_address = next_operand_address;
1925 goto execute_next_instruction;
1927 case SIGCOMP_INSTR_INPUT_BITS:/* 29 INPUT-BITS (%length, %destination, @address) */
1929 * The length operand indicates the requested number of bits.
1930 * Decompression failure occurs if this operand does not lie between 0
1933 * The destination operand specifies the memory address to which the
1934 * compressed data should be copied. Note that the requested bits are
1935 * interpreted as a 2-byte integer ranging from 0 to 2^length - 1, as
1936 * explained in Section 8.2.
1938 * If the instruction requests data that lies beyond the end of the
1939 * SigComp message, no data is returned. Instead the UDVM moves program
1940 * execution to the address specified by the address operand.
1943 if (show_instr_detail_level == 2 ){
1944 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1945 "Addr: %u ## INPUT-BITS(29) (length, destination, @address)",
1948 operand_address = current_address + 1;
1951 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &length);
1952 if (show_instr_detail_level == 2 ){
1953 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u length %u",
1954 operand_address, length);
1956 operand_address = next_operand_address;
1958 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &destination);
1959 if (show_instr_detail_level == 2 ){
1960 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Destination %u",
1961 operand_address, destination);
1963 operand_address = next_operand_address;
1966 /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
1967 next_operand_address = decode_udvm_address_operand(buff,operand_address, &at_address, current_address);
1968 if (show_instr_detail_level == 2 ){
1969 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u @Address %u",
1970 operand_address, at_address);
1972 if (show_instr_detail_level == 1)
1974 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1975 "Addr: %u ## INPUT-BITS length=%u, destination=%u, @address=%u)",
1976 current_address, length, destination, at_address);
1978 current_address = next_operand_address;
1981 * Execute actual instr.
1982 * The input_bit_order register contains the following three flags:
1985 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1986 * | reserved |F|H|P| 68 - 69
1987 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1989 input_bit_order = buff[68] << 8;
1990 input_bit_order = input_bit_order | buff[69];
1992 * If the instruction requests data that lies beyond the end of the
1993 * SigComp message, no data is returned. Instead the UDVM moves program
1994 * execution to the address specified by the address operand.
1999 goto decompression_failure;
2001 if ( input_bit_order > 7 ){
2003 goto decompression_failure;
2007 * Transfer F bit to bit_order to tell decomp dispatcher which bit order to use
2009 bit_order = ( input_bit_order & 0x0004 ) >> 2;
2010 value = decomp_dispatch_get_bits( message_tvb, udvm_tree, bit_order,
2011 buff, &old_input_bit_order, &remaining_bits,
2012 &input_bits, &input_address, length, &result_code, msg_end);
2013 if ( result_code == 11 ){
2014 used_udvm_cycles = used_udvm_cycles + 1;
2015 current_address = at_address;
2016 goto execute_next_instruction;
2019 lsb = value & 0x00ff;
2020 buff[destination] = msb;
2021 buff[destination + 1]=lsb;
2022 if (print_level_1 ){
2023 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
2024 " Loading value: %u (0x%x) at Addr: %u, remaining_bits: %u", value, value, destination, remaining_bits);
2027 used_udvm_cycles = used_udvm_cycles + 1;
2028 goto execute_next_instruction;
2030 case SIGCOMP_INSTR_INPUT_HUFFMAN: /* 30 */
2032 * INPUT-HUFFMAN (%destination, @address, #n, %bits_1, %lower_bound_1,
2033 * %upper_bound_1, %uncompressed_1, ... , %bits_n, %lower_bound_n,
2034 * %upper_bound_n, %uncompressed_n)
2036 if (show_instr_detail_level == 2 ){
2037 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2038 "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)",
2041 operand_address = current_address + 1;
2044 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &destination);
2045 if (show_instr_detail_level == 2 ){
2046 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Destination %u",
2047 operand_address, destination);
2049 operand_address = next_operand_address;
2052 /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
2053 next_operand_address = decode_udvm_address_operand(buff,operand_address, &at_address, current_address);
2054 if (show_instr_detail_level == 2 ){
2055 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u @Address %u",
2056 operand_address, at_address);
2058 operand_address = next_operand_address;
2061 next_operand_address = decode_udvm_literal_operand(buff,operand_address, &n);
2062 if (show_instr_detail_level == 2 ){
2063 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u n %u",
2064 operand_address, n);
2066 operand_address = next_operand_address;
2067 if (show_instr_detail_level == 1)
2069 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2070 "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)",
2071 current_address, destination, at_address, n, n, n, n, n);
2074 used_udvm_cycles = used_udvm_cycles + 1 + n;
2077 * Note that if n = 0 then the INPUT-HUFFMAN instruction is ignored and
2078 * program execution resumes at the following instruction.
2079 * Decompression failure occurs if (bits_1 + ... + bits_n) > 16.
2081 * In all other cases, the behavior of the INPUT-HUFFMAN instruction is
2084 * 1. Set j := 1 and set H := 0.
2086 * 2. Request bits_j compressed bits. Interpret the returned bits as an
2087 * integer k from 0 to 2^bits_j - 1, as explained in Section 8.2.
2089 * 3. Set H := H * 2^bits_j + k.
2091 * 4. If data is requested that lies beyond the end of the SigComp
2092 * message, terminate the INPUT-HUFFMAN instruction and move program
2093 * execution to the memory address specified by the address operand.
2095 * 5. If (H < lower_bound_j) or (H > upper_bound_j) then set j := j + 1.
2096 * Then go back to Step 2, unless j > n in which case decompression
2099 * 6. Copy (H + uncompressed_j - lower_bound_j) modulo 2^16 to the
2100 * memory address specified by the destination operand.
2104 * The input_bit_order register contains the following three flags:
2107 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2108 * | reserved |F|H|P| 68 - 69
2109 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2111 * Transfer H bit to bit_order to tell decomp dispatcher which bit order to use
2113 input_bit_order = buff[68] << 8;
2114 input_bit_order = input_bit_order | buff[69];
2115 bit_order = ( input_bit_order & 0x0002 ) >> 1;
2120 outside_huffman_boundaries = TRUE;
2121 print_in_loop = print_level_3;
2124 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &bits_n);
2125 if (print_in_loop ){
2126 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u bits_n %u",
2127 operand_address, bits_n);
2129 operand_address = next_operand_address;
2131 /* %lower_bound_n */
2132 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &lower_bound_n);
2133 if (print_in_loop ){
2134 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u lower_bound_n %u",
2135 operand_address, lower_bound_n);
2137 operand_address = next_operand_address;
2138 /* %upper_bound_n */
2139 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &upper_bound_n);
2140 if (print_in_loop ){
2141 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u upper_bound_n %u",
2142 operand_address, upper_bound_n);
2144 operand_address = next_operand_address;
2145 /* %uncompressed_n */
2146 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &uncompressed_n);
2147 if (print_in_loop ){
2148 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u uncompressed_n %u",
2149 operand_address, uncompressed_n);
2151 operand_address = next_operand_address;
2152 /* execute instruction */
2153 if ( outside_huffman_boundaries ) {
2155 * 2. Request bits_j compressed bits. Interpret the returned bits as an
2156 * integer k from 0 to 2^bits_j - 1, as explained in Section 8.2.
2158 k = decomp_dispatch_get_bits( message_tvb, udvm_tree, bit_order,
2159 buff, &old_input_bit_order, &remaining_bits,
2160 &input_bits, &input_address, bits_n, &result_code, msg_end);
2161 if ( result_code == 11 ){
2163 * 4. If data is requested that lies beyond the end of the SigComp
2164 * message, terminate the INPUT-HUFFMAN instruction and move program
2165 * execution to the memory address specified by the address operand.
2167 current_address = at_address;
2168 goto execute_next_instruction;
2172 * 3. Set H := H * 2^bits_j + k.
2173 * [In practice is a shift+OR operation.]
2176 H = (H << bits_n) | k;
2177 if (print_level_3 ){
2178 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," Set H(%u) := H(%u) * 2^bits_j(%u) + k(%u)",
2179 H ,oldH, 1<<bits_n,k);
2183 * 5. If (H < lower_bound_j) or (H > upper_bound_j) then set j := j + 1.
2184 * Then go back to Step 2, unless j > n in which case decompression
2187 if ((H < lower_bound_n) || (H > upper_bound_n)){
2188 outside_huffman_boundaries = TRUE;
2190 outside_huffman_boundaries = FALSE;
2191 print_in_loop = FALSE;
2193 * 6. Copy (H + uncompressed_j - lower_bound_j) modulo 2^16 to the
2194 * memory address specified by the destination operand.
2196 if (print_level_2 ){
2197 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2198 " H(%u) = H(%u) + uncompressed_n(%u) - lower_bound_n(%u)",
2199 (H + uncompressed_n - lower_bound_n ),H, uncompressed_n, lower_bound_n);
2201 H = H + uncompressed_n - lower_bound_n;
2204 buff[destination] = msb;
2205 buff[destination + 1]=lsb;
2206 if (print_level_1 ){
2207 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
2208 " Loading H: %u (0x%x) at Addr: %u,j = %u remaining_bits: %u",
2209 H, H, destination,( n - m + 1 ), remaining_bits);
2218 if ( outside_huffman_boundaries ) {
2220 goto decompression_failure;
2223 current_address = next_operand_address;
2224 goto execute_next_instruction;
2227 case SIGCOMP_INSTR_STATE_ACCESS: /* 31 */
2228 /* STATE-ACCESS (%partial_identifier_start, %partial_identifier_length,
2229 * %state_begin, %state_length, %state_address, %state_instruction)
2231 if (show_instr_detail_level == 2 ){
2232 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2233 "Addr: %u ## STATE-ACCESS(31) (partial_identifier_start, partial_identifier_length,state_begin, state_length, state_address, state_instruction)",
2236 operand_address = current_address + 1;
2239 * %partial_identifier_start
2241 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &p_id_start);
2242 if (show_instr_detail_level == 2 ){
2243 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u partial_identifier_start %u",
2244 operand_address, p_id_start);
2246 operand_address = next_operand_address;
2249 * %partial_identifier_length
2251 operand_address = next_operand_address;
2252 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &p_id_length);
2253 if (show_instr_detail_level == 2 ){
2254 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u partial_identifier_length %u",
2255 operand_address, p_id_length);
2260 operand_address = next_operand_address;
2261 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_begin);
2262 if (show_instr_detail_level == 2 ){
2263 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_begin %u",
2264 operand_address, state_begin);
2269 operand_address = next_operand_address;
2270 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_length);
2271 if (show_instr_detail_level == 2 ){
2272 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_length %u",
2273 operand_address, state_length);
2278 operand_address = next_operand_address;
2279 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_address);
2280 if (show_instr_detail_level == 2 ){
2281 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_address %u",
2282 operand_address, state_address);
2285 * %state_instruction
2287 operand_address = next_operand_address;
2288 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_instruction);
2289 if (show_instr_detail_level == 2 ){
2290 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_instruction %u",
2291 operand_address, state_instruction);
2293 if (show_instr_detail_level == 1)
2295 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2296 "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)",
2297 current_address, p_id_start, p_id_length, state_begin, state_length, state_address, state_instruction);
2299 current_address = next_operand_address;
2300 byte_copy_right = buff[66] << 8;
2301 byte_copy_right = byte_copy_right | buff[67];
2302 byte_copy_left = buff[64] << 8;
2303 byte_copy_left = byte_copy_left | buff[65];
2304 if (print_level_2 ){
2305 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
2306 " byte_copy_right = %u, byte_copy_left = %u", byte_copy_right,byte_copy_left);
2309 result_code = udvm_state_access(message_tvb, udvm_tree, buff, p_id_start, p_id_length, state_begin, &state_length,
2310 &state_address, &state_instruction, hf_id);
2311 if ( result_code != 0 ){
2312 goto decompression_failure;
2314 used_udvm_cycles = used_udvm_cycles + 1 + state_length;
2315 goto execute_next_instruction;
2317 case SIGCOMP_INSTR_STATE_CREATE: /* 32 */
2319 * STATE-CREATE (%state_length, %state_address, %state_instruction,
2320 * %minimum_access_length, %state_retention_priority)
2322 if (show_instr_detail_level == 2 ){
2323 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2324 "Addr: %u ## STATE-CREATE(32) (state_length, state_address, state_instruction,minimum_access_length, state_retention_priority)",
2327 operand_address = current_address + 1;
2332 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_length);
2333 if (show_instr_detail_level == 2 ){
2334 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_length %u",
2335 operand_address, state_length);
2340 operand_address = next_operand_address;
2341 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_address);
2342 if (show_instr_detail_level == 2 ){
2343 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_address %u",
2344 operand_address, state_address);
2347 * %state_instruction
2349 operand_address = next_operand_address;
2350 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_instruction);
2351 if (show_instr_detail_level == 2 ){
2352 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_instruction %u",
2353 operand_address, state_instruction);
2355 operand_address = next_operand_address;
2357 * %minimum_access_length
2359 operand_address = next_operand_address;
2360 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &minimum_access_length);
2361 if (show_instr_detail_level == 2 ){
2362 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u minimum_access_length %u",
2363 operand_address, minimum_access_length);
2365 operand_address = next_operand_address;
2367 * %state_retention_priority
2369 operand_address = next_operand_address;
2370 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_retention_priority);
2371 if (show_instr_detail_level == 2 ){
2372 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_retention_priority %u",
2373 operand_address, state_retention_priority);
2375 if (show_instr_detail_level == 1)
2377 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2378 "Addr: %u ## STATE-CREATE(32) (state_length=%u, state_address=%u, state_instruction=%u,minimum_access_length=%u, state_retention_priority=%u)",
2379 current_address, state_length, state_address, state_instruction,minimum_access_length, state_retention_priority);
2381 current_address = next_operand_address;
2382 /* Execute the instruction
2383 * TODO Implement the instruction
2385 * Note that the new state item cannot be created until a valid
2386 * compartment identifier has been returned by the application.
2387 * Consequently, when a STATE-CREATE instruction is encountered the UDVM
2388 * simply buffers the five supplied operands until the END-MESSAGE
2389 * instruction is reached. The steps taken at this point are described
2392 * Decompression failure MUST occur if more than four state creation
2393 * requests are made before the END-MESSAGE instruction is encountered.
2394 * Decompression failure also occurs if the minimum_access_length does
2395 * not lie between 6 and 20 inclusive, or if the
2396 * state_retention_priority is 65535.
2398 no_of_state_create++;
2399 if ( no_of_state_create > 4 ){
2401 goto decompression_failure;
2403 if (( minimum_access_length < 6 ) || ( minimum_access_length > STATE_BUFFER_SIZE )){
2405 goto decompression_failure;
2407 if ( state_retention_priority == 65535 ){
2409 goto decompression_failure;
2411 state_length_buff[no_of_state_create] = state_length;
2412 state_address_buff[no_of_state_create] = state_address;
2413 state_instruction_buff[no_of_state_create] = state_instruction;
2414 state_minimum_access_length_buff[no_of_state_create] = minimum_access_length;
2415 state_state_retention_priority_buff[no_of_state_create] = state_retention_priority;
2416 used_udvm_cycles = used_udvm_cycles + 1 + state_length;
2418 byte_copy_right = buff[66] << 8;
2419 byte_copy_right = byte_copy_right | buff[67];
2420 byte_copy_left = buff[64] << 8;
2421 byte_copy_left = byte_copy_left | buff[65];
2424 while ( n < state_length ){
2425 if ( k == byte_copy_right ){
2430 if (print_level_3 ){
2431 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2432 " Addr: %5u State value: %u (0x%x) ASCII(%s)",
2433 k,buff[k],buff[k],string);
2435 k = ( k + 1 ) & 0xffff;
2440 goto execute_next_instruction;
2442 case SIGCOMP_INSTR_STATE_FREE: /* 33 */
2444 * STATE-FREE (%partial_identifier_start, %partial_identifier_length)
2446 if (show_instr_detail_level == 2 ){
2447 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2448 "Addr: %u ## STATE-FREE (partial_identifier_start, partial_identifier_length)",
2451 operand_address = current_address + 1;
2453 * %partial_identifier_start
2455 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &p_id_start);
2456 if (show_instr_detail_level == 2 ){
2457 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u partial_identifier_start %u",
2458 operand_address, p_id_start);
2460 operand_address = next_operand_address;
2463 * %partial_identifier_length
2465 operand_address = next_operand_address;
2466 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &p_id_length);
2467 if (show_instr_detail_level == 2 ){
2468 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u partial_identifier_length %u",
2469 operand_address, p_id_length);
2471 if (show_instr_detail_level == 1)
2473 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2474 "Addr: %u ## STATE-FREE (partial_identifier_start=%u, partial_identifier_length=%u)",
2475 current_address, p_id_start, p_id_length);
2477 current_address = next_operand_address;
2479 /* Execute the instruction:
2482 udvm_state_free(buff,p_id_start,p_id_length);
2485 goto execute_next_instruction;
2487 case SIGCOMP_INSTR_OUTPUT: /* 34 OUTPUT (%output_start, %output_length) */
2488 if (show_instr_detail_level == 2 ){
2489 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2490 "Addr: %u ## OUTPUT(34) (output_start, output_length)",
2493 operand_address = current_address + 1;
2497 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &output_start);
2498 if (show_instr_detail_level == 2 ){
2499 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u output_start %u",
2500 operand_address, output_start);
2502 operand_address = next_operand_address;
2506 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &output_length);
2507 if (show_instr_detail_level == 2 ){
2508 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u output_length %u",
2509 operand_address, output_length);
2511 if (show_instr_detail_level == 1)
2513 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2514 "Addr: %u ## OUTPUT (output_start=%u, output_length=%u)",
2515 current_address, output_start, output_length);
2517 current_address = next_operand_address;
2520 * Execute instruction
2523 * The string of bytes is copied in ascending order of memory address,
2524 * respecting the bounds set by byte_copy_left and byte_copy_right.
2525 * More precisely, if a byte is copied from/to Address m then the next
2526 * byte is copied from/to Address n where n is calculated as follows:
2528 * Set k := m + 1 (modulo 2^16)
2529 * If k = byte_copy_right then set n := byte_copy_left, else set n := k
2535 byte_copy_right = buff[66] << 8;
2536 byte_copy_right = byte_copy_right | buff[67];
2537 byte_copy_left = buff[64] << 8;
2538 byte_copy_left = byte_copy_left | buff[65];
2539 if (print_level_3 ){
2540 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2541 " byte_copy_right = %u", byte_copy_right);
2543 while ( n < output_length ){
2545 if ( k == byte_copy_right ){
2548 out_buff[output_address] = buff[k];
2552 if (print_level_3 ){
2553 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2554 " Output value: %u (0x%x) ASCII(%s) from Addr: %u ,output to dispatcher position %u",
2555 buff[k],buff[k],format_text(strp,1), k,output_address);
2557 k = ( k + 1 ) & 0xffff;
2561 used_udvm_cycles = used_udvm_cycles + 1 + output_length;
2562 goto execute_next_instruction;
2564 case SIGCOMP_INSTR_END_MESSAGE: /* 35 */
2566 * END-MESSAGE (%requested_feedback_location,
2567 * %returned_parameters_location, %state_length, %state_address,
2568 * %state_instruction, %minimum_access_length,
2569 * %state_retention_priority)
2571 if (show_instr_detail_level == 2 ){
2572 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2573 "Addr: %u ## END-MESSAGE (requested_feedback_location,state_instruction, minimum_access_length,state_retention_priority)",
2576 operand_address = current_address + 1;
2578 /* %requested_feedback_location */
2579 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &requested_feedback_location);
2580 if (show_instr_detail_level == 2 ){
2581 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u requested_feedback_location %u",
2582 operand_address, requested_feedback_location);
2584 operand_address = next_operand_address;
2585 /* returned_parameters_location */
2586 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &returned_parameters_location);
2587 if (show_instr_detail_level == 2 ){
2588 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u returned_parameters_location %u",
2589 operand_address, returned_parameters_location);
2591 operand_address = next_operand_address;
2595 operand_address = next_operand_address;
2596 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_length);
2597 if (show_instr_detail_level == 2 ){
2598 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_length %u",
2599 operand_address, state_length);
2604 operand_address = next_operand_address;
2605 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_address);
2606 if (show_instr_detail_level == 2 ){
2607 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_address %u",
2608 operand_address, state_address);
2611 * %state_instruction
2613 operand_address = next_operand_address;
2614 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_instruction);
2615 if (show_instr_detail_level == 2 ){
2616 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_instruction %u",
2617 operand_address, state_instruction);
2621 * %minimum_access_length
2623 operand_address = next_operand_address;
2624 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &minimum_access_length);
2625 if (show_instr_detail_level == 2 ){
2626 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u minimum_access_length %u",
2627 operand_address, minimum_access_length);
2631 * %state_retention_priority
2633 operand_address = next_operand_address;
2634 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_retention_priority);
2635 if (show_instr_detail_level == 2 ){
2636 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_retention_priority %u",
2637 operand_address, state_retention_priority);
2639 if (show_instr_detail_level == 1)
2641 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2642 "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)",
2643 current_address, requested_feedback_location, returned_parameters_location, state_length, state_address, state_instruction, minimum_access_length,state_retention_priority);
2645 current_address = next_operand_address;
2646 /* TODO: This isn't currently totaly correct as END_INSTRUCTION might not create state */
2647 no_of_state_create++;
2648 if ( no_of_state_create > 4 ){
2650 goto decompression_failure;
2652 state_length_buff[no_of_state_create] = state_length;
2653 state_address_buff[no_of_state_create] = state_address;
2654 state_instruction_buff[no_of_state_create] = state_instruction;
2656 state_minimum_access_length_buff[no_of_state_create] = minimum_access_length;
2657 state_state_retention_priority_buff[no_of_state_create] = state_retention_priority;
2659 /* Execute the instruction
2661 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"no_of_state_create %u",no_of_state_create);
2662 if ( no_of_state_create != 0 ){
2663 memset(sha1_digest_buf, 0, STATE_BUFFER_SIZE);
2665 byte_copy_right = buff[66] << 8;
2666 byte_copy_right = byte_copy_right | buff[67];
2667 byte_copy_left = buff[64] << 8;
2668 byte_copy_left = byte_copy_left | buff[65];
2669 while ( n < no_of_state_create + 1 ){
2670 sha1buff = g_malloc(state_length_buff[n]+8);
2671 sha1buff[0] = state_length_buff[n] >> 8;
2672 sha1buff[1] = state_length_buff[n] & 0xff;
2673 sha1buff[2] = state_address_buff[n] >> 8;
2674 sha1buff[3] = state_address_buff[n] & 0xff;
2675 sha1buff[4] = state_instruction_buff[n] >> 8;
2676 sha1buff[5] = state_instruction_buff[n] & 0xff;
2677 sha1buff[6] = state_minimum_access_length_buff[n] >> 8;
2678 sha1buff[7] = state_minimum_access_length_buff[n] & 0xff;
2679 if (print_level_3 ){
2680 for( x=0; x < 8; x++){
2681 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"sha1buff %u 0x%x",
2685 k = state_address_buff[n];
2686 for( x=0; x < state_length_buff[n]; x++)
2688 if ( k == byte_copy_right ){
2691 sha1buff[8+x] = buff[k];
2692 k = ( k + 1 ) & 0xffff;
2695 sha1_starts( &ctx );
2696 sha1_update( &ctx, (guint8 *) sha1buff, state_length_buff[n] + 8);
2697 sha1_finish( &ctx, sha1_digest_buf );
2698 if (print_level_3 ){
2699 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"SHA1 digest %s",bytes_to_str(sha1_digest_buf, STATE_BUFFER_SIZE));
2702 udvm_state_create(sha1buff, sha1_digest_buf, state_minimum_access_length_buff[n]);
2703 proto_tree_add_text(udvm_tree,bytecode_tvb, 0, -1,"### Creating state ###");
2704 proto_tree_add_string(udvm_tree,hf_id, bytecode_tvb, 0, 0, bytes_to_str(sha1_digest_buf, state_minimum_access_length_buff[n]));
2713 /* At least something got decompressed, show it */
2714 decomp_tvb = tvb_new_real_data(out_buff,output_address,output_address);
2715 /* Arrange that the allocated packet data copy be freed when the
2718 tvb_set_free_cb( decomp_tvb, g_free );
2720 tvb_set_child_real_data_tvbuff(message_tvb,decomp_tvb);
2721 add_new_data_source(pinfo, decomp_tvb, "Decompressed SigComp message");
2723 proto_tree_add_text(udvm_tree, decomp_tvb, 0, -1,"SigComp message Decompressed");
2725 used_udvm_cycles = used_udvm_cycles + 1 + state_length;
2726 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"maximum_UDVM_cycles %u used_udvm_cycles %u",
2727 maximum_UDVM_cycles, used_udvm_cycles);
2732 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," ### Addr %u Invalid instruction: %u (0x%x)",
2733 current_address,current_instruction,current_instruction);
2738 decompression_failure:
2740 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"DECOMPRESSION FAILURE: %s",
2741 val_to_str(result_code, result_code_vals,"Unknown (%u)"));
2747 /* The simplest operand type is the literal (#), which encodes a
2748 * constant integer from 0 to 65535 inclusive. A literal operand may
2749 * require between 1 and 3 bytes depending on its value.
2750 * Bytecode: Operand value: Range:
2751 * 0nnnnnnn N 0 - 127
2752 * 10nnnnnn nnnnnnnn N 0 - 16383
2753 * 11000000 nnnnnnnn nnnnnnnn N 0 - 65535
2755 * Figure 8: Bytecode for a literal (#) operand
2759 decode_udvm_literal_operand(guint8 *buff,guint operand_address, guint16 *value)
2764 guint offset = operand_address;
2767 bytecode = buff[operand_address];
2768 test_bits = bytecode >> 7;
2769 if (test_bits == 1){
2770 test_bits = bytecode >> 6;
2771 if (test_bits == 2){
2773 * 10nnnnnn nnnnnnnn N 0 - 16383
2775 temp_data = buff[operand_address] & 0x1f;
2776 operand = temp_data << 8;
2777 temp_data = buff[operand_address + 1];
2778 operand = operand | temp_data;
2780 offset = offset + 2;
2784 * 111000000 nnnnnnnn nnnnnnnn N 0 - 65535
2787 temp_data = buff[operand_address] & 0x1f;
2788 operand = temp_data << 8;
2789 temp_data = buff[operand_address + 1];
2790 operand = operand | temp_data;
2792 offset = offset + 2;
2797 * 0nnnnnnn N 0 - 127
2799 operand = ( bytecode & 0x7f);
2809 * The second operand type is the reference ($), which is always used to
2810 * access a 2-byte value located elsewhere in the UDVM memory. The
2811 * bytecode for a reference operand is decoded to be a constant integer
2812 * from 0 to 65535 inclusive, which is interpreted as the memory address
2813 * containing the actual value of the operand.
2814 * Bytecode: Operand value: Range:
2816 * 0nnnnnnn memory[2 * N] 0 - 65535
2817 * 10nnnnnn nnnnnnnn memory[2 * N] 0 - 65535
2818 * 11000000 nnnnnnnn nnnnnnnn memory[N] 0 - 65535
2820 * Figure 9: Bytecode for a reference ($) operand
2823 dissect_udvm_reference_operand(guint8 *buff,guint operand_address, guint16 *value,guint *result_dest)
2827 guint offset = operand_address;
2830 guint16 temp_data16;
2832 bytecode = buff[operand_address];
2833 test_bits = bytecode >> 7;
2834 if (test_bits == 1){
2835 test_bits = bytecode >> 6;
2836 if (test_bits == 2){
2838 * 10nnnnnn nnnnnnnn memory[2 * N] 0 - 65535
2840 temp_data = buff[operand_address] & 0x3f;
2841 operand = temp_data << 8;
2842 temp_data = buff[operand_address + 1];
2843 operand = operand | temp_data;
2844 operand = (operand * 2);
2845 *result_dest = operand;
2846 temp_data16 = buff[operand] << 8;
2847 temp_data16 = temp_data16 | buff[operand+1];
2848 *value = temp_data16;
2849 offset = offset + 2;
2853 * 11000000 nnnnnnnn nnnnnnnn memory[N] 0 - 65535
2856 operand = buff[operand_address] << 8;
2857 operand = operand | buff[operand_address + 1];
2858 *result_dest = operand;
2859 temp_data16 = buff[operand] << 8;
2860 temp_data16 = temp_data16 | buff[operand+1];
2861 *value = temp_data16;
2862 offset = offset + 3;
2867 * 0nnnnnnn memory[2 * N] 0 - 65535
2869 operand = ( bytecode & 0x7f);
2870 operand = (operand * 2);
2871 *result_dest = operand;
2872 temp_data16 = buff[operand] << 8;
2873 temp_data16 = temp_data16 | buff[operand+1];
2874 *value = temp_data16;
2882 * Figure 10: Bytecode for a multitype (%) operand
2883 * Bytecode: Operand value: Range: HEX val
2884 * 00nnnnnn N 0 - 63 0x00
2885 * 01nnnnnn memory[2 * N] 0 - 65535 0x40
2886 * 1000011n 2 ^ (N + 6) 64 , 128 0x86
2887 * 10001nnn 2 ^ (N + 8) 256 , ... , 32768 0x88
2888 * 111nnnnn N + 65504 65504 - 65535 0xe0
2889 * 1001nnnn nnnnnnnn N + 61440 61440 - 65535 0x90
2890 * 101nnnnn nnnnnnnn N 0 - 8191 0xa0
2891 * 110nnnnn nnnnnnnn memory[N] 0 - 65535 0xc0
2892 * 10000000 nnnnnnnn nnnnnnnn N 0 - 65535 0x80
2893 * 10000001 nnnnnnnn nnnnnnnn memory[N] 0 - 65535 0x81
2896 decode_udvm_multitype_operand(guint8 *buff,guint operand_address, guint16 *value)
2900 guint offset = operand_address;
2904 guint16 temp_data16;
2905 guint16 memmory_addr = 0;
2907 bytecode = buff[operand_address];
2908 test_bits = ( bytecode & 0xc0 ) >> 6;
2909 switch (test_bits ){
2914 operand = buff[operand_address];
2916 *g_warning("Reading 0x%x From address %u",operand,offset);
2923 * 01nnnnnn memory[2 * N] 0 - 65535
2925 memmory_addr = ( bytecode & 0x3f) * 2;
2926 temp_data16 = buff[memmory_addr] << 8;
2927 temp_data16 = temp_data16 | buff[memmory_addr+1];
2928 *value = temp_data16;
2932 /* Check tree most significant bits */
2933 test_bits = ( bytecode & 0xe0 ) >> 5;
2934 if ( test_bits == 5 ){
2936 * 101nnnnn nnnnnnnn N 0 - 8191
2938 temp_data = buff[operand_address] & 0x1f;
2939 operand = temp_data << 8;
2940 temp_data = buff[operand_address + 1];
2941 operand = operand | temp_data;
2943 offset = offset + 2;
2945 test_bits = ( bytecode & 0xf0 ) >> 4;
2946 if ( test_bits == 9 ){
2948 * 1001nnnn nnnnnnnn N + 61440 61440 - 65535
2950 temp_data = buff[operand_address] & 0x0f;
2951 operand = temp_data << 8;
2952 temp_data = buff[operand_address + 1];
2953 operand = operand | temp_data;
2954 operand = operand + 61440;
2956 offset = offset + 2;
2958 test_bits = ( bytecode & 0x08 ) >> 3;
2959 if ( test_bits == 1){
2961 * 10001nnn 2 ^ (N + 8) 256 , ... , 32768
2964 result = 1 << ((buff[operand_address] & 0x07) + 8);
2965 operand = result & 0xffff;
2969 test_bits = ( bytecode & 0x0e ) >> 1;
2970 if ( test_bits == 3 ){
2972 * 1000 011n 2 ^ (N + 6) 64 , 128
2974 result = 1 << ((buff[operand_address] & 0x01) + 6);
2975 operand = result & 0xffff;
2980 * 1000 0000 nnnnnnnn nnnnnnnn N 0 - 65535
2981 * 1000 0001 nnnnnnnn nnnnnnnn memory[N] 0 - 65535
2984 temp_data16 = buff[operand_address + 1] << 8;
2985 temp_data16 = temp_data16 | buff[operand_address + 2];
2987 * g_warning("Reading 0x%x From address %u",temp_data16,operand_address);
2989 if ( (bytecode & 0x01) == 1 ){
2990 memmory_addr = temp_data16;
2991 temp_data16 = buff[memmory_addr] << 8;
2992 temp_data16 = temp_data16 | buff[memmory_addr+1];
2994 *value = temp_data16;
3005 test_bits = ( bytecode & 0x20 ) >> 5;
3006 if ( test_bits == 1 ){
3008 * 111nnnnn N + 65504 65504 - 65535
3010 operand = ( buff[operand_address] & 0x1f) + 65504;
3015 * 110nnnnn nnnnnnnn memory[N] 0 - 65535
3017 memmory_addr = buff[operand_address] & 0x1f;
3018 memmory_addr = memmory_addr << 8;
3019 memmory_addr = memmory_addr | buff[operand_address + 1];
3020 temp_data16 = buff[memmory_addr] << 8;
3021 temp_data16 = temp_data16 | buff[memmory_addr+1];
3022 *value = temp_data16;
3024 * g_warning("Reading 0x%x From address %u",temp_data16,memmory_addr);
3036 * The fourth operand type is the address (@). This operand is decoded
3037 * as a multitype operand followed by a further step: the memory address
3038 * of the UDVM instruction containing the address operand is added to
3039 * obtain the correct operand value. So if the operand value from
3040 * Figure 10 is D then the actual operand value of an address is
3041 * calculated as follows:
3043 * operand_value = (memory_address_of_instruction + D) modulo 2^16
3045 * Address operands are always used in instructions that control program
3046 * flow, because they ensure that the UDVM bytecode is position-
3047 * independent code (i.e., it will run independently of where it is
3048 * placed in the UDVM memory).
3051 decode_udvm_address_operand(guint8 *buff,guint operand_address, guint16 *value,guint current_address)
3055 guint next_opreand_address;
3057 next_opreand_address = decode_udvm_multitype_operand(buff, operand_address, &value1);
3058 result = value1 & 0xffff;
3059 result = result + current_address;
3060 *value = result & 0xffff;
3061 return next_opreand_address;
3066 * This is a lookup table used to reverse the bits in a byte.
3068 static guint8 reverse [] = {
3069 0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0,
3070 0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0,
3071 0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8,
3072 0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8,
3073 0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4,
3074 0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4,
3075 0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC,
3076 0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC,
3077 0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2,
3078 0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2,
3079 0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA,
3080 0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA,
3081 0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6,
3082 0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6,
3083 0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE,
3084 0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE,
3085 0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1,
3086 0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1,
3087 0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9,
3088 0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9,
3089 0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5,
3090 0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5,
3091 0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED,
3092 0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD,
3093 0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3,
3094 0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3,
3095 0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB,
3096 0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB,
3097 0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7,
3098 0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7,
3099 0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF,
3100 0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF
3105 decomp_dispatch_get_bits(
3106 tvbuff_t *message_tvb,
3107 proto_tree *udvm_tree,
3110 guint16 *old_input_bit_order,
3111 guint16 *remaining_bits,
3112 guint16 *input_bits,
3113 guint *input_address,
3115 guint16 *result_code,
3118 guint16 input_bit_order;
3119 guint16 bits_still_required = length;
3122 gint extra_bytes_available = msg_end - *input_address;
3124 gint prev_p_bit = *old_input_bit_order & 0x0001;
3125 gint bits_to_use = 0;
3128 input_bit_order = buff[68] << 8;
3129 input_bit_order = input_bit_order | buff[69];
3131 p_bit = (input_bit_order & 0x0001) != 0;
3134 * Discard any spare bits.
3135 * Note: We take care to avoid remaining_bits having the value of 8.
3137 if (prev_p_bit != p_bit)
3139 *remaining_bits = 0;
3140 *old_input_bit_order = input_bit_order;
3144 * Check we can suppy the required number of bits now, before we alter
3145 * the input buffer's state.
3147 if (*remaining_bits + extra_bytes_available * 8 < length)
3153 /* Note: This is never called with length > 16, so the following loop
3154 * never loops more than three time. */
3155 while (bits_still_required > 0)
3158 * We only put anything into input_bits if we know we will remove
3159 * at least one bit. That ensures we can simply discard the spare
3160 * bits if the P-bit changes.
3162 if (*remaining_bits == 0)
3164 octet = tvb_get_guint8(message_tvb, *input_address);
3165 if (print_level_1 ){
3166 proto_tree_add_text(udvm_tree, message_tvb, *input_address , 1,
3167 " Geting value: %u (0x%x) From Addr: %u", octet, octet, *input_address);
3169 *input_address = *input_address + 1;
3173 octet = reverse[octet];
3175 *input_bits = octet;
3176 *remaining_bits = 8;
3179 /* Add some more bits to the accumulated value. */
3180 bits_to_use = bits_still_required < *remaining_bits ? bits_still_required : *remaining_bits;
3181 bits_still_required -= bits_to_use;
3183 *input_bits <<= bits_to_use; /* Shift bits into MSByte */
3184 value = (value << bits_to_use) /* Then add to the accumulated value */
3185 | ((*input_bits >> 8) & 0xFF);
3186 *remaining_bits -= bits_to_use;
3187 *input_bits &= 0x00FF; /* Leave just the remaining bits */
3192 /* Bit reverse the entire word. */
3193 guint16 lsb = reverse[(value >> 8) & 0xFF];
3194 guint16 msb = reverse[value & 0xFF];
3196 value = ((msb << 8) | lsb) >> (16 - length);