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
44 #include "sigcomp-udvm.h"
45 #include "sigcomp_state_hdlr.h"
48 #define SIGCOMP_INSTR_DECOMPRESSION_FAILURE 0
49 #define SIGCOMP_INSTR_AND 1
50 #define SIGCOMP_INSTR_OR 2
51 #define SIGCOMP_INSTR_NOT 3
52 #define SIGCOMP_INSTR_LSHIFT 4
53 #define SIGCOMP_INSTR_RSHIFT 5
54 #define SIGCOMP_INSTR_ADD 6
55 #define SIGCOMP_INSTR_SUBTRACT 7
56 #define SIGCOMP_INSTR_MULTIPLY 8
57 #define SIGCOMP_INSTR_DIVIDE 9
58 #define SIGCOMP_INSTR_REMAINDER 10
59 #define SIGCOMP_INSTR_SORT_ASCENDING 11
60 #define SIGCOMP_INSTR_SORT_DESCENDING 12
61 #define SIGCOMP_INSTR_SHA_1 13
62 #define SIGCOMP_INSTR_LOAD 14
63 #define SIGCOMP_INSTR_MULTILOAD 15
64 #define SIGCOMP_INSTR_PUSH 16
65 #define SIGCOMP_INSTR_POP 17
66 #define SIGCOMP_INSTR_COPY 18
67 #define SIGCOMP_INSTR_COPY_LITERAL 19
68 #define SIGCOMP_INSTR_COPY_OFFSET 20
69 #define SIGCOMP_INSTR_MEMSET 21
70 #define SIGCOMP_INSTR_JUMP 22
71 #define SIGCOMP_INSTR_COMPARE 23
72 #define SIGCOMP_INSTR_CALL 24
73 #define SIGCOMP_INSTR_RETURN 25
74 #define SIGCOMP_INSTR_SWITCH 26
75 #define SIGCOMP_INSTR_CRC 27
76 #define SIGCOMP_INSTR_INPUT_BYTES 28
77 #define SIGCOMP_INSTR_INPUT_BITS 29
78 #define SIGCOMP_INSTR_INPUT_HUFFMAN 30
79 #define SIGCOMP_INSTR_STATE_ACCESS 31
80 #define SIGCOMP_INSTR_STATE_CREATE 32
81 #define SIGCOMP_INSTR_STATE_FREE 33
82 #define SIGCOMP_INSTR_OUTPUT 34
83 #define SIGCOMP_INSTR_END_MESSAGE 35
86 static gboolean print_level_1;
87 static gboolean print_level_2;
88 static gboolean print_level_3;
89 static gint show_instr_detail_level;
91 /* Internal result code values of decompression failures */
92 const value_string result_code_vals[] = {
93 { 0, "No decomprssion failure" },
94 { 1, "Partial state length less than 6 or greater than 20 bytes long" },
95 { 2, "No state match" },
96 { 3, "state_begin + state_length > size of state" },
97 { 4, "Operand_2 is Zero" },
98 { 5, "Switch statement failed j >= n" },
99 { 6, "Atempt to jump outside of UDVM memory" },
100 { 7, "L in input-bits > 16" },
101 { 8, "input_bit_order > 7" },
102 { 9, "Instruction Decompression failure encountered" },
103 {10, "Input huffman failed j > n" },
104 {11, "Input bits requested beyond end of message" },
105 {12, "more than four state creation requests are made before the END-MESSAGE instruction" },
106 {13, "state_retention_priority is 65535" },
107 {14, "Input bytes requested beond end of message" },
108 {15, "Maximum number of UDVM cycles reached" },
109 {16, "UDVM stack underflow" },
110 { 255, "This branch isn't coded yet" },
114 static int decode_udvm_literal_operand(guint8 *buff,guint operand_address, guint16 *value);
115 static int dissect_udvm_reference_operand(guint8 *buff,guint operand_address, guint16 *value, guint *result_dest);
116 static int decode_udvm_multitype_operand(guint8 *buff,guint operand_address,guint16 *value);
117 static int decode_udvm_address_operand(guint8 *buff,guint operand_address, guint16 *value,guint current_address);
118 static int decomp_dispatch_get_bits(tvbuff_t *message_tvb,proto_tree *udvm_tree,guint8 bit_order,
119 guint8 *buff,guint16 *old_input_bit_order, guint16 *remaining_bits,
120 guint16 *input_bits, guint *input_address, guint16 length, guint16 *result_code,guint msg_end);
124 decompress_sigcomp_message(tvbuff_t *bytecode_tvb, tvbuff_t *message_tvb, packet_info *pinfo,
125 proto_tree *udvm_tree, gint udvm_mem_dest,
126 gint print_flags, gint hf_id,
128 gint byte_code_state_len, gint byte_code_id_len)
130 tvbuff_t *decomp_tvb;
131 guint8 buff[UDVM_MEMORY_SIZE];
132 char string[2],*strp;
133 guint8 *out_buff; /* Largest allowed size for a message is 65535 */
143 guint code_length =0;
144 guint8 current_instruction;
145 guint current_address;
146 guint operand_address;
148 guint16 output_address = 0;
149 guint next_operand_address;
153 guint16 byte_copy_right;
154 guint16 byte_copy_left;
155 guint16 input_bit_order;
156 guint16 stack_location;
159 guint msg_end = tvb_reported_length_remaining(message_tvb, 0);
161 guint16 old_input_bit_order = 0;
162 guint16 remaining_bits = 0;
163 guint16 input_bits = 0;
164 guint8 bit_order = 0;
165 gboolean outside_huffman_boundaries = TRUE;
166 gboolean print_in_loop = FALSE;
167 guint16 instruction_address;
168 guint8 no_of_state_create = 0;
169 guint16 state_length_buff[5];
170 guint16 state_address_buff[5];
171 guint16 state_instruction_buff[5];
172 guint16 state_minimum_access_length_buff[5];
173 guint16 state_state_retention_priority_buff[5];
174 guint32 used_udvm_cycles = 0;
175 guint cycles_per_bit;
176 guint maximum_UDVM_cycles;
178 unsigned char sha1_digest_buf[20];
182 /* UDVM operand variables */
191 guint16 state_length;
192 guint16 state_address;
193 guint16 state_instruction;
198 guint16 at_address_1;
199 guint16 at_address_2;
200 guint16 at_address_3;
203 guint16 lower_bound_n;
204 guint16 upper_bound_n;
205 guint16 uncompressed_n;
207 guint16 ref_destination; /* could I have used $destination ? */
208 guint16 multy_offset;
209 guint16 output_start;
210 guint16 output_length;
211 guint16 minimum_access_length;
212 guint16 state_retention_priority;
213 guint16 requested_feedback_location;
214 guint16 returned_parameters_location;
218 /* Set print parameters */
219 print_level_1 = FALSE;
220 print_level_2 = FALSE;
221 print_level_3 = FALSE;
222 show_instr_detail_level = 0;
226 switch( print_flags ) {
231 print_level_1 = TRUE;
232 show_instr_detail_level = 1;
235 print_level_1 = TRUE;
236 print_level_2 = TRUE;
237 show_instr_detail_level = 1;
240 print_level_1 = TRUE;
241 print_level_2 = TRUE;
242 print_level_3 = TRUE;
243 show_instr_detail_level = 2;
246 print_level_1 = TRUE;
247 show_instr_detail_level = 1;
255 /* UDVM memory must be initialised to zero */
256 while ( i < UDVM_MEMORY_SIZE ) {
260 /* Set initial UDVM data
261 * The first 32 bytes of UDVM memory are then initialized to special
262 * values as illustrated in Figure 5.
265 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
266 * | UDVM_memory_size | 0 - 1
267 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
268 * | cycles_per_bit | 2 - 3
269 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
270 * | SigComp_version | 4 - 5
271 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
272 * | partial_state_ID_length | 6 - 7
273 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
274 * | state_length | 8 - 9
275 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
277 * : reserved : 10 - 31
279 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
281 * Figure 5: Initializing Useful Values in UDVM memory
283 /* UDVM_memory_size */
284 buff[0] = (UDVM_MEMORY_SIZE >> 8) & 0x00FF;
285 buff[1] = UDVM_MEMORY_SIZE & 0x00FF;
289 /* SigComp_version */
292 /* partial_state_ID_length */
293 buff[6] = (byte_code_id_len >> 8) & 0x00FF;
294 buff[7] = byte_code_id_len & 0x00FF;
296 buff[8] = (byte_code_state_len >> 8) & 0x00FF;
297 buff[9] = byte_code_state_len & 0x00FF;
299 code_length = tvb_reported_length_remaining(bytecode_tvb, 0);
301 cycles_per_bit = buff[2] << 8;
302 cycles_per_bit = cycles_per_bit | buff[3];
304 * maximum_UDVM_cycles = (8 * n + 1000) * cycles_per_bit
306 maximum_UDVM_cycles = (( 8 * (header_len + msg_end) ) + 1000) * cycles_per_bit;
308 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);
309 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);
311 /* Load bytecode into UDVM starting at "udvm_mem_dest" */
314 proto_tree_add_text(udvm_tree, bytecode_tvb, offset, 1,"Load bytecode into UDVM starting at %u",i);
315 while ( code_length > offset ) {
316 buff[i] = tvb_get_guint8(bytecode_tvb, offset);
318 proto_tree_add_text(udvm_tree, bytecode_tvb, offset, 1,
319 " Addr: %u Instruction code(0x%0x) ", i, buff[i]);
325 /* Largest allowed size for a message is 65535 */
326 out_buff = g_malloc(65535);
327 /* Start executing code */
328 current_address = udvm_mem_dest;
332 proto_tree_add_text(udvm_tree, bytecode_tvb, offset, 1,"UDVM EXECUTION STARTED at Address: %u Message size %u",
333 udvm_mem_dest,msg_end);
335 execute_next_instruction:
337 if ( used_udvm_cycles > maximum_UDVM_cycles ){
339 goto decompression_failure;
341 current_instruction = buff[current_address];
343 switch ( current_instruction ) {
344 case SIGCOMP_INSTR_DECOMPRESSION_FAILURE:
346 if ( result_code == 0 )
348 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
349 "Addr: %u ## DECOMPRESSION-FAILURE(0)",
351 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Ethereal UDVM diagnostic: %s.",
352 val_to_str(result_code, result_code_vals,"Unknown (%u)"));
353 if ( output_address > 0 ){
354 /* At least something got decompressed, show it */
355 decomp_tvb = tvb_new_real_data(out_buff,output_address,output_address);
356 /* Arrange that the allocated packet data copy be freed when the
359 tvb_set_free_cb( decomp_tvb, g_free );
360 /* Add the tvbuff to the list of tvbuffs to which the tvbuff we
361 * were handed refers, so it'll get cleaned up when that tvbuff
364 tvb_set_child_real_data_tvbuff(message_tvb,decomp_tvb);
365 add_new_data_source(pinfo, decomp_tvb, "Decompressed SigComp message(Incomplete)");
366 proto_tree_add_text(udvm_tree, decomp_tvb, 0, -1,"SigComp message Decompression failure");
373 case SIGCOMP_INSTR_AND: /* 1 AND ($operand_1, %operand_2) */
375 if (show_instr_detail_level == 2 ){
376 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
377 "Addr: %u ## AND(1) (operand_1, operand_2)",
381 operand_address = current_address + 1;
382 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &operand_1, &result_dest);
383 if (show_instr_detail_level == 2 ){
384 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_1 %u",
385 operand_address, operand_1);
387 operand_address = next_operand_address;
389 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &operand_2);
390 if (show_instr_detail_level == 2 ){
391 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_2 %u",
392 operand_address, operand_2);
394 if (show_instr_detail_level == 1)
396 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
397 "Addr: %u ## AND (operand_1=%u, operand_2=%u)",
398 current_address, operand_1, operand_2);
400 /* execute the instruction */
401 result = operand_1 & operand_2;
404 buff[result_dest] = msb;
405 buff[result_dest+1] = lsb;
407 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," Loading result %u at %u",
408 result, result_dest);
410 current_address = next_operand_address;
411 goto execute_next_instruction;
415 case SIGCOMP_INSTR_OR: /* 2 OR ($operand_1, %operand_2) */
417 if (show_instr_detail_level == 2 ){
418 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
419 "Addr: %u ## OR(2) (operand_1, operand_2)",
423 operand_address = current_address + 1;
424 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &operand_1, &result_dest);
425 if (show_instr_detail_level == 2 ){
426 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_1 %u",
427 operand_address, operand_1);
429 operand_address = next_operand_address;
431 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &operand_2);
432 if (show_instr_detail_level == 2 ){
433 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_2 %u",
434 operand_address, operand_2);
436 if (show_instr_detail_level == 1)
438 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
439 "Addr: %u ## OR (operand_1=%u, operand_2=%u)",
440 current_address, operand_1, operand_2);
442 /* execute the instruction */
443 result = operand_1 | operand_2;
446 buff[result_dest] = msb;
447 buff[result_dest+1] = lsb;
449 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," Loading result %u at %u",
450 result, result_dest);
452 current_address = next_operand_address;
453 goto execute_next_instruction;
457 case SIGCOMP_INSTR_NOT: /* 3 NOT ($operand_1) */
459 if (show_instr_detail_level == 2 ){
460 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
461 "Addr: %u ## NOT(3) ($operand_1)",
465 operand_address = current_address + 1;
466 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &operand_1, &result_dest);
467 if (show_instr_detail_level == 2 ){
468 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_1 %u",
469 operand_address, operand_1);
471 if (show_instr_detail_level == 1)
473 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
474 "Addr: %u ## NOT (operand_1=%u)",
475 current_address, operand_1);
477 /* execute the instruction */
478 result = operand_1 ^ 0xffff;
481 buff[result_dest] = msb;
482 buff[result_dest+1] = lsb;
484 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," Loading result %u at %u",
485 result, result_dest);
487 current_address = next_operand_address;
488 goto execute_next_instruction;
491 case SIGCOMP_INSTR_LSHIFT: /* 4 LSHIFT ($operand_1, %operand_2) */
493 if (show_instr_detail_level == 2 ){
494 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
495 "Addr: %u ## LSHIFT(4) ($operand_1, operand_2)",
499 operand_address = current_address + 1;
500 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &operand_1, &result_dest);
501 if (show_instr_detail_level == 2 ){
502 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_1 %u",
503 operand_address, operand_1);
505 operand_address = next_operand_address;
507 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &operand_2);
508 if (show_instr_detail_level == 2 ){
509 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_2 %u",
510 operand_address, operand_2);
512 if (show_instr_detail_level == 1)
514 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
515 "Addr: %u ## LSHIFT (operand_1=%u, operand_2=%u)",
516 current_address, operand_1, operand_2);
518 /* execute the instruction */
519 result = operand_1 << operand_2;
522 buff[result_dest] = msb;
523 buff[result_dest+1] = lsb;
525 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," Loading result %u at %u",
526 result, result_dest);
528 current_address = next_operand_address;
529 goto execute_next_instruction;
532 case SIGCOMP_INSTR_RSHIFT: /* 5 RSHIFT ($operand_1, %operand_2) */
534 if (show_instr_detail_level == 2 ){
535 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
536 "Addr: %u ## RSHIFT(5) (operand_1, operand_2)",
540 operand_address = current_address + 1;
541 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &operand_1, &result_dest);
542 if (show_instr_detail_level == 2 ){
543 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_1 %u",
544 operand_address, operand_1);
546 operand_address = next_operand_address;
548 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &operand_2);
549 if (show_instr_detail_level == 2 ){
550 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_2 %u",
551 operand_address, operand_2);
553 if (show_instr_detail_level == 1)
555 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
556 "Addr: %u ## RSHIFT (operand_1=%u, operand_2=%u)",
557 current_address, operand_1, operand_2);
559 /* execute the instruction */
560 result = operand_1 >> operand_2;
563 buff[result_dest] = msb;
564 buff[result_dest+1] = lsb;
566 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," Loading result %u at %u",
567 result, result_dest);
569 current_address = next_operand_address;
570 goto execute_next_instruction;
572 case SIGCOMP_INSTR_ADD: /* 6 ADD ($operand_1, %operand_2) */
574 if (show_instr_detail_level == 2 ){
575 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
576 "Addr: %u ## ADD(6) (operand_1, operand_2)",
580 operand_address = current_address + 1;
581 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &operand_1, &result_dest);
582 if (show_instr_detail_level == 2 ){
583 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_1 %u",
584 operand_address, operand_1);
586 operand_address = next_operand_address;
588 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &operand_2);
589 if (show_instr_detail_level == 2 ){
590 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_2 %u",
591 operand_address, operand_2);
593 if (show_instr_detail_level == 1)
595 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
596 "Addr: %u ## ADD (operand_1=%u, operand_2=%u)",
597 current_address, operand_1, operand_2);
599 /* execute the instruction */
600 result = operand_1 + operand_2;
603 buff[result_dest] = msb;
604 buff[result_dest+1] = lsb;
606 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," Loading result %u at %u",
607 result, result_dest);
609 current_address = next_operand_address;
610 goto execute_next_instruction;
612 case SIGCOMP_INSTR_SUBTRACT: /* 7 SUBTRACT ($operand_1, %operand_2) */
614 if (show_instr_detail_level == 2 ){
615 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
616 "Addr: %u ## SUBTRACT(7) (operand_1, operand_2)",
620 operand_address = current_address + 1;
621 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &operand_1, &result_dest);
622 if (show_instr_detail_level == 2 ){
623 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_1 %u",
624 operand_address, operand_1);
626 operand_address = next_operand_address;
628 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &operand_2);
629 if (show_instr_detail_level == 2 ){
630 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_2 %u",
631 operand_address, operand_2);
633 if (show_instr_detail_level == 1)
635 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
636 "Addr: %u ## SUBTRACT (operand_1=%u, operand_2=%u)",
637 current_address, operand_1, operand_2);
639 /* execute the instruction */
640 result = operand_1 - operand_2;
643 buff[result_dest] = msb;
644 buff[result_dest+1] = lsb;
646 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," Loading result %u at %u",
647 result, result_dest);
649 current_address = next_operand_address;
650 goto execute_next_instruction;
653 case SIGCOMP_INSTR_MULTIPLY: /* 8 MULTIPLY ($operand_1, %operand_2) */
655 if (show_instr_detail_level == 2 ){
656 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
657 "Addr: %u ##MULTIPLY(8) (operand_1, operand_2)",
661 operand_address = current_address + 1;
662 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &operand_1, &result_dest);
663 if (show_instr_detail_level == 2 ){
664 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_1 %u",
665 operand_address, operand_1);
667 operand_address = next_operand_address;
669 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &operand_2);
670 if (show_instr_detail_level == 2 ){
671 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_2 %u",
672 operand_address, operand_2);
674 if (show_instr_detail_level == 1)
676 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
677 "Addr: %u ## MULTIPLY (operand_1=%u, operand_2=%u)",
678 current_address, operand_1, operand_2);
681 * execute the instruction
682 * MULTIPLY (m, n) := m * n (modulo 2^16)
684 if ( operand_2 == 0){
686 goto decompression_failure;
688 result = operand_1 * operand_2;
691 buff[result_dest] = msb;
692 buff[result_dest+1] = lsb;
694 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," Loading result %u at %u",
695 result, result_dest);
697 current_address = next_operand_address;
698 goto execute_next_instruction;
701 case SIGCOMP_INSTR_DIVIDE: /* 9 DIVIDE ($operand_1, %operand_2) */
703 if (show_instr_detail_level == 2 ){
704 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
705 "Addr: %u ## DIVIDE(9) (operand_1, operand_2)",
709 operand_address = current_address + 1;
710 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &operand_1, &result_dest);
711 if (show_instr_detail_level == 2 ){
712 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_1 %u",
713 operand_address, operand_1);
715 operand_address = next_operand_address;
717 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &operand_2);
718 if (show_instr_detail_level == 2 ){
719 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_2 %u",
720 operand_address, operand_2);
722 if (show_instr_detail_level == 1)
724 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
725 "Addr: %u ## DIVIDE (operand_1=%u, operand_2=%u)",
726 current_address, operand_1, operand_2);
729 * execute the instruction
730 * DIVIDE (m, n) := floor(m / n)
731 * Decompression failure occurs if a DIVIDE or REMAINDER instruction
732 * encounters an operand_2 that is zero.
734 if ( operand_2 == 0){
736 goto decompression_failure;
738 result = operand_1 / operand_2;
741 buff[result_dest] = msb;
742 buff[result_dest+1] = lsb;
744 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," Loading result %u at %u",
745 result, result_dest);
747 current_address = next_operand_address;
748 goto execute_next_instruction;
751 case SIGCOMP_INSTR_REMAINDER: /* 10 REMAINDER ($operand_1, %operand_2) */
753 if (show_instr_detail_level == 2 ){
754 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
755 "Addr: %u ## REMAINDER(10) (operand_1, operand_2)",
759 operand_address = current_address + 1;
760 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &operand_1, &result_dest);
761 if (show_instr_detail_level == 2 ){
762 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_1 %u",
763 operand_address, operand_1);
765 operand_address = next_operand_address;
767 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &operand_2);
768 if (show_instr_detail_level == 2 ){
769 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_2 %u",
770 operand_address, operand_2);
772 if (show_instr_detail_level == 1)
774 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
775 "Addr: %u ## REMAINDER (operand_1=%u, operand_2=%u)",
776 current_address, operand_1, operand_2);
779 * execute the instruction
780 * REMAINDER (m, n) := m - n * floor(m / n)
781 * Decompression failure occurs if a DIVIDE or REMAINDER instruction
782 * encounters an operand_2 that is zero.
784 if ( operand_2 == 0){
786 goto decompression_failure;
788 result = operand_1 - operand_2 * (operand_1 / operand_2);
791 buff[result_dest] = msb;
792 buff[result_dest+1] = lsb;
794 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," Loading result %u at %u",
795 result, result_dest);
797 current_address = next_operand_address;
798 goto execute_next_instruction;
800 case SIGCOMP_INSTR_SORT_ASCENDING: /* 11 SORT-ASCENDING (%start, %n, %k) */
802 * used_udvm_cycles = 1 + k * (ceiling(log2(k)) + n)
805 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
806 "Addr: %u ## SORT-ASCENDING(11) (start, n, k))",
809 operand_address = current_address + 1;
810 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Execution of this instruction is NOT implemented");
812 * used_udvm_cycles = 1 + k * (ceiling(log2(k)) + n)
816 case SIGCOMP_INSTR_SORT_DESCENDING: /* 12 SORT-DESCENDING (%start, %n, %k) */
818 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
819 "Addr: %u ## SORT-DESCENDING(12) (start, n, k))",
822 operand_address = current_address + 1;
823 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Execution of this instruction is NOT implemented");
825 * used_udvm_cycles = 1 + k * (ceiling(log2(k)) + n)
828 case SIGCOMP_INSTR_SHA_1: /* 13 SHA-1 (%position, %length, %destination) */
830 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
831 "Addr: %u ## SHA-1(13) (position, length, destination)",
834 operand_address = current_address + 1;
836 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &position);
838 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u position %u",
839 operand_address, position);
841 operand_address = next_operand_address;
844 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &length);
846 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Length %u",
847 operand_address, length);
849 operand_address = next_operand_address;
852 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &ref_destination, &result_dest);
854 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u $destination %u",
855 operand_address, ref_destination);
857 current_address = next_operand_address;
858 used_udvm_cycles = used_udvm_cycles + 1 + length;
859 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Execution of this instruction is NOT implemented");
862 case SIGCOMP_INSTR_LOAD: /* 14 LOAD (%address, %value) */
863 if (show_instr_detail_level == 2 ){
864 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
865 "Addr: %u ## LOAD(14) (%%address, %%value)",
868 operand_address = current_address + 1;
870 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &address);
871 if (show_instr_detail_level == 2 ){
872 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Address %u",
873 operand_address, address);
875 operand_address = next_operand_address;
877 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &value);
878 if (show_instr_detail_level == 1)
880 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
881 "Addr: %u ## LOAD (%%address=%u, %%value=%u)",
882 current_address, address, value);
888 buff[address + 1] = lsb;
891 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Value %u",
892 operand_address, value);
893 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," Loading bytes at %u Value %u 0x%x",
894 address, value, value);
897 current_address = next_operand_address;
898 goto execute_next_instruction;
901 case SIGCOMP_INSTR_MULTILOAD: /* 15 MULTILOAD (%address, #n, %value_0, ..., %value_n-1) */
903 * The MULTILOAD instruction sets a contiguous block of 2-byte words in
904 * the UDVM memory to specified values.
905 * Hmm what if the value to load only takes one byte ? Chose to always load two bytes.
907 if (show_instr_detail_level == 2 ){
908 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
909 "Addr: %u ## MULTILOAD(15) (%%address, #n, value_0, ..., value_n-1)",
912 operand_address = current_address + 1;
914 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &address);
915 if (show_instr_detail_level == 2 ){
916 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Address %u",
917 operand_address, address);
919 operand_address = next_operand_address;
922 next_operand_address = decode_udvm_literal_operand(buff,operand_address, &n);
923 if (show_instr_detail_level == 2 ){
924 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u n %u",
927 if (show_instr_detail_level == 1)
929 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
930 "Addr: %u ## MULTILOAD (%%address=%u, #n=%u, value_0, ..., value_%d)",
931 current_address, address, n, n-1);
933 operand_address = next_operand_address;
934 used_udvm_cycles = used_udvm_cycles + 1 + n;
938 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &value);
943 buff[address + 1] = lsb;
946 length = next_operand_address - operand_address;
949 proto_tree_add_text(udvm_tree, bytecode_tvb, operand_address - 128, length,"Addr: %u Value %5u - Loading bytes at %5u Value %5u 0x%x",
950 operand_address, value, address, value, value);
952 address = address + 2;
953 operand_address = next_operand_address;
955 current_address = next_operand_address;
956 goto execute_next_instruction;
960 case SIGCOMP_INSTR_PUSH: /* 16 PUSH (%value) */
961 if (show_instr_detail_level == 2){
962 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
963 "Addr: %u ## PUSH(16) (value)",
966 operand_address = current_address + 1;
968 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &value);
969 if (show_instr_detail_level == 2){
970 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Value %u",
971 operand_address, value);
973 if (show_instr_detail_level == 1)
975 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
976 "Addr: %u ## PUSH (value=%u)",
977 current_address, value);
979 current_address = next_operand_address;
981 /* Push the value address onto the stack */
982 stack_location = (buff[70] << 8) | buff[71];
983 stack_fill = (buff[stack_location] << 8)
984 | buff[(stack_location+1) & 0xFFFF];
985 address = (stack_location + stack_fill * 2 + 2) & 0xFFFF;
987 buff[address] = (value >> 8) & 0x00FF;
988 buff[(address+1) & 0xFFFF] = value & 0x00FF;
990 stack_fill = (stack_fill + 1) & 0xFFFF;
991 buff[stack_location] = (stack_fill >> 8) & 0x00FF;
992 buff[(stack_location+1) & 0xFFFF] = stack_fill & 0x00FF;
995 goto execute_next_instruction;
999 case SIGCOMP_INSTR_POP: /* 17 POP (%address) */
1000 if (show_instr_detail_level == 2){
1001 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1002 "Addr: %u ## POP(16) (value)",
1005 operand_address = current_address + 1;
1007 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &destination);
1008 if (show_instr_detail_level == 2){
1009 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Value %u",
1010 operand_address, destination);
1012 if (show_instr_detail_level == 1)
1014 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1015 "Addr: %u ## POP (address=%u)",
1016 current_address, destination);
1018 current_address = next_operand_address;
1020 /* Pop value from the top of the stack */
1021 stack_location = (buff[70] << 8) | buff[71];
1022 stack_fill = (buff[stack_location] << 8)
1023 | buff[(stack_location+1) & 0xFFFF];
1024 if (stack_fill == 0)
1027 goto decompression_failure;
1030 stack_fill = (stack_fill - 1) & 0xFFFF;
1031 buff[stack_location] = (stack_fill >> 8) & 0x00FF;
1032 buff[(stack_location+1) & 0xFFFF] = stack_fill & 0x00FF;
1034 address = (stack_location + stack_fill * 2 + 2) & 0xFFFF;
1035 value = (buff[address] << 8)
1036 | buff[(address+1) & 0xFFFF];
1038 /* ... and store the popped value. */
1039 buff[destination] = (value >> 8) & 0x00FF;
1040 buff[(destination+1) & 0xFFFF] = value & 0x00FF;
1043 goto execute_next_instruction;
1047 case SIGCOMP_INSTR_COPY: /* 18 COPY (%position, %length, %destination) */
1048 if (show_instr_detail_level == 2 ){
1049 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1050 "Addr: %u ## COPY(18) (position, length, destination)",
1053 operand_address = current_address + 1;
1055 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &position);
1056 if (show_instr_detail_level == 2 ){
1057 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u position %u",
1058 operand_address, position);
1060 operand_address = next_operand_address;
1063 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &length);
1064 if (show_instr_detail_level == 2 ){
1065 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Length %u",
1066 operand_address, length);
1068 operand_address = next_operand_address;
1071 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &destination);
1072 if (show_instr_detail_level == 2 ){
1073 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Destination %u",
1074 operand_address, destination);
1076 if (show_instr_detail_level == 1)
1078 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1079 "Addr: %u ## COPY (position=%u, length=%u, destination=%u)",
1080 current_address, position, length, destination);
1082 current_address = next_operand_address;
1086 * The string of bytes is copied in ascending order of memory address,
1087 * respecting the bounds set by byte_copy_left and byte_copy_right.
1088 * More precisely, if a byte is copied from/to Address m then the next
1089 * byte is copied from/to Address n where n is calculated as follows:
1091 * Set k := m + 1 (modulo 2^16)
1092 * If k = byte_copy_right then set n := byte_copy_left, else set n := k
1098 byte_copy_right = buff[66] << 8;
1099 byte_copy_right = byte_copy_right | buff[67];
1100 byte_copy_left = buff[64] << 8;
1101 byte_copy_left = byte_copy_left | buff[65];
1102 if (print_level_2 ){
1103 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
1104 " byte_copy_right = %u", byte_copy_right);
1107 while ( n < length ){
1108 buff[k] = buff[position];
1109 if (print_level_2 ){
1110 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
1111 " Copying value: %u (0x%x) to Addr: %u",
1112 buff[position], buff[position], k);
1114 position = ( position + 1 ) & 0xffff;
1115 k = ( k + 1 ) & 0xffff;
1119 * Check for circular buffer wrapping after the positions are
1120 * incremented. If either started at BCR then they should continue
1121 * to increment beyond BCR.
1123 if ( k == byte_copy_right ){
1126 if ( position == byte_copy_right ){
1127 position = byte_copy_left;
1130 used_udvm_cycles = used_udvm_cycles + 1 + length;
1131 goto execute_next_instruction;
1134 case SIGCOMP_INSTR_COPY_LITERAL: /* 19 COPY-LITERAL (%position, %length, $destination) */
1135 if (show_instr_detail_level == 2 ){
1136 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1137 "Addr: %u ## COPY-LITERAL(19) (position, length, $destination)",
1140 operand_address = current_address + 1;
1142 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &position);
1143 if (show_instr_detail_level == 2 ){
1144 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u position %u",
1145 operand_address, position);
1147 operand_address = next_operand_address;
1150 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &length);
1151 if (show_instr_detail_level == 2 ){
1152 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Length %u",
1153 operand_address, length);
1155 operand_address = next_operand_address;
1159 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &ref_destination, &result_dest);
1160 if (show_instr_detail_level == 2 ){
1161 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u destination %u",
1162 operand_address, ref_destination);
1164 if (show_instr_detail_level == 1)
1166 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1167 "Addr: %u ## COPY-LITERAL (position=%u, length=%u, $destination=%u)",
1168 current_address, position, length, destination);
1170 current_address = next_operand_address;
1176 * The string of bytes is copied in ascending order of memory address,
1177 * respecting the bounds set by byte_copy_left and byte_copy_right.
1178 * More precisely, if a byte is copied from/to Address m then the next
1179 * byte is copied from/to Address n where n is calculated as follows:
1181 * Set k := m + 1 (modulo 2^16)
1182 * If k = byte_copy_right then set n := byte_copy_left, else set n := k
1187 k = ref_destination;
1188 byte_copy_right = buff[66] << 8;
1189 byte_copy_right = byte_copy_right | buff[67];
1190 byte_copy_left = buff[64] << 8;
1191 byte_copy_left = byte_copy_left | buff[65];
1192 if (print_level_2 ){
1193 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
1194 " byte_copy_right = %u", byte_copy_right);
1196 while ( n < length ){
1198 buff[k] = buff[position];
1199 if (print_level_2 ){
1200 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
1201 " Copying value: %u (0x%x) to Addr: %u",
1202 buff[position], buff[position], k);
1204 position = ( position + 1 ) & 0xffff;
1205 k = ( k + 1 ) & 0xffff;
1209 * Check for circular buffer wrapping after the positions are
1210 * incremented. It is important that k cannot be left set
1211 * to BCR. Also, if either started at BCR then they should continue
1212 * to increment beyond BCR.
1214 if ( k == byte_copy_right ){
1217 if ( position == byte_copy_right ){
1218 position = byte_copy_left;
1221 buff[result_dest] = k >> 8;
1222 buff[result_dest + 1] = k & 0x00ff;
1224 used_udvm_cycles = used_udvm_cycles + 1 + length;
1225 goto execute_next_instruction;
1228 case SIGCOMP_INSTR_COPY_OFFSET: /* 20 COPY-OFFSET (%offset, %length, $destination) */
1229 if (show_instr_detail_level == 2 ){
1230 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1231 "Addr: %u ## COPY-OFFSET(20) (offset, length, $destination)",
1234 operand_address = current_address + 1;
1236 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &multy_offset);
1237 if (show_instr_detail_level == 2 ){
1238 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u offset %u",
1239 operand_address, multy_offset);
1241 operand_address = next_operand_address;
1244 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &length);
1245 if (show_instr_detail_level == 2 ){
1246 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Length %u",
1247 operand_address, length);
1249 operand_address = next_operand_address;
1253 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &ref_destination, &result_dest);
1254 if (show_instr_detail_level == 2 ){
1255 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u $destination %u",
1256 operand_address, ref_destination);
1259 if (show_instr_detail_level == 1)
1261 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1262 "Addr: %u ## COPY-OFFSET (offset=%u, length=%u, $destination=%u)",
1263 current_address, multy_offset, length, result_dest);
1265 current_address = next_operand_address;
1267 /* Execute the instruction:
1268 * To derive the value of the position operand, starting at the memory
1269 * address specified by destination, the UDVM counts backwards a total
1270 * of offset memory addresses.
1272 * If the memory address specified in byte_copy_left is reached, the
1273 * next memory address is taken to be (byte_copy_right - 1) modulo 2^16.
1275 byte_copy_left = buff[64] << 8;
1276 byte_copy_left = byte_copy_left | buff[65];
1277 byte_copy_right = buff[66] << 8;
1278 byte_copy_right = byte_copy_right | buff[67];
1281 * In order to work out the position, simple arithmetic is tricky
1282 * to apply because there some nasty corner cases. A simple loop
1283 * is inefficient but the logic is simple.
1285 * FUTURE: This could be optimised.
1287 for (position = ref_destination, i = 0; i < multy_offset; i++)
1289 if ( position == byte_copy_left )
1291 position = (byte_copy_right - 1) & 0xffff;
1295 position = (position - 1) & 0xffff;
1299 if (print_level_2 ){
1300 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
1301 " byte_copy_left = %u byte_copy_right = %u position= %u",
1302 byte_copy_left, byte_copy_right, position);
1304 /* The COPY-OFFSET instruction then behaves as a COPY-LITERAL
1305 * instruction, taking the value of the position operand to be the last
1306 * memory address reached in the above step.
1312 * The string of bytes is copied in ascending order of memory address,
1313 * respecting the bounds set by byte_copy_left and byte_copy_right.
1314 * More precisely, if a byte is copied from/to Address m then the next
1315 * byte is copied from/to Address n where n is calculated as follows:
1317 * Set k := m + 1 (modulo 2^16)
1318 * If k = byte_copy_right then set n := byte_copy_left, else set n := k
1323 k = ref_destination;
1324 if (print_level_2 ){
1325 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
1326 " byte_copy_left = %u byte_copy_right = %u", byte_copy_left, byte_copy_right);
1328 while ( n < length ){
1329 buff[k] = buff[position];
1330 if (print_level_2 ){
1331 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
1332 " Copying value: %5u (0x%x) from Addr: %u to Addr: %u",
1333 buff[position], buff[position],(position), k);
1336 k = ( k + 1 ) & 0xffff;
1337 position = ( position + 1 ) & 0xffff;
1340 * Check for circular buffer wrapping after the positions are
1341 * incremented. It is important that k cannot be left set
1342 * to BCR. Also, if either started at BCR then they should continue
1343 * to increment beyond BCR.
1345 if ( k == byte_copy_right ){
1348 if ( position == byte_copy_right ){
1349 position = byte_copy_left;
1352 buff[result_dest] = k >> 8;
1353 buff[result_dest + 1] = k & 0x00ff;
1354 used_udvm_cycles = used_udvm_cycles + 1 + length;
1355 goto execute_next_instruction;
1358 case SIGCOMP_INSTR_MEMSET: /* 21 MEMSET (%address, %length, %start_value, %offset) */
1359 if (show_instr_detail_level == 2 ){
1360 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1361 "Addr: %u ## MEMSET(21) (address, length, start_value, offset)",
1364 operand_address = current_address + 1;
1367 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &address);
1368 if (show_instr_detail_level == 2 ){
1369 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Address %u",
1370 operand_address, address);
1372 operand_address = next_operand_address;
1375 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &length);
1376 if (show_instr_detail_level == 2 ){
1377 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Length %u",
1378 operand_address, length);
1380 operand_address = next_operand_address;
1382 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &start_value);
1383 if (show_instr_detail_level == 2 ){
1384 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u start_value %u",
1385 operand_address, start_value);
1387 operand_address = next_operand_address;
1390 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &multy_offset);
1391 if (show_instr_detail_level == 2 ){
1392 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u offset %u",
1393 operand_address, multy_offset);
1395 if (show_instr_detail_level == 1)
1397 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1398 "Addr: %u ## MEMSET (address=%u, length=%u, start_value=%u, offset=%u)",
1399 current_address, address, length, start_value, multy_offset);
1401 current_address = next_operand_address;
1402 /* exetute the instruction
1403 * The sequence of values used by the MEMSET instruction is specified by
1404 * the following formula:
1406 * Seq[n] := (start_value + n * offset) modulo 256
1410 byte_copy_right = buff[66] << 8;
1411 byte_copy_right = byte_copy_right | buff[67];
1412 byte_copy_left = buff[64] << 8;
1413 byte_copy_left = byte_copy_left | buff[65];
1414 if (print_level_2 ){
1415 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
1416 " byte_copy_left = %u byte_copy_right = %u", byte_copy_left, byte_copy_right);
1418 while ( n < length ){
1419 if ( k == byte_copy_right ){
1422 buff[k] = (start_value + ( n * multy_offset)) & 0xff;
1423 if (print_level_2 ){
1424 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
1425 " Storing value: %u (0x%x) at Addr: %u",
1426 buff[k], buff[k], k);
1428 k = ( k + 1 ) & 0xffff;
1431 used_udvm_cycles = used_udvm_cycles + 1 + length;
1432 goto execute_next_instruction;
1436 case SIGCOMP_INSTR_JUMP: /* 22 JUMP (@address) */
1437 if (show_instr_detail_level == 2 ){
1438 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1439 "Addr: %u ## JUMP(22) (@address)",
1442 operand_address = current_address + 1;
1444 /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
1445 next_operand_address = decode_udvm_address_operand(buff,operand_address, &at_address, current_address);
1446 if (show_instr_detail_level == 2 ){
1447 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u @Address %u",
1448 operand_address, at_address);
1450 if (show_instr_detail_level == 1)
1452 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1453 "Addr: %u ## JUMP (@address=%u)",
1454 current_address, at_address);
1456 current_address = at_address;
1458 goto execute_next_instruction;
1461 case SIGCOMP_INSTR_COMPARE: /* 23 */
1462 /* COMPARE (%value_1, %value_2, @address_1, @address_2, @address_3)
1464 if (show_instr_detail_level == 2 ){
1465 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1466 "Addr: %u ## COMPARE(23) (value_1, value_2, @address_1, @address_2, @address_3)",
1469 operand_address = current_address + 1;
1472 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &value_1);
1473 if (show_instr_detail_level == 2 ){
1474 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Value %u",
1475 operand_address, value_1);
1477 operand_address = next_operand_address;
1480 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &value_2);
1481 if (show_instr_detail_level == 2 ){
1482 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Value %u",
1483 operand_address, value_2);
1485 operand_address = next_operand_address;
1488 /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
1489 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &at_address_1);
1490 at_address_1 = ( current_address + at_address_1) & 0xffff;
1491 if (show_instr_detail_level == 2 ){
1492 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u @Address %u",
1493 operand_address, at_address_1);
1495 operand_address = next_operand_address;
1499 /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
1500 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &at_address_2);
1501 at_address_2 = ( current_address + at_address_2) & 0xffff;
1502 if (show_instr_detail_level == 2 ){
1503 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u @Address %u",
1504 operand_address, at_address_2);
1506 operand_address = next_operand_address;
1509 /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
1510 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &at_address_3);
1511 at_address_3 = ( current_address + at_address_3) & 0xffff;
1512 if (show_instr_detail_level == 2 ){
1513 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u @Address %u",
1514 operand_address, at_address_3);
1516 if (show_instr_detail_level == 1)
1518 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1519 "Addr: %u ## COMPARE (value_1=%u, value_2=%u, @address_1=%u, @address_2=%u, @address_3=%u)",
1520 current_address, value_1, value_2, at_address_1, at_address_2, at_address_3);
1522 /* execute the instruction
1523 * If value_1 < value_2 then the UDVM continues instruction execution at
1524 * the memory address specified by address 1. If value_1 = value_2 then
1525 * it jumps to the address specified by address_2. If value_1 > value_2
1526 * then it jumps to the address specified by address_3.
1528 if ( value_1 < value_2 )
1529 current_address = at_address_1;
1530 if ( value_1 == value_2 )
1531 current_address = at_address_2;
1532 if ( value_1 > value_2 )
1533 current_address = at_address_3;
1535 goto execute_next_instruction;
1538 case SIGCOMP_INSTR_CALL: /* 24 CALL (@address) (PUSH addr )*/
1539 if (show_instr_detail_level == 2){
1540 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1541 "Addr: %u ## CALL(24) (@address) (PUSH addr )",
1544 operand_address = current_address + 1;
1546 next_operand_address = decode_udvm_address_operand(buff,operand_address, &at_address, current_address);
1547 if (show_instr_detail_level == 2 ){
1548 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u @Address %u",
1549 operand_address, at_address);
1551 if (show_instr_detail_level == 1)
1553 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1554 "Addr: %u ## CALL (@address=%u)",
1555 current_address, at_address);
1557 current_address = next_operand_address;
1559 /* Push the current address onto the stack */
1560 stack_location = (buff[70] << 8) | buff[71];
1561 stack_fill = (buff[stack_location] << 8)
1562 | buff[(stack_location+1) & 0xFFFF];
1563 address = (stack_location + stack_fill * 2 + 2) & 0xFFFF;
1564 buff[address] = (current_address >> 8) & 0x00FF;
1565 buff[(address+1) & 0xFFFF] = current_address & 0x00FF;
1567 stack_fill = (stack_fill + 1) & 0xFFFF;
1568 buff[stack_location] = (stack_fill >> 8) & 0x00FF;
1569 buff[(stack_location+1) & 0xFFFF] = stack_fill & 0x00FF;
1571 /* ... and jump to the destination address */
1572 current_address = at_address;
1575 goto execute_next_instruction;
1579 case SIGCOMP_INSTR_RETURN: /* 25 POP and return */
1580 if (print_level_1 || show_instr_detail_level == 1){
1581 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1582 "Addr: %u ## POP(25) and return",
1586 /* Pop value from the top of the stack */
1587 stack_location = (buff[70] << 8) | buff[71];
1588 stack_fill = (buff[stack_location] << 8)
1589 | buff[(stack_location+1) & 0xFFFF];
1590 if (stack_fill == 0)
1593 goto decompression_failure;
1596 stack_fill = (stack_fill - 1) & 0xFFFF;
1597 buff[stack_location] = (stack_fill >> 8) & 0x00FF;
1598 buff[(stack_location+1) & 0xFFFF] = stack_fill & 0x00FF;
1600 address = (stack_location + stack_fill * 2 + 2) & 0xFFFF;
1601 at_address = (buff[address] << 8)
1602 | buff[(address+1) & 0xFFFF];
1604 /* ... and set the PC to the popped value */
1605 current_address = at_address;
1608 goto execute_next_instruction;
1612 case SIGCOMP_INSTR_SWITCH: /* 26 SWITCH (#n, %j, @address_0, @address_1, ... , @address_n-1) */
1614 * When a SWITCH instruction is encountered the UDVM reads the value of
1615 * j. It then continues instruction execution at the address specified
1618 * Decompression failure occurs if j specifies a value of n or more, or
1619 * if the address lies beyond the overall UDVM memory size.
1621 instruction_address = current_address;
1622 if (print_level_1 ){
1623 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1624 "Addr: %u ## SWITCH (#n, j, @address_0, @address_1, ... , @address_n-1))",
1627 operand_address = current_address + 1;
1629 * Number of addresses in the instruction
1631 next_operand_address = decode_udvm_literal_operand(buff,operand_address, &n);
1632 if (print_level_1 ){
1633 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u n %u",
1634 operand_address, n);
1636 operand_address = next_operand_address;
1638 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &j);
1639 if (print_level_1 ){
1640 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u j %u",
1641 operand_address, j);
1643 operand_address = next_operand_address;
1647 /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
1648 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &at_address_1);
1649 at_address_1 = ( instruction_address + at_address_1) & 0xffff;
1650 if (print_level_1 ){
1651 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u @Address %u",
1652 operand_address, at_address_1);
1655 current_address = at_address_1;
1657 operand_address = next_operand_address;
1660 /* Check decompression failure */
1661 if ( ( j == n ) || ( j > n )){
1663 goto decompression_failure;
1665 if ( current_address > UDVM_MEMORY_SIZE ){
1667 goto decompression_failure;
1669 used_udvm_cycles = used_udvm_cycles + 1 + n;
1671 goto execute_next_instruction;
1674 case SIGCOMP_INSTR_CRC: /* 27 CRC (%value, %position, %length, @address) */
1675 if (print_level_1 ){
1676 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1677 "Addr: %u ## CRC (value, position, length, @address)",
1681 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &value);
1682 if (print_level_1 ){
1683 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Value %u",
1684 operand_address, value);
1687 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &position);
1688 if (print_level_1 ){
1689 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u position %u",
1690 operand_address, position);
1692 operand_address = next_operand_address;
1695 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &length);
1696 if (print_level_1 ){
1697 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Length %u",
1698 operand_address, length);
1700 operand_address = next_operand_address;
1703 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &at_address);
1704 at_address = ( current_address + at_address) & 0xffff;
1705 if (print_level_1 ){
1706 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u @Address %u",
1707 operand_address, at_address);
1709 /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
1710 used_udvm_cycles = used_udvm_cycles + 1 + length;
1712 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Execution of this instruction is NOT implemented");
1716 case SIGCOMP_INSTR_INPUT_BYTES: /* 28 INPUT-BYTES (%length, %destination, @address) */
1717 if (show_instr_detail_level == 2 ){
1718 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1719 "Addr: %u ## INPUT-BYTES(28) length, destination, @address)",
1722 operand_address = current_address + 1;
1724 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &length);
1725 if (show_instr_detail_level == 2 ){
1726 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Length %u",
1727 operand_address, length);
1729 operand_address = next_operand_address;
1732 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &destination);
1733 if (show_instr_detail_level == 2 ){
1734 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Destination %u",
1735 operand_address, destination);
1737 operand_address = next_operand_address;
1740 /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
1741 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &at_address);
1742 at_address = ( current_address + at_address) & 0xffff;
1743 if (show_instr_detail_level == 2 ){
1744 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u @Address %u",
1745 operand_address, at_address);
1747 if (show_instr_detail_level == 1)
1749 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1750 "Addr: %u ## INPUT-BYTES length=%u, destination=%u, @address=%u)",
1751 current_address, length, destination, at_address);
1753 /* execute the instruction TODO insert checks
1757 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1758 * | byte_copy_left | 64 - 65
1759 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1760 * | byte_copy_right | 66 - 67
1761 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1762 * | input_bit_order | 68 - 69
1763 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1764 * | stack_location | 70 - 71
1765 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1767 * Figure 7: Memory addresses of the UDVM registers
1771 * The string of bytes is copied in ascending order of memory address,
1772 * respecting the bounds set by byte_copy_left and byte_copy_right.
1773 * More precisely, if a byte is copied from/to Address m then the next
1774 * byte is copied from/to Address n where n is calculated as follows:
1776 * Set k := m + 1 (modulo 2^16)
1777 * If k = byte_copy_right then set n := byte_copy_left, else set n := k
1783 byte_copy_right = buff[66] << 8;
1784 byte_copy_right = byte_copy_right | buff[67];
1785 byte_copy_left = buff[64] << 8;
1786 byte_copy_left = byte_copy_left | buff[65];
1787 if (print_level_1 ){
1788 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
1789 " byte_copy_right = %u", byte_copy_right);
1791 /* clear out remaining bits if any */
1794 /* operand_address used as dummy */
1795 while ( n < length ){
1796 if (input_address > ( msg_end - 1)){
1797 current_address = at_address;
1799 goto execute_next_instruction;
1802 if ( k == byte_copy_right ){
1805 octet = tvb_get_guint8(message_tvb, input_address);
1807 if (print_level_1 ){
1808 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
1809 " Loading value: %u (0x%x) at Addr: %u", octet, octet, k);
1813 * If the instruction requests data that lies beyond the end of the
1814 * SigComp message, no data is returned. Instead the UDVM moves program
1815 * execution to the address specified by the address operand.
1819 k = ( k + 1 ) & 0xffff;
1822 used_udvm_cycles = used_udvm_cycles + 1 + length;
1823 current_address = next_operand_address;
1824 goto execute_next_instruction;
1826 case SIGCOMP_INSTR_INPUT_BITS:/* 29 INPUT-BITS (%length, %destination, @address) */
1828 * The length operand indicates the requested number of bits.
1829 * Decompression failure occurs if this operand does not lie between 0
1832 * The destination operand specifies the memory address to which the
1833 * compressed data should be copied. Note that the requested bits are
1834 * interpreted as a 2-byte integer ranging from 0 to 2^length - 1, as
1835 * explained in Section 8.2.
1837 * If the instruction requests data that lies beyond the end of the
1838 * SigComp message, no data is returned. Instead the UDVM moves program
1839 * execution to the address specified by the address operand.
1842 if (show_instr_detail_level == 2 ){
1843 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1844 "Addr: %u ## INPUT-BITS(29) (length, destination, @address)",
1847 operand_address = current_address + 1;
1850 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &length);
1851 if (show_instr_detail_level == 2 ){
1852 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u length %u",
1853 operand_address, length);
1855 operand_address = next_operand_address;
1857 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &destination);
1858 if (show_instr_detail_level == 2 ){
1859 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Destination %u",
1860 operand_address, destination);
1862 operand_address = next_operand_address;
1865 /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
1866 next_operand_address = decode_udvm_address_operand(buff,operand_address, &at_address, current_address);
1867 if (show_instr_detail_level == 2 ){
1868 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u @Address %u",
1869 operand_address, at_address);
1871 if (show_instr_detail_level == 1)
1873 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1874 "Addr: %u ## INPUT-BITS length=%u, destination=%u, @address=%u)",
1875 current_address, length, destination, at_address);
1877 current_address = next_operand_address;
1880 * Execute actual instr.
1881 * The input_bit_order register contains the following three flags:
1884 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1885 * | reserved |F|H|P| 68 - 69
1886 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1888 input_bit_order = buff[68] << 8;
1889 input_bit_order = input_bit_order | buff[69];
1891 * If the instruction requests data that lies beyond the end of the
1892 * SigComp message, no data is returned. Instead the UDVM moves program
1893 * execution to the address specified by the address operand.
1898 goto decompression_failure;
1900 if ( input_bit_order > 7 ){
1902 goto decompression_failure;
1906 * Transfer F bit to bit_order to tell decomp dispatcher which bit order to use
1908 bit_order = ( input_bit_order & 0x0004 ) >> 2;
1909 value = decomp_dispatch_get_bits( message_tvb, udvm_tree, bit_order,
1910 buff, &old_input_bit_order, &remaining_bits,
1911 &input_bits, &input_address, length, &result_code, msg_end);
1912 if ( result_code == 11 ){
1913 used_udvm_cycles = used_udvm_cycles + 1;
1914 current_address = at_address;
1915 goto execute_next_instruction;
1918 lsb = value & 0x00ff;
1919 buff[destination] = msb;
1920 buff[destination + 1]=lsb;
1921 if (print_level_1 ){
1922 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
1923 " Loading value: %u (0x%x) at Addr: %u, remaining_bits: %u", value, value, destination, remaining_bits);
1926 used_udvm_cycles = used_udvm_cycles + 1;
1927 goto execute_next_instruction;
1929 case SIGCOMP_INSTR_INPUT_HUFFMAN: /* 30 */
1931 * INPUT-HUFFMAN (%destination, @address, #n, %bits_1, %lower_bound_1,
1932 * %upper_bound_1, %uncompressed_1, ... , %bits_n, %lower_bound_n,
1933 * %upper_bound_n, %uncompressed_n)
1935 if (show_instr_detail_level == 2 ){
1936 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1937 "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)",
1940 operand_address = current_address + 1;
1943 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &destination);
1944 if (show_instr_detail_level == 2 ){
1945 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Destination %u",
1946 operand_address, destination);
1948 operand_address = next_operand_address;
1951 /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
1952 next_operand_address = decode_udvm_address_operand(buff,operand_address, &at_address, current_address);
1953 if (show_instr_detail_level == 2 ){
1954 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u @Address %u",
1955 operand_address, at_address);
1957 operand_address = next_operand_address;
1960 next_operand_address = decode_udvm_literal_operand(buff,operand_address, &n);
1961 if (show_instr_detail_level == 2 ){
1962 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u n %u",
1963 operand_address, n);
1965 operand_address = next_operand_address;
1966 if (show_instr_detail_level == 1)
1968 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1969 "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)",
1970 current_address, destination, at_address, n, n, n, n, n);
1973 used_udvm_cycles = used_udvm_cycles + 1 + n;
1976 * Note that if n = 0 then the INPUT-HUFFMAN instruction is ignored and
1977 * program execution resumes at the following instruction.
1978 * Decompression failure occurs if (bits_1 + ... + bits_n) > 16.
1980 * In all other cases, the behavior of the INPUT-HUFFMAN instruction is
1983 * 1. Set j := 1 and set H := 0.
1985 * 2. Request bits_j compressed bits. Interpret the returned bits as an
1986 * integer k from 0 to 2^bits_j - 1, as explained in Section 8.2.
1988 * 3. Set H := H * 2^bits_j + k.
1990 * 4. If data is requested that lies beyond the end of the SigComp
1991 * message, terminate the INPUT-HUFFMAN instruction and move program
1992 * execution to the memory address specified by the address operand.
1994 * 5. If (H < lower_bound_j) or (H > upper_bound_j) then set j := j + 1.
1995 * Then go back to Step 2, unless j > n in which case decompression
1998 * 6. Copy (H + uncompressed_j - lower_bound_j) modulo 2^16 to the
1999 * memory address specified by the destination operand.
2003 * The input_bit_order register contains the following three flags:
2006 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2007 * | reserved |F|H|P| 68 - 69
2008 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2010 * Transfer H bit to bit_order to tell decomp dispatcher which bit order to use
2012 input_bit_order = buff[68] << 8;
2013 input_bit_order = input_bit_order | buff[69];
2014 bit_order = ( input_bit_order & 0x0002 ) >> 1;
2019 outside_huffman_boundaries = TRUE;
2020 print_in_loop = print_level_3;
2023 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &bits_n);
2024 if (print_in_loop ){
2025 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u bits_n %u",
2026 operand_address, bits_n);
2028 operand_address = next_operand_address;
2030 /* %lower_bound_n */
2031 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &lower_bound_n);
2032 if (print_in_loop ){
2033 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u lower_bound_n %u",
2034 operand_address, lower_bound_n);
2036 operand_address = next_operand_address;
2037 /* %upper_bound_n */
2038 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &upper_bound_n);
2039 if (print_in_loop ){
2040 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u upper_bound_n %u",
2041 operand_address, upper_bound_n);
2043 operand_address = next_operand_address;
2044 /* %uncompressed_n */
2045 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &uncompressed_n);
2046 if (print_in_loop ){
2047 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u uncompressed_n %u",
2048 operand_address, uncompressed_n);
2050 operand_address = next_operand_address;
2051 /* execute instruction */
2052 if ( outside_huffman_boundaries ) {
2054 * 2. Request bits_j compressed bits. Interpret the returned bits as an
2055 * integer k from 0 to 2^bits_j - 1, as explained in Section 8.2.
2057 k = decomp_dispatch_get_bits( message_tvb, udvm_tree, bit_order,
2058 buff, &old_input_bit_order, &remaining_bits,
2059 &input_bits, &input_address, bits_n, &result_code, msg_end);
2060 if ( result_code == 11 ){
2062 * 4. If data is requested that lies beyond the end of the SigComp
2063 * message, terminate the INPUT-HUFFMAN instruction and move program
2064 * execution to the memory address specified by the address operand.
2066 current_address = at_address;
2067 goto execute_next_instruction;
2071 * 3. Set H := H * 2^bits_j + k.
2072 * [In practice is a shift+OR operation.]
2075 H = (H << bits_n) | k;
2076 if (print_level_3 ){
2077 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," Set H(%u) := H(%u) * 2^bits_j(%u) + k(%u)",
2078 H ,oldH, 1<<bits_n,k);
2082 * 5. If (H < lower_bound_j) or (H > upper_bound_j) then set j := j + 1.
2083 * Then go back to Step 2, unless j > n in which case decompression
2086 if ((H < lower_bound_n) || (H > upper_bound_n)){
2087 outside_huffman_boundaries = TRUE;
2089 outside_huffman_boundaries = FALSE;
2090 print_in_loop = FALSE;
2092 * 6. Copy (H + uncompressed_j - lower_bound_j) modulo 2^16 to the
2093 * memory address specified by the destination operand.
2095 if (print_level_2 ){
2096 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2097 " H(%u) = H(%u) + uncompressed_n(%u) - lower_bound_n(%u)",
2098 (H + uncompressed_n - lower_bound_n ),H, uncompressed_n, lower_bound_n);
2100 H = H + uncompressed_n - lower_bound_n;
2103 buff[destination] = msb;
2104 buff[destination + 1]=lsb;
2105 if (print_level_1 ){
2106 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
2107 " Loading H: %u (0x%x) at Addr: %u,j = %u remaining_bits: %u",
2108 H, H, destination,( n - m + 1 ), remaining_bits);
2117 if ( outside_huffman_boundaries ) {
2119 goto decompression_failure;
2122 current_address = next_operand_address;
2123 goto execute_next_instruction;
2126 case SIGCOMP_INSTR_STATE_ACCESS: /* 31 */
2127 /* STATE-ACCESS (%partial_identifier_start, %partial_identifier_length,
2128 * %state_begin, %state_length, %state_address, %state_instruction)
2130 if (show_instr_detail_level == 2 ){
2131 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2132 "Addr: %u ## STATE-ACCESS(31) (partial_identifier_start, partial_identifier_length,state_begin, state_length, state_address, state_instruction)",
2135 operand_address = current_address + 1;
2138 * %partial_identifier_start
2140 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &p_id_start);
2141 if (show_instr_detail_level == 2 ){
2142 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u partial_identifier_start %u",
2143 operand_address, p_id_start);
2145 operand_address = next_operand_address;
2148 * %partial_identifier_length
2150 operand_address = next_operand_address;
2151 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &p_id_length);
2152 if (show_instr_detail_level == 2 ){
2153 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u partial_identifier_length %u",
2154 operand_address, p_id_length);
2159 operand_address = next_operand_address;
2160 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_begin);
2161 if (show_instr_detail_level == 2 ){
2162 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_begin %u",
2163 operand_address, state_begin);
2168 operand_address = next_operand_address;
2169 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_length);
2170 if (show_instr_detail_level == 2 ){
2171 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_length %u",
2172 operand_address, state_length);
2177 operand_address = next_operand_address;
2178 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_address);
2179 if (show_instr_detail_level == 2 ){
2180 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_address %u",
2181 operand_address, state_address);
2184 * %state_instruction
2186 operand_address = next_operand_address;
2187 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_instruction);
2188 if (show_instr_detail_level == 2 ){
2189 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_instruction %u",
2190 operand_address, state_instruction);
2192 if (show_instr_detail_level == 1)
2194 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2195 "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)",
2196 current_address, p_id_start, p_id_length, state_begin, state_length, state_address, state_instruction);
2198 current_address = next_operand_address;
2199 byte_copy_right = buff[66] << 8;
2200 byte_copy_right = byte_copy_right | buff[67];
2201 byte_copy_left = buff[64] << 8;
2202 byte_copy_left = byte_copy_left | buff[65];
2203 if (print_level_2 ){
2204 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
2205 " byte_copy_right = %u, byte_copy_left = %u", byte_copy_right,byte_copy_left);
2208 result_code = udvm_state_access(message_tvb, udvm_tree, buff, p_id_start, p_id_length, state_begin, &state_length,
2209 &state_address, &state_instruction, hf_id);
2210 if ( result_code != 0 ){
2211 goto decompression_failure;
2213 used_udvm_cycles = used_udvm_cycles + 1 + state_length;
2214 goto execute_next_instruction;
2216 case SIGCOMP_INSTR_STATE_CREATE: /* 32 */
2218 * STATE-CREATE (%state_length, %state_address, %state_instruction,
2219 * %minimum_access_length, %state_retention_priority)
2221 if (show_instr_detail_level == 2 ){
2222 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2223 "Addr: %u ## STATE-CREATE(32) (state_length, state_address, state_instruction,minimum_access_length, state_retention_priority)",
2226 operand_address = current_address + 1;
2231 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_length);
2232 if (show_instr_detail_level == 2 ){
2233 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_length %u",
2234 operand_address, state_length);
2239 operand_address = next_operand_address;
2240 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_address);
2241 if (show_instr_detail_level == 2 ){
2242 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_address %u",
2243 operand_address, state_address);
2246 * %state_instruction
2248 operand_address = next_operand_address;
2249 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_instruction);
2250 if (show_instr_detail_level == 2 ){
2251 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_instruction %u",
2252 operand_address, state_instruction);
2254 operand_address = next_operand_address;
2256 * %minimum_access_length
2258 operand_address = next_operand_address;
2259 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &minimum_access_length);
2260 if (show_instr_detail_level == 2 ){
2261 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u minimum_access_length %u",
2262 operand_address, minimum_access_length);
2264 operand_address = next_operand_address;
2266 * %state_retention_priority
2268 operand_address = next_operand_address;
2269 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_retention_priority);
2270 if (show_instr_detail_level == 2 ){
2271 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_retention_priority %u",
2272 operand_address, state_retention_priority);
2274 if (show_instr_detail_level == 1)
2276 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2277 "Addr: %u ## STATE-CREATE(32) (state_length=%u, state_address=%u, state_instruction=%u,minimum_access_length=%u, state_retention_priority=%u)",
2278 current_address, state_length, state_address, state_instruction,minimum_access_length, state_retention_priority);
2280 current_address = next_operand_address;
2281 /* Execute the instruction
2282 * TODO Implement the instruction
2284 * Note that the new state item cannot be created until a valid
2285 * compartment identifier has been returned by the application.
2286 * Consequently, when a STATE-CREATE instruction is encountered the UDVM
2287 * simply buffers the five supplied operands until the END-MESSAGE
2288 * instruction is reached. The steps taken at this point are described
2291 * Decompression failure MUST occur if more than four state creation
2292 * requests are made before the END-MESSAGE instruction is encountered.
2293 * Decompression failure also occurs if the minimum_access_length does
2294 * not lie between 6 and 20 inclusive, or if the
2295 * state_retention_priority is 65535.
2297 no_of_state_create++;
2298 if ( no_of_state_create > 4 ){
2300 goto decompression_failure;
2302 if (( minimum_access_length < 6 ) || ( minimum_access_length > 20 )){
2304 goto decompression_failure;
2306 if ( state_retention_priority == 65535 ){
2308 goto decompression_failure;
2310 state_length_buff[no_of_state_create] = state_length;
2311 state_address_buff[no_of_state_create] = state_address;
2312 state_instruction_buff[no_of_state_create] = state_instruction;
2313 state_minimum_access_length_buff[no_of_state_create] = minimum_access_length;
2314 state_state_retention_priority_buff[no_of_state_create] = state_retention_priority;
2315 used_udvm_cycles = used_udvm_cycles + 1 + state_length;
2317 byte_copy_right = buff[66] << 8;
2318 byte_copy_right = byte_copy_right | buff[67];
2319 byte_copy_left = buff[64] << 8;
2320 byte_copy_left = byte_copy_left | buff[65];
2323 while ( n < state_length ){
2324 if ( k == byte_copy_right ){
2329 if (print_level_3 ){
2330 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2331 " Addr: %5u State value: %u (0x%x) ASCII(%s)",
2332 k,buff[k],buff[k],string);
2334 k = ( k + 1 ) & 0xffff;
2339 goto execute_next_instruction;
2341 case SIGCOMP_INSTR_STATE_FREE: /* 33 */
2343 * STATE-FREE (%partial_identifier_start, %partial_identifier_length)
2345 if (show_instr_detail_level == 2 ){
2346 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2347 "Addr: %u ## STATE-FREE (partial_identifier_start, partial_identifier_length)",
2350 operand_address = current_address + 1;
2352 * %partial_identifier_start
2354 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &p_id_start);
2355 if (show_instr_detail_level == 2 ){
2356 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u partial_identifier_start %u",
2357 operand_address, p_id_start);
2359 operand_address = next_operand_address;
2362 * %partial_identifier_length
2364 operand_address = next_operand_address;
2365 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &p_id_length);
2366 if (show_instr_detail_level == 2 ){
2367 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u partial_identifier_length %u",
2368 operand_address, p_id_length);
2370 if (show_instr_detail_level == 1)
2372 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2373 "Addr: %u ## STATE-FREE (partial_identifier_start=%u, partial_identifier_length=%u)",
2374 current_address, p_id_start, p_id_length);
2376 current_address = next_operand_address;
2378 /* Execute the instruction:
2381 udvm_state_free(buff,p_id_start,p_id_length);
2384 goto execute_next_instruction;
2386 case SIGCOMP_INSTR_OUTPUT: /* 34 OUTPUT (%output_start, %output_length) */
2387 if (show_instr_detail_level == 2 ){
2388 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2389 "Addr: %u ## OUTPUT(34) (output_start, output_length)",
2392 operand_address = current_address + 1;
2396 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &output_start);
2397 if (show_instr_detail_level == 2 ){
2398 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u output_start %u",
2399 operand_address, output_start);
2401 operand_address = next_operand_address;
2405 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &output_length);
2406 if (show_instr_detail_level == 2 ){
2407 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u output_length %u",
2408 operand_address, output_length);
2410 if (show_instr_detail_level == 1)
2412 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2413 "Addr: %u ## OUTPUT (output_start=%u, output_length=%u)",
2414 current_address, output_start, output_length);
2416 current_address = next_operand_address;
2419 * Execute instruction
2422 * The string of bytes is copied in ascending order of memory address,
2423 * respecting the bounds set by byte_copy_left and byte_copy_right.
2424 * More precisely, if a byte is copied from/to Address m then the next
2425 * byte is copied from/to Address n where n is calculated as follows:
2427 * Set k := m + 1 (modulo 2^16)
2428 * If k = byte_copy_right then set n := byte_copy_left, else set n := k
2434 byte_copy_right = buff[66] << 8;
2435 byte_copy_right = byte_copy_right | buff[67];
2436 byte_copy_left = buff[64] << 8;
2437 byte_copy_left = byte_copy_left | buff[65];
2438 if (print_level_3 ){
2439 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2440 " byte_copy_right = %u", byte_copy_right);
2442 while ( n < output_length ){
2444 if ( k == byte_copy_right ){
2447 out_buff[output_address] = buff[k];
2451 if (print_level_3 ){
2452 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2453 " Output value: %u (0x%x) ASCII(%s) from Addr: %u ,output to dispatcher position %u",
2454 buff[k],buff[k],format_text(strp,1), k,output_address);
2456 k = ( k + 1 ) & 0xffff;
2460 used_udvm_cycles = used_udvm_cycles + 1 + output_length;
2461 goto execute_next_instruction;
2463 case SIGCOMP_INSTR_END_MESSAGE: /* 35 */
2465 * END-MESSAGE (%requested_feedback_location,
2466 * %returned_parameters_location, %state_length, %state_address,
2467 * %state_instruction, %minimum_access_length,
2468 * %state_retention_priority)
2470 if (show_instr_detail_level == 2 ){
2471 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2472 "Addr: %u ## END-MESSAGE (requested_feedback_location,state_instruction, minimum_access_length,state_retention_priority)",
2475 operand_address = current_address + 1;
2477 /* %requested_feedback_location */
2478 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &requested_feedback_location);
2479 if (show_instr_detail_level == 2 ){
2480 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u requested_feedback_location %u",
2481 operand_address, requested_feedback_location);
2483 operand_address = next_operand_address;
2484 /* returned_parameters_location */
2485 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &returned_parameters_location);
2486 if (show_instr_detail_level == 2 ){
2487 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u returned_parameters_location %u",
2488 operand_address, returned_parameters_location);
2490 operand_address = next_operand_address;
2494 operand_address = next_operand_address;
2495 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_length);
2496 if (show_instr_detail_level == 2 ){
2497 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_length %u",
2498 operand_address, state_length);
2503 operand_address = next_operand_address;
2504 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_address);
2505 if (show_instr_detail_level == 2 ){
2506 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_address %u",
2507 operand_address, state_address);
2510 * %state_instruction
2512 operand_address = next_operand_address;
2513 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_instruction);
2514 if (show_instr_detail_level == 2 ){
2515 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_instruction %u",
2516 operand_address, state_instruction);
2518 operand_address = next_operand_address;
2520 * %minimum_access_length
2522 operand_address = next_operand_address;
2523 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &minimum_access_length);
2524 if (show_instr_detail_level == 2 ){
2525 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u minimum_access_length %u",
2526 operand_address, minimum_access_length);
2528 operand_address = next_operand_address;
2531 * %state_retention_priority
2533 operand_address = next_operand_address;
2534 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_retention_priority);
2535 if (show_instr_detail_level == 2 ){
2536 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_retention_priority %u",
2537 operand_address, state_retention_priority);
2539 if (show_instr_detail_level == 1)
2541 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2542 "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)",
2543 current_address, requested_feedback_location, returned_parameters_location, state_length, state_address, state_instruction, minimum_access_length,state_retention_priority);
2545 current_address = next_operand_address;
2546 /* TODO: This isn't currently totaly correct as END_INSTRUCTION might not create state */
2547 no_of_state_create++;
2548 if ( no_of_state_create > 4 ){
2550 goto decompression_failure;
2552 state_length_buff[no_of_state_create] = state_length;
2553 state_address_buff[no_of_state_create] = state_address;
2554 state_instruction_buff[no_of_state_create] = state_instruction;
2556 state_minimum_access_length_buff[no_of_state_create] = minimum_access_length;
2557 state_state_retention_priority_buff[no_of_state_create] = state_retention_priority;
2559 /* Execute the instruction
2561 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"no_of_state_create %u",no_of_state_create);
2562 if ( no_of_state_create != 0 ){
2563 for( x=0; x < 20; x++){
2564 sha1_digest_buf[x]=0;
2567 byte_copy_right = buff[66] << 8;
2568 byte_copy_right = byte_copy_right | buff[67];
2569 byte_copy_left = buff[64] << 8;
2570 byte_copy_left = byte_copy_left | buff[65];
2571 while ( n < no_of_state_create + 1 ){
2572 sha1buff = g_malloc(state_length_buff[n]+8);
2573 sha1buff[0] = state_length_buff[n] >> 8;
2574 sha1buff[1] = state_length_buff[n] & 0xff;
2575 sha1buff[2] = state_address_buff[n] >> 8;
2576 sha1buff[3] = state_address_buff[n] & 0xff;
2577 sha1buff[4] = state_instruction_buff[n] >> 8;
2578 sha1buff[5] = state_instruction_buff[n] & 0xff;
2579 sha1buff[6] = state_minimum_access_length_buff[n] >> 8;
2580 sha1buff[7] = state_minimum_access_length_buff[n] & 0xff;
2581 if (print_level_3 ){
2582 for( x=0; x < 8; x++){
2583 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"sha1buff %u 0x%x",
2587 k = state_address_buff[n];
2588 for( x=0; x < state_length_buff[n]; x++)
2590 if ( k == byte_copy_right ){
2593 sha1buff[8+x] = buff[k];
2594 k = ( k + 1 ) & 0xffff;
2597 sha1_starts( &ctx );
2598 sha1_update( &ctx, (guint8 *) sha1buff, state_length_buff[n] + 8);
2599 sha1_finish( &ctx, sha1_digest_buf );
2600 if (print_level_3 ){
2601 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"SHA1 digest %s",bytes_to_str(sha1_digest_buf, 20));
2604 udvm_state_create(sha1buff, sha1_digest_buf, state_minimum_access_length_buff[n]);
2605 proto_tree_add_text(udvm_tree,bytecode_tvb, 0, -1,"### Creating state ###");
2606 proto_tree_add_string(udvm_tree,hf_id, bytecode_tvb, 0, 0, bytes_to_str(sha1_digest_buf, state_minimum_access_length_buff[n]));
2615 /* At least something got decompressed, show it */
2616 decomp_tvb = tvb_new_real_data(out_buff,output_address,output_address);
2617 /* Arrange that the allocated packet data copy be freed when the
2620 tvb_set_free_cb( decomp_tvb, g_free );
2622 tvb_set_child_real_data_tvbuff(message_tvb,decomp_tvb);
2623 add_new_data_source(pinfo, decomp_tvb, "Decompressed SigComp message");
2625 proto_tree_add_text(udvm_tree, decomp_tvb, 0, -1,"SigComp message Decompressed");
2627 used_udvm_cycles = used_udvm_cycles + 1 + state_length;
2628 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"maximum_UDVM_cycles %u used_udvm_cycles %u",
2629 maximum_UDVM_cycles, used_udvm_cycles);
2634 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," ### Addr %u Invalid instruction: %u (0x%x)",
2635 current_address,current_instruction,current_instruction);
2640 decompression_failure:
2642 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"DECOMPRESSION FAILURE: %s",
2643 val_to_str(result_code, result_code_vals,"Unknown (%u)"));
2649 /* The simplest operand type is the literal (#), which encodes a
2650 * constant integer from 0 to 65535 inclusive. A literal operand may
2651 * require between 1 and 3 bytes depending on its value.
2652 * Bytecode: Operand value: Range:
2653 * 0nnnnnnn N 0 - 127
2654 * 10nnnnnn nnnnnnnn N 0 - 16383
2655 * 11000000 nnnnnnnn nnnnnnnn N 0 - 65535
2657 * Figure 8: Bytecode for a literal (#) operand
2661 decode_udvm_literal_operand(guint8 *buff,guint operand_address, guint16 *value)
2666 guint offset = operand_address;
2669 bytecode = buff[operand_address];
2670 test_bits = bytecode >> 7;
2671 if (test_bits == 1){
2672 test_bits = bytecode >> 6;
2673 if (test_bits == 2){
2675 * 10nnnnnn nnnnnnnn N 0 - 16383
2677 temp_data = buff[operand_address] & 0x1f;
2678 operand = temp_data << 8;
2679 temp_data = buff[operand_address + 1];
2680 operand = operand | temp_data;
2682 offset = offset + 2;
2686 * 111000000 nnnnnnnn nnnnnnnn N 0 - 65535
2689 temp_data = buff[operand_address] & 0x1f;
2690 operand = temp_data << 8;
2691 temp_data = buff[operand_address + 1];
2692 operand = operand | temp_data;
2694 offset = offset + 2;
2699 * 0nnnnnnn N 0 - 127
2701 operand = ( bytecode & 0x7f);
2711 * The second operand type is the reference ($), which is always used to
2712 * access a 2-byte value located elsewhere in the UDVM memory. The
2713 * bytecode for a reference operand is decoded to be a constant integer
2714 * from 0 to 65535 inclusive, which is interpreted as the memory address
2715 * containing the actual value of the operand.
2716 * Bytecode: Operand value: Range:
2718 * 0nnnnnnn memory[2 * N] 0 - 65535
2719 * 10nnnnnn nnnnnnnn memory[2 * N] 0 - 65535
2720 * 11000000 nnnnnnnn nnnnnnnn memory[N] 0 - 65535
2722 * Figure 9: Bytecode for a reference ($) operand
2725 dissect_udvm_reference_operand(guint8 *buff,guint operand_address, guint16 *value,guint *result_dest)
2729 guint offset = operand_address;
2732 guint16 temp_data16;
2734 bytecode = buff[operand_address];
2735 test_bits = bytecode >> 7;
2736 if (test_bits == 1){
2737 test_bits = bytecode >> 6;
2738 if (test_bits == 2){
2740 * 10nnnnnn nnnnnnnn memory[2 * N] 0 - 65535
2742 temp_data = buff[operand_address] & 0x3f;
2743 operand = temp_data << 8;
2744 temp_data = buff[operand_address + 1];
2745 operand = operand | temp_data;
2746 operand = (operand * 2);
2747 *result_dest = operand;
2748 temp_data16 = buff[operand] << 8;
2749 temp_data16 = temp_data16 | buff[operand+1];
2750 *value = temp_data16;
2751 offset = offset + 2;
2755 * 11000000 nnnnnnnn nnnnnnnn memory[N] 0 - 65535
2758 operand = buff[operand_address] << 8;
2759 operand = operand | buff[operand_address + 1];
2760 *result_dest = operand;
2761 temp_data16 = buff[operand] << 8;
2762 temp_data16 = temp_data16 | buff[operand+1];
2763 *value = temp_data16;
2764 offset = offset + 3;
2769 * 0nnnnnnn memory[2 * N] 0 - 65535
2771 operand = ( bytecode & 0x7f);
2772 operand = (operand * 2);
2773 *result_dest = operand;
2774 temp_data16 = buff[operand] << 8;
2775 temp_data16 = temp_data16 | buff[operand+1];
2776 *value = temp_data16;
2784 * Figure 10: Bytecode for a multitype (%) operand
2785 * Bytecode: Operand value: Range: HEX val
2786 * 00nnnnnn N 0 - 63 0x00
2787 * 01nnnnnn memory[2 * N] 0 - 65535 0x40
2788 * 1000011n 2 ^ (N + 6) 64 , 128 0x86
2789 * 10001nnn 2 ^ (N + 8) 256 , ... , 32768 0x88
2790 * 111nnnnn N + 65504 65504 - 65535 0xe0
2791 * 1001nnnn nnnnnnnn N + 61440 61440 - 65535 0x90
2792 * 101nnnnn nnnnnnnn N 0 - 8191 0xa0
2793 * 110nnnnn nnnnnnnn memory[N] 0 - 65535 0xc0
2794 * 10000000 nnnnnnnn nnnnnnnn N 0 - 65535 0x80
2795 * 10000001 nnnnnnnn nnnnnnnn memory[N] 0 - 65535 0x81
2798 decode_udvm_multitype_operand(guint8 *buff,guint operand_address, guint16 *value)
2802 guint offset = operand_address;
2806 guint16 temp_data16;
2807 guint16 memmory_addr = 0;
2809 bytecode = buff[operand_address];
2810 test_bits = ( bytecode & 0xc0 ) >> 6;
2811 switch (test_bits ){
2816 operand = buff[operand_address];
2818 *g_warning("Reading 0x%x From address %u",operand,offset);
2825 * 01nnnnnn memory[2 * N] 0 - 65535
2827 memmory_addr = ( bytecode & 0x3f) * 2;
2828 temp_data16 = buff[memmory_addr] << 8;
2829 temp_data16 = temp_data16 | buff[memmory_addr+1];
2830 *value = temp_data16;
2834 /* Check tree most significant bits */
2835 test_bits = ( bytecode & 0xe0 ) >> 5;
2836 if ( test_bits == 5 ){
2838 * 101nnnnn nnnnnnnn N 0 - 8191
2840 temp_data = buff[operand_address] & 0x1f;
2841 operand = temp_data << 8;
2842 temp_data = buff[operand_address + 1];
2843 operand = operand | temp_data;
2845 offset = offset + 2;
2847 test_bits = ( bytecode & 0xf0 ) >> 4;
2848 if ( test_bits == 9 ){
2850 * 1001nnnn nnnnnnnn N + 61440 61440 - 65535
2852 temp_data = buff[operand_address] & 0x0f;
2853 operand = temp_data << 8;
2854 temp_data = buff[operand_address + 1];
2855 operand = operand | temp_data;
2856 operand = operand + 61440;
2858 offset = offset + 2;
2860 test_bits = ( bytecode & 0x08 ) >> 3;
2861 if ( test_bits == 1){
2863 * 10001nnn 2 ^ (N + 8) 256 , ... , 32768
2866 result = 1 << ((buff[operand_address] & 0x07) + 8);
2867 operand = result & 0xffff;
2871 test_bits = ( bytecode & 0x0e ) >> 1;
2872 if ( test_bits == 3 ){
2874 * 1000 011n 2 ^ (N + 6) 64 , 128
2876 result = 1 << ((buff[operand_address] & 0x01) + 6);
2877 operand = result & 0xffff;
2882 * 1000 0000 nnnnnnnn nnnnnnnn N 0 - 65535
2883 * 1000 0001 nnnnnnnn nnnnnnnn memory[N] 0 - 65535
2886 temp_data16 = buff[operand_address + 1] << 8;
2887 temp_data16 = temp_data16 | buff[operand_address + 2];
2889 * g_warning("Reading 0x%x From address %u",temp_data16,operand_address);
2891 if ( (bytecode & 0x01) == 1 ){
2892 memmory_addr = temp_data16;
2893 temp_data16 = buff[memmory_addr] << 8;
2894 temp_data16 = temp_data16 | buff[memmory_addr+1];
2896 *value = temp_data16;
2907 test_bits = ( bytecode & 0x20 ) >> 5;
2908 if ( test_bits == 1 ){
2910 * 111nnnnn N + 65504 65504 - 65535
2912 operand = ( buff[operand_address] & 0x1f) + 65504;
2917 * 110nnnnn nnnnnnnn memory[N] 0 - 65535
2919 memmory_addr = buff[operand_address] & 0x1f;
2920 memmory_addr = memmory_addr << 8;
2921 memmory_addr = memmory_addr | buff[operand_address + 1];
2922 temp_data16 = buff[memmory_addr] << 8;
2923 temp_data16 = temp_data16 | buff[memmory_addr+1];
2924 *value = temp_data16;
2926 * g_warning("Reading 0x%x From address %u",temp_data16,memmory_addr);
2938 * The fourth operand type is the address (@). This operand is decoded
2939 * as a multitype operand followed by a further step: the memory address
2940 * of the UDVM instruction containing the address operand is added to
2941 * obtain the correct operand value. So if the operand value from
2942 * Figure 10 is D then the actual operand value of an address is
2943 * calculated as follows:
2945 * operand_value = (memory_address_of_instruction + D) modulo 2^16
2947 * Address operands are always used in instructions that control program
2948 * flow, because they ensure that the UDVM bytecode is position-
2949 * independent code (i.e., it will run independently of where it is
2950 * placed in the UDVM memory).
2953 decode_udvm_address_operand(guint8 *buff,guint operand_address, guint16 *value,guint current_address)
2957 guint next_opreand_address;
2959 next_opreand_address = decode_udvm_multitype_operand(buff, operand_address, &value1);
2960 result = value1 & 0xffff;
2961 result = result + current_address;
2962 *value = result & 0xffff;
2963 return next_opreand_address;
2968 * This is a lookup table used to reverse the bits in a byte.
2970 static guint8 reverse [] = {
2971 0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0,
2972 0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0,
2973 0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8,
2974 0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8,
2975 0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4,
2976 0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4,
2977 0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC,
2978 0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC,
2979 0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2,
2980 0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2,
2981 0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA,
2982 0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA,
2983 0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6,
2984 0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6,
2985 0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE,
2986 0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE,
2987 0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1,
2988 0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1,
2989 0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9,
2990 0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9,
2991 0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5,
2992 0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5,
2993 0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED,
2994 0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD,
2995 0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3,
2996 0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3,
2997 0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB,
2998 0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB,
2999 0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7,
3000 0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7,
3001 0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF,
3002 0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF
3007 decomp_dispatch_get_bits(
3008 tvbuff_t *message_tvb,
3009 proto_tree *udvm_tree,
3012 guint16 *old_input_bit_order,
3013 guint16 *remaining_bits,
3014 guint16 *input_bits,
3015 guint *input_address,
3017 guint16 *result_code,
3020 guint16 input_bit_order;
3021 guint16 bits_still_required = length;
3024 gint extra_bytes_available = msg_end - *input_address;
3026 gint prev_p_bit = *old_input_bit_order & 0x0001;
3027 gint bits_to_use = 0;
3030 input_bit_order = buff[68] << 8;
3031 input_bit_order = input_bit_order | buff[69];
3033 p_bit = (input_bit_order & 0x0001) != 0;
3036 * Discard any spare bits.
3037 * Note: We take care to avoid remaining_bits having the value of 8.
3039 if (prev_p_bit != p_bit)
3041 *remaining_bits = 0;
3042 *old_input_bit_order = input_bit_order;
3046 * Check we can suppy the required number of bits now, before we alter
3047 * the input buffer's state.
3049 if (*remaining_bits + extra_bytes_available * 8 < length)
3055 /* Note: This is never called with length > 16, so the following loop
3056 * never loops more than three time. */
3057 while (bits_still_required > 0)
3060 * We only put anything into input_bits if we know we will remove
3061 * at least one bit. That ensures we can simply discard the spare
3062 * bits if the P-bit changes.
3064 if (*remaining_bits == 0)
3066 octet = tvb_get_guint8(message_tvb, *input_address);
3067 if (print_level_1 ){
3068 proto_tree_add_text(udvm_tree, message_tvb, *input_address , 1,
3069 " Geting value: %u (0x%x) From Addr: %u", octet, octet, *input_address);
3071 *input_address = *input_address + 1;
3075 octet = reverse[octet];
3077 *input_bits = octet;
3078 *remaining_bits = 8;
3081 /* Add some more bits to the accumulated value. */
3082 bits_to_use = bits_still_required < *remaining_bits ? bits_still_required : *remaining_bits;
3083 bits_still_required -= bits_to_use;
3085 *input_bits <<= bits_to_use; /* Shift bits into MSByte */
3086 value = (value << bits_to_use) /* Then add to the accumulated value */
3087 | ((*input_bits >> 8) & 0xFF);
3088 *remaining_bits -= bits_to_use;
3089 *input_bits &= 0x00FF; /* Leave just the remaining bits */
3094 /* Bit reverse the entire word. */
3095 guint16 lsb = reverse[(value >> 8) & 0xFF];
3096 guint16 msb = reverse[value & 0xFF];
3098 value = ((msb << 8) | lsb) >> (16 - length);