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 * Wireshark - Network traffic analyzer
9 * By Gerald Combs <gerald@wireshark.org>
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"
46 #include "crypt/sha1.h"
47 #include "wsutil/crc16.h"
50 #define SIGCOMP_INSTR_DECOMPRESSION_FAILURE 0
51 #define SIGCOMP_INSTR_AND 1
52 #define SIGCOMP_INSTR_OR 2
53 #define SIGCOMP_INSTR_NOT 3
54 #define SIGCOMP_INSTR_LSHIFT 4
55 #define SIGCOMP_INSTR_RSHIFT 5
56 #define SIGCOMP_INSTR_ADD 6
57 #define SIGCOMP_INSTR_SUBTRACT 7
58 #define SIGCOMP_INSTR_MULTIPLY 8
59 #define SIGCOMP_INSTR_DIVIDE 9
60 #define SIGCOMP_INSTR_REMAINDER 10
61 #define SIGCOMP_INSTR_SORT_ASCENDING 11
62 #define SIGCOMP_INSTR_SORT_DESCENDING 12
63 #define SIGCOMP_INSTR_SHA_1 13
64 #define SIGCOMP_INSTR_LOAD 14
65 #define SIGCOMP_INSTR_MULTILOAD 15
66 #define SIGCOMP_INSTR_PUSH 16
67 #define SIGCOMP_INSTR_POP 17
68 #define SIGCOMP_INSTR_COPY 18
69 #define SIGCOMP_INSTR_COPY_LITERAL 19
70 #define SIGCOMP_INSTR_COPY_OFFSET 20
71 #define SIGCOMP_INSTR_MEMSET 21
72 #define SIGCOMP_INSTR_JUMP 22
73 #define SIGCOMP_INSTR_COMPARE 23
74 #define SIGCOMP_INSTR_CALL 24
75 #define SIGCOMP_INSTR_RETURN 25
76 #define SIGCOMP_INSTR_SWITCH 26
77 #define SIGCOMP_INSTR_CRC 27
78 #define SIGCOMP_INSTR_INPUT_BYTES 28
79 #define SIGCOMP_INSTR_INPUT_BITS 29
80 #define SIGCOMP_INSTR_INPUT_HUFFMAN 30
81 #define SIGCOMP_INSTR_STATE_ACCESS 31
82 #define SIGCOMP_INSTR_STATE_CREATE 32
83 #define SIGCOMP_INSTR_STATE_FREE 33
84 #define SIGCOMP_INSTR_OUTPUT 34
85 #define SIGCOMP_INSTR_END_MESSAGE 35
88 static gboolean print_level_1;
89 static gboolean print_level_2;
90 static gboolean print_level_3;
91 static gint show_instr_detail_level;
93 /* Internal result code values of decompression failures */
94 const value_string result_code_vals[] = {
95 { 0, "No decompression failure" },
96 { 1, "Partial state length less than 6 or greater than 20 bytes long" },
97 { 2, "No state match" },
98 { 3, "state_begin + state_length > size of state" },
99 { 4, "Operand_2 is Zero" },
100 { 5, "Switch statement failed j >= n" },
101 { 6, "Attempt to jump outside of UDVM memory" },
102 { 7, "L in input-bits > 16" },
103 { 8, "input_bit_order > 7" },
104 { 9, "Instruction Decompression failure encountered" },
105 {10, "Input huffman failed j > n" },
106 {11, "Input bits requested beyond end of message" },
107 {12, "more than four state creation requests are made before the END-MESSAGE instruction" },
108 {13, "state_retention_priority is 65535" },
109 {14, "Input bytes requested beyond end of message" },
110 {15, "Maximum number of UDVM cycles reached" },
111 {16, "UDVM stack underflow" },
112 { 255, "This branch isn't coded yet" },
116 static int decode_udvm_literal_operand(guint8 *buff,guint operand_address, guint16 *value);
117 static int dissect_udvm_reference_operand(guint8 *buff,guint operand_address, guint16 *value, guint *result_dest);
118 static int decode_udvm_multitype_operand(guint8 *buff,guint operand_address,guint16 *value);
119 static int decode_udvm_address_operand(guint8 *buff,guint operand_address, guint16 *value,guint current_address);
120 static int decomp_dispatch_get_bits(tvbuff_t *message_tvb,proto_tree *udvm_tree,guint8 bit_order,
121 guint8 *buff,guint16 *old_input_bit_order, guint16 *remaining_bits,
122 guint16 *input_bits, guint *input_address, guint16 length, guint16 *result_code,guint msg_end);
126 decompress_sigcomp_message(tvbuff_t *bytecode_tvb, tvbuff_t *message_tvb, packet_info *pinfo,
127 proto_tree *udvm_tree, gint udvm_mem_dest,
128 gint print_flags, gint hf_id,
130 gint byte_code_state_len, gint byte_code_id_len,
133 tvbuff_t *decomp_tvb;
134 /* UDVM memory must be initialised to zero */
135 guint8 *buff = ep_alloc0(UDVM_MEMORY_SIZE);
137 guint8 *out_buff; /* Largest allowed size for a message is UDVM_MEMORY_SIZE = 65536 */
147 guint code_length =0;
148 guint8 current_instruction;
149 guint current_address;
150 guint operand_address;
152 guint16 output_address = 0;
153 guint next_operand_address;
157 guint16 byte_copy_right;
158 guint16 byte_copy_left;
159 guint16 input_bit_order;
160 guint16 stack_location;
163 guint msg_end = tvb_reported_length_remaining(message_tvb, 0);
164 guint16 result_code = 0;
165 guint16 old_input_bit_order = 0;
166 guint16 remaining_bits = 0;
167 guint16 input_bits = 0;
168 guint8 bit_order = 0;
169 gboolean outside_huffman_boundaries = TRUE;
170 gboolean print_in_loop = FALSE;
171 guint16 instruction_address;
172 guint8 no_of_state_create = 0;
173 guint16 state_length_buff[5];
174 guint16 state_address_buff[5];
175 guint16 state_instruction_buff[5];
176 guint16 state_minimum_access_length_buff[5];
177 /* guint16 state_state_retention_priority_buff[5]; */
178 guint32 used_udvm_cycles = 0;
179 guint cycles_per_bit;
180 guint maximum_UDVM_cycles;
182 unsigned char sha1_digest_buf[STATE_BUFFER_SIZE];
186 /* UDVM operand variables */
195 guint16 state_length;
196 guint16 state_address;
197 guint16 state_instruction;
202 guint16 at_address_1;
203 guint16 at_address_2;
204 guint16 at_address_3;
207 guint16 lower_bound_n;
208 guint16 upper_bound_n;
209 guint16 uncompressed_n;
211 guint16 ref_destination; /* could I have used $destination ? */
212 guint16 multy_offset;
213 guint16 output_start;
214 guint16 output_length;
215 guint16 minimum_access_length;
216 guint16 state_retention_priority;
217 guint16 requested_feedback_location;
218 guint16 returned_parameters_location;
222 /* Set print parameters */
223 print_level_1 = FALSE;
224 print_level_2 = FALSE;
225 print_level_3 = FALSE;
226 show_instr_detail_level = 0;
230 switch( print_flags ) {
235 print_level_1 = TRUE;
236 show_instr_detail_level = 1;
239 print_level_1 = TRUE;
240 print_level_2 = TRUE;
241 show_instr_detail_level = 1;
244 print_level_1 = TRUE;
245 print_level_2 = TRUE;
246 print_level_3 = TRUE;
247 show_instr_detail_level = 2;
250 print_level_1 = TRUE;
251 show_instr_detail_level = 1;
255 /* Set initial UDVM data
256 * The first 32 bytes of UDVM memory are then initialized to special
257 * values as illustrated in Figure 5.
260 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
261 * | UDVM_memory_size | 0 - 1
262 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
263 * | cycles_per_bit | 2 - 3
264 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
265 * | SigComp_version | 4 - 5
266 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
267 * | partial_state_ID_length | 6 - 7
268 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
269 * | state_length | 8 - 9
270 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
272 * : reserved : 10 - 31
274 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
276 * Figure 5: Initializing Useful Values in UDVM memory
278 /* UDVM_memory_size */
279 buff[0] = (UDVM_MEMORY_SIZE >> 8) & 0x00FF;
280 buff[1] = UDVM_MEMORY_SIZE & 0x00FF;
284 /* SigComp_version */
287 /* partial_state_ID_length */
288 buff[6] = (byte_code_id_len >> 8) & 0x00FF;
289 buff[7] = byte_code_id_len & 0x00FF;
291 buff[8] = (byte_code_state_len >> 8) & 0x00FF;
292 buff[9] = byte_code_state_len & 0x00FF;
294 code_length = tvb_reported_length_remaining(bytecode_tvb, 0);
296 cycles_per_bit = buff[2] << 8;
297 cycles_per_bit = cycles_per_bit | buff[3];
299 * maximum_UDVM_cycles = (8 * n + 1000) * cycles_per_bit
301 maximum_UDVM_cycles = (( 8 * (header_len + msg_end) ) + 1000) * cycles_per_bit;
303 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);
304 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);
306 /* Load bytecode into UDVM starting at "udvm_mem_dest" */
309 proto_tree_add_text(udvm_tree, bytecode_tvb, offset, 1,"Load bytecode into UDVM starting at %u",i);
310 while ( code_length > offset && i < UDVM_MEMORY_SIZE ) {
311 buff[i] = tvb_get_guint8(bytecode_tvb, offset);
313 proto_tree_add_text(udvm_tree, bytecode_tvb, offset, 1,
314 " Addr: %u Instruction code(0x%0x) ", i, buff[i]);
320 /* Largest allowed size for a message is UDVM_MEMORY_SIZE = 65536 */
321 out_buff = g_malloc(UDVM_MEMORY_SIZE);
322 /* Start executing code */
323 current_address = udvm_start_ip;
327 proto_tree_add_text(udvm_tree, bytecode_tvb, offset, 1,"UDVM EXECUTION STARTED at Address: %u Message size %u",
328 current_address, msg_end);
330 execute_next_instruction:
332 if ( used_udvm_cycles > maximum_UDVM_cycles ){
334 goto decompression_failure;
337 current_instruction = buff[current_address & 0xffff];
339 switch ( current_instruction ) {
340 case SIGCOMP_INSTR_DECOMPRESSION_FAILURE:
341 if ( result_code == 0 )
343 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
344 "Addr: %u ## DECOMPRESSION-FAILURE(0)",
346 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Wireshark UDVM diagnostic: %s.",
347 val_to_str(result_code, result_code_vals,"Unknown (%u)"));
348 if ( output_address > 0 ){
349 /* At least something got decompressed, show it */
350 decomp_tvb = tvb_new_child_real_data(message_tvb, out_buff,output_address,output_address);
351 /* Arrange that the allocated packet data copy be freed when the
354 tvb_set_free_cb( decomp_tvb, g_free );
355 /* Add the tvbuff to the list of tvbuffs to which the tvbuff we
356 * were handed refers, so it'll get cleaned up when that tvbuff
359 add_new_data_source(pinfo, decomp_tvb, "Decompressed SigComp message(Incomplete)");
360 proto_tree_add_text(udvm_tree, decomp_tvb, 0, -1,"SigComp message Decompression failure");
367 case SIGCOMP_INSTR_AND: /* 1 AND ($operand_1, %operand_2) */
368 if (show_instr_detail_level == 2 ){
369 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
370 "Addr: %u ## AND(1) (operand_1, operand_2)",
374 operand_address = current_address + 1;
375 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &operand_1, &result_dest);
376 if (show_instr_detail_level == 2 ){
377 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_1 %u",
378 operand_address, operand_1);
380 operand_address = next_operand_address;
382 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &operand_2);
383 if (show_instr_detail_level == 2 ){
384 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_2 %u",
385 operand_address, operand_2);
387 if (show_instr_detail_level == 1)
389 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
390 "Addr: %u ## AND (operand_1=%u, operand_2=%u)",
391 current_address, operand_1, operand_2);
393 /* execute the instruction */
394 result = operand_1 & operand_2;
397 buff[result_dest] = msb;
398 buff[(result_dest+1) & 0xffff] = lsb;
400 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," Loading result %u at %u",
401 result, result_dest);
403 current_address = next_operand_address;
404 goto execute_next_instruction;
408 case SIGCOMP_INSTR_OR: /* 2 OR ($operand_1, %operand_2) */
409 if (show_instr_detail_level == 2 ){
410 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
411 "Addr: %u ## OR(2) (operand_1, operand_2)",
415 operand_address = current_address + 1;
416 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &operand_1, &result_dest);
417 if (show_instr_detail_level == 2 ){
418 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_1 %u",
419 operand_address, operand_1);
421 operand_address = next_operand_address;
423 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &operand_2);
424 if (show_instr_detail_level == 2 ){
425 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_2 %u",
426 operand_address, operand_2);
428 if (show_instr_detail_level == 1)
430 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
431 "Addr: %u ## OR (operand_1=%u, operand_2=%u)",
432 current_address, operand_1, operand_2);
434 /* execute the instruction */
435 result = operand_1 | operand_2;
438 buff[result_dest] = msb;
439 buff[(result_dest+1) & 0xffff] = lsb;
441 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," Loading result %u at %u",
442 result, result_dest);
444 current_address = next_operand_address;
445 goto execute_next_instruction;
449 case SIGCOMP_INSTR_NOT: /* 3 NOT ($operand_1) */
450 if (show_instr_detail_level == 2 ){
451 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
452 "Addr: %u ## NOT(3) ($operand_1)",
456 operand_address = current_address + 1;
457 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &operand_1, &result_dest);
458 if (show_instr_detail_level == 2 ){
459 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_1 %u",
460 operand_address, operand_1);
462 if (show_instr_detail_level == 1)
464 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
465 "Addr: %u ## NOT (operand_1=%u)",
466 current_address, operand_1);
468 /* execute the instruction */
469 result = operand_1 ^ 0xffff;
472 buff[result_dest] = msb;
473 buff[(result_dest+1) & 0xffff] = lsb;
475 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," Loading result %u at %u",
476 result, result_dest);
478 current_address = next_operand_address;
479 goto execute_next_instruction;
482 case SIGCOMP_INSTR_LSHIFT: /* 4 LSHIFT ($operand_1, %operand_2) */
483 if (show_instr_detail_level == 2 ){
484 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
485 "Addr: %u ## LSHIFT(4) ($operand_1, operand_2)",
489 operand_address = current_address + 1;
490 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &operand_1, &result_dest);
491 if (show_instr_detail_level == 2 ){
492 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_1 %u",
493 operand_address, operand_1);
495 operand_address = next_operand_address;
497 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &operand_2);
498 if (show_instr_detail_level == 2 ){
499 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_2 %u",
500 operand_address, operand_2);
502 if (show_instr_detail_level == 1)
504 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
505 "Addr: %u ## LSHIFT (operand_1=%u, operand_2=%u)",
506 current_address, operand_1, operand_2);
508 /* execute the instruction */
509 result = operand_1 << operand_2;
512 buff[result_dest] = msb;
513 buff[(result_dest+1) & 0xffff] = lsb;
515 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," Loading result %u at %u",
516 result, result_dest);
518 current_address = next_operand_address;
519 goto execute_next_instruction;
522 case SIGCOMP_INSTR_RSHIFT: /* 5 RSHIFT ($operand_1, %operand_2) */
523 if (show_instr_detail_level == 2 ){
524 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
525 "Addr: %u ## RSHIFT(5) (operand_1, operand_2)",
529 operand_address = current_address + 1;
530 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &operand_1, &result_dest);
531 if (show_instr_detail_level == 2 ){
532 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_1 %u",
533 operand_address, operand_1);
535 operand_address = next_operand_address;
537 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &operand_2);
538 if (show_instr_detail_level == 2 ){
539 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_2 %u",
540 operand_address, operand_2);
542 if (show_instr_detail_level == 1)
544 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
545 "Addr: %u ## RSHIFT (operand_1=%u, operand_2=%u)",
546 current_address, operand_1, operand_2);
548 /* execute the instruction */
549 result = operand_1 >> operand_2;
552 buff[result_dest] = msb;
553 buff[(result_dest+1) & 0xffff] = lsb;
555 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," Loading result %u at %u",
556 result, result_dest);
558 current_address = next_operand_address;
559 goto execute_next_instruction;
561 case SIGCOMP_INSTR_ADD: /* 6 ADD ($operand_1, %operand_2) */
562 if (show_instr_detail_level == 2 ){
563 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
564 "Addr: %u ## ADD(6) (operand_1, operand_2)",
568 operand_address = current_address + 1;
569 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &operand_1, &result_dest);
570 if (show_instr_detail_level == 2 ){
571 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_1 %u",
572 operand_address, operand_1);
574 operand_address = next_operand_address;
576 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &operand_2);
577 if (show_instr_detail_level == 2 ){
578 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_2 %u",
579 operand_address, operand_2);
581 if (show_instr_detail_level == 1)
583 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
584 "Addr: %u ## ADD (operand_1=%u, operand_2=%u)",
585 current_address, operand_1, operand_2);
587 /* execute the instruction */
588 result = operand_1 + operand_2;
591 buff[result_dest] = msb;
592 buff[(result_dest+1) & 0xffff] = lsb;
594 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," Loading result %u at %u",
595 result, result_dest);
597 current_address = next_operand_address;
598 goto execute_next_instruction;
600 case SIGCOMP_INSTR_SUBTRACT: /* 7 SUBTRACT ($operand_1, %operand_2) */
601 if (show_instr_detail_level == 2 ){
602 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
603 "Addr: %u ## SUBTRACT(7) (operand_1, operand_2)",
607 operand_address = current_address + 1;
608 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &operand_1, &result_dest);
609 if (show_instr_detail_level == 2 ){
610 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_1 %u",
611 operand_address, operand_1);
613 operand_address = next_operand_address;
615 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &operand_2);
616 if (show_instr_detail_level == 2 ){
617 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_2 %u",
618 operand_address, operand_2);
620 if (show_instr_detail_level == 1)
622 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
623 "Addr: %u ## SUBTRACT (operand_1=%u, operand_2=%u)",
624 current_address, operand_1, operand_2);
626 /* execute the instruction */
627 result = operand_1 - operand_2;
630 buff[result_dest] = msb;
631 buff[(result_dest+1) & 0xffff] = lsb;
633 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," Loading result %u at %u",
634 result, result_dest);
636 current_address = next_operand_address;
637 goto execute_next_instruction;
640 case SIGCOMP_INSTR_MULTIPLY: /* 8 MULTIPLY ($operand_1, %operand_2) */
641 if (show_instr_detail_level == 2 ){
642 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
643 "Addr: %u ##MULTIPLY(8) (operand_1, operand_2)",
647 operand_address = current_address + 1;
648 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &operand_1, &result_dest);
649 if (show_instr_detail_level == 2 ){
650 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_1 %u",
651 operand_address, operand_1);
653 operand_address = next_operand_address;
655 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &operand_2);
656 if (show_instr_detail_level == 2 ){
657 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_2 %u",
658 operand_address, operand_2);
660 if (show_instr_detail_level == 1)
662 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
663 "Addr: %u ## MULTIPLY (operand_1=%u, operand_2=%u)",
664 current_address, operand_1, operand_2);
667 * execute the instruction
668 * MULTIPLY (m, n) := m * n (modulo 2^16)
670 if ( operand_2 == 0){
672 goto decompression_failure;
674 result = operand_1 * operand_2;
677 buff[result_dest] = msb;
678 buff[(result_dest+1) & 0xffff] = lsb;
680 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," Loading result %u at %u",
681 result, result_dest);
683 current_address = next_operand_address;
684 goto execute_next_instruction;
687 case SIGCOMP_INSTR_DIVIDE: /* 9 DIVIDE ($operand_1, %operand_2) */
688 if (show_instr_detail_level == 2 ){
689 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
690 "Addr: %u ## DIVIDE(9) (operand_1, operand_2)",
694 operand_address = current_address + 1;
695 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &operand_1, &result_dest);
696 if (show_instr_detail_level == 2 ){
697 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_1 %u",
698 operand_address, operand_1);
700 operand_address = next_operand_address;
702 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &operand_2);
703 if (show_instr_detail_level == 2 ){
704 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_2 %u",
705 operand_address, operand_2);
707 if (show_instr_detail_level == 1)
709 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
710 "Addr: %u ## DIVIDE (operand_1=%u, operand_2=%u)",
711 current_address, operand_1, operand_2);
714 * execute the instruction
715 * DIVIDE (m, n) := floor(m / n)
716 * Decompression failure occurs if a DIVIDE or REMAINDER instruction
717 * encounters an operand_2 that is zero.
719 if ( operand_2 == 0){
721 goto decompression_failure;
723 result = operand_1 / operand_2;
726 buff[result_dest] = msb;
727 buff[(result_dest+1) & 0xffff] = lsb;
729 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," Loading result %u at %u",
730 result, result_dest);
732 current_address = next_operand_address;
733 goto execute_next_instruction;
736 case SIGCOMP_INSTR_REMAINDER: /* 10 REMAINDER ($operand_1, %operand_2) */
737 if (show_instr_detail_level == 2 ){
738 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
739 "Addr: %u ## REMAINDER(10) (operand_1, operand_2)",
743 operand_address = current_address + 1;
744 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &operand_1, &result_dest);
745 if (show_instr_detail_level == 2 ){
746 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_1 %u",
747 operand_address, operand_1);
749 operand_address = next_operand_address;
751 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &operand_2);
752 if (show_instr_detail_level == 2 ){
753 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_2 %u",
754 operand_address, operand_2);
756 if (show_instr_detail_level == 1)
758 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
759 "Addr: %u ## REMAINDER (operand_1=%u, operand_2=%u)",
760 current_address, operand_1, operand_2);
763 * execute the instruction
764 * REMAINDER (m, n) := m - n * floor(m / n)
765 * Decompression failure occurs if a DIVIDE or REMAINDER instruction
766 * encounters an operand_2 that is zero.
768 if ( operand_2 == 0){
770 goto decompression_failure;
772 result = operand_1 - operand_2 * (operand_1 / operand_2);
775 buff[result_dest] = msb;
776 buff[(result_dest+1) & 0xffff] = lsb;
778 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," Loading result %u at %u",
779 result, result_dest);
781 current_address = next_operand_address;
782 goto execute_next_instruction;
784 case SIGCOMP_INSTR_SORT_ASCENDING: /* 11 SORT-ASCENDING (%start, %n, %k) */
786 * used_udvm_cycles = 1 + k * (ceiling(log2(k)) + n)
789 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
790 "Addr: %u ## SORT-ASCENDING(11) (start, n, k))",
793 operand_address = current_address + 1;
794 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Execution of this instruction is NOT implemented");
796 * used_udvm_cycles = 1 + k * (ceiling(log2(k)) + n)
800 case SIGCOMP_INSTR_SORT_DESCENDING: /* 12 SORT-DESCENDING (%start, %n, %k) */
802 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
803 "Addr: %u ## SORT-DESCENDING(12) (start, n, k))",
806 operand_address = current_address + 1;
807 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Execution of this instruction is NOT implemented");
809 * used_udvm_cycles = 1 + k * (ceiling(log2(k)) + n)
812 case SIGCOMP_INSTR_SHA_1: /* 13 SHA-1 (%position, %length, %destination) */
814 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
815 "Addr: %u ## SHA-1(13) (position, length, destination)",
818 operand_address = current_address + 1;
820 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &position);
822 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u position %u",
823 operand_address, position);
825 operand_address = next_operand_address;
828 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &length);
830 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Length %u",
831 operand_address, length);
833 operand_address = next_operand_address;
836 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &ref_destination, &result_dest);
838 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u $destination %u",
839 operand_address, ref_destination);
841 current_address = next_operand_address;
842 used_udvm_cycles = used_udvm_cycles + length;
846 byte_copy_right = buff[66] << 8;
847 byte_copy_right = byte_copy_right | buff[67];
848 byte_copy_left = buff[64] << 8;
849 byte_copy_left = byte_copy_left | buff[65];
852 proto_tree_add_text(udvm_tree, message_tvb, 0, -1,
853 "byte_copy_right = %u", byte_copy_right);
859 guint16 handle_now = length;
861 if ( k < byte_copy_right && byte_copy_right <= k + (length-n) ){
862 handle_now = byte_copy_right - position;
865 if (k + handle_now >= UDVM_MEMORY_SIZE)
866 goto decompression_failure;
867 sha1_update( &ctx, &buff[k], handle_now );
869 k = ( k + handle_now ) & 0xffff;
870 n = ( n + handle_now ) & 0xffff;
872 if ( k >= byte_copy_right ) {
877 sha1_finish( &ctx, sha1_digest_buf );
881 for ( n=0; n< STATE_BUFFER_SIZE; n++ ) {
883 buff[k] = sha1_digest_buf[n];
885 k = ( k + 1 ) & 0xffff;
888 if ( k == byte_copy_right ){
894 proto_tree_add_text(udvm_tree, message_tvb, 0, -1,
895 "Calculated SHA-1: %s",
896 bytes_to_str(sha1_digest_buf, STATE_BUFFER_SIZE));
899 current_address = next_operand_address;
900 goto execute_next_instruction;
903 case SIGCOMP_INSTR_LOAD: /* 14 LOAD (%address, %value) */
904 if (show_instr_detail_level == 2 ){
905 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
906 "Addr: %u ## LOAD(14) (%%address, %%value)",
909 operand_address = current_address + 1;
911 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &addr);
912 if (show_instr_detail_level == 2 ){
913 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Address %u",
914 operand_address, addr);
916 operand_address = next_operand_address;
918 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &value);
919 if (show_instr_detail_level == 1)
921 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
922 "Addr: %u ## LOAD (%%address=%u, %%value=%u)",
923 current_address, addr, value);
929 buff[(addr + 1) & 0xffff] = lsb;
932 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Value %u",
933 operand_address, value);
934 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," Loading bytes at %u Value %u 0x%x",
937 current_address = next_operand_address;
938 goto execute_next_instruction;
941 case SIGCOMP_INSTR_MULTILOAD: /* 15 MULTILOAD (%address, #n, %value_0, ..., %value_n-1) */
943 * The MULTILOAD instruction sets a contiguous block of 2-byte words in
944 * the UDVM memory to specified values.
945 * Hmm what if the value to load only takes one byte ? Chose to always load two bytes.
947 if (show_instr_detail_level == 2 ){
948 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
949 "Addr: %u ## MULTILOAD(15) (%%address, #n, value_0, ..., value_n-1)",
952 operand_address = current_address + 1;
954 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &addr);
955 if (show_instr_detail_level == 2 ){
956 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Address %u",
957 operand_address, addr);
959 operand_address = next_operand_address;
962 next_operand_address = decode_udvm_literal_operand(buff,operand_address, &n);
963 if (show_instr_detail_level == 2 ){
964 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u n %u",
967 if (show_instr_detail_level == 1)
969 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
970 "Addr: %u ## MULTILOAD (%%address=%u, #n=%u, value_0, ..., value_%d)",
971 current_address, addr, n, n-1);
973 operand_address = next_operand_address;
974 used_udvm_cycles = used_udvm_cycles + n;
978 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &value);
982 if (addr >= UDVM_MEMORY_SIZE - 1)
983 goto decompression_failure;
986 buff[(addr + 1) & 0xffff] = lsb;
989 length = next_operand_address - operand_address;
992 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1, "Addr: %u Value %5u - Loading bytes at %5u Value %5u 0x%x",
993 operand_address, value, addr, value, value);
996 operand_address = next_operand_address;
998 current_address = next_operand_address;
999 goto execute_next_instruction;
1003 case SIGCOMP_INSTR_PUSH: /* 16 PUSH (%value) */
1004 if (show_instr_detail_level == 2){
1005 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1006 "Addr: %u ## PUSH(16) (value)",
1009 operand_address = current_address + 1;
1011 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &value);
1012 if (show_instr_detail_level == 2){
1013 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Value %u",
1014 operand_address, value);
1016 if (show_instr_detail_level == 1)
1018 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1019 "Addr: %u ## PUSH (value=%u)",
1020 current_address, value);
1022 current_address = next_operand_address;
1024 /* Push the value address onto the stack */
1025 stack_location = (buff[70] << 8) | buff[71];
1026 stack_fill = (buff[stack_location] << 8)
1027 | buff[(stack_location+1) & 0xFFFF];
1028 addr = (stack_location + stack_fill * 2 + 2) & 0xFFFF;
1030 if (addr >= UDVM_MEMORY_SIZE - 1)
1031 goto decompression_failure;
1033 buff[addr] = (value >> 8) & 0x00FF;
1034 buff[(addr+1) & 0xFFFF] = value & 0x00FF;
1036 if (stack_location >= UDVM_MEMORY_SIZE - 1)
1037 goto decompression_failure;
1039 stack_fill = (stack_fill + 1) & 0xFFFF;
1040 buff[stack_location] = (stack_fill >> 8) & 0x00FF;
1041 buff[(stack_location+1) & 0xFFFF] = stack_fill & 0x00FF;
1043 goto execute_next_instruction;
1047 case SIGCOMP_INSTR_POP: /* 17 POP (%address) */
1048 if (show_instr_detail_level == 2){
1049 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1050 "Addr: %u ## POP(16) (value)",
1053 operand_address = current_address + 1;
1055 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &destination);
1056 if (show_instr_detail_level == 2){
1057 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Value %u",
1058 operand_address, destination);
1060 if (show_instr_detail_level == 1)
1062 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1063 "Addr: %u ## POP (address=%u)",
1064 current_address, destination);
1066 current_address = next_operand_address;
1068 /* Pop value from the top of the stack */
1069 stack_location = (buff[70] << 8) | buff[71];
1070 stack_fill = (buff[stack_location] << 8)
1071 | buff[(stack_location+1) & 0xFFFF];
1072 if (stack_fill == 0)
1075 goto decompression_failure;
1078 if (stack_location >= UDVM_MEMORY_SIZE - 1)
1079 goto decompression_failure;
1081 stack_fill = (stack_fill - 1) & 0xFFFF;
1082 buff[stack_location] = (stack_fill >> 8) & 0x00FF;
1083 buff[(stack_location+1) & 0xFFFF] = stack_fill & 0x00FF;
1085 addr = (stack_location + stack_fill * 2 + 2) & 0xFFFF;
1087 if (addr >= UDVM_MEMORY_SIZE - 1)
1088 goto decompression_failure;
1090 value = (buff[addr] << 8)
1091 | buff[(addr+1) & 0xFFFF];
1093 /* ... and store the popped value. */
1094 if (destination >= UDVM_MEMORY_SIZE - 1)
1095 goto decompression_failure;
1096 buff[destination] = (value >> 8) & 0x00FF;
1097 buff[(destination+1) & 0xFFFF] = value & 0x00FF;
1099 goto execute_next_instruction;
1103 case SIGCOMP_INSTR_COPY: /* 18 COPY (%position, %length, %destination) */
1104 if (show_instr_detail_level == 2 ){
1105 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1106 "Addr: %u ## COPY(18) (position, length, destination)",
1109 operand_address = current_address + 1;
1111 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &position);
1112 if (show_instr_detail_level == 2 ){
1113 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u position %u",
1114 operand_address, position);
1116 operand_address = next_operand_address;
1119 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &length);
1120 if (show_instr_detail_level == 2 ){
1121 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Length %u",
1122 operand_address, length);
1124 operand_address = next_operand_address;
1127 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &destination);
1128 if (show_instr_detail_level == 2 ){
1129 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Destination %u",
1130 operand_address, destination);
1132 if (show_instr_detail_level == 1)
1134 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1135 "Addr: %u ## COPY (position=%u, length=%u, destination=%u)",
1136 current_address, position, length, destination);
1138 current_address = next_operand_address;
1142 * The string of bytes is copied in ascending order of memory address,
1143 * respecting the bounds set by byte_copy_left and byte_copy_right.
1144 * More precisely, if a byte is copied from/to Address m then the next
1145 * byte is copied from/to Address n where n is calculated as follows:
1147 * Set k := m + 1 (modulo 2^16)
1148 * If k = byte_copy_right then set n := byte_copy_left, else set n := k
1154 byte_copy_right = buff[66] << 8;
1155 byte_copy_right = byte_copy_right | buff[67];
1156 byte_copy_left = buff[64] << 8;
1157 byte_copy_left = byte_copy_left | buff[65];
1158 if (print_level_2 ){
1159 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
1160 " byte_copy_right = %u", byte_copy_right);
1163 while ( n < length ){
1164 buff[k] = buff[position];
1165 if (print_level_2 ){
1166 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
1167 " Copying value: %u (0x%x) to Addr: %u",
1168 buff[position], buff[position], k);
1170 position = ( position + 1 ) & 0xffff;
1171 k = ( k + 1 ) & 0xffff;
1175 * Check for circular buffer wrapping after the positions are
1176 * incremented. If either started at BCR then they should continue
1177 * to increment beyond BCR.
1179 if ( k == byte_copy_right ){
1182 if ( position == byte_copy_right ){
1183 position = byte_copy_left;
1186 used_udvm_cycles = used_udvm_cycles + length;
1187 goto execute_next_instruction;
1190 case SIGCOMP_INSTR_COPY_LITERAL: /* 19 COPY-LITERAL (%position, %length, $destination) */
1191 if (show_instr_detail_level == 2 ){
1192 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1193 "Addr: %u ## COPY-LITERAL(19) (position, length, $destination)",
1196 operand_address = current_address + 1;
1198 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &position);
1199 if (show_instr_detail_level == 2 ){
1200 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u position %u",
1201 operand_address, position);
1203 operand_address = next_operand_address;
1206 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &length);
1207 if (show_instr_detail_level == 2 ){
1208 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Length %u",
1209 operand_address, length);
1211 operand_address = next_operand_address;
1215 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &ref_destination, &result_dest);
1216 if (show_instr_detail_level == 2 ){
1217 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u destination %u",
1218 operand_address, ref_destination);
1220 if (show_instr_detail_level == 1)
1222 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1223 "Addr: %u ## COPY-LITERAL (position=%u, length=%u, $destination=%u)",
1224 current_address, position, length, ref_destination);
1226 current_address = next_operand_address;
1232 * The string of bytes is copied in ascending order of memory address,
1233 * respecting the bounds set by byte_copy_left and byte_copy_right.
1234 * More precisely, if a byte is copied from/to Address m then the next
1235 * byte is copied from/to Address n where n is calculated as follows:
1237 * Set k := m + 1 (modulo 2^16)
1238 * If k = byte_copy_right then set n := byte_copy_left, else set n := k
1243 k = ref_destination;
1244 byte_copy_right = buff[66] << 8;
1245 byte_copy_right = byte_copy_right | buff[67];
1246 byte_copy_left = buff[64] << 8;
1247 byte_copy_left = byte_copy_left | buff[65];
1248 if (print_level_2 ){
1249 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
1250 " byte_copy_right = %u", byte_copy_right);
1252 while ( n < length ){
1254 buff[k] = buff[position];
1255 if (print_level_2 ){
1256 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
1257 " Copying value: %u (0x%x) to Addr: %u",
1258 buff[position], buff[position], k);
1260 position = ( position + 1 ) & 0xffff;
1261 k = ( k + 1 ) & 0xffff;
1265 * Check for circular buffer wrapping after the positions are
1266 * incremented. It is important that k cannot be left set
1267 * to BCR. Also, if either started at BCR then they should continue
1268 * to increment beyond BCR.
1270 if ( k == byte_copy_right ){
1273 if ( position == byte_copy_right ){
1274 position = byte_copy_left;
1277 buff[result_dest] = k >> 8;
1278 buff[(result_dest + 1) & 0xffff] = k & 0x00ff;
1280 used_udvm_cycles = used_udvm_cycles + length;
1281 goto execute_next_instruction;
1284 case SIGCOMP_INSTR_COPY_OFFSET: /* 20 COPY-OFFSET (%offset, %length, $destination) */
1285 if (show_instr_detail_level == 2 ){
1286 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1287 "Addr: %u ## COPY-OFFSET(20) (offset, length, $destination)",
1290 operand_address = current_address + 1;
1292 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &multy_offset);
1293 if (show_instr_detail_level == 2 ){
1294 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u offset %u",
1295 operand_address, multy_offset);
1297 operand_address = next_operand_address;
1300 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &length);
1301 if (show_instr_detail_level == 2 ){
1302 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Length %u",
1303 operand_address, length);
1305 operand_address = next_operand_address;
1309 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &ref_destination, &result_dest);
1310 if (show_instr_detail_level == 2 ){
1311 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u $destination %u",
1312 operand_address, ref_destination);
1315 if (show_instr_detail_level == 1)
1317 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1318 "Addr: %u ## COPY-OFFSET (offset=%u, length=%u, $destination=%u)",
1319 current_address, multy_offset, length, result_dest);
1321 current_address = next_operand_address;
1323 /* Execute the instruction:
1324 * To derive the value of the position operand, starting at the memory
1325 * address specified by destination, the UDVM counts backwards a total
1326 * of offset memory addresses.
1328 * If the memory address specified in byte_copy_left is reached, the
1329 * next memory address is taken to be (byte_copy_right - 1) modulo 2^16.
1331 byte_copy_left = buff[64] << 8;
1332 byte_copy_left = byte_copy_left | buff[65];
1333 byte_copy_right = buff[66] << 8;
1334 byte_copy_right = byte_copy_right | buff[67];
1337 * In order to work out the position, simple arithmetic is tricky
1338 * to apply because there some nasty corner cases. A simple loop
1339 * is inefficient but the logic is simple.
1341 * FUTURE: This could be optimised.
1343 for (position = ref_destination, i = 0; i < multy_offset; i++)
1345 if ( position == byte_copy_left )
1347 position = (byte_copy_right - 1) & 0xffff;
1351 position = (position - 1) & 0xffff;
1355 if (print_level_2 ){
1356 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
1357 " byte_copy_left = %u byte_copy_right = %u position= %u",
1358 byte_copy_left, byte_copy_right, position);
1360 /* The COPY-OFFSET instruction then behaves as a COPY-LITERAL
1361 * instruction, taking the value of the position operand to be the last
1362 * memory address reached in the above step.
1368 * The string of bytes is copied in ascending order of memory address,
1369 * respecting the bounds set by byte_copy_left and byte_copy_right.
1370 * More precisely, if a byte is copied from/to Address m then the next
1371 * byte is copied from/to Address n where n is calculated as follows:
1373 * Set k := m + 1 (modulo 2^16)
1374 * If k = byte_copy_right then set n := byte_copy_left, else set n := k
1379 k = ref_destination;
1380 if (print_level_2 ){
1381 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
1382 " byte_copy_left = %u byte_copy_right = %u", byte_copy_left, byte_copy_right);
1384 while ( n < length ){
1385 buff[k] = buff[position];
1386 if (print_level_2 ){
1387 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
1388 " Copying value: %5u (0x%x) from Addr: %u to Addr: %u",
1389 buff[position], buff[position],(position), k);
1392 k = ( k + 1 ) & 0xffff;
1393 position = ( position + 1 ) & 0xffff;
1396 * Check for circular buffer wrapping after the positions are
1397 * incremented. It is important that k cannot be left set
1398 * to BCR. Also, if either started at BCR then they should continue
1399 * to increment beyond BCR.
1401 if ( k == byte_copy_right ){
1404 if ( position == byte_copy_right ){
1405 position = byte_copy_left;
1408 buff[result_dest] = k >> 8;
1409 buff[result_dest + 1] = k & 0x00ff;
1410 used_udvm_cycles = used_udvm_cycles + length;
1411 goto execute_next_instruction;
1414 case SIGCOMP_INSTR_MEMSET: /* 21 MEMSET (%address, %length, %start_value, %offset) */
1415 if (show_instr_detail_level == 2 ){
1416 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1417 "Addr: %u ## MEMSET(21) (address, length, start_value, offset)",
1420 operand_address = current_address + 1;
1423 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &addr);
1424 if (show_instr_detail_level == 2 ){
1425 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Address %u",
1426 operand_address, addr);
1428 operand_address = next_operand_address;
1431 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &length);
1432 if (show_instr_detail_level == 2 ){
1433 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Length %u",
1434 operand_address, length);
1436 operand_address = next_operand_address;
1438 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &start_value);
1439 if (show_instr_detail_level == 2 ){
1440 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u start_value %u",
1441 operand_address, start_value);
1443 operand_address = next_operand_address;
1446 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &multy_offset);
1447 if (show_instr_detail_level == 2 ){
1448 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u offset %u",
1449 operand_address, multy_offset);
1451 if (show_instr_detail_level == 1)
1453 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1454 "Addr: %u ## MEMSET (address=%u, length=%u, start_value=%u, offset=%u)",
1455 current_address, addr, length, start_value, multy_offset);
1457 current_address = next_operand_address;
1458 /* exetute the instruction
1459 * The sequence of values used by the MEMSET instruction is specified by
1460 * the following formula:
1462 * Seq[n] := (start_value + n * offset) modulo 256
1466 byte_copy_right = buff[66] << 8;
1467 byte_copy_right = byte_copy_right | buff[67];
1468 byte_copy_left = buff[64] << 8;
1469 byte_copy_left = byte_copy_left | buff[65];
1470 if (print_level_2 ){
1471 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
1472 " byte_copy_left = %u byte_copy_right = %u", byte_copy_left, byte_copy_right);
1474 while ( n < length ){
1475 if ( k == byte_copy_right ){
1478 buff[k] = (start_value + ( n * multy_offset)) & 0xff;
1479 if (print_level_2 ){
1480 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
1481 " Storing value: %u (0x%x) at Addr: %u",
1482 buff[k], buff[k], k);
1484 k = ( k + 1 ) & 0xffff;
1487 used_udvm_cycles = used_udvm_cycles + length;
1488 goto execute_next_instruction;
1492 case SIGCOMP_INSTR_JUMP: /* 22 JUMP (@address) */
1493 if (show_instr_detail_level == 2 ){
1494 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1495 "Addr: %u ## JUMP(22) (@address)",
1498 operand_address = current_address + 1;
1500 /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
1501 next_operand_address = decode_udvm_address_operand(buff,operand_address, &at_address, current_address);
1502 if (show_instr_detail_level == 2 ){
1503 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u @Address %u",
1504 operand_address, at_address);
1506 if (show_instr_detail_level == 1)
1508 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1509 "Addr: %u ## JUMP (@address=%u)",
1510 current_address, at_address);
1512 current_address = at_address;
1513 goto execute_next_instruction;
1516 case SIGCOMP_INSTR_COMPARE: /* 23 */
1517 /* COMPARE (%value_1, %value_2, @address_1, @address_2, @address_3)
1519 if (show_instr_detail_level == 2 ){
1520 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1521 "Addr: %u ## COMPARE(23) (value_1, value_2, @address_1, @address_2, @address_3)",
1524 operand_address = current_address + 1;
1527 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &value_1);
1528 if (show_instr_detail_level == 2 ){
1529 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Value %u",
1530 operand_address, value_1);
1532 operand_address = next_operand_address;
1535 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &value_2);
1536 if (show_instr_detail_level == 2 ){
1537 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Value %u",
1538 operand_address, value_2);
1540 operand_address = next_operand_address;
1543 /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
1544 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &at_address_1);
1545 at_address_1 = ( current_address + at_address_1) & 0xffff;
1546 if (show_instr_detail_level == 2 ){
1547 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u @Address %u",
1548 operand_address, at_address_1);
1550 operand_address = next_operand_address;
1554 /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
1555 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &at_address_2);
1556 at_address_2 = ( current_address + at_address_2) & 0xffff;
1557 if (show_instr_detail_level == 2 ){
1558 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u @Address %u",
1559 operand_address, at_address_2);
1561 operand_address = next_operand_address;
1564 /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
1565 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &at_address_3);
1566 at_address_3 = ( current_address + at_address_3) & 0xffff;
1567 if (show_instr_detail_level == 2 ){
1568 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u @Address %u",
1569 operand_address, at_address_3);
1571 if (show_instr_detail_level == 1)
1573 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1574 "Addr: %u ## COMPARE (value_1=%u, value_2=%u, @address_1=%u, @address_2=%u, @address_3=%u)",
1575 current_address, value_1, value_2, at_address_1, at_address_2, at_address_3);
1577 /* execute the instruction
1578 * If value_1 < value_2 then the UDVM continues instruction execution at
1579 * the memory address specified by address 1. If value_1 = value_2 then
1580 * it jumps to the address specified by address_2. If value_1 > value_2
1581 * then it jumps to the address specified by address_3.
1583 if ( value_1 < value_2 )
1584 current_address = at_address_1;
1585 if ( value_1 == value_2 )
1586 current_address = at_address_2;
1587 if ( value_1 > value_2 )
1588 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 addr = (stack_location + stack_fill * 2 + 2) & 0xFFFF;
1618 if (addr >= UDVM_MEMORY_SIZE - 1)
1619 goto decompression_failure;
1620 buff[addr] = (current_address >> 8) & 0x00FF;
1621 buff[(addr+1) & 0xFFFF] = current_address & 0x00FF;
1623 stack_fill = (stack_fill + 1) & 0xFFFF;
1624 if (stack_location >= UDVM_MEMORY_SIZE - 1)
1625 goto decompression_failure;
1626 buff[stack_location] = (stack_fill >> 8) & 0x00FF;
1627 buff[(stack_location+1) & 0xFFFF] = stack_fill & 0x00FF;
1629 /* ... and jump to the destination address */
1630 current_address = at_address;
1632 goto execute_next_instruction;
1636 case SIGCOMP_INSTR_RETURN: /* 25 POP and return */
1637 if (print_level_1 || show_instr_detail_level == 1){
1638 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1639 "Addr: %u ## POP(25) and return",
1643 /* Pop value from the top of the stack */
1644 stack_location = (buff[70] << 8) | buff[71];
1645 stack_fill = (buff[stack_location] << 8)
1646 | buff[(stack_location+1) & 0xFFFF];
1647 if (stack_fill == 0)
1650 goto decompression_failure;
1653 stack_fill = (stack_fill - 1) & 0xFFFF;
1654 if (stack_location >= UDVM_MEMORY_SIZE - 1)
1655 goto decompression_failure;
1656 buff[stack_location] = (stack_fill >> 8) & 0x00FF;
1657 buff[(stack_location+1) & 0xFFFF] = stack_fill & 0x00FF;
1659 addr = (stack_location + stack_fill * 2 + 2) & 0xFFFF;
1660 at_address = (buff[addr] << 8)
1661 | buff[(addr+1) & 0xFFFF];
1663 /* ... and set the PC to the popped value */
1664 current_address = at_address;
1666 goto execute_next_instruction;
1670 case SIGCOMP_INSTR_SWITCH: /* 26 SWITCH (#n, %j, @address_0, @address_1, ... , @address_n-1) */
1672 * When a SWITCH instruction is encountered the UDVM reads the value of
1673 * j. It then continues instruction execution at the address specified
1676 * Decompression failure occurs if j specifies a value of n or more, or
1677 * if the address lies beyond the overall UDVM memory size.
1679 instruction_address = current_address;
1680 if (print_level_1 ){
1681 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1682 "Addr: %u ## SWITCH (#n, j, @address_0, @address_1, ... , @address_n-1))",
1685 operand_address = current_address + 1;
1687 * Number of addresses in the instruction
1689 next_operand_address = decode_udvm_literal_operand(buff,operand_address, &n);
1690 if (print_level_1 ){
1691 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u n %u",
1692 operand_address, n);
1694 operand_address = next_operand_address;
1696 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &j);
1697 if (print_level_1 ){
1698 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u j %u",
1699 operand_address, j);
1701 operand_address = next_operand_address;
1705 /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
1706 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &at_address_1);
1707 at_address_1 = ( instruction_address + at_address_1) & 0xffff;
1708 if (print_level_1 ){
1709 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u @Address %u",
1710 operand_address, at_address_1);
1713 current_address = at_address_1;
1715 operand_address = next_operand_address;
1718 /* Check decompression failure */
1719 if ( ( j == n ) || ( j > n )){
1721 goto decompression_failure;
1723 if ( current_address > UDVM_MEMORY_SIZE ){
1725 goto decompression_failure;
1727 used_udvm_cycles = used_udvm_cycles + n;
1729 goto execute_next_instruction;
1732 case SIGCOMP_INSTR_CRC: /* 27 CRC (%value, %position, %length, @address) */
1733 if (print_level_1 ){
1734 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1735 "Addr: %u ## CRC (value, position, length, @address)",
1739 operand_address = current_address + 1;
1742 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &value);
1743 if (print_level_1 ){
1744 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Value %u",
1745 operand_address, value);
1747 operand_address = next_operand_address;
1750 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &position);
1751 if (print_level_1 ){
1752 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u position %u",
1753 operand_address, position);
1755 operand_address = next_operand_address;
1758 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &length);
1759 if (print_level_1 ){
1760 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Length %u",
1761 operand_address, length);
1763 operand_address = next_operand_address;
1766 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &at_address);
1767 at_address = ( current_address + at_address) & 0xffff;
1768 if (print_level_1 ){
1769 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u @Address %u",
1770 operand_address, at_address);
1772 /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
1773 used_udvm_cycles = used_udvm_cycles + length;
1777 byte_copy_right = buff[66] << 8;
1778 byte_copy_right = byte_copy_right | buff[67];
1779 byte_copy_left = buff[64] << 8;
1780 byte_copy_left = byte_copy_left | buff[65];
1783 if (print_level_2 ){
1784 proto_tree_add_text(udvm_tree, message_tvb, 0, -1,
1785 "byte_copy_right = %u", byte_copy_right);
1790 guint16 handle_now = length - n;
1792 if ( k < byte_copy_right && byte_copy_right <= k + (length-n) ){
1793 handle_now = byte_copy_right - k;
1796 if (k + handle_now >= UDVM_MEMORY_SIZE)
1797 goto decompression_failure;
1798 result = crc16_ccitt_seed(&buff[k], handle_now, (guint16) (result ^ 0xffff));
1800 k = ( k + handle_now ) & 0xffff;
1801 n = ( n + handle_now ) & 0xffff;
1803 if ( k >= byte_copy_right ) {
1808 result = result ^ 0xffff;
1810 if (print_level_1 ){
1811 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1, "Calculated CRC %u", result);
1813 if (result != value){
1814 current_address = at_address;
1817 current_address = next_operand_address;
1819 goto execute_next_instruction;
1823 case SIGCOMP_INSTR_INPUT_BYTES: /* 28 INPUT-BYTES (%length, %destination, @address) */
1824 if (show_instr_detail_level == 2 ){
1825 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1826 "Addr: %u ## INPUT-BYTES(28) length, destination, @address)",
1829 operand_address = current_address + 1;
1831 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &length);
1832 if (show_instr_detail_level == 2 ){
1833 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Length %u",
1834 operand_address, length);
1836 operand_address = next_operand_address;
1839 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &destination);
1840 if (show_instr_detail_level == 2 ){
1841 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Destination %u",
1842 operand_address, destination);
1844 operand_address = next_operand_address;
1847 /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
1848 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &at_address);
1849 at_address = ( current_address + at_address) & 0xffff;
1850 if (show_instr_detail_level == 2 ){
1851 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u @Address %u",
1852 operand_address, at_address);
1854 if (show_instr_detail_level == 1)
1856 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1857 "Addr: %u ## INPUT-BYTES length=%u, destination=%u, @address=%u)",
1858 current_address, length, destination, at_address);
1860 /* execute the instruction TODO insert checks
1864 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1865 * | byte_copy_left | 64 - 65
1866 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1867 * | byte_copy_right | 66 - 67
1868 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1869 * | input_bit_order | 68 - 69
1870 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1871 * | stack_location | 70 - 71
1872 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1874 * Figure 7: Memory addresses of the UDVM registers
1878 * The string of bytes is copied in ascending order of memory address,
1879 * respecting the bounds set by byte_copy_left and byte_copy_right.
1880 * More precisely, if a byte is copied from/to Address m then the next
1881 * byte is copied from/to Address n where n is calculated as follows:
1883 * Set k := m + 1 (modulo 2^16)
1884 * If k = byte_copy_right then set n := byte_copy_left, else set n := k
1890 byte_copy_right = buff[66] << 8;
1891 byte_copy_right = byte_copy_right | buff[67];
1892 byte_copy_left = buff[64] << 8;
1893 byte_copy_left = byte_copy_left | buff[65];
1894 if (print_level_1 ){
1895 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
1896 " byte_copy_right = %u", byte_copy_right);
1898 /* clear out remaining bits if any */
1901 /* operand_address used as dummy */
1902 while ( n < length ){
1903 if (input_address > ( msg_end - 1)){
1904 current_address = at_address;
1906 goto execute_next_instruction;
1909 if ( k == byte_copy_right ){
1912 octet = tvb_get_guint8(message_tvb, input_address);
1914 if (print_level_1 ){
1915 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
1916 " Loading value: %u (0x%x) at Addr: %u", octet, octet, k);
1920 * If the instruction requests data that lies beyond the end of the
1921 * SigComp message, no data is returned. Instead the UDVM moves program
1922 * execution to the address specified by the address operand.
1926 k = ( k + 1 ) & 0xffff;
1929 used_udvm_cycles = used_udvm_cycles + length;
1930 current_address = next_operand_address;
1931 goto execute_next_instruction;
1933 case SIGCOMP_INSTR_INPUT_BITS:/* 29 INPUT-BITS (%length, %destination, @address) */
1935 * The length operand indicates the requested number of bits.
1936 * Decompression failure occurs if this operand does not lie between 0
1939 * The destination operand specifies the memory address to which the
1940 * compressed data should be copied. Note that the requested bits are
1941 * interpreted as a 2-byte integer ranging from 0 to 2^length - 1, as
1942 * explained in Section 8.2.
1944 * If the instruction requests data that lies beyond the end of the
1945 * SigComp message, no data is returned. Instead the UDVM moves program
1946 * execution to the address specified by the address operand.
1949 if (show_instr_detail_level == 2 ){
1950 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1951 "Addr: %u ## INPUT-BITS(29) (length, destination, @address)",
1954 operand_address = current_address + 1;
1957 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &length);
1958 if (show_instr_detail_level == 2 ){
1959 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u length %u",
1960 operand_address, length);
1962 operand_address = next_operand_address;
1964 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &destination);
1965 if (show_instr_detail_level == 2 ){
1966 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Destination %u",
1967 operand_address, destination);
1969 operand_address = next_operand_address;
1972 /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
1973 next_operand_address = decode_udvm_address_operand(buff,operand_address, &at_address, current_address);
1974 if (show_instr_detail_level == 2 ){
1975 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u @Address %u",
1976 operand_address, at_address);
1978 if (show_instr_detail_level == 1)
1980 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1981 "Addr: %u ## INPUT-BITS length=%u, destination=%u, @address=%u)",
1982 current_address, length, destination, at_address);
1984 current_address = next_operand_address;
1987 * Execute actual instr.
1988 * The input_bit_order register contains the following three flags:
1991 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1992 * | reserved |F|H|P| 68 - 69
1993 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1995 input_bit_order = buff[68] << 8;
1996 input_bit_order = input_bit_order | buff[69];
1998 * If the instruction requests data that lies beyond the end of the
1999 * SigComp message, no data is returned. Instead the UDVM moves program
2000 * execution to the address specified by the address operand.
2005 goto decompression_failure;
2007 if ( input_bit_order > 7 ){
2009 goto decompression_failure;
2013 * Transfer F bit to bit_order to tell decomp dispatcher which bit order to use
2015 bit_order = ( input_bit_order & 0x0004 ) >> 2;
2016 value = decomp_dispatch_get_bits( message_tvb, udvm_tree, bit_order,
2017 buff, &old_input_bit_order, &remaining_bits,
2018 &input_bits, &input_address, length, &result_code, msg_end);
2019 if ( result_code == 11 ){
2020 current_address = at_address;
2021 goto execute_next_instruction;
2024 lsb = value & 0x00ff;
2025 if (destination >= UDVM_MEMORY_SIZE - 1)
2026 goto decompression_failure;
2027 buff[destination] = msb;
2028 buff[(destination + 1) & 0xffff]=lsb;
2029 if (print_level_1 ){
2030 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
2031 " Loading value: %u (0x%x) at Addr: %u, remaining_bits: %u", value, value, destination, remaining_bits);
2034 goto execute_next_instruction;
2036 case SIGCOMP_INSTR_INPUT_HUFFMAN: /* 30 */
2038 * INPUT-HUFFMAN (%destination, @address, #n, %bits_1, %lower_bound_1,
2039 * %upper_bound_1, %uncompressed_1, ... , %bits_n, %lower_bound_n,
2040 * %upper_bound_n, %uncompressed_n)
2042 if (show_instr_detail_level == 2 ){
2043 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2044 "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)",
2047 operand_address = current_address + 1;
2050 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &destination);
2051 if (show_instr_detail_level == 2 ){
2052 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Destination %u",
2053 operand_address, destination);
2055 operand_address = next_operand_address;
2058 /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
2059 next_operand_address = decode_udvm_address_operand(buff,operand_address, &at_address, current_address);
2060 if (show_instr_detail_level == 2 ){
2061 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u @Address %u",
2062 operand_address, at_address);
2064 operand_address = next_operand_address;
2067 next_operand_address = decode_udvm_literal_operand(buff,operand_address, &n);
2068 if (show_instr_detail_level == 2 ){
2069 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u n %u",
2070 operand_address, n);
2072 operand_address = next_operand_address;
2073 if (show_instr_detail_level == 1)
2075 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2076 "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)",
2077 current_address, destination, at_address, n, n, n, n, n);
2080 used_udvm_cycles = used_udvm_cycles + n;
2083 * Note that if n = 0 then the INPUT-HUFFMAN instruction is ignored and
2084 * program execution resumes at the following instruction.
2085 * Decompression failure occurs if (bits_1 + ... + bits_n) > 16.
2087 * In all other cases, the behavior of the INPUT-HUFFMAN instruction is
2090 * 1. Set j := 1 and set H := 0.
2092 * 2. Request bits_j compressed bits. Interpret the returned bits as an
2093 * integer k from 0 to 2^bits_j - 1, as explained in Section 8.2.
2095 * 3. Set H := H * 2^bits_j + k.
2097 * 4. If data is requested that lies beyond the end of the SigComp
2098 * message, terminate the INPUT-HUFFMAN instruction and move program
2099 * execution to the memory address specified by the address operand.
2101 * 5. If (H < lower_bound_j) or (H > upper_bound_j) then set j := j + 1.
2102 * Then go back to Step 2, unless j > n in which case decompression
2105 * 6. Copy (H + uncompressed_j - lower_bound_j) modulo 2^16 to the
2106 * memory address specified by the destination operand.
2110 * The input_bit_order register contains the following three flags:
2113 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2114 * | reserved |F|H|P| 68 - 69
2115 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2117 * Transfer H bit to bit_order to tell decomp dispatcher which bit order to use
2119 input_bit_order = buff[68] << 8;
2120 input_bit_order = input_bit_order | buff[69];
2121 bit_order = ( input_bit_order & 0x0002 ) >> 1;
2126 outside_huffman_boundaries = TRUE;
2127 print_in_loop = print_level_3;
2130 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &bits_n);
2131 if (print_in_loop ){
2132 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u bits_n %u",
2133 operand_address, bits_n);
2135 operand_address = next_operand_address;
2137 /* %lower_bound_n */
2138 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &lower_bound_n);
2139 if (print_in_loop ){
2140 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u lower_bound_n %u",
2141 operand_address, lower_bound_n);
2143 operand_address = next_operand_address;
2144 /* %upper_bound_n */
2145 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &upper_bound_n);
2146 if (print_in_loop ){
2147 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u upper_bound_n %u",
2148 operand_address, upper_bound_n);
2150 operand_address = next_operand_address;
2151 /* %uncompressed_n */
2152 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &uncompressed_n);
2153 if (print_in_loop ){
2154 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u uncompressed_n %u",
2155 operand_address, uncompressed_n);
2157 operand_address = next_operand_address;
2158 /* execute instruction */
2159 if ( outside_huffman_boundaries ) {
2161 * 2. Request bits_j compressed bits. Interpret the returned bits as an
2162 * integer k from 0 to 2^bits_j - 1, as explained in Section 8.2.
2164 k = decomp_dispatch_get_bits( message_tvb, udvm_tree, bit_order,
2165 buff, &old_input_bit_order, &remaining_bits,
2166 &input_bits, &input_address, bits_n, &result_code, msg_end);
2167 if ( result_code == 11 ){
2169 * 4. If data is requested that lies beyond the end of the SigComp
2170 * message, terminate the INPUT-HUFFMAN instruction and move program
2171 * execution to the memory address specified by the address operand.
2173 current_address = at_address;
2174 goto execute_next_instruction;
2178 * 3. Set H := H * 2^bits_j + k.
2179 * [In practice is a shift+OR operation.]
2182 H = (H << bits_n) | k;
2183 if (print_level_3 ){
2184 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," Set H(%u) := H(%u) * 2^bits_j(%u) + k(%u)",
2185 H ,oldH, 1<<bits_n,k);
2189 * 5. If (H < lower_bound_j) or (H > upper_bound_j) then set j := j + 1.
2190 * Then go back to Step 2, unless j > n in which case decompression
2193 if ((H < lower_bound_n) || (H > upper_bound_n)){
2194 outside_huffman_boundaries = TRUE;
2196 outside_huffman_boundaries = FALSE;
2197 print_in_loop = FALSE;
2199 * 6. Copy (H + uncompressed_j - lower_bound_j) modulo 2^16 to the
2200 * memory address specified by the destination operand.
2202 if (print_level_2 ){
2203 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2204 " H(%u) = H(%u) + uncompressed_n(%u) - lower_bound_n(%u)",
2205 (H + uncompressed_n - lower_bound_n ),H, uncompressed_n, lower_bound_n);
2207 H = H + uncompressed_n - lower_bound_n;
2210 if (destination >= UDVM_MEMORY_SIZE - 1)
2211 goto decompression_failure;
2212 buff[destination] = msb;
2213 buff[(destination + 1) & 0xffff]=lsb;
2214 if (print_level_1 ){
2215 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
2216 " Loading H: %u (0x%x) at Addr: %u,j = %u remaining_bits: %u",
2217 H, H, destination,( n - m + 1 ), remaining_bits);
2226 if ( outside_huffman_boundaries ) {
2228 goto decompression_failure;
2231 current_address = next_operand_address;
2232 goto execute_next_instruction;
2235 case SIGCOMP_INSTR_STATE_ACCESS: /* 31 */
2236 /* STATE-ACCESS (%partial_identifier_start, %partial_identifier_length,
2237 * %state_begin, %state_length, %state_address, %state_instruction)
2239 if (show_instr_detail_level == 2 ){
2240 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2241 "Addr: %u ## STATE-ACCESS(31) (partial_identifier_start, partial_identifier_length,state_begin, state_length, state_address, state_instruction)",
2244 operand_address = current_address + 1;
2247 * %partial_identifier_start
2249 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &p_id_start);
2250 if (show_instr_detail_level == 2 ){
2251 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u partial_identifier_start %u",
2252 operand_address, p_id_start);
2254 operand_address = next_operand_address;
2257 * %partial_identifier_length
2259 operand_address = next_operand_address;
2260 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &p_id_length);
2261 if (show_instr_detail_level == 2 ){
2262 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u partial_identifier_length %u",
2263 operand_address, p_id_length);
2268 operand_address = next_operand_address;
2269 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_begin);
2270 if (show_instr_detail_level == 2 ){
2271 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_begin %u",
2272 operand_address, state_begin);
2277 operand_address = next_operand_address;
2278 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_length);
2279 if (show_instr_detail_level == 2 ){
2280 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_length %u",
2281 operand_address, state_length);
2286 operand_address = next_operand_address;
2287 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_address);
2288 if (show_instr_detail_level == 2 ){
2289 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_address %u",
2290 operand_address, state_address);
2293 * %state_instruction
2295 operand_address = next_operand_address;
2296 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_instruction);
2297 if (show_instr_detail_level == 2 ){
2298 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_instruction %u",
2299 operand_address, state_instruction);
2301 if (show_instr_detail_level == 1)
2303 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2304 "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)",
2305 current_address, p_id_start, p_id_length, state_begin, state_length, state_address, state_instruction);
2307 current_address = next_operand_address;
2308 byte_copy_right = buff[66] << 8;
2309 byte_copy_right = byte_copy_right | buff[67];
2310 byte_copy_left = buff[64] << 8;
2311 byte_copy_left = byte_copy_left | buff[65];
2312 if (print_level_2 ){
2313 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
2314 " byte_copy_right = %u, byte_copy_left = %u", byte_copy_right,byte_copy_left);
2317 result_code = udvm_state_access(message_tvb, udvm_tree, buff, p_id_start, p_id_length, state_begin, &state_length,
2318 &state_address, &state_instruction, hf_id);
2319 if ( result_code != 0 ){
2320 goto decompression_failure;
2322 used_udvm_cycles = used_udvm_cycles + state_length;
2323 goto execute_next_instruction;
2325 case SIGCOMP_INSTR_STATE_CREATE: /* 32 */
2327 * STATE-CREATE (%state_length, %state_address, %state_instruction,
2328 * %minimum_access_length, %state_retention_priority)
2330 if (show_instr_detail_level == 2 ){
2331 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2332 "Addr: %u ## STATE-CREATE(32) (state_length, state_address, state_instruction,minimum_access_length, state_retention_priority)",
2335 operand_address = current_address + 1;
2340 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_length);
2341 if (show_instr_detail_level == 2 ){
2342 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_length %u",
2343 operand_address, state_length);
2348 operand_address = next_operand_address;
2349 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_address);
2350 if (show_instr_detail_level == 2 ){
2351 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_address %u",
2352 operand_address, state_address);
2355 * %state_instruction
2357 operand_address = next_operand_address;
2358 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_instruction);
2359 if (show_instr_detail_level == 2 ){
2360 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_instruction %u",
2361 operand_address, state_instruction);
2363 operand_address = next_operand_address;
2365 * %minimum_access_length
2367 operand_address = next_operand_address;
2368 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &minimum_access_length);
2369 if (show_instr_detail_level == 2 ){
2370 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u minimum_access_length %u",
2371 operand_address, minimum_access_length);
2373 operand_address = next_operand_address;
2375 * %state_retention_priority
2377 operand_address = next_operand_address;
2378 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_retention_priority);
2379 if (show_instr_detail_level == 2 ){
2380 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_retention_priority %u",
2381 operand_address, state_retention_priority);
2383 if (show_instr_detail_level == 1)
2385 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2386 "Addr: %u ## STATE-CREATE(32) (state_length=%u, state_address=%u, state_instruction=%u,minimum_access_length=%u, state_retention_priority=%u)",
2387 current_address, state_length, state_address, state_instruction,minimum_access_length, state_retention_priority);
2389 current_address = next_operand_address;
2390 /* Execute the instruction
2391 * TODO Implement the instruction
2393 * Note that the new state item cannot be created until a valid
2394 * compartment identifier has been returned by the application.
2395 * Consequently, when a STATE-CREATE instruction is encountered the UDVM
2396 * simply buffers the five supplied operands until the END-MESSAGE
2397 * instruction is reached. The steps taken at this point are described
2400 * Decompression failure MUST occur if more than four state creation
2401 * requests are made before the END-MESSAGE instruction is encountered.
2402 * Decompression failure also occurs if the minimum_access_length does
2403 * not lie between 6 and 20 inclusive, or if the
2404 * state_retention_priority is 65535.
2406 no_of_state_create++;
2407 if ( no_of_state_create > 4 ){
2409 goto decompression_failure;
2411 if (( minimum_access_length < 6 ) || ( minimum_access_length > STATE_BUFFER_SIZE )){
2413 goto decompression_failure;
2415 if ( state_retention_priority == 65535 ){
2417 goto decompression_failure;
2419 state_length_buff[no_of_state_create] = state_length;
2420 state_address_buff[no_of_state_create] = state_address;
2421 state_instruction_buff[no_of_state_create] = state_instruction;
2422 state_minimum_access_length_buff[no_of_state_create] = minimum_access_length;
2423 /* state_state_retention_priority_buff[no_of_state_create] = state_retention_priority; */
2424 used_udvm_cycles = used_udvm_cycles + state_length;
2426 byte_copy_right = buff[66] << 8;
2427 byte_copy_right = byte_copy_right | buff[67];
2428 byte_copy_left = buff[64] << 8;
2429 byte_copy_left = byte_copy_left | buff[65];
2432 while ( n < state_length ){
2433 if ( k == byte_copy_right ){
2438 if (print_level_3 ){
2439 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2440 " Addr: %5u State value: %u (0x%x) ASCII(%s)",
2441 k,buff[k],buff[k],format_text(string, 1));
2443 k = ( k + 1 ) & 0xffff;
2448 goto execute_next_instruction;
2450 case SIGCOMP_INSTR_STATE_FREE: /* 33 */
2452 * STATE-FREE (%partial_identifier_start, %partial_identifier_length)
2454 if (show_instr_detail_level == 2 ){
2455 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2456 "Addr: %u ## STATE-FREE (partial_identifier_start, partial_identifier_length)",
2459 operand_address = current_address + 1;
2461 * %partial_identifier_start
2463 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &p_id_start);
2464 if (show_instr_detail_level == 2 ){
2465 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u partial_identifier_start %u",
2466 operand_address, p_id_start);
2468 operand_address = next_operand_address;
2471 * %partial_identifier_length
2473 operand_address = next_operand_address;
2474 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &p_id_length);
2475 if (show_instr_detail_level == 2 ){
2476 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u partial_identifier_length %u",
2477 operand_address, p_id_length);
2479 if (show_instr_detail_level == 1)
2481 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2482 "Addr: %u ## STATE-FREE (partial_identifier_start=%u, partial_identifier_length=%u)",
2483 current_address, p_id_start, p_id_length);
2485 current_address = next_operand_address;
2487 /* Execute the instruction:
2490 udvm_state_free(buff,p_id_start,p_id_length);
2492 goto execute_next_instruction;
2494 case SIGCOMP_INSTR_OUTPUT: /* 34 OUTPUT (%output_start, %output_length) */
2495 if (show_instr_detail_level == 2 ){
2496 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2497 "Addr: %u ## OUTPUT(34) (output_start, output_length)",
2500 operand_address = current_address + 1;
2504 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &output_start);
2505 if (show_instr_detail_level == 2 ){
2506 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u output_start %u",
2507 operand_address, output_start);
2509 operand_address = next_operand_address;
2513 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &output_length);
2514 if (show_instr_detail_level == 2 ){
2515 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u output_length %u",
2516 operand_address, output_length);
2518 if (show_instr_detail_level == 1)
2520 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2521 "Addr: %u ## OUTPUT (output_start=%u, output_length=%u)",
2522 current_address, output_start, output_length);
2524 current_address = next_operand_address;
2527 * Execute instruction
2530 * The string of bytes is copied in ascending order of memory address,
2531 * respecting the bounds set by byte_copy_left and byte_copy_right.
2532 * More precisely, if a byte is copied from/to Address m then the next
2533 * byte is copied from/to Address n where n is calculated as follows:
2535 * Set k := m + 1 (modulo 2^16)
2536 * If k = byte_copy_right then set n := byte_copy_left, else set n := k
2542 byte_copy_right = buff[66] << 8;
2543 byte_copy_right = byte_copy_right | buff[67];
2544 byte_copy_left = buff[64] << 8;
2545 byte_copy_left = byte_copy_left | buff[65];
2546 if (print_level_3 ){
2547 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2548 " byte_copy_right = %u", byte_copy_right);
2550 while ( n < output_length ){
2552 if ( k == byte_copy_right ){
2555 out_buff[output_address] = buff[k];
2558 if (print_level_3 ){
2559 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2560 " Output value: %u (0x%x) ASCII(%s) from Addr: %u ,output to dispatcher position %u",
2561 buff[k],buff[k],format_text(string,1), k,output_address);
2563 k = ( k + 1 ) & 0xffff;
2567 used_udvm_cycles = used_udvm_cycles + output_length;
2568 goto execute_next_instruction;
2570 case SIGCOMP_INSTR_END_MESSAGE: /* 35 */
2572 * END-MESSAGE (%requested_feedback_location,
2573 * %returned_parameters_location, %state_length, %state_address,
2574 * %state_instruction, %minimum_access_length,
2575 * %state_retention_priority)
2577 if (show_instr_detail_level == 2 ){
2578 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2579 "Addr: %u ## END-MESSAGE (requested_feedback_location,state_instruction, minimum_access_length,state_retention_priority)",
2582 operand_address = current_address + 1;
2584 /* %requested_feedback_location */
2585 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &requested_feedback_location);
2586 if (show_instr_detail_level == 2 ){
2587 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u requested_feedback_location %u",
2588 operand_address, requested_feedback_location);
2590 operand_address = next_operand_address;
2591 /* returned_parameters_location */
2592 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &returned_parameters_location);
2593 if (show_instr_detail_level == 2 ){
2594 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u returned_parameters_location %u",
2595 operand_address, returned_parameters_location);
2597 operand_address = next_operand_address;
2601 operand_address = next_operand_address;
2602 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_length);
2603 if (show_instr_detail_level == 2 ){
2604 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_length %u",
2605 operand_address, state_length);
2610 operand_address = next_operand_address;
2611 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_address);
2612 if (show_instr_detail_level == 2 ){
2613 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_address %u",
2614 operand_address, state_address);
2617 * %state_instruction
2619 operand_address = next_operand_address;
2620 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_instruction);
2621 if (show_instr_detail_level == 2 ){
2622 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_instruction %u",
2623 operand_address, state_instruction);
2627 * %minimum_access_length
2629 operand_address = next_operand_address;
2630 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &minimum_access_length);
2631 if (show_instr_detail_level == 2 ){
2632 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u minimum_access_length %u",
2633 operand_address, minimum_access_length);
2637 * %state_retention_priority
2639 operand_address = next_operand_address;
2640 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_retention_priority);
2641 if (show_instr_detail_level == 2 ){
2642 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_retention_priority %u",
2643 operand_address, state_retention_priority);
2645 if (show_instr_detail_level == 1)
2647 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2648 "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)",
2649 current_address, requested_feedback_location, returned_parameters_location, state_length, state_address, state_instruction, minimum_access_length,state_retention_priority);
2651 current_address = next_operand_address;
2652 /* TODO: This isn't currently totaly correct as END_INSTRUCTION might not create state */
2653 no_of_state_create++;
2654 if ( no_of_state_create > 4 ){
2656 goto decompression_failure;
2658 state_length_buff[no_of_state_create] = state_length;
2659 state_address_buff[no_of_state_create] = state_address;
2660 state_instruction_buff[no_of_state_create] = state_instruction;
2662 state_minimum_access_length_buff[no_of_state_create] = minimum_access_length;
2663 /* state_state_retention_priority_buff[no_of_state_create] = state_retention_priority; */
2665 /* Execute the instruction
2667 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"no_of_state_create %u",no_of_state_create);
2668 if ( no_of_state_create != 0 ){
2669 memset(sha1_digest_buf, 0, STATE_BUFFER_SIZE);
2671 byte_copy_right = buff[66] << 8;
2672 byte_copy_right = byte_copy_right | buff[67];
2673 byte_copy_left = buff[64] << 8;
2674 byte_copy_left = byte_copy_left | buff[65];
2675 while ( n < no_of_state_create + 1 ){
2676 sha1buff = g_malloc(state_length_buff[n]+8);
2677 sha1buff[0] = state_length_buff[n] >> 8;
2678 sha1buff[1] = state_length_buff[n] & 0xff;
2679 sha1buff[2] = state_address_buff[n] >> 8;
2680 sha1buff[3] = state_address_buff[n] & 0xff;
2681 sha1buff[4] = state_instruction_buff[n] >> 8;
2682 sha1buff[5] = state_instruction_buff[n] & 0xff;
2683 sha1buff[6] = state_minimum_access_length_buff[n] >> 8;
2684 sha1buff[7] = state_minimum_access_length_buff[n] & 0xff;
2685 if (print_level_3 ){
2686 for( x=0; x < 8; x++){
2687 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"sha1buff %u 0x%x",
2691 k = state_address_buff[n];
2692 for( x=0; x < state_length_buff[n]; x++)
2694 if ( k == byte_copy_right ){
2697 sha1buff[8+x] = buff[k];
2698 k = ( k + 1 ) & 0xffff;
2701 sha1_starts( &ctx );
2702 sha1_update( &ctx, (guint8 *) sha1buff, state_length_buff[n] + 8);
2703 sha1_finish( &ctx, sha1_digest_buf );
2704 if (print_level_3 ){
2705 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"SHA1 digest %s",bytes_to_str(sha1_digest_buf, STATE_BUFFER_SIZE));
2708 /* begin partial state-id change cco@iptel.org */
2710 udvm_state_create(sha1buff, sha1_digest_buf, state_minimum_access_length_buff[n]);
2712 udvm_state_create(sha1buff, sha1_digest_buf, STATE_MIN_ACCESS_LEN);
2713 /* end partial state-id change cco@iptel.org */
2714 proto_tree_add_text(udvm_tree,bytecode_tvb, 0, -1,"### Creating state ###");
2715 proto_tree_add_string(udvm_tree,hf_id, bytecode_tvb, 0, 0, bytes_to_str(sha1_digest_buf, state_minimum_access_length_buff[n]));
2724 /* At least something got decompressed, show it */
2725 decomp_tvb = tvb_new_child_real_data(message_tvb, out_buff,output_address,output_address);
2726 /* Arrange that the allocated packet data copy be freed when the
2729 tvb_set_free_cb( decomp_tvb, g_free );
2731 add_new_data_source(pinfo, decomp_tvb, "Decompressed SigComp message");
2733 proto_tree_add_text(udvm_tree, decomp_tvb, 0, -1,"SigComp message Decompressed");
2735 used_udvm_cycles = used_udvm_cycles + state_length;
2736 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"maximum_UDVM_cycles %u used_udvm_cycles %u",
2737 maximum_UDVM_cycles, used_udvm_cycles);
2742 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," ### Addr %u Invalid instruction: %u (0x%x)",
2743 current_address,current_instruction,current_instruction);
2748 decompression_failure:
2750 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"DECOMPRESSION FAILURE: %s",
2751 val_to_str(result_code, result_code_vals,"Unknown (%u)"));
2752 THROW(ReportedBoundsError);
2758 /* The simplest operand type is the literal (#), which encodes a
2759 * constant integer from 0 to 65535 inclusive. A literal operand may
2760 * require between 1 and 3 bytes depending on its value.
2761 * Bytecode: Operand value: Range:
2762 * 0nnnnnnn N 0 - 127
2763 * 10nnnnnn nnnnnnnn N 0 - 16383
2764 * 11000000 nnnnnnnn nnnnnnnn N 0 - 65535
2766 * Figure 8: Bytecode for a literal (#) operand
2770 decode_udvm_literal_operand(guint8 *buff,guint operand_address, guint16 *value)
2775 guint offset = operand_address;
2778 bytecode = buff[operand_address];
2779 test_bits = bytecode >> 7;
2780 if (test_bits == 1){
2781 test_bits = bytecode >> 6;
2782 if (test_bits == 2){
2784 * 10nnnnnn nnnnnnnn N 0 - 16383
2786 temp_data = buff[operand_address] & 0x1f;
2787 operand = temp_data << 8;
2788 temp_data = buff[(operand_address + 1) & 0xffff];
2789 operand = operand | temp_data;
2791 offset = offset + 2;
2795 * 111000000 nnnnnnnn nnnnnnnn N 0 - 65535
2798 temp_data = buff[operand_address] & 0x1f;
2799 operand = temp_data << 8;
2800 temp_data = buff[(operand_address + 1) & 0xffff];
2801 operand = operand | temp_data;
2803 offset = offset + 2;
2808 * 0nnnnnnn N 0 - 127
2810 operand = ( bytecode & 0x7f);
2820 * The second operand type is the reference ($), which is always used to
2821 * access a 2-byte value located elsewhere in the UDVM memory. The
2822 * bytecode for a reference operand is decoded to be a constant integer
2823 * from 0 to 65535 inclusive, which is interpreted as the memory address
2824 * containing the actual value of the operand.
2825 * Bytecode: Operand value: Range:
2827 * 0nnnnnnn memory[2 * N] 0 - 65535
2828 * 10nnnnnn nnnnnnnn memory[2 * N] 0 - 65535
2829 * 11000000 nnnnnnnn nnnnnnnn memory[N] 0 - 65535
2831 * Figure 9: Bytecode for a reference ($) operand
2834 dissect_udvm_reference_operand(guint8 *buff,guint operand_address, guint16 *value,guint *result_dest)
2838 guint offset = operand_address;
2841 guint16 temp_data16;
2843 bytecode = buff[operand_address];
2844 test_bits = bytecode >> 7;
2845 if (test_bits == 1){
2846 test_bits = bytecode >> 6;
2847 if (test_bits == 2){
2849 * 10nnnnnn nnnnnnnn memory[2 * N] 0 - 65535
2851 temp_data = buff[operand_address] & 0x3f;
2852 operand = temp_data << 8;
2853 temp_data = buff[(operand_address + 1) & 0xffff];
2854 operand = operand | temp_data;
2855 operand = (operand * 2);
2856 *result_dest = operand;
2857 temp_data16 = buff[operand] << 8;
2858 temp_data16 = temp_data16 | buff[(operand+1) & 0xffff];
2859 *value = temp_data16;
2860 offset = offset + 2;
2864 * 11000000 nnnnnnnn nnnnnnnn memory[N] 0 - 65535
2867 operand = buff[operand_address] << 8;
2868 operand = operand | buff[(operand_address + 1) & 0xffff];
2869 *result_dest = operand;
2870 temp_data16 = buff[operand] << 8;
2871 temp_data16 = temp_data16 | buff[(operand+1) & 0xffff];
2872 *value = temp_data16;
2873 offset = offset + 3;
2878 * 0nnnnnnn memory[2 * N] 0 - 65535
2880 operand = ( bytecode & 0x7f);
2881 operand = (operand * 2);
2882 *result_dest = operand;
2883 temp_data16 = buff[operand] << 8;
2884 temp_data16 = temp_data16 | buff[(operand+1) & 0xffff];
2885 *value = temp_data16;
2889 if (offset >= UDVM_MEMORY_SIZE || *result_dest >= UDVM_MEMORY_SIZE - 1 )
2890 THROW(ReportedBoundsError);
2896 * Figure 10: Bytecode for a multitype (%) operand
2897 * Bytecode: Operand value: Range: HEX val
2898 * 00nnnnnn N 0 - 63 0x00
2899 * 01nnnnnn memory[2 * N] 0 - 65535 0x40
2900 * 1000011n 2 ^ (N + 6) 64 , 128 0x86
2901 * 10001nnn 2 ^ (N + 8) 256 , ... , 32768 0x88
2902 * 111nnnnn N + 65504 65504 - 65535 0xe0
2903 * 1001nnnn nnnnnnnn N + 61440 61440 - 65535 0x90
2904 * 101nnnnn nnnnnnnn N 0 - 8191 0xa0
2905 * 110nnnnn nnnnnnnn memory[N] 0 - 65535 0xc0
2906 * 10000000 nnnnnnnn nnnnnnnn N 0 - 65535 0x80
2907 * 10000001 nnnnnnnn nnnnnnnn memory[N] 0 - 65535 0x81
2910 decode_udvm_multitype_operand(guint8 *buff,guint operand_address, guint16 *value)
2914 guint offset = operand_address;
2918 guint16 temp_data16;
2919 guint16 memmory_addr = 0;
2923 bytecode = buff[operand_address];
2924 test_bits = ( bytecode & 0xc0 ) >> 6;
2925 switch (test_bits ){
2930 operand = buff[operand_address];
2932 *g_warning("Reading 0x%x From address %u",operand,offset);
2939 * 01nnnnnn memory[2 * N] 0 - 65535
2941 memmory_addr = ( bytecode & 0x3f) * 2;
2942 temp_data16 = buff[memmory_addr] << 8;
2943 temp_data16 = temp_data16 | buff[(memmory_addr+1) & 0xffff];
2944 *value = temp_data16;
2948 /* Check tree most significant bits */
2949 test_bits = ( bytecode & 0xe0 ) >> 5;
2950 if ( test_bits == 5 ){
2952 * 101nnnnn nnnnnnnn N 0 - 8191
2954 temp_data = buff[operand_address] & 0x1f;
2955 operand = temp_data << 8;
2956 temp_data = buff[(operand_address + 1) & 0xffff];
2957 operand = operand | temp_data;
2959 offset = offset + 2;
2961 test_bits = ( bytecode & 0xf0 ) >> 4;
2962 if ( test_bits == 9 ){
2964 * 1001nnnn nnnnnnnn N + 61440 61440 - 65535
2966 temp_data = buff[operand_address] & 0x0f;
2967 operand = temp_data << 8;
2968 temp_data = buff[(operand_address + 1) & 0xffff];
2969 operand = operand | temp_data;
2970 operand = operand + 61440;
2972 offset = offset + 2;
2974 test_bits = ( bytecode & 0x08 ) >> 3;
2975 if ( test_bits == 1){
2977 * 10001nnn 2 ^ (N + 8) 256 , ... , 32768
2980 result = 1 << ((buff[operand_address] & 0x07) + 8);
2981 operand = result & 0xffff;
2985 test_bits = ( bytecode & 0x0e ) >> 1;
2986 if ( test_bits == 3 ){
2988 * 1000 011n 2 ^ (N + 6) 64 , 128
2990 result = 1 << ((buff[operand_address] & 0x01) + 6);
2991 operand = result & 0xffff;
2996 * 1000 0000 nnnnnnnn nnnnnnnn N 0 - 65535
2997 * 1000 0001 nnnnnnnn nnnnnnnn memory[N] 0 - 65535
3000 temp_data16 = buff[(operand_address + 1) & 0xffff] << 8;
3001 temp_data16 = temp_data16 | buff[(operand_address + 2) & 0xffff];
3003 * g_warning("Reading 0x%x From address %u",temp_data16,operand_address);
3005 if ( (bytecode & 0x01) == 1 ){
3006 memmory_addr = temp_data16;
3007 temp_data16 = buff[memmory_addr] << 8;
3008 temp_data16 = temp_data16 | buff[(memmory_addr+1) & 0xffff];
3010 *value = temp_data16;
3021 test_bits = ( bytecode & 0x20 ) >> 5;
3022 if ( test_bits == 1 ){
3024 * 111nnnnn N + 65504 65504 - 65535
3026 operand = ( buff[operand_address] & 0x1f) + 65504;
3031 * 110nnnnn nnnnnnnn memory[N] 0 - 65535
3033 memmory_addr = buff[operand_address] & 0x1f;
3034 memmory_addr = memmory_addr << 8;
3035 memmory_addr = memmory_addr | buff[(operand_address + 1) & 0xffff];
3036 temp_data16 = buff[memmory_addr] << 8;
3037 temp_data16 = temp_data16 | buff[(memmory_addr+1) & 0xffff];
3038 *value = temp_data16;
3040 * g_warning("Reading 0x%x From address %u",temp_data16,memmory_addr);
3052 * The fourth operand type is the address (@). This operand is decoded
3053 * as a multitype operand followed by a further step: the memory address
3054 * of the UDVM instruction containing the address operand is added to
3055 * obtain the correct operand value. So if the operand value from
3056 * Figure 10 is D then the actual operand value of an address is
3057 * calculated as follows:
3059 * operand_value = (memory_address_of_instruction + D) modulo 2^16
3061 * Address operands are always used in instructions that control program
3062 * flow, because they ensure that the UDVM bytecode is position-
3063 * independent code (i.e., it will run independently of where it is
3064 * placed in the UDVM memory).
3067 decode_udvm_address_operand(guint8 *buff,guint operand_address, guint16 *value,guint current_address)
3071 guint next_opreand_address;
3073 next_opreand_address = decode_udvm_multitype_operand(buff, operand_address, &value1);
3074 result = value1 & 0xffff;
3075 result = result + current_address;
3076 *value = result & 0xffff;
3077 return next_opreand_address;
3082 * This is a lookup table used to reverse the bits in a byte.
3084 static guint8 reverse [] = {
3085 0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0,
3086 0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0,
3087 0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8,
3088 0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8,
3089 0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4,
3090 0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4,
3091 0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC,
3092 0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC,
3093 0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2,
3094 0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2,
3095 0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA,
3096 0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA,
3097 0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6,
3098 0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6,
3099 0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE,
3100 0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE,
3101 0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1,
3102 0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1,
3103 0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9,
3104 0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9,
3105 0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5,
3106 0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5,
3107 0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED,
3108 0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD,
3109 0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3,
3110 0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3,
3111 0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB,
3112 0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB,
3113 0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7,
3114 0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7,
3115 0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF,
3116 0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF
3121 decomp_dispatch_get_bits(
3122 tvbuff_t *message_tvb,
3123 proto_tree *udvm_tree,
3126 guint16 *old_input_bit_order,
3127 guint16 *remaining_bits,
3128 guint16 *input_bits,
3129 guint *input_address,
3131 guint16 *result_code,
3134 guint16 input_bit_order;
3135 guint16 bits_still_required = length;
3138 gint extra_bytes_available = msg_end - *input_address;
3140 gint prev_p_bit = *old_input_bit_order & 0x0001;
3141 gint bits_to_use = 0;
3144 input_bit_order = buff[68] << 8;
3145 input_bit_order = input_bit_order | buff[69];
3147 p_bit = (input_bit_order & 0x0001) != 0;
3150 * Discard any spare bits.
3151 * Note: We take care to avoid remaining_bits having the value of 8.
3153 if (prev_p_bit != p_bit)
3155 *remaining_bits = 0;
3156 *old_input_bit_order = input_bit_order;
3160 * Check we can suppy the required number of bits now, before we alter
3161 * the input buffer's state.
3163 if (*remaining_bits + extra_bytes_available * 8 < length)
3169 /* Note: This is never called with length > 16, so the following loop
3170 * never loops more than three time. */
3171 while (bits_still_required > 0)
3174 * We only put anything into input_bits if we know we will remove
3175 * at least one bit. That ensures we can simply discard the spare
3176 * bits if the P-bit changes.
3178 if (*remaining_bits == 0)
3180 octet = tvb_get_guint8(message_tvb, *input_address);
3181 if (print_level_1 ){
3182 proto_tree_add_text(udvm_tree, message_tvb, *input_address , 1,
3183 " Getting value: %u (0x%x) From Addr: %u", octet, octet, *input_address);
3185 *input_address = *input_address + 1;
3189 octet = reverse[octet];
3191 *input_bits = octet;
3192 *remaining_bits = 8;
3195 /* Add some more bits to the accumulated value. */
3196 bits_to_use = bits_still_required < *remaining_bits ? bits_still_required : *remaining_bits;
3197 bits_still_required -= bits_to_use;
3199 *input_bits <<= bits_to_use; /* Shift bits into MSByte */
3200 value = (value << bits_to_use) /* Then add to the accumulated value */
3201 | ((*input_bits >> 8) & 0xFF);
3202 *remaining_bits -= bits_to_use;
3203 *input_bits &= 0x00FF; /* Leave just the remaining bits */
3208 /* Bit reverse the entire word. */
3209 guint16 lsb = reverse[(value >> 8) & 0xFF];
3210 guint16 msb = reverse[value & 0xFF];
3212 value = ((msb << 8) | lsb) >> (16 - length);