2 * Routines making up the Universal Decompressor Virtual Machine (UDVM) used for
3 * Signaling Compression (SigComp) dissection.
4 * Copyright 2004, Anders Broman <anders.broman@ericsson.com>
8 * Wireshark - Network traffic analyzer
9 * By Gerald Combs <gerald@wireshark.org>
10 * Copyright 1998 Gerald Combs
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
26 * http://www.ietf.org/rfc/rfc3320.txt?number=3320
27 * http://www.ietf.org/rfc/rfc3321.txt?number=3321
29 * http://www.ietf.org/internet-drafts/draft-ietf-rohc-sigcomp-impl-guide-05.txt
30 * http://www.ietf.org/internet-drafts/draft-ietf-rohc-sigcomp-sip-01.txt
44 #include "sigcomp-udvm.h"
45 #include "sigcomp_state_hdlr.h"
46 #include "crypt/crypt-sha1.h"
50 #define SIGCOMP_INSTR_DECOMPRESSION_FAILURE 0
51 #define SIGCOMP_INSTR_AND 1
52 #define SIGCOMP_INSTR_OR 2
53 #define SIGCOMP_INSTR_NOT 3
54 #define SIGCOMP_INSTR_LSHIFT 4
55 #define SIGCOMP_INSTR_RSHIFT 5
56 #define SIGCOMP_INSTR_ADD 6
57 #define SIGCOMP_INSTR_SUBTRACT 7
58 #define SIGCOMP_INSTR_MULTIPLY 8
59 #define SIGCOMP_INSTR_DIVIDE 9
60 #define SIGCOMP_INSTR_REMAINDER 10
61 #define SIGCOMP_INSTR_SORT_ASCENDING 11
62 #define SIGCOMP_INSTR_SORT_DESCENDING 12
63 #define SIGCOMP_INSTR_SHA_1 13
64 #define SIGCOMP_INSTR_LOAD 14
65 #define SIGCOMP_INSTR_MULTILOAD 15
66 #define SIGCOMP_INSTR_PUSH 16
67 #define SIGCOMP_INSTR_POP 17
68 #define SIGCOMP_INSTR_COPY 18
69 #define SIGCOMP_INSTR_COPY_LITERAL 19
70 #define SIGCOMP_INSTR_COPY_OFFSET 20
71 #define SIGCOMP_INSTR_MEMSET 21
72 #define SIGCOMP_INSTR_JUMP 22
73 #define SIGCOMP_INSTR_COMPARE 23
74 #define SIGCOMP_INSTR_CALL 24
75 #define SIGCOMP_INSTR_RETURN 25
76 #define SIGCOMP_INSTR_SWITCH 26
77 #define SIGCOMP_INSTR_CRC 27
78 #define SIGCOMP_INSTR_INPUT_BYTES 28
79 #define SIGCOMP_INSTR_INPUT_BITS 29
80 #define SIGCOMP_INSTR_INPUT_HUFFMAN 30
81 #define SIGCOMP_INSTR_STATE_ACCESS 31
82 #define SIGCOMP_INSTR_STATE_CREATE 32
83 #define SIGCOMP_INSTR_STATE_FREE 33
84 #define SIGCOMP_INSTR_OUTPUT 34
85 #define SIGCOMP_INSTR_END_MESSAGE 35
88 static gboolean print_level_1;
89 static gboolean print_level_2;
90 static gboolean print_level_3;
91 static gint show_instr_detail_level;
93 /* Internal result code values of decompression failures */
94 const value_string result_code_vals[] = {
95 { 0, "No decompression failure" },
96 { 1, "Partial state length less than 6 or greater than 20 bytes long" },
97 { 2, "No state match" },
98 { 3, "state_begin + state_length > size of state" },
99 { 4, "Operand_2 is Zero" },
100 { 5, "Switch statement failed j >= n" },
101 { 6, "Attempt to jump outside of UDVM memory" },
102 { 7, "L in input-bits > 16" },
103 { 8, "input_bit_order > 7" },
104 { 9, "Instruction Decompression failure encountered" },
105 {10, "Input huffman failed j > n" },
106 {11, "Input bits requested beyond end of message" },
107 {12, "more than four state creation requests are made before the END-MESSAGE instruction" },
108 {13, "state_retention_priority is 65535" },
109 {14, "Input bytes requested beyond end of message" },
110 {15, "Maximum number of UDVM cycles reached" },
111 {16, "UDVM stack underflow" },
112 { 255, "This branch isn't coded yet" },
116 static int decode_udvm_literal_operand(guint8 *buff,guint operand_address, guint16 *value);
117 static int dissect_udvm_reference_operand(guint8 *buff,guint operand_address, guint16 *value, guint *result_dest);
118 static int decode_udvm_multitype_operand(guint8 *buff,guint operand_address,guint16 *value);
119 static int decode_udvm_address_operand(guint8 *buff,guint operand_address, guint16 *value,guint current_address);
120 static int decomp_dispatch_get_bits(tvbuff_t *message_tvb,proto_tree *udvm_tree,guint8 bit_order,
121 guint8 *buff,guint16 *old_input_bit_order, guint16 *remaining_bits,
122 guint16 *input_bits, guint *input_address, guint16 length, guint16 *result_code,guint msg_end);
126 decompress_sigcomp_message(tvbuff_t *bytecode_tvb, tvbuff_t *message_tvb, packet_info *pinfo,
127 proto_tree *udvm_tree, gint udvm_mem_dest,
128 gint print_flags, gint hf_id,
130 gint byte_code_state_len, gint byte_code_id_len,
133 tvbuff_t *decomp_tvb;
134 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_child_real_data(message_tvb, 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 add_new_data_source(pinfo, decomp_tvb, "Decompressed SigComp message(Incomplete)");
365 proto_tree_add_text(udvm_tree, decomp_tvb, 0, -1,"SigComp message Decompression failure");
372 case SIGCOMP_INSTR_AND: /* 1 AND ($operand_1, %operand_2) */
374 if (show_instr_detail_level == 2 ){
375 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
376 "Addr: %u ## AND(1) (operand_1, operand_2)",
380 operand_address = current_address + 1;
381 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &operand_1, &result_dest);
382 if (show_instr_detail_level == 2 ){
383 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_1 %u",
384 operand_address, operand_1);
386 operand_address = next_operand_address;
388 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &operand_2);
389 if (show_instr_detail_level == 2 ){
390 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_2 %u",
391 operand_address, operand_2);
393 if (show_instr_detail_level == 1)
395 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
396 "Addr: %u ## AND (operand_1=%u, operand_2=%u)",
397 current_address, operand_1, operand_2);
399 /* execute the instruction */
400 result = operand_1 & operand_2;
403 buff[result_dest] = msb;
404 buff[result_dest+1] = lsb;
406 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," Loading result %u at %u",
407 result, result_dest);
409 current_address = next_operand_address;
410 goto execute_next_instruction;
414 case SIGCOMP_INSTR_OR: /* 2 OR ($operand_1, %operand_2) */
416 if (show_instr_detail_level == 2 ){
417 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
418 "Addr: %u ## OR(2) (operand_1, operand_2)",
422 operand_address = current_address + 1;
423 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &operand_1, &result_dest);
424 if (show_instr_detail_level == 2 ){
425 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_1 %u",
426 operand_address, operand_1);
428 operand_address = next_operand_address;
430 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &operand_2);
431 if (show_instr_detail_level == 2 ){
432 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_2 %u",
433 operand_address, operand_2);
435 if (show_instr_detail_level == 1)
437 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
438 "Addr: %u ## OR (operand_1=%u, operand_2=%u)",
439 current_address, operand_1, operand_2);
441 /* execute the instruction */
442 result = operand_1 | operand_2;
445 buff[result_dest] = msb;
446 buff[result_dest+1] = lsb;
448 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," Loading result %u at %u",
449 result, result_dest);
451 current_address = next_operand_address;
452 goto execute_next_instruction;
456 case SIGCOMP_INSTR_NOT: /* 3 NOT ($operand_1) */
458 if (show_instr_detail_level == 2 ){
459 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
460 "Addr: %u ## NOT(3) ($operand_1)",
464 operand_address = current_address + 1;
465 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &operand_1, &result_dest);
466 if (show_instr_detail_level == 2 ){
467 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_1 %u",
468 operand_address, operand_1);
470 if (show_instr_detail_level == 1)
472 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
473 "Addr: %u ## NOT (operand_1=%u)",
474 current_address, operand_1);
476 /* execute the instruction */
477 result = operand_1 ^ 0xffff;
480 buff[result_dest] = msb;
481 buff[result_dest+1] = lsb;
483 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," Loading result %u at %u",
484 result, result_dest);
486 current_address = next_operand_address;
487 goto execute_next_instruction;
490 case SIGCOMP_INSTR_LSHIFT: /* 4 LSHIFT ($operand_1, %operand_2) */
492 if (show_instr_detail_level == 2 ){
493 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
494 "Addr: %u ## LSHIFT(4) ($operand_1, operand_2)",
498 operand_address = current_address + 1;
499 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &operand_1, &result_dest);
500 if (show_instr_detail_level == 2 ){
501 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_1 %u",
502 operand_address, operand_1);
504 operand_address = next_operand_address;
506 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &operand_2);
507 if (show_instr_detail_level == 2 ){
508 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_2 %u",
509 operand_address, operand_2);
511 if (show_instr_detail_level == 1)
513 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
514 "Addr: %u ## LSHIFT (operand_1=%u, operand_2=%u)",
515 current_address, operand_1, operand_2);
517 /* execute the instruction */
518 result = operand_1 << operand_2;
521 buff[result_dest] = msb;
522 buff[result_dest+1] = lsb;
524 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," Loading result %u at %u",
525 result, result_dest);
527 current_address = next_operand_address;
528 goto execute_next_instruction;
531 case SIGCOMP_INSTR_RSHIFT: /* 5 RSHIFT ($operand_1, %operand_2) */
533 if (show_instr_detail_level == 2 ){
534 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
535 "Addr: %u ## RSHIFT(5) (operand_1, operand_2)",
539 operand_address = current_address + 1;
540 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &operand_1, &result_dest);
541 if (show_instr_detail_level == 2 ){
542 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_1 %u",
543 operand_address, operand_1);
545 operand_address = next_operand_address;
547 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &operand_2);
548 if (show_instr_detail_level == 2 ){
549 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_2 %u",
550 operand_address, operand_2);
552 if (show_instr_detail_level == 1)
554 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
555 "Addr: %u ## RSHIFT (operand_1=%u, operand_2=%u)",
556 current_address, operand_1, operand_2);
558 /* execute the instruction */
559 result = operand_1 >> operand_2;
562 buff[result_dest] = msb;
563 buff[result_dest+1] = lsb;
565 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," Loading result %u at %u",
566 result, result_dest);
568 current_address = next_operand_address;
569 goto execute_next_instruction;
571 case SIGCOMP_INSTR_ADD: /* 6 ADD ($operand_1, %operand_2) */
573 if (show_instr_detail_level == 2 ){
574 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
575 "Addr: %u ## ADD(6) (operand_1, operand_2)",
579 operand_address = current_address + 1;
580 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &operand_1, &result_dest);
581 if (show_instr_detail_level == 2 ){
582 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_1 %u",
583 operand_address, operand_1);
585 operand_address = next_operand_address;
587 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &operand_2);
588 if (show_instr_detail_level == 2 ){
589 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_2 %u",
590 operand_address, operand_2);
592 if (show_instr_detail_level == 1)
594 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
595 "Addr: %u ## ADD (operand_1=%u, operand_2=%u)",
596 current_address, operand_1, operand_2);
598 /* execute the instruction */
599 result = operand_1 + operand_2;
602 buff[result_dest] = msb;
603 buff[result_dest+1] = lsb;
605 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," Loading result %u at %u",
606 result, result_dest);
608 current_address = next_operand_address;
609 goto execute_next_instruction;
611 case SIGCOMP_INSTR_SUBTRACT: /* 7 SUBTRACT ($operand_1, %operand_2) */
613 if (show_instr_detail_level == 2 ){
614 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
615 "Addr: %u ## SUBTRACT(7) (operand_1, operand_2)",
619 operand_address = current_address + 1;
620 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &operand_1, &result_dest);
621 if (show_instr_detail_level == 2 ){
622 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_1 %u",
623 operand_address, operand_1);
625 operand_address = next_operand_address;
627 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &operand_2);
628 if (show_instr_detail_level == 2 ){
629 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_2 %u",
630 operand_address, operand_2);
632 if (show_instr_detail_level == 1)
634 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
635 "Addr: %u ## SUBTRACT (operand_1=%u, operand_2=%u)",
636 current_address, operand_1, operand_2);
638 /* execute the instruction */
639 result = operand_1 - operand_2;
642 buff[result_dest] = msb;
643 buff[result_dest+1] = lsb;
645 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," Loading result %u at %u",
646 result, result_dest);
648 current_address = next_operand_address;
649 goto execute_next_instruction;
652 case SIGCOMP_INSTR_MULTIPLY: /* 8 MULTIPLY ($operand_1, %operand_2) */
654 if (show_instr_detail_level == 2 ){
655 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
656 "Addr: %u ##MULTIPLY(8) (operand_1, operand_2)",
660 operand_address = current_address + 1;
661 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &operand_1, &result_dest);
662 if (show_instr_detail_level == 2 ){
663 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_1 %u",
664 operand_address, operand_1);
666 operand_address = next_operand_address;
668 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &operand_2);
669 if (show_instr_detail_level == 2 ){
670 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_2 %u",
671 operand_address, operand_2);
673 if (show_instr_detail_level == 1)
675 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
676 "Addr: %u ## MULTIPLY (operand_1=%u, operand_2=%u)",
677 current_address, operand_1, operand_2);
680 * execute the instruction
681 * MULTIPLY (m, n) := m * n (modulo 2^16)
683 if ( operand_2 == 0){
685 goto decompression_failure;
687 result = operand_1 * operand_2;
690 buff[result_dest] = msb;
691 buff[result_dest+1] = lsb;
693 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," Loading result %u at %u",
694 result, result_dest);
696 current_address = next_operand_address;
697 goto execute_next_instruction;
700 case SIGCOMP_INSTR_DIVIDE: /* 9 DIVIDE ($operand_1, %operand_2) */
702 if (show_instr_detail_level == 2 ){
703 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
704 "Addr: %u ## DIVIDE(9) (operand_1, operand_2)",
708 operand_address = current_address + 1;
709 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &operand_1, &result_dest);
710 if (show_instr_detail_level == 2 ){
711 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_1 %u",
712 operand_address, operand_1);
714 operand_address = next_operand_address;
716 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &operand_2);
717 if (show_instr_detail_level == 2 ){
718 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_2 %u",
719 operand_address, operand_2);
721 if (show_instr_detail_level == 1)
723 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
724 "Addr: %u ## DIVIDE (operand_1=%u, operand_2=%u)",
725 current_address, operand_1, operand_2);
728 * execute the instruction
729 * DIVIDE (m, n) := floor(m / n)
730 * Decompression failure occurs if a DIVIDE or REMAINDER instruction
731 * encounters an operand_2 that is zero.
733 if ( operand_2 == 0){
735 goto decompression_failure;
737 result = operand_1 / operand_2;
740 buff[result_dest] = msb;
741 buff[result_dest+1] = lsb;
743 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," Loading result %u at %u",
744 result, result_dest);
746 current_address = next_operand_address;
747 goto execute_next_instruction;
750 case SIGCOMP_INSTR_REMAINDER: /* 10 REMAINDER ($operand_1, %operand_2) */
752 if (show_instr_detail_level == 2 ){
753 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
754 "Addr: %u ## REMAINDER(10) (operand_1, operand_2)",
758 operand_address = current_address + 1;
759 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &operand_1, &result_dest);
760 if (show_instr_detail_level == 2 ){
761 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_1 %u",
762 operand_address, operand_1);
764 operand_address = next_operand_address;
766 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &operand_2);
767 if (show_instr_detail_level == 2 ){
768 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_2 %u",
769 operand_address, operand_2);
771 if (show_instr_detail_level == 1)
773 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
774 "Addr: %u ## REMAINDER (operand_1=%u, operand_2=%u)",
775 current_address, operand_1, operand_2);
778 * execute the instruction
779 * REMAINDER (m, n) := m - n * floor(m / n)
780 * Decompression failure occurs if a DIVIDE or REMAINDER instruction
781 * encounters an operand_2 that is zero.
783 if ( operand_2 == 0){
785 goto decompression_failure;
787 result = operand_1 - operand_2 * (operand_1 / operand_2);
790 buff[result_dest] = msb;
791 buff[result_dest+1] = lsb;
793 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," Loading result %u at %u",
794 result, result_dest);
796 current_address = next_operand_address;
797 goto execute_next_instruction;
799 case SIGCOMP_INSTR_SORT_ASCENDING: /* 11 SORT-ASCENDING (%start, %n, %k) */
801 * used_udvm_cycles = 1 + k * (ceiling(log2(k)) + n)
804 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
805 "Addr: %u ## SORT-ASCENDING(11) (start, n, k))",
808 operand_address = current_address + 1;
809 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Execution of this instruction is NOT implemented");
811 * used_udvm_cycles = 1 + k * (ceiling(log2(k)) + n)
815 case SIGCOMP_INSTR_SORT_DESCENDING: /* 12 SORT-DESCENDING (%start, %n, %k) */
817 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
818 "Addr: %u ## SORT-DESCENDING(12) (start, n, k))",
821 operand_address = current_address + 1;
822 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Execution of this instruction is NOT implemented");
824 * used_udvm_cycles = 1 + k * (ceiling(log2(k)) + n)
827 case SIGCOMP_INSTR_SHA_1: /* 13 SHA-1 (%position, %length, %destination) */
829 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
830 "Addr: %u ## SHA-1(13) (position, length, destination)",
833 operand_address = current_address + 1;
835 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &position);
837 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u position %u",
838 operand_address, position);
840 operand_address = next_operand_address;
843 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &length);
845 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Length %u",
846 operand_address, length);
848 operand_address = next_operand_address;
851 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &ref_destination, &result_dest);
853 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u $destination %u",
854 operand_address, ref_destination);
856 current_address = next_operand_address;
857 used_udvm_cycles = used_udvm_cycles + 1 + length;
861 byte_copy_right = buff[66] << 8;
862 byte_copy_right = byte_copy_right | buff[67];
863 byte_copy_left = buff[64] << 8;
864 byte_copy_left = byte_copy_left | buff[65];
867 proto_tree_add_text(udvm_tree, message_tvb, 0, -1,
868 "byte_copy_right = %u", byte_copy_right);
874 guint16 handle_now = length;
876 if ( k < byte_copy_right && byte_copy_right <= k + (length-n) ){
877 handle_now = byte_copy_right - position;
880 if (k + handle_now >= UDVM_MEMORY_SIZE)
881 goto decompression_failure;
882 sha1_update( &ctx, &buff[k], handle_now );
884 k = ( k + handle_now ) & 0xffff;
885 n = ( n + handle_now ) & 0xffff;
887 if ( k >= byte_copy_right ) {
892 sha1_finish( &ctx, sha1_digest_buf );
896 for ( n=0; n< STATE_BUFFER_SIZE; n++ ) {
898 buff[k] = sha1_digest_buf[n];
900 k = ( k + 1 ) & 0xffff;
903 if ( k == byte_copy_right ){
909 proto_tree_add_text(udvm_tree, message_tvb, 0, -1,
910 "Calculated SHA-1: %s",
911 bytes_to_str(sha1_digest_buf, STATE_BUFFER_SIZE));
914 current_address = next_operand_address;
915 goto execute_next_instruction;
918 case SIGCOMP_INSTR_LOAD: /* 14 LOAD (%address, %value) */
919 if (show_instr_detail_level == 2 ){
920 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
921 "Addr: %u ## LOAD(14) (%%address, %%value)",
924 operand_address = current_address + 1;
926 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &address);
927 if (show_instr_detail_level == 2 ){
928 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Address %u",
929 operand_address, address);
931 operand_address = next_operand_address;
933 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &value);
934 if (show_instr_detail_level == 1)
936 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
937 "Addr: %u ## LOAD (%%address=%u, %%value=%u)",
938 current_address, address, value);
944 buff[address + 1] = lsb;
947 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Value %u",
948 operand_address, value);
949 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," Loading bytes at %u Value %u 0x%x",
950 address, value, value);
953 current_address = next_operand_address;
954 goto execute_next_instruction;
957 case SIGCOMP_INSTR_MULTILOAD: /* 15 MULTILOAD (%address, #n, %value_0, ..., %value_n-1) */
959 * The MULTILOAD instruction sets a contiguous block of 2-byte words in
960 * the UDVM memory to specified values.
961 * Hmm what if the value to load only takes one byte ? Chose to always load two bytes.
963 if (show_instr_detail_level == 2 ){
964 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
965 "Addr: %u ## MULTILOAD(15) (%%address, #n, value_0, ..., value_n-1)",
968 operand_address = current_address + 1;
970 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &address);
971 if (show_instr_detail_level == 2 ){
972 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Address %u",
973 operand_address, address);
975 operand_address = next_operand_address;
978 next_operand_address = decode_udvm_literal_operand(buff,operand_address, &n);
979 if (show_instr_detail_level == 2 ){
980 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u n %u",
983 if (show_instr_detail_level == 1)
985 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
986 "Addr: %u ## MULTILOAD (%%address=%u, #n=%u, value_0, ..., value_%d)",
987 current_address, address, n, n-1);
989 operand_address = next_operand_address;
990 used_udvm_cycles = used_udvm_cycles + 1 + n;
994 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &value);
998 if (address >= UDVM_MEMORY_SIZE - 1)
999 goto decompression_failure;
1001 buff[address] = msb;
1002 buff[address + 1] = lsb;
1005 length = next_operand_address - operand_address;
1007 if (print_level_1 ){
1008 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1, "Addr: %u Value %5u - Loading bytes at %5u Value %5u 0x%x",
1009 operand_address, value, address, value, value);
1011 address = address + 2;
1012 operand_address = next_operand_address;
1014 current_address = next_operand_address;
1015 goto execute_next_instruction;
1019 case SIGCOMP_INSTR_PUSH: /* 16 PUSH (%value) */
1020 if (show_instr_detail_level == 2){
1021 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1022 "Addr: %u ## PUSH(16) (value)",
1025 operand_address = current_address + 1;
1027 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &value);
1028 if (show_instr_detail_level == 2){
1029 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Value %u",
1030 operand_address, value);
1032 if (show_instr_detail_level == 1)
1034 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1035 "Addr: %u ## PUSH (value=%u)",
1036 current_address, value);
1038 current_address = next_operand_address;
1040 /* Push the value address onto the stack */
1041 stack_location = (buff[70] << 8) | buff[71];
1042 stack_fill = (buff[stack_location] << 8)
1043 | buff[(stack_location+1) & 0xFFFF];
1044 address = (stack_location + stack_fill * 2 + 2) & 0xFFFF;
1046 if (address >= UDVM_MEMORY_SIZE - 1)
1047 goto decompression_failure;
1049 buff[address] = (value >> 8) & 0x00FF;
1050 buff[(address+1) & 0xFFFF] = value & 0x00FF;
1052 if (stack_location >= UDVM_MEMORY_SIZE - 1)
1053 goto decompression_failure;
1055 stack_fill = (stack_fill + 1) & 0xFFFF;
1056 buff[stack_location] = (stack_fill >> 8) & 0x00FF;
1057 buff[(stack_location+1) & 0xFFFF] = stack_fill & 0x00FF;
1060 goto execute_next_instruction;
1064 case SIGCOMP_INSTR_POP: /* 17 POP (%address) */
1065 if (show_instr_detail_level == 2){
1066 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1067 "Addr: %u ## POP(16) (value)",
1070 operand_address = current_address + 1;
1072 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &destination);
1073 if (show_instr_detail_level == 2){
1074 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Value %u",
1075 operand_address, destination);
1077 if (show_instr_detail_level == 1)
1079 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1080 "Addr: %u ## POP (address=%u)",
1081 current_address, destination);
1083 current_address = next_operand_address;
1085 /* Pop value from the top of the stack */
1086 stack_location = (buff[70] << 8) | buff[71];
1087 stack_fill = (buff[stack_location] << 8)
1088 | buff[(stack_location+1) & 0xFFFF];
1089 if (stack_fill == 0)
1092 goto decompression_failure;
1095 if (stack_location >= UDVM_MEMORY_SIZE - 1)
1096 goto decompression_failure;
1098 stack_fill = (stack_fill - 1) & 0xFFFF;
1099 buff[stack_location] = (stack_fill >> 8) & 0x00FF;
1100 buff[(stack_location+1) & 0xFFFF] = stack_fill & 0x00FF;
1102 address = (stack_location + stack_fill * 2 + 2) & 0xFFFF;
1104 if (address >= UDVM_MEMORY_SIZE - 1)
1105 goto decompression_failure;
1107 value = (buff[address] << 8)
1108 | buff[(address+1) & 0xFFFF];
1110 /* ... and store the popped value. */
1111 if (destination >= UDVM_MEMORY_SIZE - 1)
1112 goto decompression_failure;
1113 buff[destination] = (value >> 8) & 0x00FF;
1114 buff[(destination+1) & 0xFFFF] = value & 0x00FF;
1117 goto execute_next_instruction;
1121 case SIGCOMP_INSTR_COPY: /* 18 COPY (%position, %length, %destination) */
1122 if (show_instr_detail_level == 2 ){
1123 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1124 "Addr: %u ## COPY(18) (position, length, destination)",
1127 operand_address = current_address + 1;
1129 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &position);
1130 if (show_instr_detail_level == 2 ){
1131 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u position %u",
1132 operand_address, position);
1134 operand_address = next_operand_address;
1137 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &length);
1138 if (show_instr_detail_level == 2 ){
1139 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Length %u",
1140 operand_address, length);
1142 operand_address = next_operand_address;
1145 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &destination);
1146 if (show_instr_detail_level == 2 ){
1147 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Destination %u",
1148 operand_address, destination);
1150 if (show_instr_detail_level == 1)
1152 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1153 "Addr: %u ## COPY (position=%u, length=%u, destination=%u)",
1154 current_address, position, length, destination);
1156 current_address = next_operand_address;
1160 * The string of bytes is copied in ascending order of memory address,
1161 * respecting the bounds set by byte_copy_left and byte_copy_right.
1162 * More precisely, if a byte is copied from/to Address m then the next
1163 * byte is copied from/to Address n where n is calculated as follows:
1165 * Set k := m + 1 (modulo 2^16)
1166 * If k = byte_copy_right then set n := byte_copy_left, else set n := k
1172 byte_copy_right = buff[66] << 8;
1173 byte_copy_right = byte_copy_right | buff[67];
1174 byte_copy_left = buff[64] << 8;
1175 byte_copy_left = byte_copy_left | buff[65];
1176 if (print_level_2 ){
1177 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
1178 " byte_copy_right = %u", byte_copy_right);
1181 while ( n < length ){
1182 buff[k] = buff[position];
1183 if (print_level_2 ){
1184 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
1185 " Copying value: %u (0x%x) to Addr: %u",
1186 buff[position], buff[position], k);
1188 position = ( position + 1 ) & 0xffff;
1189 k = ( k + 1 ) & 0xffff;
1193 * Check for circular buffer wrapping after the positions are
1194 * incremented. If either started at BCR then they should continue
1195 * to increment beyond BCR.
1197 if ( k == byte_copy_right ){
1200 if ( position == byte_copy_right ){
1201 position = byte_copy_left;
1204 used_udvm_cycles = used_udvm_cycles + 1 + length;
1205 goto execute_next_instruction;
1208 case SIGCOMP_INSTR_COPY_LITERAL: /* 19 COPY-LITERAL (%position, %length, $destination) */
1209 if (show_instr_detail_level == 2 ){
1210 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1211 "Addr: %u ## COPY-LITERAL(19) (position, length, $destination)",
1214 operand_address = current_address + 1;
1216 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &position);
1217 if (show_instr_detail_level == 2 ){
1218 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u position %u",
1219 operand_address, position);
1221 operand_address = next_operand_address;
1224 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &length);
1225 if (show_instr_detail_level == 2 ){
1226 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Length %u",
1227 operand_address, length);
1229 operand_address = next_operand_address;
1233 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &ref_destination, &result_dest);
1234 if (show_instr_detail_level == 2 ){
1235 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u destination %u",
1236 operand_address, ref_destination);
1238 if (show_instr_detail_level == 1)
1240 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1241 "Addr: %u ## COPY-LITERAL (position=%u, length=%u, $destination=%u)",
1242 current_address, position, length, ref_destination);
1244 current_address = next_operand_address;
1250 * The string of bytes is copied in ascending order of memory address,
1251 * respecting the bounds set by byte_copy_left and byte_copy_right.
1252 * More precisely, if a byte is copied from/to Address m then the next
1253 * byte is copied from/to Address n where n is calculated as follows:
1255 * Set k := m + 1 (modulo 2^16)
1256 * If k = byte_copy_right then set n := byte_copy_left, else set n := k
1261 k = ref_destination;
1262 byte_copy_right = buff[66] << 8;
1263 byte_copy_right = byte_copy_right | buff[67];
1264 byte_copy_left = buff[64] << 8;
1265 byte_copy_left = byte_copy_left | buff[65];
1266 if (print_level_2 ){
1267 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
1268 " byte_copy_right = %u", byte_copy_right);
1270 while ( n < length ){
1272 buff[k] = buff[position];
1273 if (print_level_2 ){
1274 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
1275 " Copying value: %u (0x%x) to Addr: %u",
1276 buff[position], buff[position], k);
1278 position = ( position + 1 ) & 0xffff;
1279 k = ( k + 1 ) & 0xffff;
1283 * Check for circular buffer wrapping after the positions are
1284 * incremented. It is important that k cannot be left set
1285 * to BCR. Also, if either started at BCR then they should continue
1286 * to increment beyond BCR.
1288 if ( k == byte_copy_right ){
1291 if ( position == byte_copy_right ){
1292 position = byte_copy_left;
1295 buff[result_dest] = k >> 8;
1296 buff[result_dest + 1] = k & 0x00ff;
1298 used_udvm_cycles = used_udvm_cycles + 1 + length;
1299 goto execute_next_instruction;
1302 case SIGCOMP_INSTR_COPY_OFFSET: /* 20 COPY-OFFSET (%offset, %length, $destination) */
1303 if (show_instr_detail_level == 2 ){
1304 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1305 "Addr: %u ## COPY-OFFSET(20) (offset, length, $destination)",
1308 operand_address = current_address + 1;
1310 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &multy_offset);
1311 if (show_instr_detail_level == 2 ){
1312 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u offset %u",
1313 operand_address, multy_offset);
1315 operand_address = next_operand_address;
1318 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &length);
1319 if (show_instr_detail_level == 2 ){
1320 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Length %u",
1321 operand_address, length);
1323 operand_address = next_operand_address;
1327 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &ref_destination, &result_dest);
1328 if (show_instr_detail_level == 2 ){
1329 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u $destination %u",
1330 operand_address, ref_destination);
1333 if (show_instr_detail_level == 1)
1335 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1336 "Addr: %u ## COPY-OFFSET (offset=%u, length=%u, $destination=%u)",
1337 current_address, multy_offset, length, result_dest);
1339 current_address = next_operand_address;
1341 /* Execute the instruction:
1342 * To derive the value of the position operand, starting at the memory
1343 * address specified by destination, the UDVM counts backwards a total
1344 * of offset memory addresses.
1346 * If the memory address specified in byte_copy_left is reached, the
1347 * next memory address is taken to be (byte_copy_right - 1) modulo 2^16.
1349 byte_copy_left = buff[64] << 8;
1350 byte_copy_left = byte_copy_left | buff[65];
1351 byte_copy_right = buff[66] << 8;
1352 byte_copy_right = byte_copy_right | buff[67];
1355 * In order to work out the position, simple arithmetic is tricky
1356 * to apply because there some nasty corner cases. A simple loop
1357 * is inefficient but the logic is simple.
1359 * FUTURE: This could be optimised.
1361 for (position = ref_destination, i = 0; i < multy_offset; i++)
1363 if ( position == byte_copy_left )
1365 position = (byte_copy_right - 1) & 0xffff;
1369 position = (position - 1) & 0xffff;
1373 if (print_level_2 ){
1374 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
1375 " byte_copy_left = %u byte_copy_right = %u position= %u",
1376 byte_copy_left, byte_copy_right, position);
1378 /* The COPY-OFFSET instruction then behaves as a COPY-LITERAL
1379 * instruction, taking the value of the position operand to be the last
1380 * memory address reached in the above step.
1386 * The string of bytes is copied in ascending order of memory address,
1387 * respecting the bounds set by byte_copy_left and byte_copy_right.
1388 * More precisely, if a byte is copied from/to Address m then the next
1389 * byte is copied from/to Address n where n is calculated as follows:
1391 * Set k := m + 1 (modulo 2^16)
1392 * If k = byte_copy_right then set n := byte_copy_left, else set n := k
1397 k = ref_destination;
1398 if (print_level_2 ){
1399 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
1400 " byte_copy_left = %u byte_copy_right = %u", byte_copy_left, byte_copy_right);
1402 while ( n < length ){
1403 buff[k] = buff[position];
1404 if (print_level_2 ){
1405 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
1406 " Copying value: %5u (0x%x) from Addr: %u to Addr: %u",
1407 buff[position], buff[position],(position), k);
1410 k = ( k + 1 ) & 0xffff;
1411 position = ( position + 1 ) & 0xffff;
1414 * Check for circular buffer wrapping after the positions are
1415 * incremented. It is important that k cannot be left set
1416 * to BCR. Also, if either started at BCR then they should continue
1417 * to increment beyond BCR.
1419 if ( k == byte_copy_right ){
1422 if ( position == byte_copy_right ){
1423 position = byte_copy_left;
1426 buff[result_dest] = k >> 8;
1427 buff[result_dest + 1] = k & 0x00ff;
1428 used_udvm_cycles = used_udvm_cycles + 1 + length;
1429 goto execute_next_instruction;
1432 case SIGCOMP_INSTR_MEMSET: /* 21 MEMSET (%address, %length, %start_value, %offset) */
1433 if (show_instr_detail_level == 2 ){
1434 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1435 "Addr: %u ## MEMSET(21) (address, length, start_value, offset)",
1438 operand_address = current_address + 1;
1441 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &address);
1442 if (show_instr_detail_level == 2 ){
1443 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Address %u",
1444 operand_address, address);
1446 operand_address = next_operand_address;
1449 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &length);
1450 if (show_instr_detail_level == 2 ){
1451 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Length %u",
1452 operand_address, length);
1454 operand_address = next_operand_address;
1456 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &start_value);
1457 if (show_instr_detail_level == 2 ){
1458 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u start_value %u",
1459 operand_address, start_value);
1461 operand_address = next_operand_address;
1464 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &multy_offset);
1465 if (show_instr_detail_level == 2 ){
1466 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u offset %u",
1467 operand_address, multy_offset);
1469 if (show_instr_detail_level == 1)
1471 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1472 "Addr: %u ## MEMSET (address=%u, length=%u, start_value=%u, offset=%u)",
1473 current_address, address, length, start_value, multy_offset);
1475 current_address = next_operand_address;
1476 /* exetute the instruction
1477 * The sequence of values used by the MEMSET instruction is specified by
1478 * the following formula:
1480 * Seq[n] := (start_value + n * offset) modulo 256
1484 byte_copy_right = buff[66] << 8;
1485 byte_copy_right = byte_copy_right | buff[67];
1486 byte_copy_left = buff[64] << 8;
1487 byte_copy_left = byte_copy_left | buff[65];
1488 if (print_level_2 ){
1489 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
1490 " byte_copy_left = %u byte_copy_right = %u", byte_copy_left, byte_copy_right);
1492 while ( n < length ){
1493 if ( k == byte_copy_right ){
1496 buff[k] = (start_value + ( n * multy_offset)) & 0xff;
1497 if (print_level_2 ){
1498 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
1499 " Storing value: %u (0x%x) at Addr: %u",
1500 buff[k], buff[k], k);
1502 k = ( k + 1 ) & 0xffff;
1505 used_udvm_cycles = used_udvm_cycles + 1 + length;
1506 goto execute_next_instruction;
1510 case SIGCOMP_INSTR_JUMP: /* 22 JUMP (@address) */
1511 if (show_instr_detail_level == 2 ){
1512 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1513 "Addr: %u ## JUMP(22) (@address)",
1516 operand_address = current_address + 1;
1518 /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
1519 next_operand_address = decode_udvm_address_operand(buff,operand_address, &at_address, current_address);
1520 if (show_instr_detail_level == 2 ){
1521 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u @Address %u",
1522 operand_address, at_address);
1524 if (show_instr_detail_level == 1)
1526 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1527 "Addr: %u ## JUMP (@address=%u)",
1528 current_address, at_address);
1530 current_address = at_address;
1532 goto execute_next_instruction;
1535 case SIGCOMP_INSTR_COMPARE: /* 23 */
1536 /* COMPARE (%value_1, %value_2, @address_1, @address_2, @address_3)
1538 if (show_instr_detail_level == 2 ){
1539 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1540 "Addr: %u ## COMPARE(23) (value_1, value_2, @address_1, @address_2, @address_3)",
1543 operand_address = current_address + 1;
1546 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &value_1);
1547 if (show_instr_detail_level == 2 ){
1548 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Value %u",
1549 operand_address, value_1);
1551 operand_address = next_operand_address;
1554 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &value_2);
1555 if (show_instr_detail_level == 2 ){
1556 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Value %u",
1557 operand_address, value_2);
1559 operand_address = next_operand_address;
1562 /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
1563 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &at_address_1);
1564 at_address_1 = ( current_address + at_address_1) & 0xffff;
1565 if (show_instr_detail_level == 2 ){
1566 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u @Address %u",
1567 operand_address, at_address_1);
1569 operand_address = next_operand_address;
1573 /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
1574 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &at_address_2);
1575 at_address_2 = ( current_address + at_address_2) & 0xffff;
1576 if (show_instr_detail_level == 2 ){
1577 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u @Address %u",
1578 operand_address, at_address_2);
1580 operand_address = next_operand_address;
1583 /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
1584 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &at_address_3);
1585 at_address_3 = ( current_address + at_address_3) & 0xffff;
1586 if (show_instr_detail_level == 2 ){
1587 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u @Address %u",
1588 operand_address, at_address_3);
1590 if (show_instr_detail_level == 1)
1592 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1593 "Addr: %u ## COMPARE (value_1=%u, value_2=%u, @address_1=%u, @address_2=%u, @address_3=%u)",
1594 current_address, value_1, value_2, at_address_1, at_address_2, at_address_3);
1596 /* execute the instruction
1597 * If value_1 < value_2 then the UDVM continues instruction execution at
1598 * the memory address specified by address 1. If value_1 = value_2 then
1599 * it jumps to the address specified by address_2. If value_1 > value_2
1600 * then it jumps to the address specified by address_3.
1602 if ( value_1 < value_2 )
1603 current_address = at_address_1;
1604 if ( value_1 == value_2 )
1605 current_address = at_address_2;
1606 if ( value_1 > value_2 )
1607 current_address = at_address_3;
1609 goto execute_next_instruction;
1612 case SIGCOMP_INSTR_CALL: /* 24 CALL (@address) (PUSH addr )*/
1613 if (show_instr_detail_level == 2){
1614 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1615 "Addr: %u ## CALL(24) (@address) (PUSH addr )",
1618 operand_address = current_address + 1;
1620 next_operand_address = decode_udvm_address_operand(buff,operand_address, &at_address, current_address);
1621 if (show_instr_detail_level == 2 ){
1622 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u @Address %u",
1623 operand_address, at_address);
1625 if (show_instr_detail_level == 1)
1627 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1628 "Addr: %u ## CALL (@address=%u)",
1629 current_address, at_address);
1631 current_address = next_operand_address;
1633 /* Push the current address onto the stack */
1634 stack_location = (buff[70] << 8) | buff[71];
1635 stack_fill = (buff[stack_location] << 8)
1636 | buff[(stack_location+1) & 0xFFFF];
1637 address = (stack_location + stack_fill * 2 + 2) & 0xFFFF;
1638 if (address >= UDVM_MEMORY_SIZE - 1)
1639 goto decompression_failure;
1640 buff[address] = (current_address >> 8) & 0x00FF;
1641 buff[(address+1) & 0xFFFF] = current_address & 0x00FF;
1643 stack_fill = (stack_fill + 1) & 0xFFFF;
1644 if (stack_location >= UDVM_MEMORY_SIZE - 1)
1645 goto decompression_failure;
1646 buff[stack_location] = (stack_fill >> 8) & 0x00FF;
1647 buff[(stack_location+1) & 0xFFFF] = stack_fill & 0x00FF;
1649 /* ... and jump to the destination address */
1650 current_address = at_address;
1653 goto execute_next_instruction;
1657 case SIGCOMP_INSTR_RETURN: /* 25 POP and return */
1658 if (print_level_1 || show_instr_detail_level == 1){
1659 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1660 "Addr: %u ## POP(25) and return",
1664 /* Pop value from the top of the stack */
1665 stack_location = (buff[70] << 8) | buff[71];
1666 stack_fill = (buff[stack_location] << 8)
1667 | buff[(stack_location+1) & 0xFFFF];
1668 if (stack_fill == 0)
1671 goto decompression_failure;
1674 stack_fill = (stack_fill - 1) & 0xFFFF;
1675 if (stack_location >= UDVM_MEMORY_SIZE - 1)
1676 goto decompression_failure;
1677 buff[stack_location] = (stack_fill >> 8) & 0x00FF;
1678 buff[(stack_location+1) & 0xFFFF] = stack_fill & 0x00FF;
1680 address = (stack_location + stack_fill * 2 + 2) & 0xFFFF;
1681 at_address = (buff[address] << 8)
1682 | buff[(address+1) & 0xFFFF];
1684 /* ... and set the PC to the popped value */
1685 current_address = at_address;
1688 goto execute_next_instruction;
1692 case SIGCOMP_INSTR_SWITCH: /* 26 SWITCH (#n, %j, @address_0, @address_1, ... , @address_n-1) */
1694 * When a SWITCH instruction is encountered the UDVM reads the value of
1695 * j. It then continues instruction execution at the address specified
1698 * Decompression failure occurs if j specifies a value of n or more, or
1699 * if the address lies beyond the overall UDVM memory size.
1701 instruction_address = current_address;
1702 if (print_level_1 ){
1703 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1704 "Addr: %u ## SWITCH (#n, j, @address_0, @address_1, ... , @address_n-1))",
1707 operand_address = current_address + 1;
1709 * Number of addresses in the instruction
1711 next_operand_address = decode_udvm_literal_operand(buff,operand_address, &n);
1712 if (print_level_1 ){
1713 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u n %u",
1714 operand_address, n);
1716 operand_address = next_operand_address;
1718 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &j);
1719 if (print_level_1 ){
1720 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u j %u",
1721 operand_address, j);
1723 operand_address = next_operand_address;
1727 /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
1728 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &at_address_1);
1729 at_address_1 = ( instruction_address + at_address_1) & 0xffff;
1730 if (print_level_1 ){
1731 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u @Address %u",
1732 operand_address, at_address_1);
1735 current_address = at_address_1;
1737 operand_address = next_operand_address;
1740 /* Check decompression failure */
1741 if ( ( j == n ) || ( j > n )){
1743 goto decompression_failure;
1745 if ( current_address > UDVM_MEMORY_SIZE ){
1747 goto decompression_failure;
1749 used_udvm_cycles = used_udvm_cycles + 1 + n;
1751 goto execute_next_instruction;
1754 case SIGCOMP_INSTR_CRC: /* 27 CRC (%value, %position, %length, @address) */
1755 if (print_level_1 ){
1756 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1757 "Addr: %u ## CRC (value, position, length, @address)",
1761 operand_address = current_address + 1;
1764 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &value);
1765 if (print_level_1 ){
1766 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Value %u",
1767 operand_address, value);
1769 operand_address = next_operand_address;
1772 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &position);
1773 if (print_level_1 ){
1774 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u position %u",
1775 operand_address, position);
1777 operand_address = next_operand_address;
1780 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &length);
1781 if (print_level_1 ){
1782 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Length %u",
1783 operand_address, length);
1785 operand_address = next_operand_address;
1788 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &at_address);
1789 at_address = ( current_address + at_address) & 0xffff;
1790 if (print_level_1 ){
1791 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u @Address %u",
1792 operand_address, at_address);
1794 /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
1795 used_udvm_cycles = used_udvm_cycles + 1 + length;
1799 byte_copy_right = buff[66] << 8;
1800 byte_copy_right = byte_copy_right | buff[67];
1801 byte_copy_left = buff[64] << 8;
1802 byte_copy_left = byte_copy_left | buff[65];
1805 if (print_level_2 ){
1806 proto_tree_add_text(udvm_tree, message_tvb, 0, -1,
1807 "byte_copy_right = %u", byte_copy_right);
1812 guint16 handle_now = length - n;
1814 if ( k < byte_copy_right && byte_copy_right <= k + (length-n) ){
1815 handle_now = byte_copy_right - k;
1818 if (k + handle_now >= UDVM_MEMORY_SIZE)
1819 goto decompression_failure;
1820 result = crc16_ccitt_seed(&buff[k], handle_now, (guint16) (result ^ 0xffff));
1822 k = ( k + handle_now ) & 0xffff;
1823 n = ( n + handle_now ) & 0xffff;
1825 if ( k >= byte_copy_right ) {
1830 result = result ^ 0xffff;
1832 if (print_level_1 ){
1833 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1, "Calculated CRC %u", result);
1835 if (result != value){
1836 current_address = at_address;
1839 current_address = next_operand_address;
1841 goto execute_next_instruction;
1845 case SIGCOMP_INSTR_INPUT_BYTES: /* 28 INPUT-BYTES (%length, %destination, @address) */
1846 if (show_instr_detail_level == 2 ){
1847 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1848 "Addr: %u ## INPUT-BYTES(28) length, destination, @address)",
1851 operand_address = current_address + 1;
1853 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &length);
1854 if (show_instr_detail_level == 2 ){
1855 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Length %u",
1856 operand_address, length);
1858 operand_address = next_operand_address;
1861 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &destination);
1862 if (show_instr_detail_level == 2 ){
1863 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Destination %u",
1864 operand_address, destination);
1866 operand_address = next_operand_address;
1869 /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
1870 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &at_address);
1871 at_address = ( current_address + at_address) & 0xffff;
1872 if (show_instr_detail_level == 2 ){
1873 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u @Address %u",
1874 operand_address, at_address);
1876 if (show_instr_detail_level == 1)
1878 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1879 "Addr: %u ## INPUT-BYTES length=%u, destination=%u, @address=%u)",
1880 current_address, length, destination, at_address);
1882 /* execute the instruction TODO insert checks
1886 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1887 * | byte_copy_left | 64 - 65
1888 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1889 * | byte_copy_right | 66 - 67
1890 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1891 * | input_bit_order | 68 - 69
1892 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1893 * | stack_location | 70 - 71
1894 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1896 * Figure 7: Memory addresses of the UDVM registers
1900 * The string of bytes is copied in ascending order of memory address,
1901 * respecting the bounds set by byte_copy_left and byte_copy_right.
1902 * More precisely, if a byte is copied from/to Address m then the next
1903 * byte is copied from/to Address n where n is calculated as follows:
1905 * Set k := m + 1 (modulo 2^16)
1906 * If k = byte_copy_right then set n := byte_copy_left, else set n := k
1912 byte_copy_right = buff[66] << 8;
1913 byte_copy_right = byte_copy_right | buff[67];
1914 byte_copy_left = buff[64] << 8;
1915 byte_copy_left = byte_copy_left | buff[65];
1916 if (print_level_1 ){
1917 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
1918 " byte_copy_right = %u", byte_copy_right);
1920 /* clear out remaining bits if any */
1923 /* operand_address used as dummy */
1924 while ( n < length ){
1925 if (input_address > ( msg_end - 1)){
1926 current_address = at_address;
1928 goto execute_next_instruction;
1931 if ( k == byte_copy_right ){
1934 octet = tvb_get_guint8(message_tvb, input_address);
1936 if (print_level_1 ){
1937 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
1938 " Loading value: %u (0x%x) at Addr: %u", octet, octet, k);
1942 * If the instruction requests data that lies beyond the end of the
1943 * SigComp message, no data is returned. Instead the UDVM moves program
1944 * execution to the address specified by the address operand.
1948 k = ( k + 1 ) & 0xffff;
1951 used_udvm_cycles = used_udvm_cycles + 1 + length;
1952 current_address = next_operand_address;
1953 goto execute_next_instruction;
1955 case SIGCOMP_INSTR_INPUT_BITS:/* 29 INPUT-BITS (%length, %destination, @address) */
1957 * The length operand indicates the requested number of bits.
1958 * Decompression failure occurs if this operand does not lie between 0
1961 * The destination operand specifies the memory address to which the
1962 * compressed data should be copied. Note that the requested bits are
1963 * interpreted as a 2-byte integer ranging from 0 to 2^length - 1, as
1964 * explained in Section 8.2.
1966 * If the instruction requests data that lies beyond the end of the
1967 * SigComp message, no data is returned. Instead the UDVM moves program
1968 * execution to the address specified by the address operand.
1971 if (show_instr_detail_level == 2 ){
1972 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1973 "Addr: %u ## INPUT-BITS(29) (length, destination, @address)",
1976 operand_address = current_address + 1;
1979 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &length);
1980 if (show_instr_detail_level == 2 ){
1981 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u length %u",
1982 operand_address, length);
1984 operand_address = next_operand_address;
1986 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &destination);
1987 if (show_instr_detail_level == 2 ){
1988 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Destination %u",
1989 operand_address, destination);
1991 operand_address = next_operand_address;
1994 /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
1995 next_operand_address = decode_udvm_address_operand(buff,operand_address, &at_address, current_address);
1996 if (show_instr_detail_level == 2 ){
1997 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u @Address %u",
1998 operand_address, at_address);
2000 if (show_instr_detail_level == 1)
2002 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2003 "Addr: %u ## INPUT-BITS length=%u, destination=%u, @address=%u)",
2004 current_address, length, destination, at_address);
2006 current_address = next_operand_address;
2009 * Execute actual instr.
2010 * The input_bit_order register contains the following three flags:
2013 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2014 * | reserved |F|H|P| 68 - 69
2015 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2017 input_bit_order = buff[68] << 8;
2018 input_bit_order = input_bit_order | buff[69];
2020 * If the instruction requests data that lies beyond the end of the
2021 * SigComp message, no data is returned. Instead the UDVM moves program
2022 * execution to the address specified by the address operand.
2027 goto decompression_failure;
2029 if ( input_bit_order > 7 ){
2031 goto decompression_failure;
2035 * Transfer F bit to bit_order to tell decomp dispatcher which bit order to use
2037 bit_order = ( input_bit_order & 0x0004 ) >> 2;
2038 value = decomp_dispatch_get_bits( message_tvb, udvm_tree, bit_order,
2039 buff, &old_input_bit_order, &remaining_bits,
2040 &input_bits, &input_address, length, &result_code, msg_end);
2041 if ( result_code == 11 ){
2042 used_udvm_cycles = used_udvm_cycles + 1;
2043 current_address = at_address;
2044 goto execute_next_instruction;
2047 lsb = value & 0x00ff;
2048 if (destination >= UDVM_MEMORY_SIZE - 1)
2049 goto decompression_failure;
2050 buff[destination] = msb;
2051 buff[destination + 1]=lsb;
2052 if (print_level_1 ){
2053 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
2054 " Loading value: %u (0x%x) at Addr: %u, remaining_bits: %u", value, value, destination, remaining_bits);
2057 used_udvm_cycles = used_udvm_cycles + 1;
2058 goto execute_next_instruction;
2060 case SIGCOMP_INSTR_INPUT_HUFFMAN: /* 30 */
2062 * INPUT-HUFFMAN (%destination, @address, #n, %bits_1, %lower_bound_1,
2063 * %upper_bound_1, %uncompressed_1, ... , %bits_n, %lower_bound_n,
2064 * %upper_bound_n, %uncompressed_n)
2066 if (show_instr_detail_level == 2 ){
2067 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2068 "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)",
2071 operand_address = current_address + 1;
2074 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &destination);
2075 if (show_instr_detail_level == 2 ){
2076 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Destination %u",
2077 operand_address, destination);
2079 operand_address = next_operand_address;
2082 /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
2083 next_operand_address = decode_udvm_address_operand(buff,operand_address, &at_address, current_address);
2084 if (show_instr_detail_level == 2 ){
2085 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u @Address %u",
2086 operand_address, at_address);
2088 operand_address = next_operand_address;
2091 next_operand_address = decode_udvm_literal_operand(buff,operand_address, &n);
2092 if (show_instr_detail_level == 2 ){
2093 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u n %u",
2094 operand_address, n);
2096 operand_address = next_operand_address;
2097 if (show_instr_detail_level == 1)
2099 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2100 "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)",
2101 current_address, destination, at_address, n, n, n, n, n);
2104 used_udvm_cycles = used_udvm_cycles + 1 + n;
2107 * Note that if n = 0 then the INPUT-HUFFMAN instruction is ignored and
2108 * program execution resumes at the following instruction.
2109 * Decompression failure occurs if (bits_1 + ... + bits_n) > 16.
2111 * In all other cases, the behavior of the INPUT-HUFFMAN instruction is
2114 * 1. Set j := 1 and set H := 0.
2116 * 2. Request bits_j compressed bits. Interpret the returned bits as an
2117 * integer k from 0 to 2^bits_j - 1, as explained in Section 8.2.
2119 * 3. Set H := H * 2^bits_j + k.
2121 * 4. If data is requested that lies beyond the end of the SigComp
2122 * message, terminate the INPUT-HUFFMAN instruction and move program
2123 * execution to the memory address specified by the address operand.
2125 * 5. If (H < lower_bound_j) or (H > upper_bound_j) then set j := j + 1.
2126 * Then go back to Step 2, unless j > n in which case decompression
2129 * 6. Copy (H + uncompressed_j - lower_bound_j) modulo 2^16 to the
2130 * memory address specified by the destination operand.
2134 * The input_bit_order register contains the following three flags:
2137 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2138 * | reserved |F|H|P| 68 - 69
2139 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2141 * Transfer H bit to bit_order to tell decomp dispatcher which bit order to use
2143 input_bit_order = buff[68] << 8;
2144 input_bit_order = input_bit_order | buff[69];
2145 bit_order = ( input_bit_order & 0x0002 ) >> 1;
2150 outside_huffman_boundaries = TRUE;
2151 print_in_loop = print_level_3;
2154 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &bits_n);
2155 if (print_in_loop ){
2156 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u bits_n %u",
2157 operand_address, bits_n);
2159 operand_address = next_operand_address;
2161 /* %lower_bound_n */
2162 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &lower_bound_n);
2163 if (print_in_loop ){
2164 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u lower_bound_n %u",
2165 operand_address, lower_bound_n);
2167 operand_address = next_operand_address;
2168 /* %upper_bound_n */
2169 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &upper_bound_n);
2170 if (print_in_loop ){
2171 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u upper_bound_n %u",
2172 operand_address, upper_bound_n);
2174 operand_address = next_operand_address;
2175 /* %uncompressed_n */
2176 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &uncompressed_n);
2177 if (print_in_loop ){
2178 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u uncompressed_n %u",
2179 operand_address, uncompressed_n);
2181 operand_address = next_operand_address;
2182 /* execute instruction */
2183 if ( outside_huffman_boundaries ) {
2185 * 2. Request bits_j compressed bits. Interpret the returned bits as an
2186 * integer k from 0 to 2^bits_j - 1, as explained in Section 8.2.
2188 k = decomp_dispatch_get_bits( message_tvb, udvm_tree, bit_order,
2189 buff, &old_input_bit_order, &remaining_bits,
2190 &input_bits, &input_address, bits_n, &result_code, msg_end);
2191 if ( result_code == 11 ){
2193 * 4. If data is requested that lies beyond the end of the SigComp
2194 * message, terminate the INPUT-HUFFMAN instruction and move program
2195 * execution to the memory address specified by the address operand.
2197 current_address = at_address;
2198 goto execute_next_instruction;
2202 * 3. Set H := H * 2^bits_j + k.
2203 * [In practice is a shift+OR operation.]
2206 H = (H << bits_n) | k;
2207 if (print_level_3 ){
2208 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," Set H(%u) := H(%u) * 2^bits_j(%u) + k(%u)",
2209 H ,oldH, 1<<bits_n,k);
2213 * 5. If (H < lower_bound_j) or (H > upper_bound_j) then set j := j + 1.
2214 * Then go back to Step 2, unless j > n in which case decompression
2217 if ((H < lower_bound_n) || (H > upper_bound_n)){
2218 outside_huffman_boundaries = TRUE;
2220 outside_huffman_boundaries = FALSE;
2221 print_in_loop = FALSE;
2223 * 6. Copy (H + uncompressed_j - lower_bound_j) modulo 2^16 to the
2224 * memory address specified by the destination operand.
2226 if (print_level_2 ){
2227 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2228 " H(%u) = H(%u) + uncompressed_n(%u) - lower_bound_n(%u)",
2229 (H + uncompressed_n - lower_bound_n ),H, uncompressed_n, lower_bound_n);
2231 H = H + uncompressed_n - lower_bound_n;
2234 if (destination >= UDVM_MEMORY_SIZE - 1)
2235 goto decompression_failure;
2236 buff[destination] = msb;
2237 buff[destination + 1]=lsb;
2238 if (print_level_1 ){
2239 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
2240 " Loading H: %u (0x%x) at Addr: %u,j = %u remaining_bits: %u",
2241 H, H, destination,( n - m + 1 ), remaining_bits);
2250 if ( outside_huffman_boundaries ) {
2252 goto decompression_failure;
2255 current_address = next_operand_address;
2256 goto execute_next_instruction;
2259 case SIGCOMP_INSTR_STATE_ACCESS: /* 31 */
2260 /* STATE-ACCESS (%partial_identifier_start, %partial_identifier_length,
2261 * %state_begin, %state_length, %state_address, %state_instruction)
2263 if (show_instr_detail_level == 2 ){
2264 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2265 "Addr: %u ## STATE-ACCESS(31) (partial_identifier_start, partial_identifier_length,state_begin, state_length, state_address, state_instruction)",
2268 operand_address = current_address + 1;
2271 * %partial_identifier_start
2273 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &p_id_start);
2274 if (show_instr_detail_level == 2 ){
2275 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u partial_identifier_start %u",
2276 operand_address, p_id_start);
2278 operand_address = next_operand_address;
2281 * %partial_identifier_length
2283 operand_address = next_operand_address;
2284 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &p_id_length);
2285 if (show_instr_detail_level == 2 ){
2286 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u partial_identifier_length %u",
2287 operand_address, p_id_length);
2292 operand_address = next_operand_address;
2293 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_begin);
2294 if (show_instr_detail_level == 2 ){
2295 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_begin %u",
2296 operand_address, state_begin);
2301 operand_address = next_operand_address;
2302 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_length);
2303 if (show_instr_detail_level == 2 ){
2304 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_length %u",
2305 operand_address, state_length);
2310 operand_address = next_operand_address;
2311 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_address);
2312 if (show_instr_detail_level == 2 ){
2313 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_address %u",
2314 operand_address, state_address);
2317 * %state_instruction
2319 operand_address = next_operand_address;
2320 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_instruction);
2321 if (show_instr_detail_level == 2 ){
2322 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_instruction %u",
2323 operand_address, state_instruction);
2325 if (show_instr_detail_level == 1)
2327 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2328 "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)",
2329 current_address, p_id_start, p_id_length, state_begin, state_length, state_address, state_instruction);
2331 current_address = next_operand_address;
2332 byte_copy_right = buff[66] << 8;
2333 byte_copy_right = byte_copy_right | buff[67];
2334 byte_copy_left = buff[64] << 8;
2335 byte_copy_left = byte_copy_left | buff[65];
2336 if (print_level_2 ){
2337 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
2338 " byte_copy_right = %u, byte_copy_left = %u", byte_copy_right,byte_copy_left);
2341 result_code = udvm_state_access(message_tvb, udvm_tree, buff, p_id_start, p_id_length, state_begin, &state_length,
2342 &state_address, &state_instruction, hf_id);
2343 if ( result_code != 0 ){
2344 goto decompression_failure;
2346 used_udvm_cycles = used_udvm_cycles + 1 + state_length;
2347 goto execute_next_instruction;
2349 case SIGCOMP_INSTR_STATE_CREATE: /* 32 */
2351 * STATE-CREATE (%state_length, %state_address, %state_instruction,
2352 * %minimum_access_length, %state_retention_priority)
2354 if (show_instr_detail_level == 2 ){
2355 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2356 "Addr: %u ## STATE-CREATE(32) (state_length, state_address, state_instruction,minimum_access_length, state_retention_priority)",
2359 operand_address = current_address + 1;
2364 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_length);
2365 if (show_instr_detail_level == 2 ){
2366 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_length %u",
2367 operand_address, state_length);
2372 operand_address = next_operand_address;
2373 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_address);
2374 if (show_instr_detail_level == 2 ){
2375 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_address %u",
2376 operand_address, state_address);
2379 * %state_instruction
2381 operand_address = next_operand_address;
2382 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_instruction);
2383 if (show_instr_detail_level == 2 ){
2384 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_instruction %u",
2385 operand_address, state_instruction);
2387 operand_address = next_operand_address;
2389 * %minimum_access_length
2391 operand_address = next_operand_address;
2392 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &minimum_access_length);
2393 if (show_instr_detail_level == 2 ){
2394 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u minimum_access_length %u",
2395 operand_address, minimum_access_length);
2397 operand_address = next_operand_address;
2399 * %state_retention_priority
2401 operand_address = next_operand_address;
2402 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_retention_priority);
2403 if (show_instr_detail_level == 2 ){
2404 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_retention_priority %u",
2405 operand_address, state_retention_priority);
2407 if (show_instr_detail_level == 1)
2409 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2410 "Addr: %u ## STATE-CREATE(32) (state_length=%u, state_address=%u, state_instruction=%u,minimum_access_length=%u, state_retention_priority=%u)",
2411 current_address, state_length, state_address, state_instruction,minimum_access_length, state_retention_priority);
2413 current_address = next_operand_address;
2414 /* Execute the instruction
2415 * TODO Implement the instruction
2417 * Note that the new state item cannot be created until a valid
2418 * compartment identifier has been returned by the application.
2419 * Consequently, when a STATE-CREATE instruction is encountered the UDVM
2420 * simply buffers the five supplied operands until the END-MESSAGE
2421 * instruction is reached. The steps taken at this point are described
2424 * Decompression failure MUST occur if more than four state creation
2425 * requests are made before the END-MESSAGE instruction is encountered.
2426 * Decompression failure also occurs if the minimum_access_length does
2427 * not lie between 6 and 20 inclusive, or if the
2428 * state_retention_priority is 65535.
2430 no_of_state_create++;
2431 if ( no_of_state_create > 4 ){
2433 goto decompression_failure;
2435 if (( minimum_access_length < 6 ) || ( minimum_access_length > STATE_BUFFER_SIZE )){
2437 goto decompression_failure;
2439 if ( state_retention_priority == 65535 ){
2441 goto decompression_failure;
2443 state_length_buff[no_of_state_create] = state_length;
2444 state_address_buff[no_of_state_create] = state_address;
2445 state_instruction_buff[no_of_state_create] = state_instruction;
2446 state_minimum_access_length_buff[no_of_state_create] = minimum_access_length;
2447 state_state_retention_priority_buff[no_of_state_create] = state_retention_priority;
2448 used_udvm_cycles = used_udvm_cycles + 1 + state_length;
2450 byte_copy_right = buff[66] << 8;
2451 byte_copy_right = byte_copy_right | buff[67];
2452 byte_copy_left = buff[64] << 8;
2453 byte_copy_left = byte_copy_left | buff[65];
2456 while ( n < state_length ){
2457 if ( k == byte_copy_right ){
2462 if (print_level_3 ){
2463 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2464 " Addr: %5u State value: %u (0x%x) ASCII(%s)",
2465 k,buff[k],buff[k],format_text(string, 1));
2467 k = ( k + 1 ) & 0xffff;
2472 goto execute_next_instruction;
2474 case SIGCOMP_INSTR_STATE_FREE: /* 33 */
2476 * STATE-FREE (%partial_identifier_start, %partial_identifier_length)
2478 if (show_instr_detail_level == 2 ){
2479 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2480 "Addr: %u ## STATE-FREE (partial_identifier_start, partial_identifier_length)",
2483 operand_address = current_address + 1;
2485 * %partial_identifier_start
2487 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &p_id_start);
2488 if (show_instr_detail_level == 2 ){
2489 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u partial_identifier_start %u",
2490 operand_address, p_id_start);
2492 operand_address = next_operand_address;
2495 * %partial_identifier_length
2497 operand_address = next_operand_address;
2498 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &p_id_length);
2499 if (show_instr_detail_level == 2 ){
2500 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u partial_identifier_length %u",
2501 operand_address, p_id_length);
2503 if (show_instr_detail_level == 1)
2505 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2506 "Addr: %u ## STATE-FREE (partial_identifier_start=%u, partial_identifier_length=%u)",
2507 current_address, p_id_start, p_id_length);
2509 current_address = next_operand_address;
2511 /* Execute the instruction:
2514 udvm_state_free(buff,p_id_start,p_id_length);
2517 goto execute_next_instruction;
2519 case SIGCOMP_INSTR_OUTPUT: /* 34 OUTPUT (%output_start, %output_length) */
2520 if (show_instr_detail_level == 2 ){
2521 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2522 "Addr: %u ## OUTPUT(34) (output_start, output_length)",
2525 operand_address = current_address + 1;
2529 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &output_start);
2530 if (show_instr_detail_level == 2 ){
2531 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u output_start %u",
2532 operand_address, output_start);
2534 operand_address = next_operand_address;
2538 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &output_length);
2539 if (show_instr_detail_level == 2 ){
2540 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u output_length %u",
2541 operand_address, output_length);
2543 if (show_instr_detail_level == 1)
2545 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2546 "Addr: %u ## OUTPUT (output_start=%u, output_length=%u)",
2547 current_address, output_start, output_length);
2549 current_address = next_operand_address;
2552 * Execute instruction
2555 * The string of bytes is copied in ascending order of memory address,
2556 * respecting the bounds set by byte_copy_left and byte_copy_right.
2557 * More precisely, if a byte is copied from/to Address m then the next
2558 * byte is copied from/to Address n where n is calculated as follows:
2560 * Set k := m + 1 (modulo 2^16)
2561 * If k = byte_copy_right then set n := byte_copy_left, else set n := k
2567 byte_copy_right = buff[66] << 8;
2568 byte_copy_right = byte_copy_right | buff[67];
2569 byte_copy_left = buff[64] << 8;
2570 byte_copy_left = byte_copy_left | buff[65];
2571 if (print_level_3 ){
2572 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2573 " byte_copy_right = %u", byte_copy_right);
2575 while ( n < output_length ){
2577 if ( k == byte_copy_right ){
2580 out_buff[output_address] = buff[k];
2583 if (print_level_3 ){
2584 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2585 " Output value: %u (0x%x) ASCII(%s) from Addr: %u ,output to dispatcher position %u",
2586 buff[k],buff[k],format_text(string,1), k,output_address);
2588 k = ( k + 1 ) & 0xffff;
2592 used_udvm_cycles = used_udvm_cycles + 1 + output_length;
2593 goto execute_next_instruction;
2595 case SIGCOMP_INSTR_END_MESSAGE: /* 35 */
2597 * END-MESSAGE (%requested_feedback_location,
2598 * %returned_parameters_location, %state_length, %state_address,
2599 * %state_instruction, %minimum_access_length,
2600 * %state_retention_priority)
2602 if (show_instr_detail_level == 2 ){
2603 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2604 "Addr: %u ## END-MESSAGE (requested_feedback_location,state_instruction, minimum_access_length,state_retention_priority)",
2607 operand_address = current_address + 1;
2609 /* %requested_feedback_location */
2610 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &requested_feedback_location);
2611 if (show_instr_detail_level == 2 ){
2612 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u requested_feedback_location %u",
2613 operand_address, requested_feedback_location);
2615 operand_address = next_operand_address;
2616 /* returned_parameters_location */
2617 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &returned_parameters_location);
2618 if (show_instr_detail_level == 2 ){
2619 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u returned_parameters_location %u",
2620 operand_address, returned_parameters_location);
2622 operand_address = next_operand_address;
2626 operand_address = next_operand_address;
2627 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_length);
2628 if (show_instr_detail_level == 2 ){
2629 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_length %u",
2630 operand_address, state_length);
2635 operand_address = next_operand_address;
2636 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_address);
2637 if (show_instr_detail_level == 2 ){
2638 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_address %u",
2639 operand_address, state_address);
2642 * %state_instruction
2644 operand_address = next_operand_address;
2645 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_instruction);
2646 if (show_instr_detail_level == 2 ){
2647 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_instruction %u",
2648 operand_address, state_instruction);
2652 * %minimum_access_length
2654 operand_address = next_operand_address;
2655 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &minimum_access_length);
2656 if (show_instr_detail_level == 2 ){
2657 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u minimum_access_length %u",
2658 operand_address, minimum_access_length);
2662 * %state_retention_priority
2664 operand_address = next_operand_address;
2665 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_retention_priority);
2666 if (show_instr_detail_level == 2 ){
2667 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_retention_priority %u",
2668 operand_address, state_retention_priority);
2670 if (show_instr_detail_level == 1)
2672 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2673 "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)",
2674 current_address, requested_feedback_location, returned_parameters_location, state_length, state_address, state_instruction, minimum_access_length,state_retention_priority);
2676 current_address = next_operand_address;
2677 /* TODO: This isn't currently totaly correct as END_INSTRUCTION might not create state */
2678 no_of_state_create++;
2679 if ( no_of_state_create > 4 ){
2681 goto decompression_failure;
2683 state_length_buff[no_of_state_create] = state_length;
2684 state_address_buff[no_of_state_create] = state_address;
2685 state_instruction_buff[no_of_state_create] = state_instruction;
2687 state_minimum_access_length_buff[no_of_state_create] = minimum_access_length;
2688 state_state_retention_priority_buff[no_of_state_create] = state_retention_priority;
2690 /* Execute the instruction
2692 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"no_of_state_create %u",no_of_state_create);
2693 if ( no_of_state_create != 0 ){
2694 memset(sha1_digest_buf, 0, STATE_BUFFER_SIZE);
2696 byte_copy_right = buff[66] << 8;
2697 byte_copy_right = byte_copy_right | buff[67];
2698 byte_copy_left = buff[64] << 8;
2699 byte_copy_left = byte_copy_left | buff[65];
2700 while ( n < no_of_state_create + 1 ){
2701 sha1buff = g_malloc(state_length_buff[n]+8);
2702 sha1buff[0] = state_length_buff[n] >> 8;
2703 sha1buff[1] = state_length_buff[n] & 0xff;
2704 sha1buff[2] = state_address_buff[n] >> 8;
2705 sha1buff[3] = state_address_buff[n] & 0xff;
2706 sha1buff[4] = state_instruction_buff[n] >> 8;
2707 sha1buff[5] = state_instruction_buff[n] & 0xff;
2708 sha1buff[6] = state_minimum_access_length_buff[n] >> 8;
2709 sha1buff[7] = state_minimum_access_length_buff[n] & 0xff;
2710 if (print_level_3 ){
2711 for( x=0; x < 8; x++){
2712 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"sha1buff %u 0x%x",
2716 k = state_address_buff[n];
2717 for( x=0; x < state_length_buff[n]; x++)
2719 if ( k == byte_copy_right ){
2722 sha1buff[8+x] = buff[k];
2723 k = ( k + 1 ) & 0xffff;
2726 sha1_starts( &ctx );
2727 sha1_update( &ctx, (guint8 *) sha1buff, state_length_buff[n] + 8);
2728 sha1_finish( &ctx, sha1_digest_buf );
2729 if (print_level_3 ){
2730 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"SHA1 digest %s",bytes_to_str(sha1_digest_buf, STATE_BUFFER_SIZE));
2733 /* begin partial state-id change cco@iptel.org */
2735 udvm_state_create(sha1buff, sha1_digest_buf, state_minimum_access_length_buff[n]);
2737 udvm_state_create(sha1buff, sha1_digest_buf, STATE_MIN_ACCESS_LEN);
2738 /* end partial state-id change cco@iptel.org */
2739 proto_tree_add_text(udvm_tree,bytecode_tvb, 0, -1,"### Creating state ###");
2740 proto_tree_add_string(udvm_tree,hf_id, bytecode_tvb, 0, 0, bytes_to_str(sha1_digest_buf, state_minimum_access_length_buff[n]));
2749 /* At least something got decompressed, show it */
2750 decomp_tvb = tvb_new_child_real_data(message_tvb, out_buff,output_address,output_address);
2751 /* Arrange that the allocated packet data copy be freed when the
2754 tvb_set_free_cb( decomp_tvb, g_free );
2756 add_new_data_source(pinfo, decomp_tvb, "Decompressed SigComp message");
2758 proto_tree_add_text(udvm_tree, decomp_tvb, 0, -1,"SigComp message Decompressed");
2760 used_udvm_cycles = used_udvm_cycles + 1 + state_length;
2761 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"maximum_UDVM_cycles %u used_udvm_cycles %u",
2762 maximum_UDVM_cycles, used_udvm_cycles);
2767 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," ### Addr %u Invalid instruction: %u (0x%x)",
2768 current_address,current_instruction,current_instruction);
2773 decompression_failure:
2775 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"DECOMPRESSION FAILURE: %s",
2776 val_to_str(result_code, result_code_vals,"Unknown (%u)"));
2777 THROW(ReportedBoundsError);
2783 /* The simplest operand type is the literal (#), which encodes a
2784 * constant integer from 0 to 65535 inclusive. A literal operand may
2785 * require between 1 and 3 bytes depending on its value.
2786 * Bytecode: Operand value: Range:
2787 * 0nnnnnnn N 0 - 127
2788 * 10nnnnnn nnnnnnnn N 0 - 16383
2789 * 11000000 nnnnnnnn nnnnnnnn N 0 - 65535
2791 * Figure 8: Bytecode for a literal (#) operand
2795 decode_udvm_literal_operand(guint8 *buff,guint operand_address, guint16 *value)
2800 guint offset = operand_address;
2803 bytecode = buff[operand_address];
2804 test_bits = bytecode >> 7;
2805 if (test_bits == 1){
2806 test_bits = bytecode >> 6;
2807 if (test_bits == 2){
2809 * 10nnnnnn nnnnnnnn N 0 - 16383
2811 temp_data = buff[operand_address] & 0x1f;
2812 operand = temp_data << 8;
2813 temp_data = buff[operand_address + 1];
2814 operand = operand | temp_data;
2816 offset = offset + 2;
2820 * 111000000 nnnnnnnn nnnnnnnn N 0 - 65535
2823 temp_data = buff[operand_address] & 0x1f;
2824 operand = temp_data << 8;
2825 temp_data = buff[operand_address + 1];
2826 operand = operand | temp_data;
2828 offset = offset + 2;
2833 * 0nnnnnnn N 0 - 127
2835 operand = ( bytecode & 0x7f);
2845 * The second operand type is the reference ($), which is always used to
2846 * access a 2-byte value located elsewhere in the UDVM memory. The
2847 * bytecode for a reference operand is decoded to be a constant integer
2848 * from 0 to 65535 inclusive, which is interpreted as the memory address
2849 * containing the actual value of the operand.
2850 * Bytecode: Operand value: Range:
2852 * 0nnnnnnn memory[2 * N] 0 - 65535
2853 * 10nnnnnn nnnnnnnn memory[2 * N] 0 - 65535
2854 * 11000000 nnnnnnnn nnnnnnnn memory[N] 0 - 65535
2856 * Figure 9: Bytecode for a reference ($) operand
2859 dissect_udvm_reference_operand(guint8 *buff,guint operand_address, guint16 *value,guint *result_dest)
2863 guint offset = operand_address;
2866 guint16 temp_data16;
2868 bytecode = buff[operand_address];
2869 test_bits = bytecode >> 7;
2870 if (test_bits == 1){
2871 test_bits = bytecode >> 6;
2872 if (test_bits == 2){
2874 * 10nnnnnn nnnnnnnn memory[2 * N] 0 - 65535
2876 temp_data = buff[operand_address] & 0x3f;
2877 operand = temp_data << 8;
2878 temp_data = buff[operand_address + 1];
2879 operand = operand | temp_data;
2880 operand = (operand * 2);
2881 *result_dest = operand;
2882 temp_data16 = buff[operand] << 8;
2883 temp_data16 = temp_data16 | buff[operand+1];
2884 *value = temp_data16;
2885 offset = offset + 2;
2889 * 11000000 nnnnnnnn nnnnnnnn memory[N] 0 - 65535
2892 operand = buff[operand_address] << 8;
2893 operand = operand | buff[operand_address + 1];
2894 *result_dest = operand;
2895 temp_data16 = buff[operand] << 8;
2896 temp_data16 = temp_data16 | buff[operand+1];
2897 *value = temp_data16;
2898 offset = offset + 3;
2903 * 0nnnnnnn memory[2 * N] 0 - 65535
2905 operand = ( bytecode & 0x7f);
2906 operand = (operand * 2);
2907 *result_dest = operand;
2908 temp_data16 = buff[operand] << 8;
2909 temp_data16 = temp_data16 | buff[operand+1];
2910 *value = temp_data16;
2914 if (offset >= UDVM_MEMORY_SIZE || *result_dest >= UDVM_MEMORY_SIZE - 1 )
2915 THROW(ReportedBoundsError);
2921 * Figure 10: Bytecode for a multitype (%) operand
2922 * Bytecode: Operand value: Range: HEX val
2923 * 00nnnnnn N 0 - 63 0x00
2924 * 01nnnnnn memory[2 * N] 0 - 65535 0x40
2925 * 1000011n 2 ^ (N + 6) 64 , 128 0x86
2926 * 10001nnn 2 ^ (N + 8) 256 , ... , 32768 0x88
2927 * 111nnnnn N + 65504 65504 - 65535 0xe0
2928 * 1001nnnn nnnnnnnn N + 61440 61440 - 65535 0x90
2929 * 101nnnnn nnnnnnnn N 0 - 8191 0xa0
2930 * 110nnnnn nnnnnnnn memory[N] 0 - 65535 0xc0
2931 * 10000000 nnnnnnnn nnnnnnnn N 0 - 65535 0x80
2932 * 10000001 nnnnnnnn nnnnnnnn memory[N] 0 - 65535 0x81
2935 decode_udvm_multitype_operand(guint8 *buff,guint operand_address, guint16 *value)
2939 guint offset = operand_address;
2943 guint16 temp_data16;
2944 guint16 memmory_addr = 0;
2946 bytecode = buff[operand_address];
2947 test_bits = ( bytecode & 0xc0 ) >> 6;
2948 switch (test_bits ){
2953 operand = buff[operand_address];
2955 *g_warning("Reading 0x%x From address %u",operand,offset);
2962 * 01nnnnnn memory[2 * N] 0 - 65535
2964 memmory_addr = ( bytecode & 0x3f) * 2;
2965 temp_data16 = buff[memmory_addr] << 8;
2966 temp_data16 = temp_data16 | buff[memmory_addr+1];
2967 *value = temp_data16;
2971 /* Check tree most significant bits */
2972 test_bits = ( bytecode & 0xe0 ) >> 5;
2973 if ( test_bits == 5 ){
2975 * 101nnnnn nnnnnnnn N 0 - 8191
2977 temp_data = buff[operand_address] & 0x1f;
2978 operand = temp_data << 8;
2979 temp_data = buff[operand_address + 1];
2980 operand = operand | temp_data;
2982 offset = offset + 2;
2984 test_bits = ( bytecode & 0xf0 ) >> 4;
2985 if ( test_bits == 9 ){
2987 * 1001nnnn nnnnnnnn N + 61440 61440 - 65535
2989 temp_data = buff[operand_address] & 0x0f;
2990 operand = temp_data << 8;
2991 temp_data = buff[operand_address + 1];
2992 operand = operand | temp_data;
2993 operand = operand + 61440;
2995 offset = offset + 2;
2997 test_bits = ( bytecode & 0x08 ) >> 3;
2998 if ( test_bits == 1){
3000 * 10001nnn 2 ^ (N + 8) 256 , ... , 32768
3003 result = 1 << ((buff[operand_address] & 0x07) + 8);
3004 operand = result & 0xffff;
3008 test_bits = ( bytecode & 0x0e ) >> 1;
3009 if ( test_bits == 3 ){
3011 * 1000 011n 2 ^ (N + 6) 64 , 128
3013 result = 1 << ((buff[operand_address] & 0x01) + 6);
3014 operand = result & 0xffff;
3019 * 1000 0000 nnnnnnnn nnnnnnnn N 0 - 65535
3020 * 1000 0001 nnnnnnnn nnnnnnnn memory[N] 0 - 65535
3023 temp_data16 = buff[operand_address + 1] << 8;
3024 temp_data16 = temp_data16 | buff[operand_address + 2];
3026 * g_warning("Reading 0x%x From address %u",temp_data16,operand_address);
3028 if ( (bytecode & 0x01) == 1 ){
3029 memmory_addr = temp_data16;
3030 temp_data16 = buff[memmory_addr] << 8;
3031 temp_data16 = temp_data16 | buff[memmory_addr+1];
3033 *value = temp_data16;
3044 test_bits = ( bytecode & 0x20 ) >> 5;
3045 if ( test_bits == 1 ){
3047 * 111nnnnn N + 65504 65504 - 65535
3049 operand = ( buff[operand_address] & 0x1f) + 65504;
3054 * 110nnnnn nnnnnnnn memory[N] 0 - 65535
3056 memmory_addr = buff[operand_address] & 0x1f;
3057 memmory_addr = memmory_addr << 8;
3058 memmory_addr = memmory_addr | buff[operand_address + 1];
3059 temp_data16 = buff[memmory_addr] << 8;
3060 temp_data16 = temp_data16 | buff[memmory_addr+1];
3061 *value = temp_data16;
3063 * g_warning("Reading 0x%x From address %u",temp_data16,memmory_addr);
3075 * The fourth operand type is the address (@). This operand is decoded
3076 * as a multitype operand followed by a further step: the memory address
3077 * of the UDVM instruction containing the address operand is added to
3078 * obtain the correct operand value. So if the operand value from
3079 * Figure 10 is D then the actual operand value of an address is
3080 * calculated as follows:
3082 * operand_value = (memory_address_of_instruction + D) modulo 2^16
3084 * Address operands are always used in instructions that control program
3085 * flow, because they ensure that the UDVM bytecode is position-
3086 * independent code (i.e., it will run independently of where it is
3087 * placed in the UDVM memory).
3090 decode_udvm_address_operand(guint8 *buff,guint operand_address, guint16 *value,guint current_address)
3094 guint next_opreand_address;
3096 next_opreand_address = decode_udvm_multitype_operand(buff, operand_address, &value1);
3097 result = value1 & 0xffff;
3098 result = result + current_address;
3099 *value = result & 0xffff;
3100 return next_opreand_address;
3105 * This is a lookup table used to reverse the bits in a byte.
3107 static guint8 reverse [] = {
3108 0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0,
3109 0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0,
3110 0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8,
3111 0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8,
3112 0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4,
3113 0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4,
3114 0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC,
3115 0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC,
3116 0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2,
3117 0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2,
3118 0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA,
3119 0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA,
3120 0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6,
3121 0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6,
3122 0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE,
3123 0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE,
3124 0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1,
3125 0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1,
3126 0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9,
3127 0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9,
3128 0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5,
3129 0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5,
3130 0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED,
3131 0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD,
3132 0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3,
3133 0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3,
3134 0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB,
3135 0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB,
3136 0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7,
3137 0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7,
3138 0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF,
3139 0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF
3144 decomp_dispatch_get_bits(
3145 tvbuff_t *message_tvb,
3146 proto_tree *udvm_tree,
3149 guint16 *old_input_bit_order,
3150 guint16 *remaining_bits,
3151 guint16 *input_bits,
3152 guint *input_address,
3154 guint16 *result_code,
3157 guint16 input_bit_order;
3158 guint16 bits_still_required = length;
3161 gint extra_bytes_available = msg_end - *input_address;
3163 gint prev_p_bit = *old_input_bit_order & 0x0001;
3164 gint bits_to_use = 0;
3167 input_bit_order = buff[68] << 8;
3168 input_bit_order = input_bit_order | buff[69];
3170 p_bit = (input_bit_order & 0x0001) != 0;
3173 * Discard any spare bits.
3174 * Note: We take care to avoid remaining_bits having the value of 8.
3176 if (prev_p_bit != p_bit)
3178 *remaining_bits = 0;
3179 *old_input_bit_order = input_bit_order;
3183 * Check we can suppy the required number of bits now, before we alter
3184 * the input buffer's state.
3186 if (*remaining_bits + extra_bytes_available * 8 < length)
3192 /* Note: This is never called with length > 16, so the following loop
3193 * never loops more than three time. */
3194 while (bits_still_required > 0)
3197 * We only put anything into input_bits if we know we will remove
3198 * at least one bit. That ensures we can simply discard the spare
3199 * bits if the P-bit changes.
3201 if (*remaining_bits == 0)
3203 octet = tvb_get_guint8(message_tvb, *input_address);
3204 if (print_level_1 ){
3205 proto_tree_add_text(udvm_tree, message_tvb, *input_address , 1,
3206 " Getting value: %u (0x%x) From Addr: %u", octet, octet, *input_address);
3208 *input_address = *input_address + 1;
3212 octet = reverse[octet];
3214 *input_bits = octet;
3215 *remaining_bits = 8;
3218 /* Add some more bits to the accumulated value. */
3219 bits_to_use = bits_still_required < *remaining_bits ? bits_still_required : *remaining_bits;
3220 bits_still_required -= bits_to_use;
3222 *input_bits <<= bits_to_use; /* Shift bits into MSByte */
3223 value = (value << bits_to_use) /* Then add to the accumulated value */
3224 | ((*input_bits >> 8) & 0xFF);
3225 *remaining_bits -= bits_to_use;
3226 *input_bits &= 0x00FF; /* Leave just the remaining bits */
3231 /* Bit reverse the entire word. */
3232 guint16 lsb = reverse[(value >> 8) & 0xFF];
3233 guint16 msb = reverse[value & 0xFF];
3235 value = ((msb << 8) | lsb) >> (16 - length);