2 * Routines making up the Universal Decompressor Virtual Machine (UDVM) used for
3 * Signaling Compression (SigComp) dissection.
4 * Copyright 2004, Anders Broman <anders.broman@ericsson.com>
8 * Wireshark - Network traffic analyzer
9 * By Gerald Combs <gerald@wireshark.org>
10 * Copyright 1998 Gerald Combs
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
26 * http://www.ietf.org/rfc/rfc3320.txt?number=3320
27 * http://www.ietf.org/rfc/rfc3321.txt?number=3321
29 * http://www.ietf.org/internet-drafts/draft-ietf-rohc-sigcomp-impl-guide-05.txt
30 * http://www.ietf.org/internet-drafts/draft-ietf-rohc-sigcomp-sip-01.txt
44 #include "sigcomp-udvm.h"
45 #include "sigcomp_state_hdlr.h"
50 #define SIGCOMP_INSTR_DECOMPRESSION_FAILURE 0
51 #define SIGCOMP_INSTR_AND 1
52 #define SIGCOMP_INSTR_OR 2
53 #define SIGCOMP_INSTR_NOT 3
54 #define SIGCOMP_INSTR_LSHIFT 4
55 #define SIGCOMP_INSTR_RSHIFT 5
56 #define SIGCOMP_INSTR_ADD 6
57 #define SIGCOMP_INSTR_SUBTRACT 7
58 #define SIGCOMP_INSTR_MULTIPLY 8
59 #define SIGCOMP_INSTR_DIVIDE 9
60 #define SIGCOMP_INSTR_REMAINDER 10
61 #define SIGCOMP_INSTR_SORT_ASCENDING 11
62 #define SIGCOMP_INSTR_SORT_DESCENDING 12
63 #define SIGCOMP_INSTR_SHA_1 13
64 #define SIGCOMP_INSTR_LOAD 14
65 #define SIGCOMP_INSTR_MULTILOAD 15
66 #define SIGCOMP_INSTR_PUSH 16
67 #define SIGCOMP_INSTR_POP 17
68 #define SIGCOMP_INSTR_COPY 18
69 #define SIGCOMP_INSTR_COPY_LITERAL 19
70 #define SIGCOMP_INSTR_COPY_OFFSET 20
71 #define SIGCOMP_INSTR_MEMSET 21
72 #define SIGCOMP_INSTR_JUMP 22
73 #define SIGCOMP_INSTR_COMPARE 23
74 #define SIGCOMP_INSTR_CALL 24
75 #define SIGCOMP_INSTR_RETURN 25
76 #define SIGCOMP_INSTR_SWITCH 26
77 #define SIGCOMP_INSTR_CRC 27
78 #define SIGCOMP_INSTR_INPUT_BYTES 28
79 #define SIGCOMP_INSTR_INPUT_BITS 29
80 #define SIGCOMP_INSTR_INPUT_HUFFMAN 30
81 #define SIGCOMP_INSTR_STATE_ACCESS 31
82 #define SIGCOMP_INSTR_STATE_CREATE 32
83 #define SIGCOMP_INSTR_STATE_FREE 33
84 #define SIGCOMP_INSTR_OUTPUT 34
85 #define SIGCOMP_INSTR_END_MESSAGE 35
88 static gboolean print_level_1;
89 static gboolean print_level_2;
90 static gboolean print_level_3;
91 static gint show_instr_detail_level;
93 /* Internal result code values of decompression failures */
94 const value_string result_code_vals[] = {
95 { 0, "No decompression failure" },
96 { 1, "Partial state length less than 6 or greater than 20 bytes long" },
97 { 2, "No state match" },
98 { 3, "state_begin + state_length > size of state" },
99 { 4, "Operand_2 is Zero" },
100 { 5, "Switch statement failed j >= n" },
101 { 6, "Atempt to jump outside of UDVM memory" },
102 { 7, "L in input-bits > 16" },
103 { 8, "input_bit_order > 7" },
104 { 9, "Instruction Decompression failure encountered" },
105 {10, "Input huffman failed j > n" },
106 {11, "Input bits requested beyond end of message" },
107 {12, "more than four state creation requests are made before the END-MESSAGE instruction" },
108 {13, "state_retention_priority is 65535" },
109 {14, "Input bytes requested beond end of message" },
110 {15, "Maximum number of UDVM cycles reached" },
111 {16, "UDVM stack underflow" },
112 { 255, "This branch isn't coded yet" },
116 static int decode_udvm_literal_operand(guint8 *buff,guint operand_address, guint16 *value);
117 static int dissect_udvm_reference_operand(guint8 *buff,guint operand_address, guint16 *value, guint *result_dest);
118 static int decode_udvm_multitype_operand(guint8 *buff,guint operand_address,guint16 *value);
119 static int decode_udvm_address_operand(guint8 *buff,guint operand_address, guint16 *value,guint current_address);
120 static int decomp_dispatch_get_bits(tvbuff_t *message_tvb,proto_tree *udvm_tree,guint8 bit_order,
121 guint8 *buff,guint16 *old_input_bit_order, guint16 *remaining_bits,
122 guint16 *input_bits, guint *input_address, guint16 length, guint16 *result_code,guint msg_end);
126 decompress_sigcomp_message(tvbuff_t *bytecode_tvb, tvbuff_t *message_tvb, packet_info *pinfo,
127 proto_tree *udvm_tree, gint udvm_mem_dest,
128 gint print_flags, gint hf_id,
130 gint byte_code_state_len, gint byte_code_id_len,
133 tvbuff_t *decomp_tvb;
134 guint8 buff[UDVM_MEMORY_SIZE];
136 guint8 *out_buff; /* Largest allowed size for a message is 65535 */
146 guint code_length =0;
147 guint8 current_instruction;
148 guint current_address;
149 guint operand_address;
151 guint16 output_address = 0;
152 guint next_operand_address;
156 guint16 byte_copy_right;
157 guint16 byte_copy_left;
158 guint16 input_bit_order;
159 guint16 stack_location;
162 guint msg_end = tvb_reported_length_remaining(message_tvb, 0);
163 guint16 result_code = 0;
164 guint16 old_input_bit_order = 0;
165 guint16 remaining_bits = 0;
166 guint16 input_bits = 0;
167 guint8 bit_order = 0;
168 gboolean outside_huffman_boundaries = TRUE;
169 gboolean print_in_loop = FALSE;
170 guint16 instruction_address;
171 guint8 no_of_state_create = 0;
172 guint16 state_length_buff[5];
173 guint16 state_address_buff[5];
174 guint16 state_instruction_buff[5];
175 guint16 state_minimum_access_length_buff[5];
176 guint16 state_state_retention_priority_buff[5];
177 guint32 used_udvm_cycles = 0;
178 guint cycles_per_bit;
179 guint maximum_UDVM_cycles;
181 unsigned char sha1_digest_buf[STATE_BUFFER_SIZE];
185 /* UDVM operand variables */
194 guint16 state_length;
195 guint16 state_address;
196 guint16 state_instruction;
201 guint16 at_address_1;
202 guint16 at_address_2;
203 guint16 at_address_3;
206 guint16 lower_bound_n;
207 guint16 upper_bound_n;
208 guint16 uncompressed_n;
210 guint16 ref_destination; /* could I have used $destination ? */
211 guint16 multy_offset;
212 guint16 output_start;
213 guint16 output_length;
214 guint16 minimum_access_length;
215 guint16 state_retention_priority;
216 guint16 requested_feedback_location;
217 guint16 returned_parameters_location;
221 /* Set print parameters */
222 print_level_1 = FALSE;
223 print_level_2 = FALSE;
224 print_level_3 = FALSE;
225 show_instr_detail_level = 0;
229 switch( print_flags ) {
234 print_level_1 = TRUE;
235 show_instr_detail_level = 1;
238 print_level_1 = TRUE;
239 print_level_2 = TRUE;
240 show_instr_detail_level = 1;
243 print_level_1 = TRUE;
244 print_level_2 = TRUE;
245 print_level_3 = TRUE;
246 show_instr_detail_level = 2;
249 print_level_1 = TRUE;
250 show_instr_detail_level = 1;
258 /* UDVM memory must be initialised to zero */
259 memset(buff, 0, 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 && i < UDVM_MEMORY_SIZE ) {
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_start_ip;
332 proto_tree_add_text(udvm_tree, bytecode_tvb, offset, 1,"UDVM EXECUTION STARTED at Address: %u Message size %u",
333 current_address, 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,"Wireshark 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;
862 byte_copy_right = buff[66] << 8;
863 byte_copy_right = byte_copy_right | buff[67];
864 byte_copy_left = buff[64] << 8;
865 byte_copy_left = byte_copy_left | buff[65];
868 proto_tree_add_text(udvm_tree, message_tvb, 0, -1,
869 "byte_copy_right = %u", byte_copy_right);
875 guint16 handle_now = length;
877 if ( k < byte_copy_right && byte_copy_right <= k + (length-n) ){
878 handle_now = byte_copy_right - position;
881 if (k + handle_now >= UDVM_MEMORY_SIZE)
882 goto decompression_failure;
883 sha1_update( &ctx, &buff[k], handle_now );
885 k = ( k + handle_now ) & 0xffff;
886 n = ( n + handle_now ) & 0xffff;
888 if ( k >= byte_copy_right ) {
893 sha1_finish( &ctx, sha1_digest_buf );
897 for ( n=0; n< STATE_BUFFER_SIZE; n++ ) {
899 buff[k] = sha1_digest_buf[n];
901 k = ( k + 1 ) & 0xffff;
904 if ( k == byte_copy_right ){
910 proto_tree_add_text(udvm_tree, message_tvb, 0, -1,
911 "Calculated SHA-1: %s",
912 bytes_to_str(sha1_digest_buf, STATE_BUFFER_SIZE));
915 current_address = next_operand_address;
916 goto execute_next_instruction;
919 case SIGCOMP_INSTR_LOAD: /* 14 LOAD (%address, %value) */
920 if (show_instr_detail_level == 2 ){
921 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
922 "Addr: %u ## LOAD(14) (%%address, %%value)",
925 operand_address = current_address + 1;
927 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &address);
928 if (show_instr_detail_level == 2 ){
929 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Address %u",
930 operand_address, address);
932 operand_address = next_operand_address;
934 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &value);
935 if (show_instr_detail_level == 1)
937 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
938 "Addr: %u ## LOAD (%%address=%u, %%value=%u)",
939 current_address, address, value);
945 buff[address + 1] = lsb;
948 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Value %u",
949 operand_address, value);
950 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," Loading bytes at %u Value %u 0x%x",
951 address, value, value);
954 current_address = next_operand_address;
955 goto execute_next_instruction;
958 case SIGCOMP_INSTR_MULTILOAD: /* 15 MULTILOAD (%address, #n, %value_0, ..., %value_n-1) */
960 * The MULTILOAD instruction sets a contiguous block of 2-byte words in
961 * the UDVM memory to specified values.
962 * Hmm what if the value to load only takes one byte ? Chose to always load two bytes.
964 if (show_instr_detail_level == 2 ){
965 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
966 "Addr: %u ## MULTILOAD(15) (%%address, #n, value_0, ..., value_n-1)",
969 operand_address = current_address + 1;
971 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &address);
972 if (show_instr_detail_level == 2 ){
973 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Address %u",
974 operand_address, address);
976 operand_address = next_operand_address;
979 next_operand_address = decode_udvm_literal_operand(buff,operand_address, &n);
980 if (show_instr_detail_level == 2 ){
981 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u n %u",
984 if (show_instr_detail_level == 1)
986 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
987 "Addr: %u ## MULTILOAD (%%address=%u, #n=%u, value_0, ..., value_%d)",
988 current_address, address, n, n-1);
990 operand_address = next_operand_address;
991 used_udvm_cycles = used_udvm_cycles + 1 + n;
995 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &value);
999 if (address >= UDVM_MEMORY_SIZE - 1)
1000 goto decompression_failure;
1002 buff[address] = msb;
1003 buff[address + 1] = lsb;
1006 length = next_operand_address - operand_address;
1008 if (print_level_1 ){
1009 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1, "Addr: %u Value %5u - Loading bytes at %5u Value %5u 0x%x",
1010 operand_address, value, address, value, value);
1012 address = address + 2;
1013 operand_address = next_operand_address;
1015 current_address = next_operand_address;
1016 goto execute_next_instruction;
1020 case SIGCOMP_INSTR_PUSH: /* 16 PUSH (%value) */
1021 if (show_instr_detail_level == 2){
1022 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1023 "Addr: %u ## PUSH(16) (value)",
1026 operand_address = current_address + 1;
1028 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &value);
1029 if (show_instr_detail_level == 2){
1030 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Value %u",
1031 operand_address, value);
1033 if (show_instr_detail_level == 1)
1035 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1036 "Addr: %u ## PUSH (value=%u)",
1037 current_address, value);
1039 current_address = next_operand_address;
1041 /* Push the value address onto the stack */
1042 stack_location = (buff[70] << 8) | buff[71];
1043 stack_fill = (buff[stack_location] << 8)
1044 | buff[(stack_location+1) & 0xFFFF];
1045 address = (stack_location + stack_fill * 2 + 2) & 0xFFFF;
1047 if (address >= UDVM_MEMORY_SIZE - 1)
1048 goto decompression_failure;
1050 buff[address] = (value >> 8) & 0x00FF;
1051 buff[(address+1) & 0xFFFF] = value & 0x00FF;
1053 if (stack_location >= UDVM_MEMORY_SIZE - 1)
1054 goto decompression_failure;
1056 stack_fill = (stack_fill + 1) & 0xFFFF;
1057 buff[stack_location] = (stack_fill >> 8) & 0x00FF;
1058 buff[(stack_location+1) & 0xFFFF] = stack_fill & 0x00FF;
1061 goto execute_next_instruction;
1065 case SIGCOMP_INSTR_POP: /* 17 POP (%address) */
1066 if (show_instr_detail_level == 2){
1067 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1068 "Addr: %u ## POP(16) (value)",
1071 operand_address = current_address + 1;
1073 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &destination);
1074 if (show_instr_detail_level == 2){
1075 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Value %u",
1076 operand_address, destination);
1078 if (show_instr_detail_level == 1)
1080 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1081 "Addr: %u ## POP (address=%u)",
1082 current_address, destination);
1084 current_address = next_operand_address;
1086 /* Pop value from the top of the stack */
1087 stack_location = (buff[70] << 8) | buff[71];
1088 stack_fill = (buff[stack_location] << 8)
1089 | buff[(stack_location+1) & 0xFFFF];
1090 if (stack_fill == 0)
1093 goto decompression_failure;
1096 if (stack_location >= UDVM_MEMORY_SIZE - 1)
1097 goto decompression_failure;
1099 stack_fill = (stack_fill - 1) & 0xFFFF;
1100 buff[stack_location] = (stack_fill >> 8) & 0x00FF;
1101 buff[(stack_location+1) & 0xFFFF] = stack_fill & 0x00FF;
1103 address = (stack_location + stack_fill * 2 + 2) & 0xFFFF;
1105 if (address >= UDVM_MEMORY_SIZE - 1)
1106 goto decompression_failure;
1108 value = (buff[address] << 8)
1109 | buff[(address+1) & 0xFFFF];
1111 /* ... and store the popped value. */
1112 if (destination >= UDVM_MEMORY_SIZE - 1)
1113 goto decompression_failure;
1114 buff[destination] = (value >> 8) & 0x00FF;
1115 buff[(destination+1) & 0xFFFF] = value & 0x00FF;
1118 goto execute_next_instruction;
1122 case SIGCOMP_INSTR_COPY: /* 18 COPY (%position, %length, %destination) */
1123 if (show_instr_detail_level == 2 ){
1124 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1125 "Addr: %u ## COPY(18) (position, length, destination)",
1128 operand_address = current_address + 1;
1130 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &position);
1131 if (show_instr_detail_level == 2 ){
1132 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u position %u",
1133 operand_address, position);
1135 operand_address = next_operand_address;
1138 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &length);
1139 if (show_instr_detail_level == 2 ){
1140 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Length %u",
1141 operand_address, length);
1143 operand_address = next_operand_address;
1146 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &destination);
1147 if (show_instr_detail_level == 2 ){
1148 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Destination %u",
1149 operand_address, destination);
1151 if (show_instr_detail_level == 1)
1153 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1154 "Addr: %u ## COPY (position=%u, length=%u, destination=%u)",
1155 current_address, position, length, destination);
1157 current_address = next_operand_address;
1161 * The string of bytes is copied in ascending order of memory address,
1162 * respecting the bounds set by byte_copy_left and byte_copy_right.
1163 * More precisely, if a byte is copied from/to Address m then the next
1164 * byte is copied from/to Address n where n is calculated as follows:
1166 * Set k := m + 1 (modulo 2^16)
1167 * If k = byte_copy_right then set n := byte_copy_left, else set n := k
1173 byte_copy_right = buff[66] << 8;
1174 byte_copy_right = byte_copy_right | buff[67];
1175 byte_copy_left = buff[64] << 8;
1176 byte_copy_left = byte_copy_left | buff[65];
1177 if (print_level_2 ){
1178 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
1179 " byte_copy_right = %u", byte_copy_right);
1182 while ( n < length ){
1183 buff[k] = buff[position];
1184 if (print_level_2 ){
1185 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
1186 " Copying value: %u (0x%x) to Addr: %u",
1187 buff[position], buff[position], k);
1189 position = ( position + 1 ) & 0xffff;
1190 k = ( k + 1 ) & 0xffff;
1194 * Check for circular buffer wrapping after the positions are
1195 * incremented. If either started at BCR then they should continue
1196 * to increment beyond BCR.
1198 if ( k == byte_copy_right ){
1201 if ( position == byte_copy_right ){
1202 position = byte_copy_left;
1205 used_udvm_cycles = used_udvm_cycles + 1 + length;
1206 goto execute_next_instruction;
1209 case SIGCOMP_INSTR_COPY_LITERAL: /* 19 COPY-LITERAL (%position, %length, $destination) */
1210 if (show_instr_detail_level == 2 ){
1211 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1212 "Addr: %u ## COPY-LITERAL(19) (position, length, $destination)",
1215 operand_address = current_address + 1;
1217 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &position);
1218 if (show_instr_detail_level == 2 ){
1219 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u position %u",
1220 operand_address, position);
1222 operand_address = next_operand_address;
1225 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &length);
1226 if (show_instr_detail_level == 2 ){
1227 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Length %u",
1228 operand_address, length);
1230 operand_address = next_operand_address;
1234 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &ref_destination, &result_dest);
1235 if (show_instr_detail_level == 2 ){
1236 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u destination %u",
1237 operand_address, ref_destination);
1239 if (show_instr_detail_level == 1)
1241 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1242 "Addr: %u ## COPY-LITERAL (position=%u, length=%u, $destination=%u)",
1243 current_address, position, length, destination);
1245 current_address = next_operand_address;
1251 * The string of bytes is copied in ascending order of memory address,
1252 * respecting the bounds set by byte_copy_left and byte_copy_right.
1253 * More precisely, if a byte is copied from/to Address m then the next
1254 * byte is copied from/to Address n where n is calculated as follows:
1256 * Set k := m + 1 (modulo 2^16)
1257 * If k = byte_copy_right then set n := byte_copy_left, else set n := k
1262 k = ref_destination;
1263 byte_copy_right = buff[66] << 8;
1264 byte_copy_right = byte_copy_right | buff[67];
1265 byte_copy_left = buff[64] << 8;
1266 byte_copy_left = byte_copy_left | buff[65];
1267 if (print_level_2 ){
1268 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
1269 " byte_copy_right = %u", byte_copy_right);
1271 while ( n < length ){
1273 buff[k] = buff[position];
1274 if (print_level_2 ){
1275 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
1276 " Copying value: %u (0x%x) to Addr: %u",
1277 buff[position], buff[position], k);
1279 position = ( position + 1 ) & 0xffff;
1280 k = ( k + 1 ) & 0xffff;
1284 * Check for circular buffer wrapping after the positions are
1285 * incremented. It is important that k cannot be left set
1286 * to BCR. Also, if either started at BCR then they should continue
1287 * to increment beyond BCR.
1289 if ( k == byte_copy_right ){
1292 if ( position == byte_copy_right ){
1293 position = byte_copy_left;
1296 buff[result_dest] = k >> 8;
1297 buff[result_dest + 1] = k & 0x00ff;
1299 used_udvm_cycles = used_udvm_cycles + 1 + length;
1300 goto execute_next_instruction;
1303 case SIGCOMP_INSTR_COPY_OFFSET: /* 20 COPY-OFFSET (%offset, %length, $destination) */
1304 if (show_instr_detail_level == 2 ){
1305 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1306 "Addr: %u ## COPY-OFFSET(20) (offset, length, $destination)",
1309 operand_address = current_address + 1;
1311 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &multy_offset);
1312 if (show_instr_detail_level == 2 ){
1313 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u offset %u",
1314 operand_address, multy_offset);
1316 operand_address = next_operand_address;
1319 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &length);
1320 if (show_instr_detail_level == 2 ){
1321 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Length %u",
1322 operand_address, length);
1324 operand_address = next_operand_address;
1328 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &ref_destination, &result_dest);
1329 if (show_instr_detail_level == 2 ){
1330 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u $destination %u",
1331 operand_address, ref_destination);
1334 if (show_instr_detail_level == 1)
1336 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1337 "Addr: %u ## COPY-OFFSET (offset=%u, length=%u, $destination=%u)",
1338 current_address, multy_offset, length, result_dest);
1340 current_address = next_operand_address;
1342 /* Execute the instruction:
1343 * To derive the value of the position operand, starting at the memory
1344 * address specified by destination, the UDVM counts backwards a total
1345 * of offset memory addresses.
1347 * If the memory address specified in byte_copy_left is reached, the
1348 * next memory address is taken to be (byte_copy_right - 1) modulo 2^16.
1350 byte_copy_left = buff[64] << 8;
1351 byte_copy_left = byte_copy_left | buff[65];
1352 byte_copy_right = buff[66] << 8;
1353 byte_copy_right = byte_copy_right | buff[67];
1356 * In order to work out the position, simple arithmetic is tricky
1357 * to apply because there some nasty corner cases. A simple loop
1358 * is inefficient but the logic is simple.
1360 * FUTURE: This could be optimised.
1362 for (position = ref_destination, i = 0; i < multy_offset; i++)
1364 if ( position == byte_copy_left )
1366 position = (byte_copy_right - 1) & 0xffff;
1370 position = (position - 1) & 0xffff;
1374 if (print_level_2 ){
1375 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
1376 " byte_copy_left = %u byte_copy_right = %u position= %u",
1377 byte_copy_left, byte_copy_right, position);
1379 /* The COPY-OFFSET instruction then behaves as a COPY-LITERAL
1380 * instruction, taking the value of the position operand to be the last
1381 * memory address reached in the above step.
1387 * The string of bytes is copied in ascending order of memory address,
1388 * respecting the bounds set by byte_copy_left and byte_copy_right.
1389 * More precisely, if a byte is copied from/to Address m then the next
1390 * byte is copied from/to Address n where n is calculated as follows:
1392 * Set k := m + 1 (modulo 2^16)
1393 * If k = byte_copy_right then set n := byte_copy_left, else set n := k
1398 k = ref_destination;
1399 if (print_level_2 ){
1400 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
1401 " byte_copy_left = %u byte_copy_right = %u", byte_copy_left, byte_copy_right);
1403 while ( n < length ){
1404 buff[k] = buff[position];
1405 if (print_level_2 ){
1406 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
1407 " Copying value: %5u (0x%x) from Addr: %u to Addr: %u",
1408 buff[position], buff[position],(position), k);
1411 k = ( k + 1 ) & 0xffff;
1412 position = ( position + 1 ) & 0xffff;
1415 * Check for circular buffer wrapping after the positions are
1416 * incremented. It is important that k cannot be left set
1417 * to BCR. Also, if either started at BCR then they should continue
1418 * to increment beyond BCR.
1420 if ( k == byte_copy_right ){
1423 if ( position == byte_copy_right ){
1424 position = byte_copy_left;
1427 buff[result_dest] = k >> 8;
1428 buff[result_dest + 1] = k & 0x00ff;
1429 used_udvm_cycles = used_udvm_cycles + 1 + length;
1430 goto execute_next_instruction;
1433 case SIGCOMP_INSTR_MEMSET: /* 21 MEMSET (%address, %length, %start_value, %offset) */
1434 if (show_instr_detail_level == 2 ){
1435 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1436 "Addr: %u ## MEMSET(21) (address, length, start_value, offset)",
1439 operand_address = current_address + 1;
1442 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &address);
1443 if (show_instr_detail_level == 2 ){
1444 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Address %u",
1445 operand_address, address);
1447 operand_address = next_operand_address;
1450 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &length);
1451 if (show_instr_detail_level == 2 ){
1452 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Length %u",
1453 operand_address, length);
1455 operand_address = next_operand_address;
1457 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &start_value);
1458 if (show_instr_detail_level == 2 ){
1459 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u start_value %u",
1460 operand_address, start_value);
1462 operand_address = next_operand_address;
1465 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &multy_offset);
1466 if (show_instr_detail_level == 2 ){
1467 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u offset %u",
1468 operand_address, multy_offset);
1470 if (show_instr_detail_level == 1)
1472 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1473 "Addr: %u ## MEMSET (address=%u, length=%u, start_value=%u, offset=%u)",
1474 current_address, address, length, start_value, multy_offset);
1476 current_address = next_operand_address;
1477 /* exetute the instruction
1478 * The sequence of values used by the MEMSET instruction is specified by
1479 * the following formula:
1481 * Seq[n] := (start_value + n * offset) modulo 256
1485 byte_copy_right = buff[66] << 8;
1486 byte_copy_right = byte_copy_right | buff[67];
1487 byte_copy_left = buff[64] << 8;
1488 byte_copy_left = byte_copy_left | buff[65];
1489 if (print_level_2 ){
1490 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
1491 " byte_copy_left = %u byte_copy_right = %u", byte_copy_left, byte_copy_right);
1493 while ( n < length ){
1494 if ( k == byte_copy_right ){
1497 buff[k] = (start_value + ( n * multy_offset)) & 0xff;
1498 if (print_level_2 ){
1499 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
1500 " Storing value: %u (0x%x) at Addr: %u",
1501 buff[k], buff[k], k);
1503 k = ( k + 1 ) & 0xffff;
1506 used_udvm_cycles = used_udvm_cycles + 1 + length;
1507 goto execute_next_instruction;
1511 case SIGCOMP_INSTR_JUMP: /* 22 JUMP (@address) */
1512 if (show_instr_detail_level == 2 ){
1513 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1514 "Addr: %u ## JUMP(22) (@address)",
1517 operand_address = current_address + 1;
1519 /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
1520 next_operand_address = decode_udvm_address_operand(buff,operand_address, &at_address, current_address);
1521 if (show_instr_detail_level == 2 ){
1522 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u @Address %u",
1523 operand_address, at_address);
1525 if (show_instr_detail_level == 1)
1527 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1528 "Addr: %u ## JUMP (@address=%u)",
1529 current_address, at_address);
1531 current_address = at_address;
1533 goto execute_next_instruction;
1536 case SIGCOMP_INSTR_COMPARE: /* 23 */
1537 /* COMPARE (%value_1, %value_2, @address_1, @address_2, @address_3)
1539 if (show_instr_detail_level == 2 ){
1540 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1541 "Addr: %u ## COMPARE(23) (value_1, value_2, @address_1, @address_2, @address_3)",
1544 operand_address = current_address + 1;
1547 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &value_1);
1548 if (show_instr_detail_level == 2 ){
1549 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Value %u",
1550 operand_address, value_1);
1552 operand_address = next_operand_address;
1555 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &value_2);
1556 if (show_instr_detail_level == 2 ){
1557 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Value %u",
1558 operand_address, value_2);
1560 operand_address = next_operand_address;
1563 /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
1564 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &at_address_1);
1565 at_address_1 = ( current_address + at_address_1) & 0xffff;
1566 if (show_instr_detail_level == 2 ){
1567 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u @Address %u",
1568 operand_address, at_address_1);
1570 operand_address = next_operand_address;
1574 /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
1575 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &at_address_2);
1576 at_address_2 = ( current_address + at_address_2) & 0xffff;
1577 if (show_instr_detail_level == 2 ){
1578 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u @Address %u",
1579 operand_address, at_address_2);
1581 operand_address = next_operand_address;
1584 /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
1585 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &at_address_3);
1586 at_address_3 = ( current_address + at_address_3) & 0xffff;
1587 if (show_instr_detail_level == 2 ){
1588 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u @Address %u",
1589 operand_address, at_address_3);
1591 if (show_instr_detail_level == 1)
1593 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1594 "Addr: %u ## COMPARE (value_1=%u, value_2=%u, @address_1=%u, @address_2=%u, @address_3=%u)",
1595 current_address, value_1, value_2, at_address_1, at_address_2, at_address_3);
1597 /* execute the instruction
1598 * If value_1 < value_2 then the UDVM continues instruction execution at
1599 * the memory address specified by address 1. If value_1 = value_2 then
1600 * it jumps to the address specified by address_2. If value_1 > value_2
1601 * then it jumps to the address specified by address_3.
1603 if ( value_1 < value_2 )
1604 current_address = at_address_1;
1605 if ( value_1 == value_2 )
1606 current_address = at_address_2;
1607 if ( value_1 > value_2 )
1608 current_address = at_address_3;
1610 goto execute_next_instruction;
1613 case SIGCOMP_INSTR_CALL: /* 24 CALL (@address) (PUSH addr )*/
1614 if (show_instr_detail_level == 2){
1615 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1616 "Addr: %u ## CALL(24) (@address) (PUSH addr )",
1619 operand_address = current_address + 1;
1621 next_operand_address = decode_udvm_address_operand(buff,operand_address, &at_address, current_address);
1622 if (show_instr_detail_level == 2 ){
1623 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u @Address %u",
1624 operand_address, at_address);
1626 if (show_instr_detail_level == 1)
1628 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1629 "Addr: %u ## CALL (@address=%u)",
1630 current_address, at_address);
1632 current_address = next_operand_address;
1634 /* Push the current address onto the stack */
1635 stack_location = (buff[70] << 8) | buff[71];
1636 stack_fill = (buff[stack_location] << 8)
1637 | buff[(stack_location+1) & 0xFFFF];
1638 address = (stack_location + stack_fill * 2 + 2) & 0xFFFF;
1639 if (address >= UDVM_MEMORY_SIZE - 1)
1640 goto decompression_failure;
1641 buff[address] = (current_address >> 8) & 0x00FF;
1642 buff[(address+1) & 0xFFFF] = current_address & 0x00FF;
1644 stack_fill = (stack_fill + 1) & 0xFFFF;
1645 if (stack_location >= UDVM_MEMORY_SIZE - 1)
1646 goto decompression_failure;
1647 buff[stack_location] = (stack_fill >> 8) & 0x00FF;
1648 buff[(stack_location+1) & 0xFFFF] = stack_fill & 0x00FF;
1650 /* ... and jump to the destination address */
1651 current_address = at_address;
1654 goto execute_next_instruction;
1658 case SIGCOMP_INSTR_RETURN: /* 25 POP and return */
1659 if (print_level_1 || show_instr_detail_level == 1){
1660 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1661 "Addr: %u ## POP(25) and return",
1665 /* Pop value from the top of the stack */
1666 stack_location = (buff[70] << 8) | buff[71];
1667 stack_fill = (buff[stack_location] << 8)
1668 | buff[(stack_location+1) & 0xFFFF];
1669 if (stack_fill == 0)
1672 goto decompression_failure;
1675 stack_fill = (stack_fill - 1) & 0xFFFF;
1676 if (stack_location >= UDVM_MEMORY_SIZE - 1)
1677 goto decompression_failure;
1678 buff[stack_location] = (stack_fill >> 8) & 0x00FF;
1679 buff[(stack_location+1) & 0xFFFF] = stack_fill & 0x00FF;
1681 address = (stack_location + stack_fill * 2 + 2) & 0xFFFF;
1682 at_address = (buff[address] << 8)
1683 | buff[(address+1) & 0xFFFF];
1685 /* ... and set the PC to the popped value */
1686 current_address = at_address;
1689 goto execute_next_instruction;
1693 case SIGCOMP_INSTR_SWITCH: /* 26 SWITCH (#n, %j, @address_0, @address_1, ... , @address_n-1) */
1695 * When a SWITCH instruction is encountered the UDVM reads the value of
1696 * j. It then continues instruction execution at the address specified
1699 * Decompression failure occurs if j specifies a value of n or more, or
1700 * if the address lies beyond the overall UDVM memory size.
1702 instruction_address = current_address;
1703 if (print_level_1 ){
1704 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1705 "Addr: %u ## SWITCH (#n, j, @address_0, @address_1, ... , @address_n-1))",
1708 operand_address = current_address + 1;
1710 * Number of addresses in the instruction
1712 next_operand_address = decode_udvm_literal_operand(buff,operand_address, &n);
1713 if (print_level_1 ){
1714 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u n %u",
1715 operand_address, n);
1717 operand_address = next_operand_address;
1719 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &j);
1720 if (print_level_1 ){
1721 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u j %u",
1722 operand_address, j);
1724 operand_address = next_operand_address;
1728 /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
1729 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &at_address_1);
1730 at_address_1 = ( instruction_address + at_address_1) & 0xffff;
1731 if (print_level_1 ){
1732 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u @Address %u",
1733 operand_address, at_address_1);
1736 current_address = at_address_1;
1738 operand_address = next_operand_address;
1741 /* Check decompression failure */
1742 if ( ( j == n ) || ( j > n )){
1744 goto decompression_failure;
1746 if ( current_address > UDVM_MEMORY_SIZE ){
1748 goto decompression_failure;
1750 used_udvm_cycles = used_udvm_cycles + 1 + n;
1752 goto execute_next_instruction;
1755 case SIGCOMP_INSTR_CRC: /* 27 CRC (%value, %position, %length, @address) */
1756 if (print_level_1 ){
1757 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1758 "Addr: %u ## CRC (value, position, length, @address)",
1762 operand_address = current_address + 1;
1765 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &value);
1766 if (print_level_1 ){
1767 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Value %u",
1768 operand_address, value);
1770 operand_address = next_operand_address;
1773 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &position);
1774 if (print_level_1 ){
1775 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u position %u",
1776 operand_address, position);
1778 operand_address = next_operand_address;
1781 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &length);
1782 if (print_level_1 ){
1783 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Length %u",
1784 operand_address, length);
1786 operand_address = next_operand_address;
1789 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &at_address);
1790 at_address = ( current_address + at_address) & 0xffff;
1791 if (print_level_1 ){
1792 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u @Address %u",
1793 operand_address, at_address);
1795 /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
1796 used_udvm_cycles = used_udvm_cycles + 1 + length;
1800 byte_copy_right = buff[66] << 8;
1801 byte_copy_right = byte_copy_right | buff[67];
1802 byte_copy_left = buff[64] << 8;
1803 byte_copy_left = byte_copy_left | buff[65];
1806 if (print_level_2 ){
1807 proto_tree_add_text(udvm_tree, message_tvb, 0, -1,
1808 "byte_copy_right = %u", byte_copy_right);
1813 guint16 handle_now = length - n;
1815 if ( k < byte_copy_right && byte_copy_right <= k + (length-n) ){
1816 handle_now = byte_copy_right - k;
1819 if (k + handle_now >= UDVM_MEMORY_SIZE)
1820 goto decompression_failure;
1821 result = crc16_ccitt_seed(&buff[k], handle_now, (guint16) (result ^ 0xffff));
1823 k = ( k + handle_now ) & 0xffff;
1824 n = ( n + handle_now ) & 0xffff;
1826 if ( k >= byte_copy_right ) {
1831 result = result ^ 0xffff;
1833 if (print_level_1 ){
1834 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1, "Calculated CRC %u", result);
1836 if (result != value){
1837 current_address = at_address;
1840 current_address = next_operand_address;
1842 goto execute_next_instruction;
1846 case SIGCOMP_INSTR_INPUT_BYTES: /* 28 INPUT-BYTES (%length, %destination, @address) */
1847 if (show_instr_detail_level == 2 ){
1848 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1849 "Addr: %u ## INPUT-BYTES(28) length, destination, @address)",
1852 operand_address = current_address + 1;
1854 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &length);
1855 if (show_instr_detail_level == 2 ){
1856 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Length %u",
1857 operand_address, length);
1859 operand_address = next_operand_address;
1862 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &destination);
1863 if (show_instr_detail_level == 2 ){
1864 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Destination %u",
1865 operand_address, destination);
1867 operand_address = next_operand_address;
1870 /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
1871 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &at_address);
1872 at_address = ( current_address + at_address) & 0xffff;
1873 if (show_instr_detail_level == 2 ){
1874 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u @Address %u",
1875 operand_address, at_address);
1877 if (show_instr_detail_level == 1)
1879 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1880 "Addr: %u ## INPUT-BYTES length=%u, destination=%u, @address=%u)",
1881 current_address, length, destination, at_address);
1883 /* execute the instruction TODO insert checks
1887 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1888 * | byte_copy_left | 64 - 65
1889 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1890 * | byte_copy_right | 66 - 67
1891 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1892 * | input_bit_order | 68 - 69
1893 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1894 * | stack_location | 70 - 71
1895 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1897 * Figure 7: Memory addresses of the UDVM registers
1901 * The string of bytes is copied in ascending order of memory address,
1902 * respecting the bounds set by byte_copy_left and byte_copy_right.
1903 * More precisely, if a byte is copied from/to Address m then the next
1904 * byte is copied from/to Address n where n is calculated as follows:
1906 * Set k := m + 1 (modulo 2^16)
1907 * If k = byte_copy_right then set n := byte_copy_left, else set n := k
1913 byte_copy_right = buff[66] << 8;
1914 byte_copy_right = byte_copy_right | buff[67];
1915 byte_copy_left = buff[64] << 8;
1916 byte_copy_left = byte_copy_left | buff[65];
1917 if (print_level_1 ){
1918 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
1919 " byte_copy_right = %u", byte_copy_right);
1921 /* clear out remaining bits if any */
1924 /* operand_address used as dummy */
1925 while ( n < length ){
1926 if (input_address > ( msg_end - 1)){
1927 current_address = at_address;
1929 goto execute_next_instruction;
1932 if ( k == byte_copy_right ){
1935 octet = tvb_get_guint8(message_tvb, input_address);
1937 if (print_level_1 ){
1938 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
1939 " Loading value: %u (0x%x) at Addr: %u", octet, octet, k);
1943 * If the instruction requests data that lies beyond the end of the
1944 * SigComp message, no data is returned. Instead the UDVM moves program
1945 * execution to the address specified by the address operand.
1949 k = ( k + 1 ) & 0xffff;
1952 used_udvm_cycles = used_udvm_cycles + 1 + length;
1953 current_address = next_operand_address;
1954 goto execute_next_instruction;
1956 case SIGCOMP_INSTR_INPUT_BITS:/* 29 INPUT-BITS (%length, %destination, @address) */
1958 * The length operand indicates the requested number of bits.
1959 * Decompression failure occurs if this operand does not lie between 0
1962 * The destination operand specifies the memory address to which the
1963 * compressed data should be copied. Note that the requested bits are
1964 * interpreted as a 2-byte integer ranging from 0 to 2^length - 1, as
1965 * explained in Section 8.2.
1967 * If the instruction requests data that lies beyond the end of the
1968 * SigComp message, no data is returned. Instead the UDVM moves program
1969 * execution to the address specified by the address operand.
1972 if (show_instr_detail_level == 2 ){
1973 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1974 "Addr: %u ## INPUT-BITS(29) (length, destination, @address)",
1977 operand_address = current_address + 1;
1980 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &length);
1981 if (show_instr_detail_level == 2 ){
1982 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u length %u",
1983 operand_address, length);
1985 operand_address = next_operand_address;
1987 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &destination);
1988 if (show_instr_detail_level == 2 ){
1989 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Destination %u",
1990 operand_address, destination);
1992 operand_address = next_operand_address;
1995 /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
1996 next_operand_address = decode_udvm_address_operand(buff,operand_address, &at_address, current_address);
1997 if (show_instr_detail_level == 2 ){
1998 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u @Address %u",
1999 operand_address, at_address);
2001 if (show_instr_detail_level == 1)
2003 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2004 "Addr: %u ## INPUT-BITS length=%u, destination=%u, @address=%u)",
2005 current_address, length, destination, at_address);
2007 current_address = next_operand_address;
2010 * Execute actual instr.
2011 * The input_bit_order register contains the following three flags:
2014 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2015 * | reserved |F|H|P| 68 - 69
2016 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2018 input_bit_order = buff[68] << 8;
2019 input_bit_order = input_bit_order | buff[69];
2021 * If the instruction requests data that lies beyond the end of the
2022 * SigComp message, no data is returned. Instead the UDVM moves program
2023 * execution to the address specified by the address operand.
2028 goto decompression_failure;
2030 if ( input_bit_order > 7 ){
2032 goto decompression_failure;
2036 * Transfer F bit to bit_order to tell decomp dispatcher which bit order to use
2038 bit_order = ( input_bit_order & 0x0004 ) >> 2;
2039 value = decomp_dispatch_get_bits( message_tvb, udvm_tree, bit_order,
2040 buff, &old_input_bit_order, &remaining_bits,
2041 &input_bits, &input_address, length, &result_code, msg_end);
2042 if ( result_code == 11 ){
2043 used_udvm_cycles = used_udvm_cycles + 1;
2044 current_address = at_address;
2045 goto execute_next_instruction;
2048 lsb = value & 0x00ff;
2049 if (destination >= UDVM_MEMORY_SIZE - 1)
2050 goto decompression_failure;
2051 buff[destination] = msb;
2052 buff[destination + 1]=lsb;
2053 if (print_level_1 ){
2054 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
2055 " Loading value: %u (0x%x) at Addr: %u, remaining_bits: %u", value, value, destination, remaining_bits);
2058 used_udvm_cycles = used_udvm_cycles + 1;
2059 goto execute_next_instruction;
2061 case SIGCOMP_INSTR_INPUT_HUFFMAN: /* 30 */
2063 * INPUT-HUFFMAN (%destination, @address, #n, %bits_1, %lower_bound_1,
2064 * %upper_bound_1, %uncompressed_1, ... , %bits_n, %lower_bound_n,
2065 * %upper_bound_n, %uncompressed_n)
2067 if (show_instr_detail_level == 2 ){
2068 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2069 "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)",
2072 operand_address = current_address + 1;
2075 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &destination);
2076 if (show_instr_detail_level == 2 ){
2077 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Destination %u",
2078 operand_address, destination);
2080 operand_address = next_operand_address;
2083 /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
2084 next_operand_address = decode_udvm_address_operand(buff,operand_address, &at_address, current_address);
2085 if (show_instr_detail_level == 2 ){
2086 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u @Address %u",
2087 operand_address, at_address);
2089 operand_address = next_operand_address;
2092 next_operand_address = decode_udvm_literal_operand(buff,operand_address, &n);
2093 if (show_instr_detail_level == 2 ){
2094 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u n %u",
2095 operand_address, n);
2097 operand_address = next_operand_address;
2098 if (show_instr_detail_level == 1)
2100 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2101 "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)",
2102 current_address, destination, at_address, n, n, n, n, n);
2105 used_udvm_cycles = used_udvm_cycles + 1 + n;
2108 * Note that if n = 0 then the INPUT-HUFFMAN instruction is ignored and
2109 * program execution resumes at the following instruction.
2110 * Decompression failure occurs if (bits_1 + ... + bits_n) > 16.
2112 * In all other cases, the behavior of the INPUT-HUFFMAN instruction is
2115 * 1. Set j := 1 and set H := 0.
2117 * 2. Request bits_j compressed bits. Interpret the returned bits as an
2118 * integer k from 0 to 2^bits_j - 1, as explained in Section 8.2.
2120 * 3. Set H := H * 2^bits_j + k.
2122 * 4. If data is requested that lies beyond the end of the SigComp
2123 * message, terminate the INPUT-HUFFMAN instruction and move program
2124 * execution to the memory address specified by the address operand.
2126 * 5. If (H < lower_bound_j) or (H > upper_bound_j) then set j := j + 1.
2127 * Then go back to Step 2, unless j > n in which case decompression
2130 * 6. Copy (H + uncompressed_j - lower_bound_j) modulo 2^16 to the
2131 * memory address specified by the destination operand.
2135 * The input_bit_order register contains the following three flags:
2138 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2139 * | reserved |F|H|P| 68 - 69
2140 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2142 * Transfer H bit to bit_order to tell decomp dispatcher which bit order to use
2144 input_bit_order = buff[68] << 8;
2145 input_bit_order = input_bit_order | buff[69];
2146 bit_order = ( input_bit_order & 0x0002 ) >> 1;
2151 outside_huffman_boundaries = TRUE;
2152 print_in_loop = print_level_3;
2155 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &bits_n);
2156 if (print_in_loop ){
2157 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u bits_n %u",
2158 operand_address, bits_n);
2160 operand_address = next_operand_address;
2162 /* %lower_bound_n */
2163 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &lower_bound_n);
2164 if (print_in_loop ){
2165 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u lower_bound_n %u",
2166 operand_address, lower_bound_n);
2168 operand_address = next_operand_address;
2169 /* %upper_bound_n */
2170 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &upper_bound_n);
2171 if (print_in_loop ){
2172 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u upper_bound_n %u",
2173 operand_address, upper_bound_n);
2175 operand_address = next_operand_address;
2176 /* %uncompressed_n */
2177 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &uncompressed_n);
2178 if (print_in_loop ){
2179 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u uncompressed_n %u",
2180 operand_address, uncompressed_n);
2182 operand_address = next_operand_address;
2183 /* execute instruction */
2184 if ( outside_huffman_boundaries ) {
2186 * 2. Request bits_j compressed bits. Interpret the returned bits as an
2187 * integer k from 0 to 2^bits_j - 1, as explained in Section 8.2.
2189 k = decomp_dispatch_get_bits( message_tvb, udvm_tree, bit_order,
2190 buff, &old_input_bit_order, &remaining_bits,
2191 &input_bits, &input_address, bits_n, &result_code, msg_end);
2192 if ( result_code == 11 ){
2194 * 4. If data is requested that lies beyond the end of the SigComp
2195 * message, terminate the INPUT-HUFFMAN instruction and move program
2196 * execution to the memory address specified by the address operand.
2198 current_address = at_address;
2199 goto execute_next_instruction;
2203 * 3. Set H := H * 2^bits_j + k.
2204 * [In practice is a shift+OR operation.]
2207 H = (H << bits_n) | k;
2208 if (print_level_3 ){
2209 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," Set H(%u) := H(%u) * 2^bits_j(%u) + k(%u)",
2210 H ,oldH, 1<<bits_n,k);
2214 * 5. If (H < lower_bound_j) or (H > upper_bound_j) then set j := j + 1.
2215 * Then go back to Step 2, unless j > n in which case decompression
2218 if ((H < lower_bound_n) || (H > upper_bound_n)){
2219 outside_huffman_boundaries = TRUE;
2221 outside_huffman_boundaries = FALSE;
2222 print_in_loop = FALSE;
2224 * 6. Copy (H + uncompressed_j - lower_bound_j) modulo 2^16 to the
2225 * memory address specified by the destination operand.
2227 if (print_level_2 ){
2228 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2229 " H(%u) = H(%u) + uncompressed_n(%u) - lower_bound_n(%u)",
2230 (H + uncompressed_n - lower_bound_n ),H, uncompressed_n, lower_bound_n);
2232 H = H + uncompressed_n - lower_bound_n;
2235 if (destination >= UDVM_MEMORY_SIZE - 1)
2236 goto decompression_failure;
2237 buff[destination] = msb;
2238 buff[destination + 1]=lsb;
2239 if (print_level_1 ){
2240 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
2241 " Loading H: %u (0x%x) at Addr: %u,j = %u remaining_bits: %u",
2242 H, H, destination,( n - m + 1 ), remaining_bits);
2251 if ( outside_huffman_boundaries ) {
2253 goto decompression_failure;
2256 current_address = next_operand_address;
2257 goto execute_next_instruction;
2260 case SIGCOMP_INSTR_STATE_ACCESS: /* 31 */
2261 /* STATE-ACCESS (%partial_identifier_start, %partial_identifier_length,
2262 * %state_begin, %state_length, %state_address, %state_instruction)
2264 if (show_instr_detail_level == 2 ){
2265 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2266 "Addr: %u ## STATE-ACCESS(31) (partial_identifier_start, partial_identifier_length,state_begin, state_length, state_address, state_instruction)",
2269 operand_address = current_address + 1;
2272 * %partial_identifier_start
2274 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &p_id_start);
2275 if (show_instr_detail_level == 2 ){
2276 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u partial_identifier_start %u",
2277 operand_address, p_id_start);
2279 operand_address = next_operand_address;
2282 * %partial_identifier_length
2284 operand_address = next_operand_address;
2285 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &p_id_length);
2286 if (show_instr_detail_level == 2 ){
2287 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u partial_identifier_length %u",
2288 operand_address, p_id_length);
2293 operand_address = next_operand_address;
2294 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_begin);
2295 if (show_instr_detail_level == 2 ){
2296 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_begin %u",
2297 operand_address, state_begin);
2302 operand_address = next_operand_address;
2303 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_length);
2304 if (show_instr_detail_level == 2 ){
2305 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_length %u",
2306 operand_address, state_length);
2311 operand_address = next_operand_address;
2312 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_address);
2313 if (show_instr_detail_level == 2 ){
2314 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_address %u",
2315 operand_address, state_address);
2318 * %state_instruction
2320 operand_address = next_operand_address;
2321 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_instruction);
2322 if (show_instr_detail_level == 2 ){
2323 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_instruction %u",
2324 operand_address, state_instruction);
2326 if (show_instr_detail_level == 1)
2328 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2329 "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)",
2330 current_address, p_id_start, p_id_length, state_begin, state_length, state_address, state_instruction);
2332 current_address = next_operand_address;
2333 byte_copy_right = buff[66] << 8;
2334 byte_copy_right = byte_copy_right | buff[67];
2335 byte_copy_left = buff[64] << 8;
2336 byte_copy_left = byte_copy_left | buff[65];
2337 if (print_level_2 ){
2338 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
2339 " byte_copy_right = %u, byte_copy_left = %u", byte_copy_right,byte_copy_left);
2342 result_code = udvm_state_access(message_tvb, udvm_tree, buff, p_id_start, p_id_length, state_begin, &state_length,
2343 &state_address, &state_instruction, hf_id);
2344 if ( result_code != 0 ){
2345 goto decompression_failure;
2347 used_udvm_cycles = used_udvm_cycles + 1 + state_length;
2348 goto execute_next_instruction;
2350 case SIGCOMP_INSTR_STATE_CREATE: /* 32 */
2352 * STATE-CREATE (%state_length, %state_address, %state_instruction,
2353 * %minimum_access_length, %state_retention_priority)
2355 if (show_instr_detail_level == 2 ){
2356 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2357 "Addr: %u ## STATE-CREATE(32) (state_length, state_address, state_instruction,minimum_access_length, state_retention_priority)",
2360 operand_address = current_address + 1;
2365 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_length);
2366 if (show_instr_detail_level == 2 ){
2367 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_length %u",
2368 operand_address, state_length);
2373 operand_address = next_operand_address;
2374 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_address);
2375 if (show_instr_detail_level == 2 ){
2376 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_address %u",
2377 operand_address, state_address);
2380 * %state_instruction
2382 operand_address = next_operand_address;
2383 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_instruction);
2384 if (show_instr_detail_level == 2 ){
2385 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_instruction %u",
2386 operand_address, state_instruction);
2388 operand_address = next_operand_address;
2390 * %minimum_access_length
2392 operand_address = next_operand_address;
2393 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &minimum_access_length);
2394 if (show_instr_detail_level == 2 ){
2395 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u minimum_access_length %u",
2396 operand_address, minimum_access_length);
2398 operand_address = next_operand_address;
2400 * %state_retention_priority
2402 operand_address = next_operand_address;
2403 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_retention_priority);
2404 if (show_instr_detail_level == 2 ){
2405 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_retention_priority %u",
2406 operand_address, state_retention_priority);
2408 if (show_instr_detail_level == 1)
2410 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2411 "Addr: %u ## STATE-CREATE(32) (state_length=%u, state_address=%u, state_instruction=%u,minimum_access_length=%u, state_retention_priority=%u)",
2412 current_address, state_length, state_address, state_instruction,minimum_access_length, state_retention_priority);
2414 current_address = next_operand_address;
2415 /* Execute the instruction
2416 * TODO Implement the instruction
2418 * Note that the new state item cannot be created until a valid
2419 * compartment identifier has been returned by the application.
2420 * Consequently, when a STATE-CREATE instruction is encountered the UDVM
2421 * simply buffers the five supplied operands until the END-MESSAGE
2422 * instruction is reached. The steps taken at this point are described
2425 * Decompression failure MUST occur if more than four state creation
2426 * requests are made before the END-MESSAGE instruction is encountered.
2427 * Decompression failure also occurs if the minimum_access_length does
2428 * not lie between 6 and 20 inclusive, or if the
2429 * state_retention_priority is 65535.
2431 no_of_state_create++;
2432 if ( no_of_state_create > 4 ){
2434 goto decompression_failure;
2436 if (( minimum_access_length < 6 ) || ( minimum_access_length > STATE_BUFFER_SIZE )){
2438 goto decompression_failure;
2440 if ( state_retention_priority == 65535 ){
2442 goto decompression_failure;
2444 state_length_buff[no_of_state_create] = state_length;
2445 state_address_buff[no_of_state_create] = state_address;
2446 state_instruction_buff[no_of_state_create] = state_instruction;
2447 state_minimum_access_length_buff[no_of_state_create] = minimum_access_length;
2448 state_state_retention_priority_buff[no_of_state_create] = state_retention_priority;
2449 used_udvm_cycles = used_udvm_cycles + 1 + state_length;
2451 byte_copy_right = buff[66] << 8;
2452 byte_copy_right = byte_copy_right | buff[67];
2453 byte_copy_left = buff[64] << 8;
2454 byte_copy_left = byte_copy_left | buff[65];
2457 while ( n < state_length ){
2458 if ( k == byte_copy_right ){
2463 if (print_level_3 ){
2464 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2465 " Addr: %5u State value: %u (0x%x) ASCII(%s)",
2466 k,buff[k],buff[k],format_text(string, 1));
2468 k = ( k + 1 ) & 0xffff;
2473 goto execute_next_instruction;
2475 case SIGCOMP_INSTR_STATE_FREE: /* 33 */
2477 * STATE-FREE (%partial_identifier_start, %partial_identifier_length)
2479 if (show_instr_detail_level == 2 ){
2480 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2481 "Addr: %u ## STATE-FREE (partial_identifier_start, partial_identifier_length)",
2484 operand_address = current_address + 1;
2486 * %partial_identifier_start
2488 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &p_id_start);
2489 if (show_instr_detail_level == 2 ){
2490 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u partial_identifier_start %u",
2491 operand_address, p_id_start);
2493 operand_address = next_operand_address;
2496 * %partial_identifier_length
2498 operand_address = next_operand_address;
2499 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &p_id_length);
2500 if (show_instr_detail_level == 2 ){
2501 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u partial_identifier_length %u",
2502 operand_address, p_id_length);
2504 if (show_instr_detail_level == 1)
2506 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2507 "Addr: %u ## STATE-FREE (partial_identifier_start=%u, partial_identifier_length=%u)",
2508 current_address, p_id_start, p_id_length);
2510 current_address = next_operand_address;
2512 /* Execute the instruction:
2515 udvm_state_free(buff,p_id_start,p_id_length);
2518 goto execute_next_instruction;
2520 case SIGCOMP_INSTR_OUTPUT: /* 34 OUTPUT (%output_start, %output_length) */
2521 if (show_instr_detail_level == 2 ){
2522 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2523 "Addr: %u ## OUTPUT(34) (output_start, output_length)",
2526 operand_address = current_address + 1;
2530 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &output_start);
2531 if (show_instr_detail_level == 2 ){
2532 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u output_start %u",
2533 operand_address, output_start);
2535 operand_address = next_operand_address;
2539 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &output_length);
2540 if (show_instr_detail_level == 2 ){
2541 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u output_length %u",
2542 operand_address, output_length);
2544 if (show_instr_detail_level == 1)
2546 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2547 "Addr: %u ## OUTPUT (output_start=%u, output_length=%u)",
2548 current_address, output_start, output_length);
2550 current_address = next_operand_address;
2553 * Execute instruction
2556 * The string of bytes is copied in ascending order of memory address,
2557 * respecting the bounds set by byte_copy_left and byte_copy_right.
2558 * More precisely, if a byte is copied from/to Address m then the next
2559 * byte is copied from/to Address n where n is calculated as follows:
2561 * Set k := m + 1 (modulo 2^16)
2562 * If k = byte_copy_right then set n := byte_copy_left, else set n := k
2568 byte_copy_right = buff[66] << 8;
2569 byte_copy_right = byte_copy_right | buff[67];
2570 byte_copy_left = buff[64] << 8;
2571 byte_copy_left = byte_copy_left | buff[65];
2572 if (print_level_3 ){
2573 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2574 " byte_copy_right = %u", byte_copy_right);
2576 while ( n < output_length ){
2578 if ( k == byte_copy_right ){
2581 out_buff[output_address] = buff[k];
2584 if (print_level_3 ){
2585 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2586 " Output value: %u (0x%x) ASCII(%s) from Addr: %u ,output to dispatcher position %u",
2587 buff[k],buff[k],format_text(string,1), k,output_address);
2589 k = ( k + 1 ) & 0xffff;
2593 used_udvm_cycles = used_udvm_cycles + 1 + output_length;
2594 goto execute_next_instruction;
2596 case SIGCOMP_INSTR_END_MESSAGE: /* 35 */
2598 * END-MESSAGE (%requested_feedback_location,
2599 * %returned_parameters_location, %state_length, %state_address,
2600 * %state_instruction, %minimum_access_length,
2601 * %state_retention_priority)
2603 if (show_instr_detail_level == 2 ){
2604 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2605 "Addr: %u ## END-MESSAGE (requested_feedback_location,state_instruction, minimum_access_length,state_retention_priority)",
2608 operand_address = current_address + 1;
2610 /* %requested_feedback_location */
2611 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &requested_feedback_location);
2612 if (show_instr_detail_level == 2 ){
2613 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u requested_feedback_location %u",
2614 operand_address, requested_feedback_location);
2616 operand_address = next_operand_address;
2617 /* returned_parameters_location */
2618 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &returned_parameters_location);
2619 if (show_instr_detail_level == 2 ){
2620 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u returned_parameters_location %u",
2621 operand_address, returned_parameters_location);
2623 operand_address = next_operand_address;
2627 operand_address = next_operand_address;
2628 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_length);
2629 if (show_instr_detail_level == 2 ){
2630 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_length %u",
2631 operand_address, state_length);
2636 operand_address = next_operand_address;
2637 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_address);
2638 if (show_instr_detail_level == 2 ){
2639 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_address %u",
2640 operand_address, state_address);
2643 * %state_instruction
2645 operand_address = next_operand_address;
2646 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_instruction);
2647 if (show_instr_detail_level == 2 ){
2648 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_instruction %u",
2649 operand_address, state_instruction);
2653 * %minimum_access_length
2655 operand_address = next_operand_address;
2656 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &minimum_access_length);
2657 if (show_instr_detail_level == 2 ){
2658 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u minimum_access_length %u",
2659 operand_address, minimum_access_length);
2663 * %state_retention_priority
2665 operand_address = next_operand_address;
2666 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_retention_priority);
2667 if (show_instr_detail_level == 2 ){
2668 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_retention_priority %u",
2669 operand_address, state_retention_priority);
2671 if (show_instr_detail_level == 1)
2673 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2674 "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)",
2675 current_address, requested_feedback_location, returned_parameters_location, state_length, state_address, state_instruction, minimum_access_length,state_retention_priority);
2677 current_address = next_operand_address;
2678 /* TODO: This isn't currently totaly correct as END_INSTRUCTION might not create state */
2679 no_of_state_create++;
2680 if ( no_of_state_create > 4 ){
2682 goto decompression_failure;
2684 state_length_buff[no_of_state_create] = state_length;
2685 state_address_buff[no_of_state_create] = state_address;
2686 state_instruction_buff[no_of_state_create] = state_instruction;
2688 state_minimum_access_length_buff[no_of_state_create] = minimum_access_length;
2689 state_state_retention_priority_buff[no_of_state_create] = state_retention_priority;
2691 /* Execute the instruction
2693 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"no_of_state_create %u",no_of_state_create);
2694 if ( no_of_state_create != 0 ){
2695 memset(sha1_digest_buf, 0, STATE_BUFFER_SIZE);
2697 byte_copy_right = buff[66] << 8;
2698 byte_copy_right = byte_copy_right | buff[67];
2699 byte_copy_left = buff[64] << 8;
2700 byte_copy_left = byte_copy_left | buff[65];
2701 while ( n < no_of_state_create + 1 ){
2702 sha1buff = g_malloc(state_length_buff[n]+8);
2703 sha1buff[0] = state_length_buff[n] >> 8;
2704 sha1buff[1] = state_length_buff[n] & 0xff;
2705 sha1buff[2] = state_address_buff[n] >> 8;
2706 sha1buff[3] = state_address_buff[n] & 0xff;
2707 sha1buff[4] = state_instruction_buff[n] >> 8;
2708 sha1buff[5] = state_instruction_buff[n] & 0xff;
2709 sha1buff[6] = state_minimum_access_length_buff[n] >> 8;
2710 sha1buff[7] = state_minimum_access_length_buff[n] & 0xff;
2711 if (print_level_3 ){
2712 for( x=0; x < 8; x++){
2713 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"sha1buff %u 0x%x",
2717 k = state_address_buff[n];
2718 for( x=0; x < state_length_buff[n]; x++)
2720 if ( k == byte_copy_right ){
2723 sha1buff[8+x] = buff[k];
2724 k = ( k + 1 ) & 0xffff;
2727 sha1_starts( &ctx );
2728 sha1_update( &ctx, (guint8 *) sha1buff, state_length_buff[n] + 8);
2729 sha1_finish( &ctx, sha1_digest_buf );
2730 if (print_level_3 ){
2731 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"SHA1 digest %s",bytes_to_str(sha1_digest_buf, STATE_BUFFER_SIZE));
2734 udvm_state_create(sha1buff, sha1_digest_buf, state_minimum_access_length_buff[n]);
2735 proto_tree_add_text(udvm_tree,bytecode_tvb, 0, -1,"### Creating state ###");
2736 proto_tree_add_string(udvm_tree,hf_id, bytecode_tvb, 0, 0, bytes_to_str(sha1_digest_buf, state_minimum_access_length_buff[n]));
2745 /* At least something got decompressed, show it */
2746 decomp_tvb = tvb_new_real_data(out_buff,output_address,output_address);
2747 /* Arrange that the allocated packet data copy be freed when the
2750 tvb_set_free_cb( decomp_tvb, g_free );
2752 tvb_set_child_real_data_tvbuff(message_tvb,decomp_tvb);
2753 add_new_data_source(pinfo, decomp_tvb, "Decompressed SigComp message");
2755 proto_tree_add_text(udvm_tree, decomp_tvb, 0, -1,"SigComp message Decompressed");
2757 used_udvm_cycles = used_udvm_cycles + 1 + state_length;
2758 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"maximum_UDVM_cycles %u used_udvm_cycles %u",
2759 maximum_UDVM_cycles, used_udvm_cycles);
2764 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," ### Addr %u Invalid instruction: %u (0x%x)",
2765 current_address,current_instruction,current_instruction);
2770 decompression_failure:
2772 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"DECOMPRESSION FAILURE: %s",
2773 val_to_str(result_code, result_code_vals,"Unknown (%u)"));
2774 THROW(ReportedBoundsError);
2780 /* The simplest operand type is the literal (#), which encodes a
2781 * constant integer from 0 to 65535 inclusive. A literal operand may
2782 * require between 1 and 3 bytes depending on its value.
2783 * Bytecode: Operand value: Range:
2784 * 0nnnnnnn N 0 - 127
2785 * 10nnnnnn nnnnnnnn N 0 - 16383
2786 * 11000000 nnnnnnnn nnnnnnnn N 0 - 65535
2788 * Figure 8: Bytecode for a literal (#) operand
2792 decode_udvm_literal_operand(guint8 *buff,guint operand_address, guint16 *value)
2797 guint offset = operand_address;
2800 bytecode = buff[operand_address];
2801 test_bits = bytecode >> 7;
2802 if (test_bits == 1){
2803 test_bits = bytecode >> 6;
2804 if (test_bits == 2){
2806 * 10nnnnnn nnnnnnnn N 0 - 16383
2808 temp_data = buff[operand_address] & 0x1f;
2809 operand = temp_data << 8;
2810 temp_data = buff[operand_address + 1];
2811 operand = operand | temp_data;
2813 offset = offset + 2;
2817 * 111000000 nnnnnnnn nnnnnnnn N 0 - 65535
2820 temp_data = buff[operand_address] & 0x1f;
2821 operand = temp_data << 8;
2822 temp_data = buff[operand_address + 1];
2823 operand = operand | temp_data;
2825 offset = offset + 2;
2830 * 0nnnnnnn N 0 - 127
2832 operand = ( bytecode & 0x7f);
2842 * The second operand type is the reference ($), which is always used to
2843 * access a 2-byte value located elsewhere in the UDVM memory. The
2844 * bytecode for a reference operand is decoded to be a constant integer
2845 * from 0 to 65535 inclusive, which is interpreted as the memory address
2846 * containing the actual value of the operand.
2847 * Bytecode: Operand value: Range:
2849 * 0nnnnnnn memory[2 * N] 0 - 65535
2850 * 10nnnnnn nnnnnnnn memory[2 * N] 0 - 65535
2851 * 11000000 nnnnnnnn nnnnnnnn memory[N] 0 - 65535
2853 * Figure 9: Bytecode for a reference ($) operand
2856 dissect_udvm_reference_operand(guint8 *buff,guint operand_address, guint16 *value,guint *result_dest)
2860 guint offset = operand_address;
2863 guint16 temp_data16;
2865 bytecode = buff[operand_address];
2866 test_bits = bytecode >> 7;
2867 if (test_bits == 1){
2868 test_bits = bytecode >> 6;
2869 if (test_bits == 2){
2871 * 10nnnnnn nnnnnnnn memory[2 * N] 0 - 65535
2873 temp_data = buff[operand_address] & 0x3f;
2874 operand = temp_data << 8;
2875 temp_data = buff[operand_address + 1];
2876 operand = operand | temp_data;
2877 operand = (operand * 2);
2878 *result_dest = operand;
2879 temp_data16 = buff[operand] << 8;
2880 temp_data16 = temp_data16 | buff[operand+1];
2881 *value = temp_data16;
2882 offset = offset + 2;
2886 * 11000000 nnnnnnnn nnnnnnnn memory[N] 0 - 65535
2889 operand = buff[operand_address] << 8;
2890 operand = operand | buff[operand_address + 1];
2891 *result_dest = operand;
2892 temp_data16 = buff[operand] << 8;
2893 temp_data16 = temp_data16 | buff[operand+1];
2894 *value = temp_data16;
2895 offset = offset + 3;
2900 * 0nnnnnnn memory[2 * N] 0 - 65535
2902 operand = ( bytecode & 0x7f);
2903 operand = (operand * 2);
2904 *result_dest = operand;
2905 temp_data16 = buff[operand] << 8;
2906 temp_data16 = temp_data16 | buff[operand+1];
2907 *value = temp_data16;
2911 if (offset >= UDVM_MEMORY_SIZE || *result_dest >= UDVM_MEMORY_SIZE - 1 )
2912 THROW(ReportedBoundsError);
2918 * Figure 10: Bytecode for a multitype (%) operand
2919 * Bytecode: Operand value: Range: HEX val
2920 * 00nnnnnn N 0 - 63 0x00
2921 * 01nnnnnn memory[2 * N] 0 - 65535 0x40
2922 * 1000011n 2 ^ (N + 6) 64 , 128 0x86
2923 * 10001nnn 2 ^ (N + 8) 256 , ... , 32768 0x88
2924 * 111nnnnn N + 65504 65504 - 65535 0xe0
2925 * 1001nnnn nnnnnnnn N + 61440 61440 - 65535 0x90
2926 * 101nnnnn nnnnnnnn N 0 - 8191 0xa0
2927 * 110nnnnn nnnnnnnn memory[N] 0 - 65535 0xc0
2928 * 10000000 nnnnnnnn nnnnnnnn N 0 - 65535 0x80
2929 * 10000001 nnnnnnnn nnnnnnnn memory[N] 0 - 65535 0x81
2932 decode_udvm_multitype_operand(guint8 *buff,guint operand_address, guint16 *value)
2936 guint offset = operand_address;
2940 guint16 temp_data16;
2941 guint16 memmory_addr = 0;
2943 bytecode = buff[operand_address];
2944 test_bits = ( bytecode & 0xc0 ) >> 6;
2945 switch (test_bits ){
2950 operand = buff[operand_address];
2952 *g_warning("Reading 0x%x From address %u",operand,offset);
2959 * 01nnnnnn memory[2 * N] 0 - 65535
2961 memmory_addr = ( bytecode & 0x3f) * 2;
2962 temp_data16 = buff[memmory_addr] << 8;
2963 temp_data16 = temp_data16 | buff[memmory_addr+1];
2964 *value = temp_data16;
2968 /* Check tree most significant bits */
2969 test_bits = ( bytecode & 0xe0 ) >> 5;
2970 if ( test_bits == 5 ){
2972 * 101nnnnn nnnnnnnn N 0 - 8191
2974 temp_data = buff[operand_address] & 0x1f;
2975 operand = temp_data << 8;
2976 temp_data = buff[operand_address + 1];
2977 operand = operand | temp_data;
2979 offset = offset + 2;
2981 test_bits = ( bytecode & 0xf0 ) >> 4;
2982 if ( test_bits == 9 ){
2984 * 1001nnnn nnnnnnnn N + 61440 61440 - 65535
2986 temp_data = buff[operand_address] & 0x0f;
2987 operand = temp_data << 8;
2988 temp_data = buff[operand_address + 1];
2989 operand = operand | temp_data;
2990 operand = operand + 61440;
2992 offset = offset + 2;
2994 test_bits = ( bytecode & 0x08 ) >> 3;
2995 if ( test_bits == 1){
2997 * 10001nnn 2 ^ (N + 8) 256 , ... , 32768
3000 result = 1 << ((buff[operand_address] & 0x07) + 8);
3001 operand = result & 0xffff;
3005 test_bits = ( bytecode & 0x0e ) >> 1;
3006 if ( test_bits == 3 ){
3008 * 1000 011n 2 ^ (N + 6) 64 , 128
3010 result = 1 << ((buff[operand_address] & 0x01) + 6);
3011 operand = result & 0xffff;
3016 * 1000 0000 nnnnnnnn nnnnnnnn N 0 - 65535
3017 * 1000 0001 nnnnnnnn nnnnnnnn memory[N] 0 - 65535
3020 temp_data16 = buff[operand_address + 1] << 8;
3021 temp_data16 = temp_data16 | buff[operand_address + 2];
3023 * g_warning("Reading 0x%x From address %u",temp_data16,operand_address);
3025 if ( (bytecode & 0x01) == 1 ){
3026 memmory_addr = temp_data16;
3027 temp_data16 = buff[memmory_addr] << 8;
3028 temp_data16 = temp_data16 | buff[memmory_addr+1];
3030 *value = temp_data16;
3041 test_bits = ( bytecode & 0x20 ) >> 5;
3042 if ( test_bits == 1 ){
3044 * 111nnnnn N + 65504 65504 - 65535
3046 operand = ( buff[operand_address] & 0x1f) + 65504;
3051 * 110nnnnn nnnnnnnn memory[N] 0 - 65535
3053 memmory_addr = buff[operand_address] & 0x1f;
3054 memmory_addr = memmory_addr << 8;
3055 memmory_addr = memmory_addr | buff[operand_address + 1];
3056 temp_data16 = buff[memmory_addr] << 8;
3057 temp_data16 = temp_data16 | buff[memmory_addr+1];
3058 *value = temp_data16;
3060 * g_warning("Reading 0x%x From address %u",temp_data16,memmory_addr);
3072 * The fourth operand type is the address (@). This operand is decoded
3073 * as a multitype operand followed by a further step: the memory address
3074 * of the UDVM instruction containing the address operand is added to
3075 * obtain the correct operand value. So if the operand value from
3076 * Figure 10 is D then the actual operand value of an address is
3077 * calculated as follows:
3079 * operand_value = (memory_address_of_instruction + D) modulo 2^16
3081 * Address operands are always used in instructions that control program
3082 * flow, because they ensure that the UDVM bytecode is position-
3083 * independent code (i.e., it will run independently of where it is
3084 * placed in the UDVM memory).
3087 decode_udvm_address_operand(guint8 *buff,guint operand_address, guint16 *value,guint current_address)
3091 guint next_opreand_address;
3093 next_opreand_address = decode_udvm_multitype_operand(buff, operand_address, &value1);
3094 result = value1 & 0xffff;
3095 result = result + current_address;
3096 *value = result & 0xffff;
3097 return next_opreand_address;
3102 * This is a lookup table used to reverse the bits in a byte.
3104 static guint8 reverse [] = {
3105 0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0,
3106 0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0,
3107 0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8,
3108 0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8,
3109 0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4,
3110 0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4,
3111 0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC,
3112 0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC,
3113 0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2,
3114 0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2,
3115 0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA,
3116 0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA,
3117 0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6,
3118 0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6,
3119 0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE,
3120 0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE,
3121 0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1,
3122 0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1,
3123 0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9,
3124 0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9,
3125 0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5,
3126 0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5,
3127 0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED,
3128 0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD,
3129 0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3,
3130 0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3,
3131 0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB,
3132 0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB,
3133 0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7,
3134 0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7,
3135 0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF,
3136 0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF
3141 decomp_dispatch_get_bits(
3142 tvbuff_t *message_tvb,
3143 proto_tree *udvm_tree,
3146 guint16 *old_input_bit_order,
3147 guint16 *remaining_bits,
3148 guint16 *input_bits,
3149 guint *input_address,
3151 guint16 *result_code,
3154 guint16 input_bit_order;
3155 guint16 bits_still_required = length;
3158 gint extra_bytes_available = msg_end - *input_address;
3160 gint prev_p_bit = *old_input_bit_order & 0x0001;
3161 gint bits_to_use = 0;
3164 input_bit_order = buff[68] << 8;
3165 input_bit_order = input_bit_order | buff[69];
3167 p_bit = (input_bit_order & 0x0001) != 0;
3170 * Discard any spare bits.
3171 * Note: We take care to avoid remaining_bits having the value of 8.
3173 if (prev_p_bit != p_bit)
3175 *remaining_bits = 0;
3176 *old_input_bit_order = input_bit_order;
3180 * Check we can suppy the required number of bits now, before we alter
3181 * the input buffer's state.
3183 if (*remaining_bits + extra_bytes_available * 8 < length)
3189 /* Note: This is never called with length > 16, so the following loop
3190 * never loops more than three time. */
3191 while (bits_still_required > 0)
3194 * We only put anything into input_bits if we know we will remove
3195 * at least one bit. That ensures we can simply discard the spare
3196 * bits if the P-bit changes.
3198 if (*remaining_bits == 0)
3200 octet = tvb_get_guint8(message_tvb, *input_address);
3201 if (print_level_1 ){
3202 proto_tree_add_text(udvm_tree, message_tvb, *input_address , 1,
3203 " Geting value: %u (0x%x) From Addr: %u", octet, octet, *input_address);
3205 *input_address = *input_address + 1;
3209 octet = reverse[octet];
3211 *input_bits = octet;
3212 *remaining_bits = 8;
3215 /* Add some more bits to the accumulated value. */
3216 bits_to_use = bits_still_required < *remaining_bits ? bits_still_required : *remaining_bits;
3217 bits_still_required -= bits_to_use;
3219 *input_bits <<= bits_to_use; /* Shift bits into MSByte */
3220 value = (value << bits_to_use) /* Then add to the accumulated value */
3221 | ((*input_bits >> 8) & 0xFF);
3222 *remaining_bits -= bits_to_use;
3223 *input_bits &= 0x00FF; /* Leave just the remaining bits */
3228 /* Bit reverse the entire word. */
3229 guint16 lsb = reverse[(value >> 8) & 0xFF];
3230 guint16 msb = reverse[value & 0xFF];
3232 value = ((msb << 8) | lsb) >> (16 - length);