2 * Routines making up the Universal Decompressor Virtual Machine (UDVM) used for
3 * Signaling Compression (SigComp) dissection.
4 * Copyright 2004, Anders Broman <anders.broman@ericsson.com>
8 * Ethereal - Network traffic analyzer
9 * By Gerald Combs <gerald@ethereal.com>
10 * Copyright 1998 Gerald Combs
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
26 * http://www.ietf.org/rfc/rfc3320.txt?number=3320
27 * http://www.ietf.org/rfc/rfc3321.txt?number=3321
29 * http://www.ietf.org/internet-drafts/draft-ietf-rohc-sigcomp-impl-guide-03.txt
30 * http://www.ietf.org/internet-drafts/draft-ietf-rohc-sigcomp-sip-01.txt
42 #ifdef NEED_SNPRINTF_H
43 # include "snprintf.h"
48 #include "sigcomp-udvm.h"
49 #include "sigcomp_state_hdlr.h"
52 #define SIGCOMP_INSTR_DECOMPRESSION_FAILURE 0
53 #define SIGCOMP_INSTR_AND 1
54 #define SIGCOMP_INSTR_OR 2
55 #define SIGCOMP_INSTR_NOT 3
56 #define SIGCOMP_INSTR_LSHIFT 4
57 #define SIGCOMP_INSTR_RSHIFT 5
58 #define SIGCOMP_INSTR_ADD 6
59 #define SIGCOMP_INSTR_SUBTRACT 7
60 #define SIGCOMP_INSTR_MULTIPLY 8
61 #define SIGCOMP_INSTR_DIVIDE 9
62 #define SIGCOMP_INSTR_REMAINDER 10
63 #define SIGCOMP_INSTR_SORT_ASCENDING 11
64 #define SIGCOMP_INSTR_SORT_DESCENDING 12
65 #define SIGCOMP_INSTR_SHA_1 13
66 #define SIGCOMP_INSTR_LOAD 14
67 #define SIGCOMP_INSTR_MULTILOAD 15
68 #define SIGCOMP_INSTR_PUSH 16
69 #define SIGCOMP_INSTR_POP 17
70 #define SIGCOMP_INSTR_COPY 18
71 #define SIGCOMP_INSTR_COPY_LITERAL 19
72 #define SIGCOMP_INSTR_COPY_OFFSET 20
73 #define SIGCOMP_INSTR_MEMSET 21
74 #define SIGCOMP_INSTR_JUMP 22
75 #define SIGCOMP_INSTR_COMPARE 23
76 #define SIGCOMP_INSTR_CALL 24
77 #define SIGCOMP_INSTR_RETURN 25
78 #define SIGCOMP_INSTR_SWITCH 26
79 #define SIGCOMP_INSTR_CRC 27
80 #define SIGCOMP_INSTR_INPUT_BYTES 28
81 #define SIGCOMP_INSTR_INPUT_BITS 29
82 #define SIGCOMP_INSTR_INPUT_HUFFMAN 30
83 #define SIGCOMP_INSTR_STATE_ACCESS 31
84 #define SIGCOMP_INSTR_STATE_CREATE 32
85 #define SIGCOMP_INSTR_STATE_FREE 33
86 #define SIGCOMP_INSTR_OUTPUT 34
87 #define SIGCOMP_INSTR_END_MESSAGE 35
90 static gboolean print_level_1;
91 static gboolean print_level_2;
92 static gboolean print_level_3;
93 static gint show_instr_detail_level;
95 /* Internal result code values of decompression failures */
96 const value_string result_code_vals[] = {
97 { 0, "No decomprssion failure" },
98 { 1, "Partial state length less than 6 or greater than 20 bytes long" },
99 { 2, "No state match" },
100 { 3, "state_begin + state_length > size of state" },
101 { 4, "Operand_2 is Zero" },
102 { 5, "Switch statement failed j >= n" },
103 { 6, "Atempt to jump outside of UDVM memory" },
104 { 7, "L in input-bits > 16" },
105 { 8, "input_bit_order > 7" },
106 { 9, "Instruction Decompression failure encountered" },
107 {10, "Input huffman failed j > n" },
108 {11, "Input bits requested beyond end of message" },
109 {12, "more than four state creation requests are made before the END-MESSAGE instruction" },
110 {13, "state_retention_priority is 65535" },
111 {14, "Input bytes requested beond end of message" },
112 {15, "Maximum number of UDVM cycles reached" },
113 {16, "UDVM stack underflow" },
114 { 255, "This branch isn't coded yet" },
118 static int decode_udvm_literal_operand(guint8 *buff,guint operand_address, guint16 *value);
119 static int dissect_udvm_reference_operand(guint8 *buff,guint operand_address, guint16 *value, guint *result_dest);
120 static int decode_udvm_multitype_operand(guint8 *buff,guint operand_address,guint16 *value);
121 static int decode_udvm_address_operand(guint8 *buff,guint operand_address, guint16 *value,guint current_address);
122 static int decomp_dispatch_get_bits(tvbuff_t *message_tvb,proto_tree *udvm_tree,guint8 bit_order,
123 guint8 *buff,guint16 *old_input_bit_order, guint16 *remaining_bits,
124 guint16 *input_bits, guint *input_address, guint16 length, guint16 *result_code,guint msg_end);
128 decompress_sigcomp_message(tvbuff_t *bytecode_tvb, tvbuff_t *message_tvb, packet_info *pinfo,
129 proto_tree *udvm_tree, gint udvm_mem_dest,
130 gint print_flags, gint hf_id,
132 gint byte_code_state_len, gint byte_code_id_len)
134 tvbuff_t *decomp_tvb;
135 guint8 buff[UDVM_MEMORY_SIZE];
136 char string[2],*strp;
137 guint8 *out_buff; /* Largest allowed size for a message is 65535 */
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);
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[20];
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;
259 /* UDVM memory must be initialised to zero */
260 while ( i < UDVM_MEMORY_SIZE ) {
264 /* Set initial UDVM data
265 * The first 32 bytes of UDVM memory are then initialized to special
266 * values as illustrated in Figure 5.
269 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
270 * | UDVM_memory_size | 0 - 1
271 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
272 * | cycles_per_bit | 2 - 3
273 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
274 * | SigComp_version | 4 - 5
275 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
276 * | partial_state_ID_length | 6 - 7
277 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
278 * | state_length | 8 - 9
279 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
281 * : reserved : 10 - 31
283 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
285 * Figure 5: Initializing Useful Values in UDVM memory
287 /* UDVM_memory_size */
288 buff[0] = (UDVM_MEMORY_SIZE >> 8) & 0x00FF;
289 buff[1] = UDVM_MEMORY_SIZE & 0x00FF;
293 /* SigComp_version */
296 /* partial_state_ID_length */
297 buff[6] = (byte_code_id_len >> 8) & 0x00FF;
298 buff[7] = byte_code_id_len & 0x00FF;
300 buff[8] = (byte_code_state_len >> 8) & 0x00FF;
301 buff[9] = byte_code_state_len & 0x00FF;
303 code_length = tvb_reported_length_remaining(bytecode_tvb, 0);
305 cycles_per_bit = buff[2] << 8;
306 cycles_per_bit = cycles_per_bit | buff[3];
308 * maximum_UDVM_cycles = (8 * n + 1000) * cycles_per_bit
310 maximum_UDVM_cycles = (( 8 * (header_len + msg_end) ) + 1000) * cycles_per_bit;
312 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);
313 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);
315 /* Load bytecode into UDVM starting at "udvm_mem_dest" */
318 proto_tree_add_text(udvm_tree, bytecode_tvb, offset, 1,"Load bytecode into UDVM starting at %u",i);
319 while ( code_length > offset ) {
320 buff[i] = tvb_get_guint8(bytecode_tvb, offset);
322 proto_tree_add_text(udvm_tree, bytecode_tvb, offset, 1,
323 " Addr: %u Instruction code(0x%0x) ", i, buff[i]);
329 /* Largest allowed size for a message is 65535 */
330 out_buff = g_malloc(65535);
331 /* Start executing code */
332 current_address = udvm_mem_dest;
336 proto_tree_add_text(udvm_tree, bytecode_tvb, offset, 1,"UDVM EXECUTION STARTED at Address: %u Message size %u",
337 udvm_mem_dest,msg_end);
339 execute_next_instruction:
341 if ( used_udvm_cycles > maximum_UDVM_cycles ){
343 goto decompression_failure;
345 current_instruction = buff[current_address];
347 switch ( current_instruction ) {
348 case SIGCOMP_INSTR_DECOMPRESSION_FAILURE:
350 if ( result_code == 0 )
352 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
353 "Addr: %u ## DECOMPRESSION-FAILURE(0)",
355 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Ethereal UDVM diagnostic: %s.",
356 val_to_str(result_code, result_code_vals,"Unknown (%u)"));
357 if ( output_address > 0 ){
358 /* At least something got decompressed, show it */
359 decomp_tvb = tvb_new_real_data(out_buff,output_address,output_address);
360 /* Arrange that the allocated packet data copy be freed when the
363 tvb_set_free_cb( decomp_tvb, g_free );
364 /* Add the tvbuff to the list of tvbuffs to which the tvbuff we
365 * were handed refers, so it'll get cleaned up when that tvbuff
368 tvb_set_child_real_data_tvbuff(message_tvb,decomp_tvb);
369 add_new_data_source(pinfo, decomp_tvb, "Decompressed SigComp message(Incomplete)");
370 proto_tree_add_text(udvm_tree, decomp_tvb, 0, -1,"SigComp message Decompression failure");
377 case SIGCOMP_INSTR_AND: /* 1 AND ($operand_1, %operand_2) */
379 if (show_instr_detail_level == 2 ){
380 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
381 "Addr: %u ## AND(1) (operand_1, operand_2)",
385 operand_address = current_address + 1;
386 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &operand_1, &result_dest);
387 if (show_instr_detail_level == 2 ){
388 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_1 %u",
389 operand_address, operand_1);
391 operand_address = next_operand_address;
393 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &operand_2);
394 if (show_instr_detail_level == 2 ){
395 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_2 %u",
396 operand_address, operand_2);
398 if (show_instr_detail_level == 1)
400 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
401 "Addr: %u ## AND (operand_1=%u, operand_2=%u)",
402 current_address, operand_1, operand_2);
404 /* execute the instruction */
405 result = operand_1 & operand_2;
408 buff[result_dest] = msb;
409 buff[result_dest+1] = lsb;
411 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," Loading result %u at %u",
412 result, result_dest);
414 current_address = next_operand_address;
415 goto execute_next_instruction;
419 case SIGCOMP_INSTR_OR: /* 2 OR ($operand_1, %operand_2) */
421 if (show_instr_detail_level == 2 ){
422 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
423 "Addr: %u ## OR(2) (operand_1, operand_2)",
427 operand_address = current_address + 1;
428 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &operand_1, &result_dest);
429 if (show_instr_detail_level == 2 ){
430 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_1 %u",
431 operand_address, operand_1);
433 operand_address = next_operand_address;
435 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &operand_2);
436 if (show_instr_detail_level == 2 ){
437 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_2 %u",
438 operand_address, operand_2);
440 if (show_instr_detail_level == 1)
442 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
443 "Addr: %u ## OR (operand_1=%u, operand_2=%u)",
444 current_address, operand_1, operand_2);
446 /* execute the instruction */
447 result = operand_1 | operand_2;
450 buff[result_dest] = msb;
451 buff[result_dest+1] = lsb;
453 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," Loading result %u at %u",
454 result, result_dest);
456 current_address = next_operand_address;
457 goto execute_next_instruction;
461 case SIGCOMP_INSTR_NOT: /* 3 NOT ($operand_1) */
463 if (show_instr_detail_level == 2 ){
464 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
465 "Addr: %u ## NOT(3) ($operand_1)",
469 operand_address = current_address + 1;
470 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &operand_1, &result_dest);
471 if (show_instr_detail_level == 2 ){
472 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_1 %u",
473 operand_address, operand_1);
475 if (show_instr_detail_level == 1)
477 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
478 "Addr: %u ## NOT (operand_1=%u)",
479 current_address, operand_1);
481 /* execute the instruction */
482 result = operand_1 ^ 0xffff;
485 buff[result_dest] = msb;
486 buff[result_dest+1] = lsb;
488 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," Loading result %u at %u",
489 result, result_dest);
491 current_address = next_operand_address;
492 goto execute_next_instruction;
495 case SIGCOMP_INSTR_LSHIFT: /* 4 LSHIFT ($operand_1, %operand_2) */
497 if (show_instr_detail_level == 2 ){
498 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
499 "Addr: %u ## LSHIFT(4) ($operand_1, operand_2)",
503 operand_address = current_address + 1;
504 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &operand_1, &result_dest);
505 if (show_instr_detail_level == 2 ){
506 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_1 %u",
507 operand_address, operand_1);
509 operand_address = next_operand_address;
511 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &operand_2);
512 if (show_instr_detail_level == 2 ){
513 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_2 %u",
514 operand_address, operand_2);
516 if (show_instr_detail_level == 1)
518 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
519 "Addr: %u ## LSHIFT (operand_1=%u, operand_2=%u)",
520 current_address, operand_1, operand_2);
522 /* execute the instruction */
523 result = operand_1 << operand_2;
526 buff[result_dest] = msb;
527 buff[result_dest+1] = lsb;
529 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," Loading result %u at %u",
530 result, result_dest);
532 current_address = next_operand_address;
533 goto execute_next_instruction;
536 case SIGCOMP_INSTR_RSHIFT: /* 5 RSHIFT ($operand_1, %operand_2) */
538 if (show_instr_detail_level == 2 ){
539 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
540 "Addr: %u ## RSHIFT(5) (operand_1, operand_2)",
544 operand_address = current_address + 1;
545 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &operand_1, &result_dest);
546 if (show_instr_detail_level == 2 ){
547 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_1 %u",
548 operand_address, operand_1);
550 operand_address = next_operand_address;
552 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &operand_2);
553 if (show_instr_detail_level == 2 ){
554 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_2 %u",
555 operand_address, operand_2);
557 if (show_instr_detail_level == 1)
559 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
560 "Addr: %u ## RSHIFT (operand_1=%u, operand_2=%u)",
561 current_address, operand_1, operand_2);
563 /* execute the instruction */
564 result = operand_1 >> operand_2;
567 buff[result_dest] = msb;
568 buff[result_dest+1] = lsb;
570 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," Loading result %u at %u",
571 result, result_dest);
573 current_address = next_operand_address;
574 goto execute_next_instruction;
576 case SIGCOMP_INSTR_ADD: /* 6 ADD ($operand_1, %operand_2) */
578 if (show_instr_detail_level == 2 ){
579 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
580 "Addr: %u ## ADD(6) (operand_1, operand_2)",
584 operand_address = current_address + 1;
585 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &operand_1, &result_dest);
586 if (show_instr_detail_level == 2 ){
587 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_1 %u",
588 operand_address, operand_1);
590 operand_address = next_operand_address;
592 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &operand_2);
593 if (show_instr_detail_level == 2 ){
594 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_2 %u",
595 operand_address, operand_2);
597 if (show_instr_detail_level == 1)
599 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
600 "Addr: %u ## ADD (operand_1=%u, operand_2=%u)",
601 current_address, operand_1, operand_2);
603 /* execute the instruction */
604 result = operand_1 + operand_2;
607 buff[result_dest] = msb;
608 buff[result_dest+1] = lsb;
610 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," Loading result %u at %u",
611 result, result_dest);
613 current_address = next_operand_address;
614 goto execute_next_instruction;
616 case SIGCOMP_INSTR_SUBTRACT: /* 7 SUBTRACT ($operand_1, %operand_2) */
618 if (show_instr_detail_level == 2 ){
619 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
620 "Addr: %u ## SUBTRACT(7) (operand_1, operand_2)",
624 operand_address = current_address + 1;
625 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &operand_1, &result_dest);
626 if (show_instr_detail_level == 2 ){
627 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_1 %u",
628 operand_address, operand_1);
630 operand_address = next_operand_address;
632 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &operand_2);
633 if (show_instr_detail_level == 2 ){
634 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_2 %u",
635 operand_address, operand_2);
637 if (show_instr_detail_level == 1)
639 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
640 "Addr: %u ## SUBTRACT (operand_1=%u, operand_2=%u)",
641 current_address, operand_1, operand_2);
643 /* execute the instruction */
644 result = operand_1 - operand_2;
647 buff[result_dest] = msb;
648 buff[result_dest+1] = lsb;
650 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," Loading result %u at %u",
651 result, result_dest);
653 current_address = next_operand_address;
654 goto execute_next_instruction;
657 case SIGCOMP_INSTR_MULTIPLY: /* 8 MULTIPLY ($operand_1, %operand_2) */
659 if (show_instr_detail_level == 2 ){
660 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
661 "Addr: %u ##MULTIPLY(8) (operand_1, operand_2)",
665 operand_address = current_address + 1;
666 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &operand_1, &result_dest);
667 if (show_instr_detail_level == 2 ){
668 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_1 %u",
669 operand_address, operand_1);
671 operand_address = next_operand_address;
673 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &operand_2);
674 if (show_instr_detail_level == 2 ){
675 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_2 %u",
676 operand_address, operand_2);
678 if (show_instr_detail_level == 1)
680 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
681 "Addr: %u ## MULTIPLY (operand_1=%u, operand_2=%u)",
682 current_address, operand_1, operand_2);
685 * execute the instruction
686 * MULTIPLY (m, n) := m * n (modulo 2^16)
688 if ( operand_2 == 0){
690 goto decompression_failure;
692 result = operand_1 * operand_2;
695 buff[result_dest] = msb;
696 buff[result_dest+1] = lsb;
698 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," Loading result %u at %u",
699 result, result_dest);
701 current_address = next_operand_address;
702 goto execute_next_instruction;
705 case SIGCOMP_INSTR_DIVIDE: /* 9 DIVIDE ($operand_1, %operand_2) */
707 if (show_instr_detail_level == 2 ){
708 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
709 "Addr: %u ## DIVIDE(9) (operand_1, operand_2)",
713 operand_address = current_address + 1;
714 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &operand_1, &result_dest);
715 if (show_instr_detail_level == 2 ){
716 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_1 %u",
717 operand_address, operand_1);
719 operand_address = next_operand_address;
721 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &operand_2);
722 if (show_instr_detail_level == 2 ){
723 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_2 %u",
724 operand_address, operand_2);
726 if (show_instr_detail_level == 1)
728 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
729 "Addr: %u ## DIVIDE (operand_1=%u, operand_2=%u)",
730 current_address, operand_1, operand_2);
733 * execute the instruction
734 * DIVIDE (m, n) := floor(m / n)
735 * Decompression failure occurs if a DIVIDE or REMAINDER instruction
736 * encounters an operand_2 that is zero.
738 if ( operand_2 == 0){
740 goto decompression_failure;
742 result = operand_1 / operand_2;
745 buff[result_dest] = msb;
746 buff[result_dest+1] = lsb;
748 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," Loading result %u at %u",
749 result, result_dest);
751 current_address = next_operand_address;
752 goto execute_next_instruction;
755 case SIGCOMP_INSTR_REMAINDER: /* 10 REMAINDER ($operand_1, %operand_2) */
757 if (show_instr_detail_level == 2 ){
758 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
759 "Addr: %u ## REMAINDER(10) (operand_1, operand_2)",
763 operand_address = current_address + 1;
764 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &operand_1, &result_dest);
765 if (show_instr_detail_level == 2 ){
766 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_1 %u",
767 operand_address, operand_1);
769 operand_address = next_operand_address;
771 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &operand_2);
772 if (show_instr_detail_level == 2 ){
773 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_2 %u",
774 operand_address, operand_2);
776 if (show_instr_detail_level == 1)
778 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
779 "Addr: %u ## REMAINDER (operand_1=%u, operand_2=%u)",
780 current_address, operand_1, operand_2);
783 * execute the instruction
784 * REMAINDER (m, n) := m - n * floor(m / n)
785 * Decompression failure occurs if a DIVIDE or REMAINDER instruction
786 * encounters an operand_2 that is zero.
788 if ( operand_2 == 0){
790 goto decompression_failure;
792 result = operand_1 - operand_2 * (operand_1 / operand_2);
795 buff[result_dest] = msb;
796 buff[result_dest+1] = lsb;
798 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," Loading result %u at %u",
799 result, result_dest);
801 current_address = next_operand_address;
802 goto execute_next_instruction;
804 case SIGCOMP_INSTR_SORT_ASCENDING: /* 11 SORT-ASCENDING (%start, %n, %k) */
806 * used_udvm_cycles = 1 + k * (ceiling(log2(k)) + n)
809 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
810 "Addr: %u ## SORT-ASCENDING(11) (start, n, k))",
813 operand_address = current_address + 1;
814 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Execution of this instruction is NOT implemented");
816 * used_udvm_cycles = 1 + k * (ceiling(log2(k)) + n)
820 case SIGCOMP_INSTR_SORT_DESCENDING: /* 12 SORT-DESCENDING (%start, %n, %k) */
822 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
823 "Addr: %u ## SORT-DESCENDING(12) (start, n, k))",
826 operand_address = current_address + 1;
827 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Execution of this instruction is NOT implemented");
829 * used_udvm_cycles = 1 + k * (ceiling(log2(k)) + n)
832 case SIGCOMP_INSTR_SHA_1: /* 13 SHA-1 (%position, %length, %destination) */
834 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
835 "Addr: %u ## SHA-1(13) (position, length, destination)",
838 operand_address = current_address + 1;
840 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &position);
842 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u position %u",
843 operand_address, position);
845 operand_address = next_operand_address;
848 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &length);
850 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Length %u",
851 operand_address, length);
853 operand_address = next_operand_address;
856 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &ref_destination, &result_dest);
858 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u $destination %u",
859 operand_address, ref_destination);
861 current_address = next_operand_address;
862 used_udvm_cycles = used_udvm_cycles + 1 + length;
863 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Execution of this instruction is NOT implemented");
866 case SIGCOMP_INSTR_LOAD: /* 14 LOAD (%address, %value) */
867 if (show_instr_detail_level == 2 ){
868 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
869 "Addr: %u ## LOAD(14) (%%address, %%value)",
872 operand_address = current_address + 1;
874 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &address);
875 if (show_instr_detail_level == 2 ){
876 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Address %u",
877 operand_address, address);
879 operand_address = next_operand_address;
881 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &value);
882 if (show_instr_detail_level == 1)
884 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
885 "Addr: %u ## LOAD (%%address=%u, %%value=%u)",
886 current_address, address, value);
892 buff[address + 1] = lsb;
895 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Value %u",
896 operand_address, value);
897 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," Loading bytes at %u Value %u 0x%x",
898 address, value, value);
901 current_address = next_operand_address;
902 goto execute_next_instruction;
905 case SIGCOMP_INSTR_MULTILOAD: /* 15 MULTILOAD (%address, #n, %value_0, ..., %value_n-1) */
907 * The MULTILOAD instruction sets a contiguous block of 2-byte words in
908 * the UDVM memory to specified values.
909 * Hmm what if the value to load only takes one byte ? Chose to always load two bytes.
911 if (show_instr_detail_level == 2 ){
912 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
913 "Addr: %u ## MULTILOAD(15) (%%address, #n, value_0, ..., value_n-1)",
916 operand_address = current_address + 1;
918 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &address);
919 if (show_instr_detail_level == 2 ){
920 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Address %u",
921 operand_address, address);
923 operand_address = next_operand_address;
926 next_operand_address = decode_udvm_literal_operand(buff,operand_address, &n);
927 if (show_instr_detail_level == 2 ){
928 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u n %u",
931 if (show_instr_detail_level == 1)
933 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
934 "Addr: %u ## MULTILOAD (%%address=%u, #n=%u, value_0, ..., value_%d)",
935 current_address, address, n, n-1);
937 operand_address = next_operand_address;
938 used_udvm_cycles = used_udvm_cycles + 1 + n;
942 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &value);
947 buff[address + 1] = lsb;
950 length = next_operand_address - operand_address;
953 proto_tree_add_text(udvm_tree, bytecode_tvb, operand_address - 128, length,"Addr: %u Value %5u - Loading bytes at %5u Value %5u 0x%x",
954 operand_address, value, address, value, value);
956 address = address + 2;
957 operand_address = next_operand_address;
959 current_address = next_operand_address;
960 goto execute_next_instruction;
964 case SIGCOMP_INSTR_PUSH: /* 16 PUSH (%value) */
965 if (show_instr_detail_level == 2){
966 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
967 "Addr: %u ## PUSH(16) (value)",
970 operand_address = current_address + 1;
972 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &value);
973 if (show_instr_detail_level == 2){
974 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Value %u",
975 operand_address, value);
977 if (show_instr_detail_level == 1)
979 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
980 "Addr: %u ## PUSH (value=%u)",
981 current_address, value);
983 current_address = next_operand_address;
985 /* Push the value address onto the stack */
986 stack_location = (buff[70] << 8) | buff[71];
987 stack_fill = (buff[stack_location] << 8)
988 | buff[(stack_location+1) & 0xFFFF];
989 address = (stack_location + stack_fill * 2 + 2) & 0xFFFF;
991 buff[address] = (value >> 8) & 0x00FF;
992 buff[(address+1) & 0xFFFF] = value & 0x00FF;
994 stack_fill = (stack_fill + 1) & 0xFFFF;
995 buff[stack_location] = (stack_fill >> 8) & 0x00FF;
996 buff[(stack_location+1) & 0xFFFF] = stack_fill & 0x00FF;
999 goto execute_next_instruction;
1003 case SIGCOMP_INSTR_POP: /* 17 POP (%address) */
1004 if (show_instr_detail_level == 2){
1005 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1006 "Addr: %u ## POP(16) (value)",
1009 operand_address = current_address + 1;
1011 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &destination);
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, destination);
1016 if (show_instr_detail_level == 1)
1018 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1019 "Addr: %u ## POP (address=%u)",
1020 current_address, destination);
1022 current_address = next_operand_address;
1024 /* Pop value from the top of the stack */
1025 stack_location = (buff[70] << 8) | buff[71];
1026 stack_fill = (buff[stack_location] << 8)
1027 | buff[(stack_location+1) & 0xFFFF];
1028 if (stack_fill == 0)
1031 goto decompression_failure;
1034 stack_fill = (stack_fill - 1) & 0xFFFF;
1035 buff[stack_location] = (stack_fill >> 8) & 0x00FF;
1036 buff[(stack_location+1) & 0xFFFF] = stack_fill & 0x00FF;
1038 address = (stack_location + stack_fill * 2 + 2) & 0xFFFF;
1039 value = (buff[address] << 8)
1040 | buff[(address+1) & 0xFFFF];
1042 /* ... and store the popped value. */
1043 buff[destination] = (value >> 8) & 0x00FF;
1044 buff[(destination+1) & 0xFFFF] = value & 0x00FF;
1047 goto execute_next_instruction;
1051 case SIGCOMP_INSTR_COPY: /* 18 COPY (%position, %length, %destination) */
1052 if (show_instr_detail_level == 2 ){
1053 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1054 "Addr: %u ## COPY(18) (position, length, destination)",
1057 operand_address = current_address + 1;
1059 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &position);
1060 if (show_instr_detail_level == 2 ){
1061 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u position %u",
1062 operand_address, position);
1064 operand_address = next_operand_address;
1067 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &length);
1068 if (show_instr_detail_level == 2 ){
1069 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Length %u",
1070 operand_address, length);
1072 operand_address = next_operand_address;
1075 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &destination);
1076 if (show_instr_detail_level == 2 ){
1077 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Destination %u",
1078 operand_address, destination);
1080 if (show_instr_detail_level == 1)
1082 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1083 "Addr: %u ## COPY (position=%u, length=%u, destination=%u)",
1084 current_address, position, length, destination);
1086 current_address = next_operand_address;
1090 * The string of bytes is copied in ascending order of memory address,
1091 * respecting the bounds set by byte_copy_left and byte_copy_right.
1092 * More precisely, if a byte is copied from/to Address m then the next
1093 * byte is copied from/to Address n where n is calculated as follows:
1095 * Set k := m + 1 (modulo 2^16)
1096 * If k = byte_copy_right then set n := byte_copy_left, else set n := k
1102 byte_copy_right = buff[66] << 8;
1103 byte_copy_right = byte_copy_right | buff[67];
1104 byte_copy_left = buff[64] << 8;
1105 byte_copy_left = byte_copy_left | buff[65];
1106 if (print_level_2 ){
1107 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
1108 " byte_copy_right = %u", byte_copy_right);
1111 while ( n < length ){
1112 buff[k] = buff[position];
1113 if (print_level_2 ){
1114 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
1115 " Copying value: %u (0x%x) to Addr: %u",
1116 buff[position], buff[position], k);
1118 position = ( position + 1 ) & 0xffff;
1119 k = ( k + 1 ) & 0xffff;
1123 * Check for circular buffer wrapping after the positions are
1124 * incremented. If either started at BCR then they should continue
1125 * to increment beyond BCR.
1127 if ( k == byte_copy_right ){
1130 if ( position == byte_copy_right ){
1131 position = byte_copy_left;
1134 used_udvm_cycles = used_udvm_cycles + 1 + length;
1135 goto execute_next_instruction;
1138 case SIGCOMP_INSTR_COPY_LITERAL: /* 19 COPY-LITERAL (%position, %length, $destination) */
1139 if (show_instr_detail_level == 2 ){
1140 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1141 "Addr: %u ## COPY-LITERAL(19) (position, length, $destination)",
1144 operand_address = current_address + 1;
1146 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &position);
1147 if (show_instr_detail_level == 2 ){
1148 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u position %u",
1149 operand_address, position);
1151 operand_address = next_operand_address;
1154 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &length);
1155 if (show_instr_detail_level == 2 ){
1156 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Length %u",
1157 operand_address, length);
1159 operand_address = next_operand_address;
1163 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &ref_destination, &result_dest);
1164 if (show_instr_detail_level == 2 ){
1165 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u destination %u",
1166 operand_address, ref_destination);
1168 if (show_instr_detail_level == 1)
1170 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1171 "Addr: %u ## COPY-LITERAL (position=%u, length=%u, $destination=%u)",
1172 current_address, position, length, destination);
1174 current_address = next_operand_address;
1180 * The string of bytes is copied in ascending order of memory address,
1181 * respecting the bounds set by byte_copy_left and byte_copy_right.
1182 * More precisely, if a byte is copied from/to Address m then the next
1183 * byte is copied from/to Address n where n is calculated as follows:
1185 * Set k := m + 1 (modulo 2^16)
1186 * If k = byte_copy_right then set n := byte_copy_left, else set n := k
1191 k = ref_destination;
1192 byte_copy_right = buff[66] << 8;
1193 byte_copy_right = byte_copy_right | buff[67];
1194 byte_copy_left = buff[64] << 8;
1195 byte_copy_left = byte_copy_left | buff[65];
1196 if (print_level_2 ){
1197 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
1198 " byte_copy_right = %u", byte_copy_right);
1200 while ( n < length ){
1202 buff[k] = buff[position];
1203 if (print_level_2 ){
1204 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
1205 " Copying value: %u (0x%x) to Addr: %u",
1206 buff[position], buff[position], k);
1208 position = ( position + 1 ) & 0xffff;
1209 k = ( k + 1 ) & 0xffff;
1213 * Check for circular buffer wrapping after the positions are
1214 * incremented. It is important that k cannot be left set
1215 * to BCR. Also, if either started at BCR then they should continue
1216 * to increment beyond BCR.
1218 if ( k == byte_copy_right ){
1221 if ( position == byte_copy_right ){
1222 position = byte_copy_left;
1225 buff[result_dest] = k >> 8;
1226 buff[result_dest + 1] = k & 0x00ff;
1228 used_udvm_cycles = used_udvm_cycles + 1 + length;
1229 goto execute_next_instruction;
1232 case SIGCOMP_INSTR_COPY_OFFSET: /* 20 COPY-OFFSET (%offset, %length, $destination) */
1233 if (show_instr_detail_level == 2 ){
1234 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1235 "Addr: %u ## COPY-OFFSET(20) (offset, length, $destination)",
1238 operand_address = current_address + 1;
1240 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &multy_offset);
1241 if (show_instr_detail_level == 2 ){
1242 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u offset %u",
1243 operand_address, multy_offset);
1245 operand_address = next_operand_address;
1248 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &length);
1249 if (show_instr_detail_level == 2 ){
1250 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Length %u",
1251 operand_address, length);
1253 operand_address = next_operand_address;
1257 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &ref_destination, &result_dest);
1258 if (show_instr_detail_level == 2 ){
1259 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u $destination %u",
1260 operand_address, ref_destination);
1263 if (show_instr_detail_level == 1)
1265 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1266 "Addr: %u ## COPY-OFFSET (offset=%u, length=%u, $destination=%u)",
1267 current_address, multy_offset, length, result_dest);
1269 current_address = next_operand_address;
1271 /* Execute the instruction:
1272 * To derive the value of the position operand, starting at the memory
1273 * address specified by destination, the UDVM counts backwards a total
1274 * of offset memory addresses.
1276 * If the memory address specified in byte_copy_left is reached, the
1277 * next memory address is taken to be (byte_copy_right - 1) modulo 2^16.
1279 byte_copy_left = buff[64] << 8;
1280 byte_copy_left = byte_copy_left | buff[65];
1281 byte_copy_right = buff[66] << 8;
1282 byte_copy_right = byte_copy_right | buff[67];
1285 * In order to work out the position, simple arithmetic is tricky
1286 * to apply because there some nasty corner cases. A simple loop
1287 * is inefficient but the logic is simple.
1289 * FUTURE: This could be optimised.
1291 for (position = ref_destination, i = 0; i < multy_offset; i++)
1293 if ( position == byte_copy_left )
1295 position = (byte_copy_right - 1) & 0xffff;
1299 position = (position - 1) & 0xffff;
1303 if (print_level_2 ){
1304 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
1305 " byte_copy_left = %u byte_copy_right = %u position= %u",
1306 byte_copy_left, byte_copy_right, position);
1308 /* The COPY-OFFSET instruction then behaves as a COPY-LITERAL
1309 * instruction, taking the value of the position operand to be the last
1310 * memory address reached in the above step.
1316 * The string of bytes is copied in ascending order of memory address,
1317 * respecting the bounds set by byte_copy_left and byte_copy_right.
1318 * More precisely, if a byte is copied from/to Address m then the next
1319 * byte is copied from/to Address n where n is calculated as follows:
1321 * Set k := m + 1 (modulo 2^16)
1322 * If k = byte_copy_right then set n := byte_copy_left, else set n := k
1327 k = ref_destination;
1328 if (print_level_2 ){
1329 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
1330 " byte_copy_left = %u byte_copy_right = %u", byte_copy_left, byte_copy_right);
1332 while ( n < length ){
1333 buff[k] = buff[position];
1334 if (print_level_2 ){
1335 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
1336 " Copying value: %5u (0x%x) from Addr: %u to Addr: %u",
1337 buff[position], buff[position],(position), k);
1340 k = ( k + 1 ) & 0xffff;
1341 position = ( position + 1 ) & 0xffff;
1344 * Check for circular buffer wrapping after the positions are
1345 * incremented. It is important that k cannot be left set
1346 * to BCR. Also, if either started at BCR then they should continue
1347 * to increment beyond BCR.
1349 if ( k == byte_copy_right ){
1352 if ( position == byte_copy_right ){
1353 position = byte_copy_left;
1356 buff[result_dest] = k >> 8;
1357 buff[result_dest + 1] = k & 0x00ff;
1358 used_udvm_cycles = used_udvm_cycles + 1 + length;
1359 goto execute_next_instruction;
1362 case SIGCOMP_INSTR_MEMSET: /* 21 MEMSET (%address, %length, %start_value, %offset) */
1363 if (show_instr_detail_level == 2 ){
1364 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1365 "Addr: %u ## MEMSET(21) (address, length, start_value, offset)",
1368 operand_address = current_address + 1;
1371 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &address);
1372 if (show_instr_detail_level == 2 ){
1373 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Address %u",
1374 operand_address, address);
1376 operand_address = next_operand_address;
1379 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &length);
1380 if (show_instr_detail_level == 2 ){
1381 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Length %u",
1382 operand_address, length);
1384 operand_address = next_operand_address;
1386 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &start_value);
1387 if (show_instr_detail_level == 2 ){
1388 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u start_value %u",
1389 operand_address, start_value);
1391 operand_address = next_operand_address;
1394 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &multy_offset);
1395 if (show_instr_detail_level == 2 ){
1396 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u offset %u",
1397 operand_address, multy_offset);
1399 if (show_instr_detail_level == 1)
1401 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1402 "Addr: %u ## MEMSET (address=%u, length=%u, start_value=%u, offset=%u)",
1403 current_address, address, length, start_value, multy_offset);
1405 current_address = next_operand_address;
1406 /* exetute the instruction
1407 * The sequence of values used by the MEMSET instruction is specified by
1408 * the following formula:
1410 * Seq[n] := (start_value + n * offset) modulo 256
1414 byte_copy_right = buff[66] << 8;
1415 byte_copy_right = byte_copy_right | buff[67];
1416 byte_copy_left = buff[64] << 8;
1417 byte_copy_left = byte_copy_left | buff[65];
1418 if (print_level_2 ){
1419 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
1420 " byte_copy_left = %u byte_copy_right = %u", byte_copy_left, byte_copy_right);
1422 while ( n < length ){
1423 if ( k == byte_copy_right ){
1426 buff[k] = (start_value + ( n * multy_offset)) & 0xff;
1427 if (print_level_2 ){
1428 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
1429 " Storing value: %u (0x%x) at Addr: %u",
1430 buff[k], buff[k], k);
1432 k = ( k + 1 ) & 0xffff;
1435 used_udvm_cycles = used_udvm_cycles + 1 + length;
1436 goto execute_next_instruction;
1440 case SIGCOMP_INSTR_JUMP: /* 22 JUMP (@address) */
1441 if (show_instr_detail_level == 2 ){
1442 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1443 "Addr: %u ## JUMP(22) (@address)",
1446 operand_address = current_address + 1;
1448 /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
1449 next_operand_address = decode_udvm_address_operand(buff,operand_address, &at_address, current_address);
1450 if (show_instr_detail_level == 2 ){
1451 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u @Address %u",
1452 operand_address, at_address);
1454 if (show_instr_detail_level == 1)
1456 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1457 "Addr: %u ## JUMP (@address=%u)",
1458 current_address, at_address);
1460 current_address = at_address;
1462 goto execute_next_instruction;
1465 case SIGCOMP_INSTR_COMPARE: /* 23 */
1466 /* COMPARE (%value_1, %value_2, @address_1, @address_2, @address_3)
1468 if (show_instr_detail_level == 2 ){
1469 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1470 "Addr: %u ## COMPARE(23) (value_1, value_2, @address_1, @address_2, @address_3)",
1473 operand_address = current_address + 1;
1476 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &value_1);
1477 if (show_instr_detail_level == 2 ){
1478 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Value %u",
1479 operand_address, value_1);
1481 operand_address = next_operand_address;
1484 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &value_2);
1485 if (show_instr_detail_level == 2 ){
1486 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Value %u",
1487 operand_address, value_2);
1489 operand_address = next_operand_address;
1492 /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
1493 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &at_address_1);
1494 at_address_1 = ( current_address + at_address_1) & 0xffff;
1495 if (show_instr_detail_level == 2 ){
1496 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u @Address %u",
1497 operand_address, at_address_1);
1499 operand_address = next_operand_address;
1503 /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
1504 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &at_address_2);
1505 at_address_2 = ( current_address + at_address_2) & 0xffff;
1506 if (show_instr_detail_level == 2 ){
1507 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u @Address %u",
1508 operand_address, at_address_2);
1510 operand_address = next_operand_address;
1513 /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
1514 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &at_address_3);
1515 at_address_3 = ( current_address + at_address_3) & 0xffff;
1516 if (show_instr_detail_level == 2 ){
1517 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u @Address %u",
1518 operand_address, at_address_3);
1520 if (show_instr_detail_level == 1)
1522 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1523 "Addr: %u ## COMPARE (value_1=%u, value_2=%u, @address_1=%u, @address_2=%u, @address_3=%u)",
1524 current_address, value_1, value_2, at_address_1, at_address_2, at_address_3);
1526 /* execute the instruction
1527 * If value_1 < value_2 then the UDVM continues instruction execution at
1528 * the memory address specified by address 1. If value_1 = value_2 then
1529 * it jumps to the address specified by address_2. If value_1 > value_2
1530 * then it jumps to the address specified by address_3.
1532 if ( value_1 < value_2 )
1533 current_address = at_address_1;
1534 if ( value_1 == value_2 )
1535 current_address = at_address_2;
1536 if ( value_1 > value_2 )
1537 current_address = at_address_3;
1539 goto execute_next_instruction;
1542 case SIGCOMP_INSTR_CALL: /* 24 CALL (@address) (PUSH addr )*/
1543 if (show_instr_detail_level == 2){
1544 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1545 "Addr: %u ## CALL(24) (@address) (PUSH addr )",
1548 operand_address = current_address + 1;
1550 next_operand_address = decode_udvm_address_operand(buff,operand_address, &at_address, current_address);
1551 if (show_instr_detail_level == 2 ){
1552 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u @Address %u",
1553 operand_address, at_address);
1555 if (show_instr_detail_level == 1)
1557 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1558 "Addr: %u ## CALL (@address=%u)",
1559 current_address, at_address);
1561 current_address = next_operand_address;
1563 /* Push the current address onto the stack */
1564 stack_location = (buff[70] << 8) | buff[71];
1565 stack_fill = (buff[stack_location] << 8)
1566 | buff[(stack_location+1) & 0xFFFF];
1567 address = (stack_location + stack_fill * 2 + 2) & 0xFFFF;
1568 buff[address] = (current_address >> 8) & 0x00FF;
1569 buff[(address+1) & 0xFFFF] = current_address & 0x00FF;
1571 stack_fill = (stack_fill + 1) & 0xFFFF;
1572 buff[stack_location] = (stack_fill >> 8) & 0x00FF;
1573 buff[(stack_location+1) & 0xFFFF] = stack_fill & 0x00FF;
1575 /* ... and jump to the destination address */
1576 current_address = at_address;
1579 goto execute_next_instruction;
1583 case SIGCOMP_INSTR_RETURN: /* 25 POP and return */
1584 if (print_level_1 || show_instr_detail_level == 1){
1585 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1586 "Addr: %u ## POP(25) and return",
1590 /* Pop value from the top of the stack */
1591 stack_location = (buff[70] << 8) | buff[71];
1592 stack_fill = (buff[stack_location] << 8)
1593 | buff[(stack_location+1) & 0xFFFF];
1594 if (stack_fill == 0)
1597 goto decompression_failure;
1600 stack_fill = (stack_fill - 1) & 0xFFFF;
1601 buff[stack_location] = (stack_fill >> 8) & 0x00FF;
1602 buff[(stack_location+1) & 0xFFFF] = stack_fill & 0x00FF;
1604 address = (stack_location + stack_fill * 2 + 2) & 0xFFFF;
1605 at_address = (buff[address] << 8)
1606 | buff[(address+1) & 0xFFFF];
1608 /* ... and set the PC to the popped value */
1609 current_address = at_address;
1612 goto execute_next_instruction;
1616 case SIGCOMP_INSTR_SWITCH: /* 26 SWITCH (#n, %j, @address_0, @address_1, ... , @address_n-1) */
1618 * When a SWITCH instruction is encountered the UDVM reads the value of
1619 * j. It then continues instruction execution at the address specified
1622 * Decompression failure occurs if j specifies a value of n or more, or
1623 * if the address lies beyond the overall UDVM memory size.
1625 instruction_address = current_address;
1626 if (print_level_1 ){
1627 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1628 "Addr: %u ## SWITCH (#n, j, @address_0, @address_1, ... , @address_n-1))",
1631 operand_address = current_address + 1;
1633 * Number of addresses in the instruction
1635 next_operand_address = decode_udvm_literal_operand(buff,operand_address, &n);
1636 if (print_level_1 ){
1637 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u n %u",
1638 operand_address, n);
1640 operand_address = next_operand_address;
1642 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &j);
1643 if (print_level_1 ){
1644 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u j %u",
1645 operand_address, j);
1647 operand_address = next_operand_address;
1651 /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
1652 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &at_address_1);
1653 at_address_1 = ( instruction_address + at_address_1) & 0xffff;
1654 if (print_level_1 ){
1655 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u @Address %u",
1656 operand_address, at_address_1);
1659 current_address = at_address_1;
1661 operand_address = next_operand_address;
1664 /* Check decompression failure */
1665 if ( ( j == n ) || ( j > n )){
1667 goto decompression_failure;
1669 if ( current_address > UDVM_MEMORY_SIZE ){
1671 goto decompression_failure;
1673 used_udvm_cycles = used_udvm_cycles + 1 + n;
1675 goto execute_next_instruction;
1678 case SIGCOMP_INSTR_CRC: /* 27 CRC (%value, %position, %length, @address) */
1679 if (print_level_1 ){
1680 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1681 "Addr: %u ## CRC (value, position, length, @address)",
1685 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &value);
1686 if (print_level_1 ){
1687 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Value %u",
1688 operand_address, value);
1691 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &position);
1692 if (print_level_1 ){
1693 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u position %u",
1694 operand_address, position);
1696 operand_address = next_operand_address;
1699 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &length);
1700 if (print_level_1 ){
1701 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Length %u",
1702 operand_address, length);
1704 operand_address = next_operand_address;
1707 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &at_address);
1708 at_address = ( current_address + at_address) & 0xffff;
1709 if (print_level_1 ){
1710 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u @Address %u",
1711 operand_address, at_address);
1713 /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
1714 used_udvm_cycles = used_udvm_cycles + 1 + length;
1716 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Execution of this instruction is NOT implemented");
1720 case SIGCOMP_INSTR_INPUT_BYTES: /* 28 INPUT-BYTES (%length, %destination, @address) */
1721 if (show_instr_detail_level == 2 ){
1722 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1723 "Addr: %u ## INPUT-BYTES(28) length, destination, @address)",
1726 operand_address = current_address + 1;
1728 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &length);
1729 if (show_instr_detail_level == 2 ){
1730 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Length %u",
1731 operand_address, length);
1733 operand_address = next_operand_address;
1736 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &destination);
1737 if (show_instr_detail_level == 2 ){
1738 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Destination %u",
1739 operand_address, destination);
1741 operand_address = next_operand_address;
1744 /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
1745 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &at_address);
1746 at_address = ( current_address + at_address) & 0xffff;
1747 if (show_instr_detail_level == 2 ){
1748 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u @Address %u",
1749 operand_address, at_address);
1751 if (show_instr_detail_level == 1)
1753 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1754 "Addr: %u ## INPUT-BYTES length=%u, destination=%u, @address=%u)",
1755 current_address, length, destination, at_address);
1757 /* execute the instruction TODO insert checks
1761 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1762 * | byte_copy_left | 64 - 65
1763 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1764 * | byte_copy_right | 66 - 67
1765 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1766 * | input_bit_order | 68 - 69
1767 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1768 * | stack_location | 70 - 71
1769 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1771 * Figure 7: Memory addresses of the UDVM registers
1775 * The string of bytes is copied in ascending order of memory address,
1776 * respecting the bounds set by byte_copy_left and byte_copy_right.
1777 * More precisely, if a byte is copied from/to Address m then the next
1778 * byte is copied from/to Address n where n is calculated as follows:
1780 * Set k := m + 1 (modulo 2^16)
1781 * If k = byte_copy_right then set n := byte_copy_left, else set n := k
1787 byte_copy_right = buff[66] << 8;
1788 byte_copy_right = byte_copy_right | buff[67];
1789 byte_copy_left = buff[64] << 8;
1790 byte_copy_left = byte_copy_left | buff[65];
1791 if (print_level_1 ){
1792 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
1793 " byte_copy_right = %u", byte_copy_right);
1795 /* clear out remaining bits if any */
1798 /* operand_address used as dummy */
1799 while ( n < length ){
1800 if (input_address > ( msg_end - 1)){
1801 current_address = at_address;
1803 goto execute_next_instruction;
1806 if ( k == byte_copy_right ){
1809 octet = tvb_get_guint8(message_tvb, input_address);
1811 if (print_level_1 ){
1812 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
1813 " Loading value: %u (0x%x) at Addr: %u", octet, octet, k);
1817 * If the instruction requests data that lies beyond the end of the
1818 * SigComp message, no data is returned. Instead the UDVM moves program
1819 * execution to the address specified by the address operand.
1823 k = ( k + 1 ) & 0xffff;
1826 used_udvm_cycles = used_udvm_cycles + 1 + length;
1827 current_address = next_operand_address;
1828 goto execute_next_instruction;
1830 case SIGCOMP_INSTR_INPUT_BITS:/* 29 INPUT-BITS (%length, %destination, @address) */
1832 * The length operand indicates the requested number of bits.
1833 * Decompression failure occurs if this operand does not lie between 0
1836 * The destination operand specifies the memory address to which the
1837 * compressed data should be copied. Note that the requested bits are
1838 * interpreted as a 2-byte integer ranging from 0 to 2^length - 1, as
1839 * explained in Section 8.2.
1841 * If the instruction requests data that lies beyond the end of the
1842 * SigComp message, no data is returned. Instead the UDVM moves program
1843 * execution to the address specified by the address operand.
1846 if (show_instr_detail_level == 2 ){
1847 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1848 "Addr: %u ## INPUT-BITS(29) (length, destination, @address)",
1851 operand_address = current_address + 1;
1854 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &length);
1855 if (show_instr_detail_level == 2 ){
1856 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u length %u",
1857 operand_address, length);
1859 operand_address = next_operand_address;
1861 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &destination);
1862 if (show_instr_detail_level == 2 ){
1863 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Destination %u",
1864 operand_address, destination);
1866 operand_address = next_operand_address;
1869 /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
1870 next_operand_address = decode_udvm_address_operand(buff,operand_address, &at_address, current_address);
1871 if (show_instr_detail_level == 2 ){
1872 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u @Address %u",
1873 operand_address, at_address);
1875 if (show_instr_detail_level == 1)
1877 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1878 "Addr: %u ## INPUT-BITS length=%u, destination=%u, @address=%u)",
1879 current_address, length, destination, at_address);
1881 current_address = next_operand_address;
1884 * Execute actual instr.
1885 * The input_bit_order register contains the following three flags:
1888 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1889 * | reserved |F|H|P| 68 - 69
1890 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1892 input_bit_order = buff[68] << 8;
1893 input_bit_order = input_bit_order | buff[69];
1895 * If the instruction requests data that lies beyond the end of the
1896 * SigComp message, no data is returned. Instead the UDVM moves program
1897 * execution to the address specified by the address operand.
1902 goto decompression_failure;
1904 if ( input_bit_order > 7 ){
1906 goto decompression_failure;
1910 * Transfer F bit to bit_order to tell decomp dispatcher which bit order to use
1912 bit_order = ( input_bit_order & 0x0004 ) >> 2;
1913 value = decomp_dispatch_get_bits( message_tvb, udvm_tree, bit_order,
1914 buff, &old_input_bit_order, &remaining_bits,
1915 &input_bits, &input_address, length, &result_code, msg_end);
1916 if ( result_code == 11 ){
1917 used_udvm_cycles = used_udvm_cycles + 1;
1918 current_address = at_address;
1919 goto execute_next_instruction;
1922 lsb = value & 0x00ff;
1923 buff[destination] = msb;
1924 buff[destination + 1]=lsb;
1925 if (print_level_1 ){
1926 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
1927 " Loading value: %u (0x%x) at Addr: %u, remaining_bits: %u", value, value, destination, remaining_bits);
1930 used_udvm_cycles = used_udvm_cycles + 1;
1931 goto execute_next_instruction;
1933 case SIGCOMP_INSTR_INPUT_HUFFMAN: /* 30 */
1935 * INPUT-HUFFMAN (%destination, @address, #n, %bits_1, %lower_bound_1,
1936 * %upper_bound_1, %uncompressed_1, ... , %bits_n, %lower_bound_n,
1937 * %upper_bound_n, %uncompressed_n)
1939 if (show_instr_detail_level == 2 ){
1940 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1941 "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)",
1944 operand_address = current_address + 1;
1947 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &destination);
1948 if (show_instr_detail_level == 2 ){
1949 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Destination %u",
1950 operand_address, destination);
1952 operand_address = next_operand_address;
1955 /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
1956 next_operand_address = decode_udvm_address_operand(buff,operand_address, &at_address, current_address);
1957 if (show_instr_detail_level == 2 ){
1958 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u @Address %u",
1959 operand_address, at_address);
1961 operand_address = next_operand_address;
1964 next_operand_address = decode_udvm_literal_operand(buff,operand_address, &n);
1965 if (show_instr_detail_level == 2 ){
1966 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u n %u",
1967 operand_address, n);
1969 operand_address = next_operand_address;
1970 if (show_instr_detail_level == 1)
1972 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1973 "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)",
1974 current_address, destination, at_address, n, n, n, n, n);
1977 used_udvm_cycles = used_udvm_cycles + 1 + n;
1980 * Note that if n = 0 then the INPUT-HUFFMAN instruction is ignored and
1981 * program execution resumes at the following instruction.
1982 * Decompression failure occurs if (bits_1 + ... + bits_n) > 16.
1984 * In all other cases, the behavior of the INPUT-HUFFMAN instruction is
1987 * 1. Set j := 1 and set H := 0.
1989 * 2. Request bits_j compressed bits. Interpret the returned bits as an
1990 * integer k from 0 to 2^bits_j - 1, as explained in Section 8.2.
1992 * 3. Set H := H * 2^bits_j + k.
1994 * 4. If data is requested that lies beyond the end of the SigComp
1995 * message, terminate the INPUT-HUFFMAN instruction and move program
1996 * execution to the memory address specified by the address operand.
1998 * 5. If (H < lower_bound_j) or (H > upper_bound_j) then set j := j + 1.
1999 * Then go back to Step 2, unless j > n in which case decompression
2002 * 6. Copy (H + uncompressed_j - lower_bound_j) modulo 2^16 to the
2003 * memory address specified by the destination operand.
2007 * The input_bit_order register contains the following three flags:
2010 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2011 * | reserved |F|H|P| 68 - 69
2012 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2014 * Transfer H bit to bit_order to tell decomp dispatcher which bit order to use
2016 input_bit_order = buff[68] << 8;
2017 input_bit_order = input_bit_order | buff[69];
2018 bit_order = ( input_bit_order & 0x0002 ) >> 1;
2023 outside_huffman_boundaries = TRUE;
2024 print_in_loop = print_level_3;
2027 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &bits_n);
2028 if (print_in_loop ){
2029 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u bits_n %u",
2030 operand_address, bits_n);
2032 operand_address = next_operand_address;
2034 /* %lower_bound_n */
2035 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &lower_bound_n);
2036 if (print_in_loop ){
2037 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u lower_bound_n %u",
2038 operand_address, lower_bound_n);
2040 operand_address = next_operand_address;
2041 /* %upper_bound_n */
2042 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &upper_bound_n);
2043 if (print_in_loop ){
2044 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u upper_bound_n %u",
2045 operand_address, upper_bound_n);
2047 operand_address = next_operand_address;
2048 /* %uncompressed_n */
2049 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &uncompressed_n);
2050 if (print_in_loop ){
2051 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u uncompressed_n %u",
2052 operand_address, uncompressed_n);
2054 operand_address = next_operand_address;
2055 /* execute instruction */
2056 if ( outside_huffman_boundaries ) {
2058 * 2. Request bits_j compressed bits. Interpret the returned bits as an
2059 * integer k from 0 to 2^bits_j - 1, as explained in Section 8.2.
2061 k = decomp_dispatch_get_bits( message_tvb, udvm_tree, bit_order,
2062 buff, &old_input_bit_order, &remaining_bits,
2063 &input_bits, &input_address, bits_n, &result_code, msg_end);
2064 if ( result_code == 11 ){
2066 * 4. If data is requested that lies beyond the end of the SigComp
2067 * message, terminate the INPUT-HUFFMAN instruction and move program
2068 * execution to the memory address specified by the address operand.
2070 current_address = at_address;
2071 goto execute_next_instruction;
2075 * 3. Set H := H * 2^bits_j + k.
2076 * [In practice is a shift+OR operation.]
2079 H = (H << bits_n) | k;
2080 if (print_level_3 ){
2081 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," Set H(%u) := H(%u) * 2^bits_j(%u) + k(%u)",
2082 H ,oldH, 1<<bits_n,k);
2086 * 5. If (H < lower_bound_j) or (H > upper_bound_j) then set j := j + 1.
2087 * Then go back to Step 2, unless j > n in which case decompression
2090 if ((H < lower_bound_n) || (H > upper_bound_n)){
2091 outside_huffman_boundaries = TRUE;
2093 outside_huffman_boundaries = FALSE;
2094 print_in_loop = FALSE;
2096 * 6. Copy (H + uncompressed_j - lower_bound_j) modulo 2^16 to the
2097 * memory address specified by the destination operand.
2099 if (print_level_2 ){
2100 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2101 " H(%u) = H(%u) + uncompressed_n(%u) - lower_bound_n(%u)",
2102 (H + uncompressed_n - lower_bound_n ),H, uncompressed_n, lower_bound_n);
2104 H = H + uncompressed_n - lower_bound_n;
2107 buff[destination] = msb;
2108 buff[destination + 1]=lsb;
2109 if (print_level_1 ){
2110 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
2111 " Loading H: %u (0x%x) at Addr: %u,j = %u remaining_bits: %u",
2112 H, H, destination,( n - m + 1 ), remaining_bits);
2121 if ( outside_huffman_boundaries ) {
2123 goto decompression_failure;
2126 current_address = next_operand_address;
2127 goto execute_next_instruction;
2130 case SIGCOMP_INSTR_STATE_ACCESS: /* 31 */
2131 /* STATE-ACCESS (%partial_identifier_start, %partial_identifier_length,
2132 * %state_begin, %state_length, %state_address, %state_instruction)
2134 if (show_instr_detail_level == 2 ){
2135 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2136 "Addr: %u ## STATE-ACCESS(31) (partial_identifier_start, partial_identifier_length,state_begin, state_length, state_address, state_instruction)",
2139 operand_address = current_address + 1;
2142 * %partial_identifier_start
2144 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &p_id_start);
2145 if (show_instr_detail_level == 2 ){
2146 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u partial_identifier_start %u",
2147 operand_address, p_id_start);
2149 operand_address = next_operand_address;
2152 * %partial_identifier_length
2154 operand_address = next_operand_address;
2155 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &p_id_length);
2156 if (show_instr_detail_level == 2 ){
2157 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u partial_identifier_length %u",
2158 operand_address, p_id_length);
2163 operand_address = next_operand_address;
2164 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_begin);
2165 if (show_instr_detail_level == 2 ){
2166 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_begin %u",
2167 operand_address, state_begin);
2172 operand_address = next_operand_address;
2173 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_length);
2174 if (show_instr_detail_level == 2 ){
2175 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_length %u",
2176 operand_address, state_length);
2181 operand_address = next_operand_address;
2182 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_address);
2183 if (show_instr_detail_level == 2 ){
2184 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_address %u",
2185 operand_address, state_address);
2188 * %state_instruction
2190 operand_address = next_operand_address;
2191 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_instruction);
2192 if (show_instr_detail_level == 2 ){
2193 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_instruction %u",
2194 operand_address, state_instruction);
2196 if (show_instr_detail_level == 1)
2198 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2199 "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)",
2200 current_address, p_id_start, p_id_length, state_begin, state_length, state_address, state_instruction);
2202 current_address = next_operand_address;
2203 byte_copy_right = buff[66] << 8;
2204 byte_copy_right = byte_copy_right | buff[67];
2205 byte_copy_left = buff[64] << 8;
2206 byte_copy_left = byte_copy_left | buff[65];
2207 if (print_level_2 ){
2208 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
2209 " byte_copy_right = %u, byte_copy_left = %u", byte_copy_right,byte_copy_left);
2212 result_code = udvm_state_access(message_tvb, udvm_tree, buff, p_id_start, p_id_length, state_begin, &state_length,
2213 &state_address, &state_instruction, hf_id);
2214 if ( result_code != 0 ){
2215 goto decompression_failure;
2217 used_udvm_cycles = used_udvm_cycles + 1 + state_length;
2218 goto execute_next_instruction;
2220 case SIGCOMP_INSTR_STATE_CREATE: /* 32 */
2222 * STATE-CREATE (%state_length, %state_address, %state_instruction,
2223 * %minimum_access_length, %state_retention_priority)
2225 if (show_instr_detail_level == 2 ){
2226 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2227 "Addr: %u ## STATE-CREATE(32) (state_length, state_address, state_instruction,minimum_access_length, state_retention_priority)",
2230 operand_address = current_address + 1;
2235 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_length);
2236 if (show_instr_detail_level == 2 ){
2237 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_length %u",
2238 operand_address, state_length);
2243 operand_address = next_operand_address;
2244 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_address);
2245 if (show_instr_detail_level == 2 ){
2246 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_address %u",
2247 operand_address, state_address);
2250 * %state_instruction
2252 operand_address = next_operand_address;
2253 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_instruction);
2254 if (show_instr_detail_level == 2 ){
2255 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_instruction %u",
2256 operand_address, state_instruction);
2258 operand_address = next_operand_address;
2260 * %minimum_access_length
2262 operand_address = next_operand_address;
2263 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &minimum_access_length);
2264 if (show_instr_detail_level == 2 ){
2265 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u minimum_access_length %u",
2266 operand_address, minimum_access_length);
2268 operand_address = next_operand_address;
2270 * %state_retention_priority
2272 operand_address = next_operand_address;
2273 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_retention_priority);
2274 if (show_instr_detail_level == 2 ){
2275 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_retention_priority %u",
2276 operand_address, state_retention_priority);
2278 if (show_instr_detail_level == 1)
2280 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2281 "Addr: %u ## STATE-CREATE(32) (state_length=%u, state_address=%u, state_instruction=%u,minimum_access_length=%u, state_retention_priority=%u)",
2282 current_address, state_length, state_address, state_instruction,minimum_access_length, state_retention_priority);
2284 current_address = next_operand_address;
2285 /* Execute the instruction
2286 * TODO Implement the instruction
2288 * Note that the new state item cannot be created until a valid
2289 * compartment identifier has been returned by the application.
2290 * Consequently, when a STATE-CREATE instruction is encountered the UDVM
2291 * simply buffers the five supplied operands until the END-MESSAGE
2292 * instruction is reached. The steps taken at this point are described
2295 * Decompression failure MUST occur if more than four state creation
2296 * requests are made before the END-MESSAGE instruction is encountered.
2297 * Decompression failure also occurs if the minimum_access_length does
2298 * not lie between 6 and 20 inclusive, or if the
2299 * state_retention_priority is 65535.
2301 no_of_state_create++;
2302 if ( no_of_state_create > 4 ){
2304 goto decompression_failure;
2306 if (( minimum_access_length < 6 ) || ( minimum_access_length > 20 )){
2308 goto decompression_failure;
2310 if ( state_retention_priority == 65535 ){
2312 goto decompression_failure;
2314 state_length_buff[no_of_state_create] = state_length;
2315 state_address_buff[no_of_state_create] = state_address;
2316 state_instruction_buff[no_of_state_create] = state_instruction;
2317 state_minimum_access_length_buff[no_of_state_create] = minimum_access_length;
2318 state_state_retention_priority_buff[no_of_state_create] = state_retention_priority;
2319 used_udvm_cycles = used_udvm_cycles + 1 + state_length;
2321 byte_copy_right = buff[66] << 8;
2322 byte_copy_right = byte_copy_right | buff[67];
2323 byte_copy_left = buff[64] << 8;
2324 byte_copy_left = byte_copy_left | buff[65];
2327 while ( n < state_length ){
2328 if ( k == byte_copy_right ){
2333 if (print_level_3 ){
2334 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2335 " Addr: %5u State value: %u (0x%x) ASCII(%s)",
2336 k,buff[k],buff[k],string);
2338 k = ( k + 1 ) & 0xffff;
2343 goto execute_next_instruction;
2345 case SIGCOMP_INSTR_STATE_FREE: /* 33 */
2347 * STATE-FREE (%partial_identifier_start, %partial_identifier_length)
2349 if (show_instr_detail_level == 2 ){
2350 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2351 "Addr: %u ## STATE-FREE (partial_identifier_start, partial_identifier_length)",
2354 operand_address = current_address + 1;
2356 * %partial_identifier_start
2358 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &p_id_start);
2359 if (show_instr_detail_level == 2 ){
2360 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u partial_identifier_start %u",
2361 operand_address, p_id_start);
2363 operand_address = next_operand_address;
2366 * %partial_identifier_length
2368 operand_address = next_operand_address;
2369 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &p_id_length);
2370 if (show_instr_detail_level == 2 ){
2371 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u partial_identifier_length %u",
2372 operand_address, p_id_length);
2374 if (show_instr_detail_level == 1)
2376 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2377 "Addr: %u ## STATE-FREE (partial_identifier_start=%u, partial_identifier_length=%u)",
2378 current_address, p_id_start, p_id_length);
2380 current_address = next_operand_address;
2382 /* Execute the instruction:
2385 udvm_state_free(buff,p_id_start,p_id_length);
2388 goto execute_next_instruction;
2390 case SIGCOMP_INSTR_OUTPUT: /* 34 OUTPUT (%output_start, %output_length) */
2391 if (show_instr_detail_level == 2 ){
2392 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2393 "Addr: %u ## OUTPUT(34) (output_start, output_length)",
2396 operand_address = current_address + 1;
2400 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &output_start);
2401 if (show_instr_detail_level == 2 ){
2402 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u output_start %u",
2403 operand_address, output_start);
2405 operand_address = next_operand_address;
2409 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &output_length);
2410 if (show_instr_detail_level == 2 ){
2411 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u output_length %u",
2412 operand_address, output_length);
2414 if (show_instr_detail_level == 1)
2416 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2417 "Addr: %u ## OUTPUT (output_start=%u, output_length=%u)",
2418 current_address, output_start, output_length);
2420 current_address = next_operand_address;
2423 * Execute instruction
2426 * The string of bytes is copied in ascending order of memory address,
2427 * respecting the bounds set by byte_copy_left and byte_copy_right.
2428 * More precisely, if a byte is copied from/to Address m then the next
2429 * byte is copied from/to Address n where n is calculated as follows:
2431 * Set k := m + 1 (modulo 2^16)
2432 * If k = byte_copy_right then set n := byte_copy_left, else set n := k
2438 byte_copy_right = buff[66] << 8;
2439 byte_copy_right = byte_copy_right | buff[67];
2440 byte_copy_left = buff[64] << 8;
2441 byte_copy_left = byte_copy_left | buff[65];
2442 if (print_level_3 ){
2443 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2444 " byte_copy_right = %u", byte_copy_right);
2446 while ( n < output_length ){
2448 if ( k == byte_copy_right ){
2451 out_buff[output_address] = buff[k];
2455 if (print_level_3 ){
2456 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2457 " Output value: %u (0x%x) ASCII(%s) from Addr: %u ,output to dispatcher position %u",
2458 buff[k],buff[k],format_text(strp,1), k,output_address);
2460 k = ( k + 1 ) & 0xffff;
2464 used_udvm_cycles = used_udvm_cycles + 1 + output_length;
2465 goto execute_next_instruction;
2467 case SIGCOMP_INSTR_END_MESSAGE: /* 35 */
2469 * END-MESSAGE (%requested_feedback_location,
2470 * %returned_parameters_location, %state_length, %state_address,
2471 * %state_instruction, %minimum_access_length,
2472 * %state_retention_priority)
2474 if (show_instr_detail_level == 2 ){
2475 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2476 "Addr: %u ## END-MESSAGE (requested_feedback_location,state_instruction, minimum_access_length,state_retention_priority)",
2479 operand_address = current_address + 1;
2481 /* %requested_feedback_location */
2482 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &requested_feedback_location);
2483 if (show_instr_detail_level == 2 ){
2484 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u requested_feedback_location %u",
2485 operand_address, requested_feedback_location);
2487 operand_address = next_operand_address;
2488 /* returned_parameters_location */
2489 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &returned_parameters_location);
2490 if (show_instr_detail_level == 2 ){
2491 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u returned_parameters_location %u",
2492 operand_address, returned_parameters_location);
2494 operand_address = next_operand_address;
2498 operand_address = next_operand_address;
2499 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_length);
2500 if (show_instr_detail_level == 2 ){
2501 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_length %u",
2502 operand_address, state_length);
2507 operand_address = next_operand_address;
2508 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_address);
2509 if (show_instr_detail_level == 2 ){
2510 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_address %u",
2511 operand_address, state_address);
2514 * %state_instruction
2516 operand_address = next_operand_address;
2517 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_instruction);
2518 if (show_instr_detail_level == 2 ){
2519 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_instruction %u",
2520 operand_address, state_instruction);
2522 operand_address = next_operand_address;
2524 * %minimum_access_length
2526 operand_address = next_operand_address;
2527 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &minimum_access_length);
2528 if (show_instr_detail_level == 2 ){
2529 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u minimum_access_length %u",
2530 operand_address, minimum_access_length);
2532 operand_address = next_operand_address;
2535 * %state_retention_priority
2537 operand_address = next_operand_address;
2538 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_retention_priority);
2539 if (show_instr_detail_level == 2 ){
2540 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_retention_priority %u",
2541 operand_address, state_retention_priority);
2543 if (show_instr_detail_level == 1)
2545 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2546 "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)",
2547 current_address, requested_feedback_location, returned_parameters_location, state_length, state_address, state_instruction, minimum_access_length,state_retention_priority);
2549 current_address = next_operand_address;
2550 /* TODO: This isn't currently totaly correct as END_INSTRUCTION might not create state */
2551 no_of_state_create++;
2552 if ( no_of_state_create > 4 ){
2554 goto decompression_failure;
2556 state_length_buff[no_of_state_create] = state_length;
2557 state_address_buff[no_of_state_create] = state_address;
2558 state_instruction_buff[no_of_state_create] = state_instruction;
2560 state_minimum_access_length_buff[no_of_state_create] = minimum_access_length;
2561 state_state_retention_priority_buff[no_of_state_create] = state_retention_priority;
2563 /* Execute the instruction
2565 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"no_of_state_create %u",no_of_state_create);
2566 if ( no_of_state_create != 0 ){
2567 for( x=0; x < 20; x++){
2568 sha1_digest_buf[x]=0;
2571 byte_copy_right = buff[66] << 8;
2572 byte_copy_right = byte_copy_right | buff[67];
2573 byte_copy_left = buff[64] << 8;
2574 byte_copy_left = byte_copy_left | buff[65];
2575 while ( n < no_of_state_create + 1 ){
2576 sha1buff = g_malloc(state_length_buff[n]+8);
2577 sha1buff[0] = state_length_buff[n] >> 8;
2578 sha1buff[1] = state_length_buff[n] & 0xff;
2579 sha1buff[2] = state_address_buff[n] >> 8;
2580 sha1buff[3] = state_address_buff[n] & 0xff;
2581 sha1buff[4] = state_instruction_buff[n] >> 8;
2582 sha1buff[5] = state_instruction_buff[n] & 0xff;
2583 sha1buff[6] = state_minimum_access_length_buff[n] >> 8;
2584 sha1buff[7] = state_minimum_access_length_buff[n] & 0xff;
2585 if (print_level_3 ){
2586 for( x=0; x < 8; x++){
2587 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"sha1buff %u 0x%x",
2591 k = state_address_buff[n];
2592 for( x=0; x < state_length_buff[n]; x++)
2594 if ( k == byte_copy_right ){
2597 sha1buff[8+x] = buff[k];
2598 k = ( k + 1 ) & 0xffff;
2601 sha1_starts( &ctx );
2602 sha1_update( &ctx, (guint8 *) sha1buff, state_length_buff[n] + 8);
2603 sha1_finish( &ctx, sha1_digest_buf );
2604 if (print_level_3 ){
2605 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"SHA1 digest %s",bytes_to_str(sha1_digest_buf, 20));
2608 udvm_state_create(sha1buff, sha1_digest_buf, state_minimum_access_length_buff[n]);
2609 proto_tree_add_text(udvm_tree,bytecode_tvb, 0, -1,"### Creating state ###");
2610 proto_tree_add_string(udvm_tree,hf_id, bytecode_tvb, 0, 0, bytes_to_str(sha1_digest_buf, state_minimum_access_length_buff[n]));
2619 /* At least something got decompressed, show it */
2620 decomp_tvb = tvb_new_real_data(out_buff,output_address,output_address);
2621 /* Arrange that the allocated packet data copy be freed when the
2624 tvb_set_free_cb( decomp_tvb, g_free );
2626 tvb_set_child_real_data_tvbuff(message_tvb,decomp_tvb);
2627 add_new_data_source(pinfo, decomp_tvb, "Decompressed SigComp message");
2629 proto_tree_add_text(udvm_tree, decomp_tvb, 0, -1,"SigComp message Decompressed");
2631 used_udvm_cycles = used_udvm_cycles + 1 + state_length;
2632 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"maximum_UDVM_cycles %u used_udvm_cycles %u",
2633 maximum_UDVM_cycles, used_udvm_cycles);
2638 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," ### Addr %u Invalid instruction: %u (0x%x)",
2639 current_address,current_instruction,current_instruction);
2644 decompression_failure:
2646 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"DECOMPRESSION FAILURE: %s",
2647 val_to_str(result_code, result_code_vals,"Unknown (%u)"));
2653 /* The simplest operand type is the literal (#), which encodes a
2654 * constant integer from 0 to 65535 inclusive. A literal operand may
2655 * require between 1 and 3 bytes depending on its value.
2656 * Bytecode: Operand value: Range:
2657 * 0nnnnnnn N 0 - 127
2658 * 10nnnnnn nnnnnnnn N 0 - 16383
2659 * 11000000 nnnnnnnn nnnnnnnn N 0 - 65535
2661 * Figure 8: Bytecode for a literal (#) operand
2665 decode_udvm_literal_operand(guint8 *buff,guint operand_address, guint16 *value)
2670 guint offset = operand_address;
2673 bytecode = buff[operand_address];
2674 test_bits = bytecode >> 7;
2675 if (test_bits == 1){
2676 test_bits = bytecode >> 6;
2677 if (test_bits == 2){
2679 * 10nnnnnn nnnnnnnn N 0 - 16383
2681 temp_data = buff[operand_address] & 0x1f;
2682 operand = temp_data << 8;
2683 temp_data = buff[operand_address + 1];
2684 operand = operand | temp_data;
2686 offset = offset + 2;
2690 * 111000000 nnnnnnnn nnnnnnnn N 0 - 65535
2693 temp_data = buff[operand_address] & 0x1f;
2694 operand = temp_data << 8;
2695 temp_data = buff[operand_address + 1];
2696 operand = operand | temp_data;
2698 offset = offset + 2;
2703 * 0nnnnnnn N 0 - 127
2705 operand = ( bytecode & 0x7f);
2715 * The second operand type is the reference ($), which is always used to
2716 * access a 2-byte value located elsewhere in the UDVM memory. The
2717 * bytecode for a reference operand is decoded to be a constant integer
2718 * from 0 to 65535 inclusive, which is interpreted as the memory address
2719 * containing the actual value of the operand.
2720 * Bytecode: Operand value: Range:
2722 * 0nnnnnnn memory[2 * N] 0 - 65535
2723 * 10nnnnnn nnnnnnnn memory[2 * N] 0 - 65535
2724 * 11000000 nnnnnnnn nnnnnnnn memory[N] 0 - 65535
2726 * Figure 9: Bytecode for a reference ($) operand
2729 dissect_udvm_reference_operand(guint8 *buff,guint operand_address, guint16 *value,guint *result_dest)
2733 guint offset = operand_address;
2736 guint16 temp_data16;
2738 bytecode = buff[operand_address];
2739 test_bits = bytecode >> 7;
2740 if (test_bits == 1){
2741 test_bits = bytecode >> 6;
2742 if (test_bits == 2){
2744 * 10nnnnnn nnnnnnnn memory[2 * N] 0 - 65535
2746 temp_data = buff[operand_address] & 0x3f;
2747 operand = temp_data << 8;
2748 temp_data = buff[operand_address + 1];
2749 operand = operand | temp_data;
2750 operand = (operand * 2);
2751 *result_dest = operand;
2752 temp_data16 = buff[operand] << 8;
2753 temp_data16 = temp_data16 | buff[operand+1];
2754 *value = temp_data16;
2755 offset = offset + 2;
2759 * 11000000 nnnnnnnn nnnnnnnn memory[N] 0 - 65535
2762 operand = buff[operand_address] << 8;
2763 operand = operand | buff[operand_address + 1];
2764 *result_dest = operand;
2765 temp_data16 = buff[operand] << 8;
2766 temp_data16 = temp_data16 | buff[operand+1];
2767 *value = temp_data16;
2768 offset = offset + 3;
2773 * 0nnnnnnn memory[2 * N] 0 - 65535
2775 operand = ( bytecode & 0x7f);
2776 operand = (operand * 2);
2777 *result_dest = operand;
2778 temp_data16 = buff[operand] << 8;
2779 temp_data16 = temp_data16 | buff[operand+1];
2780 *value = temp_data16;
2788 * Figure 10: Bytecode for a multitype (%) operand
2789 * Bytecode: Operand value: Range: HEX val
2790 * 00nnnnnn N 0 - 63 0x00
2791 * 01nnnnnn memory[2 * N] 0 - 65535 0x40
2792 * 1000011n 2 ^ (N + 6) 64 , 128 0x86
2793 * 10001nnn 2 ^ (N + 8) 256 , ... , 32768 0x88
2794 * 111nnnnn N + 65504 65504 - 65535 0xe0
2795 * 1001nnnn nnnnnnnn N + 61440 61440 - 65535 0x90
2796 * 101nnnnn nnnnnnnn N 0 - 8191 0xa0
2797 * 110nnnnn nnnnnnnn memory[N] 0 - 65535 0xc0
2798 * 10000000 nnnnnnnn nnnnnnnn N 0 - 65535 0x80
2799 * 10000001 nnnnnnnn nnnnnnnn memory[N] 0 - 65535 0x81
2802 decode_udvm_multitype_operand(guint8 *buff,guint operand_address, guint16 *value)
2806 guint offset = operand_address;
2810 guint16 temp_data16;
2811 guint16 memmory_addr = 0;
2813 bytecode = buff[operand_address];
2814 test_bits = ( bytecode & 0xc0 ) >> 6;
2815 switch (test_bits ){
2820 operand = buff[operand_address];
2822 *g_warning("Reading 0x%x From address %u",operand,offset);
2829 * 01nnnnnn memory[2 * N] 0 - 65535
2831 memmory_addr = ( bytecode & 0x3f) * 2;
2832 temp_data16 = buff[memmory_addr] << 8;
2833 temp_data16 = temp_data16 | buff[memmory_addr+1];
2834 *value = temp_data16;
2838 /* Check tree most significant bits */
2839 test_bits = ( bytecode & 0xe0 ) >> 5;
2840 if ( test_bits == 5 ){
2842 * 101nnnnn nnnnnnnn N 0 - 8191
2844 temp_data = buff[operand_address] & 0x1f;
2845 operand = temp_data << 8;
2846 temp_data = buff[operand_address + 1];
2847 operand = operand | temp_data;
2849 offset = offset + 2;
2851 test_bits = ( bytecode & 0xf0 ) >> 4;
2852 if ( test_bits == 9 ){
2854 * 1001nnnn nnnnnnnn N + 61440 61440 - 65535
2856 temp_data = buff[operand_address] & 0x0f;
2857 operand = temp_data << 8;
2858 temp_data = buff[operand_address + 1];
2859 operand = operand | temp_data;
2860 operand = operand + 61440;
2862 offset = offset + 2;
2864 test_bits = ( bytecode & 0x08 ) >> 3;
2865 if ( test_bits == 1){
2867 * 10001nnn 2 ^ (N + 8) 256 , ... , 32768
2870 result = 1 << ((buff[operand_address] & 0x07) + 8);
2871 operand = result & 0xffff;
2875 test_bits = ( bytecode & 0x0e ) >> 1;
2876 if ( test_bits == 3 ){
2878 * 1000 011n 2 ^ (N + 6) 64 , 128
2880 result = 1 << ((buff[operand_address] & 0x01) + 6);
2881 operand = result & 0xffff;
2886 * 1000 0000 nnnnnnnn nnnnnnnn N 0 - 65535
2887 * 1000 0001 nnnnnnnn nnnnnnnn memory[N] 0 - 65535
2890 temp_data16 = buff[operand_address + 1] << 8;
2891 temp_data16 = temp_data16 | buff[operand_address + 2];
2893 * g_warning("Reading 0x%x From address %u",temp_data16,operand_address);
2895 if ( (bytecode & 0x01) == 1 ){
2896 memmory_addr = temp_data16;
2897 temp_data16 = buff[memmory_addr] << 8;
2898 temp_data16 = temp_data16 | buff[memmory_addr+1];
2900 *value = temp_data16;
2911 test_bits = ( bytecode & 0x20 ) >> 5;
2912 if ( test_bits == 1 ){
2914 * 111nnnnn N + 65504 65504 - 65535
2916 operand = ( buff[operand_address] & 0x1f) + 65504;
2921 * 110nnnnn nnnnnnnn memory[N] 0 - 65535
2923 memmory_addr = buff[operand_address] & 0x1f;
2924 memmory_addr = memmory_addr << 8;
2925 memmory_addr = memmory_addr | buff[operand_address + 1];
2926 temp_data16 = buff[memmory_addr] << 8;
2927 temp_data16 = temp_data16 | buff[memmory_addr+1];
2928 *value = temp_data16;
2930 * g_warning("Reading 0x%x From address %u",temp_data16,memmory_addr);
2942 * The fourth operand type is the address (@). This operand is decoded
2943 * as a multitype operand followed by a further step: the memory address
2944 * of the UDVM instruction containing the address operand is added to
2945 * obtain the correct operand value. So if the operand value from
2946 * Figure 10 is D then the actual operand value of an address is
2947 * calculated as follows:
2949 * operand_value = (memory_address_of_instruction + D) modulo 2^16
2951 * Address operands are always used in instructions that control program
2952 * flow, because they ensure that the UDVM bytecode is position-
2953 * independent code (i.e., it will run independently of where it is
2954 * placed in the UDVM memory).
2957 decode_udvm_address_operand(guint8 *buff,guint operand_address, guint16 *value,guint current_address)
2961 guint next_opreand_address;
2963 next_opreand_address = decode_udvm_multitype_operand(buff, operand_address, &value1);
2964 result = value1 & 0xffff;
2965 result = result + current_address;
2966 *value = result & 0xffff;
2967 return next_opreand_address;
2972 * This is a lookup table used to reverse the bits in a byte.
2974 static guint8 reverse [] = {
2975 0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0,
2976 0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0,
2977 0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8,
2978 0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8,
2979 0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4,
2980 0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4,
2981 0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC,
2982 0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC,
2983 0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2,
2984 0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2,
2985 0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA,
2986 0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA,
2987 0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6,
2988 0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6,
2989 0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE,
2990 0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE,
2991 0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1,
2992 0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1,
2993 0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9,
2994 0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9,
2995 0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5,
2996 0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5,
2997 0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED,
2998 0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD,
2999 0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3,
3000 0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3,
3001 0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB,
3002 0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB,
3003 0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7,
3004 0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7,
3005 0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF,
3006 0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF
3011 decomp_dispatch_get_bits(
3012 tvbuff_t *message_tvb,
3013 proto_tree *udvm_tree,
3016 guint16 *old_input_bit_order,
3017 guint16 *remaining_bits,
3018 guint16 *input_bits,
3019 guint *input_address,
3021 guint16 *result_code,
3024 guint16 input_bit_order;
3025 guint16 bits_still_required = length;
3028 gint extra_bytes_available = msg_end - *input_address;
3030 gint prev_p_bit = *old_input_bit_order & 0x0001;
3031 gint bits_to_use = 0;
3034 input_bit_order = buff[68] << 8;
3035 input_bit_order = input_bit_order | buff[69];
3037 p_bit = (input_bit_order & 0x0001) != 0;
3040 * Discard any spare bits.
3041 * Note: We take care to avoid remaining_bits having the value of 8.
3043 if (prev_p_bit != p_bit)
3045 *remaining_bits = 0;
3046 *old_input_bit_order = input_bit_order;
3050 * Check we can suppy the required number of bits now, before we alter
3051 * the input buffer's state.
3053 if (*remaining_bits + extra_bytes_available * 8 < length)
3059 /* Note: This is never called with length > 16, so the following loop
3060 * never loops more than three time. */
3061 while (bits_still_required > 0)
3064 * We only put anything into input_bits if we know we will remove
3065 * at least one bit. That ensures we can simply discard the spare
3066 * bits if the P-bit changes.
3068 if (*remaining_bits == 0)
3070 octet = tvb_get_guint8(message_tvb, *input_address);
3071 if (print_level_1 ){
3072 proto_tree_add_text(udvm_tree, message_tvb, *input_address , 1,
3073 " Geting value: %u (0x%x) From Addr: %u", octet, octet, *input_address);
3075 *input_address = *input_address + 1;
3079 octet = reverse[octet];
3081 *input_bits = octet;
3082 *remaining_bits = 8;
3085 /* Add some more bits to the accumulated value. */
3086 bits_to_use = bits_still_required < *remaining_bits ? bits_still_required : *remaining_bits;
3087 bits_still_required -= bits_to_use;
3089 *input_bits <<= bits_to_use; /* Shift bits into MSByte */
3090 value = (value << bits_to_use) /* Then add to the accumulated value */
3091 | ((*input_bits >> 8) & 0xFF);
3092 *remaining_bits -= bits_to_use;
3093 *input_bits &= 0x00FF; /* Leave just the remaining bits */
3098 /* Bit reverse the entire word. */
3099 guint16 lsb = reverse[(value >> 8) & 0xFF];
3100 guint16 msb = reverse[value & 0xFF];
3102 value = ((msb << 8) | lsb) >> (16 - length);