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>
6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
8 * Copyright 1998 Gerald Combs
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version 2
13 * of the License, or (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24 * http://www.ietf.org/rfc/rfc3320.txt?number=3320
25 * http://www.ietf.org/rfc/rfc3321.txt?number=3321
27 * http://www.ietf.org/internet-drafts/draft-ietf-rohc-sigcomp-impl-guide-05.txt
28 * http://www.ietf.org/internet-drafts/draft-ietf-rohc-sigcomp-sip-01.txt
38 #include <epan/emem.h>
40 #include <wsutil/sha1.h>
41 #include <wsutil/crc16.h>
44 #include "exceptions.h"
47 #include "sigcomp-udvm.h"
48 #include "sigcomp_state_hdlr.h"
51 #define SIGCOMP_INSTR_DECOMPRESSION_FAILURE 0
52 #define SIGCOMP_INSTR_AND 1
53 #define SIGCOMP_INSTR_OR 2
54 #define SIGCOMP_INSTR_NOT 3
55 #define SIGCOMP_INSTR_LSHIFT 4
56 #define SIGCOMP_INSTR_RSHIFT 5
57 #define SIGCOMP_INSTR_ADD 6
58 #define SIGCOMP_INSTR_SUBTRACT 7
59 #define SIGCOMP_INSTR_MULTIPLY 8
60 #define SIGCOMP_INSTR_DIVIDE 9
61 #define SIGCOMP_INSTR_REMAINDER 10
62 #define SIGCOMP_INSTR_SORT_ASCENDING 11
63 #define SIGCOMP_INSTR_SORT_DESCENDING 12
64 #define SIGCOMP_INSTR_SHA_1 13
65 #define SIGCOMP_INSTR_LOAD 14
66 #define SIGCOMP_INSTR_MULTILOAD 15
67 #define SIGCOMP_INSTR_PUSH 16
68 #define SIGCOMP_INSTR_POP 17
69 #define SIGCOMP_INSTR_COPY 18
70 #define SIGCOMP_INSTR_COPY_LITERAL 19
71 #define SIGCOMP_INSTR_COPY_OFFSET 20
72 #define SIGCOMP_INSTR_MEMSET 21
73 #define SIGCOMP_INSTR_JUMP 22
74 #define SIGCOMP_INSTR_COMPARE 23
75 #define SIGCOMP_INSTR_CALL 24
76 #define SIGCOMP_INSTR_RETURN 25
77 #define SIGCOMP_INSTR_SWITCH 26
78 #define SIGCOMP_INSTR_CRC 27
79 #define SIGCOMP_INSTR_INPUT_BYTES 28
80 #define SIGCOMP_INSTR_INPUT_BITS 29
81 #define SIGCOMP_INSTR_INPUT_HUFFMAN 30
82 #define SIGCOMP_INSTR_STATE_ACCESS 31
83 #define SIGCOMP_INSTR_STATE_CREATE 32
84 #define SIGCOMP_INSTR_STATE_FREE 33
85 #define SIGCOMP_INSTR_OUTPUT 34
86 #define SIGCOMP_INSTR_END_MESSAGE 35
89 static gboolean print_level_1;
90 static gboolean print_level_2;
91 static gboolean print_level_3;
92 static gint show_instr_detail_level;
94 /* Internal result code values of decompression failures */
95 const value_string result_code_vals[] = {
96 { 0, "No decompression failure" },
97 { 1, "Partial state length less than 6 or greater than 20 bytes long" },
98 { 2, "No state match" },
99 { 3, "state_begin + state_length > size of state" },
100 { 4, "Operand_2 is Zero" },
101 { 5, "Switch statement failed j >= n" },
102 { 6, "Attempt to jump outside of UDVM memory" },
103 { 7, "L in input-bits > 16" },
104 { 8, "input_bit_order > 7" },
105 { 9, "Instruction Decompression failure encountered" },
106 {10, "Input huffman failed j > n" },
107 {11, "Input bits requested beyond end of message" },
108 {12, "more than four state creation requests are made before the END-MESSAGE instruction" },
109 {13, "state_retention_priority is 65535" },
110 {14, "Input bytes requested beyond end of message" },
111 {15, "Maximum number of UDVM cycles reached" },
112 {16, "UDVM stack underflow" },
113 { 255, "This branch isn't coded yet" },
117 static int decode_udvm_literal_operand(guint8 *buff,guint operand_address, guint16 *value);
118 static int dissect_udvm_reference_operand(guint8 *buff,guint operand_address, guint16 *value, guint *result_dest);
119 static int decode_udvm_multitype_operand(guint8 *buff,guint operand_address,guint16 *value);
120 static int decode_udvm_address_operand(guint8 *buff,guint operand_address, guint16 *value,guint current_address);
121 static int decomp_dispatch_get_bits(tvbuff_t *message_tvb,proto_tree *udvm_tree,guint8 bit_order,
122 guint8 *buff,guint16 *old_input_bit_order, guint16 *remaining_bits,
123 guint16 *input_bits, guint *input_address, guint16 length, guint16 *result_code,guint msg_end);
127 decompress_sigcomp_message(tvbuff_t *bytecode_tvb, tvbuff_t *message_tvb, packet_info *pinfo,
128 proto_tree *udvm_tree, gint udvm_mem_dest,
129 gint print_flags, gint hf_id,
131 gint byte_code_state_len, gint byte_code_id_len,
134 tvbuff_t *decomp_tvb;
135 /* UDVM memory must be initialised to zero */
136 guint8 *buff = (guint8 *)ep_alloc0(UDVM_MEMORY_SIZE);
138 guint8 *out_buff; /* Largest allowed size for a message is UDVM_MEMORY_SIZE = 65536 */
148 guint code_length =0;
149 guint8 current_instruction;
150 guint current_address;
151 guint operand_address;
153 guint16 output_address = 0;
154 guint next_operand_address;
158 guint16 byte_copy_right;
159 guint16 byte_copy_left;
160 guint16 input_bit_order;
161 guint16 stack_location;
164 guint msg_end = tvb_reported_length_remaining(message_tvb, 0);
165 guint16 result_code = 0;
166 guint16 old_input_bit_order = 0;
167 guint16 remaining_bits = 0;
168 guint16 input_bits = 0;
169 guint8 bit_order = 0;
170 gboolean outside_huffman_boundaries = TRUE;
171 gboolean print_in_loop = FALSE;
172 guint16 instruction_address;
173 guint8 no_of_state_create = 0;
174 guint16 state_length_buff[5];
175 guint16 state_address_buff[5];
176 guint16 state_instruction_buff[5];
177 guint16 state_minimum_access_length_buff[5];
178 /* guint16 state_state_retention_priority_buff[5]; */
179 guint32 used_udvm_cycles = 0;
180 guint cycles_per_bit;
181 guint maximum_UDVM_cycles;
183 unsigned char sha1_digest_buf[STATE_BUFFER_SIZE];
187 /* UDVM operand variables */
196 guint16 state_length;
197 guint16 state_address;
198 guint16 state_instruction;
203 guint16 at_address_1;
204 guint16 at_address_2;
205 guint16 at_address_3;
208 guint16 lower_bound_n;
209 guint16 upper_bound_n;
210 guint16 uncompressed_n;
212 guint16 ref_destination; /* could I have used $destination ? */
213 guint16 multy_offset;
214 guint16 output_start;
215 guint16 output_length;
216 guint16 minimum_access_length;
217 guint16 state_retention_priority;
218 guint16 requested_feedback_location;
219 guint16 returned_parameters_location;
223 /* Set print parameters */
224 print_level_1 = FALSE;
225 print_level_2 = FALSE;
226 print_level_3 = FALSE;
227 show_instr_detail_level = 0;
231 switch( print_flags ) {
236 print_level_1 = TRUE;
237 show_instr_detail_level = 1;
240 print_level_1 = TRUE;
241 print_level_2 = TRUE;
242 show_instr_detail_level = 1;
245 print_level_1 = TRUE;
246 print_level_2 = TRUE;
247 print_level_3 = TRUE;
248 show_instr_detail_level = 2;
251 print_level_1 = TRUE;
252 show_instr_detail_level = 1;
256 /* Set initial UDVM data
257 * The first 32 bytes of UDVM memory are then initialized to special
258 * values as illustrated in Figure 5.
261 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
262 * | UDVM_memory_size | 0 - 1
263 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
264 * | cycles_per_bit | 2 - 3
265 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
266 * | SigComp_version | 4 - 5
267 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
268 * | partial_state_ID_length | 6 - 7
269 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
270 * | state_length | 8 - 9
271 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
273 * : reserved : 10 - 31
275 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
277 * Figure 5: Initializing Useful Values in UDVM memory
279 /* UDVM_memory_size */
280 buff[0] = (UDVM_MEMORY_SIZE >> 8) & 0x00FF;
281 buff[1] = UDVM_MEMORY_SIZE & 0x00FF;
285 /* SigComp_version */
288 /* partial_state_ID_length */
289 buff[6] = (byte_code_id_len >> 8) & 0x00FF;
290 buff[7] = byte_code_id_len & 0x00FF;
292 buff[8] = (byte_code_state_len >> 8) & 0x00FF;
293 buff[9] = byte_code_state_len & 0x00FF;
295 code_length = tvb_reported_length_remaining(bytecode_tvb, 0);
297 cycles_per_bit = buff[2] << 8;
298 cycles_per_bit = cycles_per_bit | buff[3];
300 * maximum_UDVM_cycles = (8 * n + 1000) * cycles_per_bit
302 maximum_UDVM_cycles = (( 8 * (header_len + msg_end) ) + 1000) * cycles_per_bit;
304 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);
305 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);
307 /* Load bytecode into UDVM starting at "udvm_mem_dest" */
310 proto_tree_add_text(udvm_tree, bytecode_tvb, offset, 1,"Load bytecode into UDVM starting at %u",i);
311 while ( code_length > offset && i < UDVM_MEMORY_SIZE ) {
312 buff[i] = tvb_get_guint8(bytecode_tvb, offset);
314 proto_tree_add_text(udvm_tree, bytecode_tvb, offset, 1,
315 " Addr: %u Instruction code(0x%0x) ", i, buff[i]);
321 /* Largest allowed size for a message is UDVM_MEMORY_SIZE = 65536 */
322 out_buff = (guint8 *)g_malloc(UDVM_MEMORY_SIZE);
323 /* Start executing code */
324 current_address = udvm_start_ip;
327 proto_tree_add_text(udvm_tree, bytecode_tvb, offset, 1,"UDVM EXECUTION STARTED at Address: %u Message size %u",
328 current_address, msg_end);
330 execute_next_instruction:
332 if ( used_udvm_cycles > maximum_UDVM_cycles ){
334 goto decompression_failure;
337 current_instruction = buff[current_address & 0xffff];
339 switch ( current_instruction ) {
340 case SIGCOMP_INSTR_DECOMPRESSION_FAILURE:
341 if ( result_code == 0 )
343 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
344 "Addr: %u ## DECOMPRESSION-FAILURE(0)",
346 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Wireshark UDVM diagnostic: %s.",
347 val_to_str(result_code, result_code_vals,"Unknown (%u)"));
348 if ( output_address > 0 ){
349 /* At least something got decompressed, show it */
350 decomp_tvb = tvb_new_child_real_data(message_tvb, out_buff,output_address,output_address);
351 /* Arrange that the allocated packet data copy be freed when the
354 tvb_set_free_cb( decomp_tvb, g_free );
355 /* Add the tvbuff to the list of tvbuffs to which the tvbuff we
356 * were handed refers, so it'll get cleaned up when that tvbuff
359 add_new_data_source(pinfo, decomp_tvb, "Decompressed SigComp message(Incomplete)");
360 proto_tree_add_text(udvm_tree, decomp_tvb, 0, -1,"SigComp message Decompression failure");
367 case SIGCOMP_INSTR_AND: /* 1 AND ($operand_1, %operand_2) */
368 if (show_instr_detail_level == 2 ){
369 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
370 "Addr: %u ## AND(1) (operand_1, operand_2)",
374 operand_address = current_address + 1;
375 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &operand_1, &result_dest);
376 if (show_instr_detail_level == 2 ){
377 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_1 %u",
378 operand_address, operand_1);
380 operand_address = next_operand_address;
382 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &operand_2);
383 if (show_instr_detail_level == 2 ){
384 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_2 %u",
385 operand_address, operand_2);
387 if (show_instr_detail_level == 1)
389 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
390 "Addr: %u ## AND (operand_1=%u, operand_2=%u)",
391 current_address, operand_1, operand_2);
393 /* execute the instruction */
394 result = operand_1 & operand_2;
397 buff[result_dest] = msb;
398 buff[(result_dest+1) & 0xffff] = lsb;
400 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," Loading result %u at %u",
401 result, result_dest);
403 current_address = next_operand_address;
404 goto execute_next_instruction;
408 case SIGCOMP_INSTR_OR: /* 2 OR ($operand_1, %operand_2) */
409 if (show_instr_detail_level == 2 ){
410 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
411 "Addr: %u ## OR(2) (operand_1, operand_2)",
415 operand_address = current_address + 1;
416 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &operand_1, &result_dest);
417 if (show_instr_detail_level == 2 ){
418 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_1 %u",
419 operand_address, operand_1);
421 operand_address = next_operand_address;
423 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &operand_2);
424 if (show_instr_detail_level == 2 ){
425 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_2 %u",
426 operand_address, operand_2);
428 if (show_instr_detail_level == 1)
430 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
431 "Addr: %u ## OR (operand_1=%u, operand_2=%u)",
432 current_address, operand_1, operand_2);
434 /* execute the instruction */
435 result = operand_1 | operand_2;
438 buff[result_dest] = msb;
439 buff[(result_dest+1) & 0xffff] = lsb;
441 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," Loading result %u at %u",
442 result, result_dest);
444 current_address = next_operand_address;
445 goto execute_next_instruction;
449 case SIGCOMP_INSTR_NOT: /* 3 NOT ($operand_1) */
450 if (show_instr_detail_level == 2 ){
451 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
452 "Addr: %u ## NOT(3) ($operand_1)",
456 operand_address = current_address + 1;
457 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &operand_1, &result_dest);
458 if (show_instr_detail_level == 2 ){
459 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_1 %u",
460 operand_address, operand_1);
462 if (show_instr_detail_level == 1)
464 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
465 "Addr: %u ## NOT (operand_1=%u)",
466 current_address, operand_1);
468 /* execute the instruction */
469 result = operand_1 ^ 0xffff;
472 buff[result_dest] = msb;
473 buff[(result_dest+1) & 0xffff] = lsb;
475 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," Loading result %u at %u",
476 result, result_dest);
478 current_address = next_operand_address;
479 goto execute_next_instruction;
482 case SIGCOMP_INSTR_LSHIFT: /* 4 LSHIFT ($operand_1, %operand_2) */
483 if (show_instr_detail_level == 2 ){
484 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
485 "Addr: %u ## LSHIFT(4) ($operand_1, operand_2)",
489 operand_address = current_address + 1;
490 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &operand_1, &result_dest);
491 if (show_instr_detail_level == 2 ){
492 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_1 %u",
493 operand_address, operand_1);
495 operand_address = next_operand_address;
497 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &operand_2);
498 if (show_instr_detail_level == 2 ){
499 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_2 %u",
500 operand_address, operand_2);
502 if (show_instr_detail_level == 1)
504 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
505 "Addr: %u ## LSHIFT (operand_1=%u, operand_2=%u)",
506 current_address, operand_1, operand_2);
508 /* execute the instruction */
509 result = operand_1 << operand_2;
512 buff[result_dest] = msb;
513 buff[(result_dest+1) & 0xffff] = lsb;
515 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," Loading result %u at %u",
516 result, result_dest);
518 current_address = next_operand_address;
519 goto execute_next_instruction;
522 case SIGCOMP_INSTR_RSHIFT: /* 5 RSHIFT ($operand_1, %operand_2) */
523 if (show_instr_detail_level == 2 ){
524 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
525 "Addr: %u ## RSHIFT(5) (operand_1, operand_2)",
529 operand_address = current_address + 1;
530 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &operand_1, &result_dest);
531 if (show_instr_detail_level == 2 ){
532 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_1 %u",
533 operand_address, operand_1);
535 operand_address = next_operand_address;
537 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &operand_2);
538 if (show_instr_detail_level == 2 ){
539 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_2 %u",
540 operand_address, operand_2);
542 if (show_instr_detail_level == 1)
544 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
545 "Addr: %u ## RSHIFT (operand_1=%u, operand_2=%u)",
546 current_address, operand_1, operand_2);
548 /* execute the instruction */
549 result = operand_1 >> operand_2;
552 buff[result_dest] = msb;
553 buff[(result_dest+1) & 0xffff] = lsb;
555 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," Loading result %u at %u",
556 result, result_dest);
558 current_address = next_operand_address;
559 goto execute_next_instruction;
561 case SIGCOMP_INSTR_ADD: /* 6 ADD ($operand_1, %operand_2) */
562 if (show_instr_detail_level == 2 ){
563 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
564 "Addr: %u ## ADD(6) (operand_1, operand_2)",
568 operand_address = current_address + 1;
569 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &operand_1, &result_dest);
570 if (show_instr_detail_level == 2 ){
571 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_1 %u",
572 operand_address, operand_1);
574 operand_address = next_operand_address;
576 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &operand_2);
577 if (show_instr_detail_level == 2 ){
578 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_2 %u",
579 operand_address, operand_2);
581 if (show_instr_detail_level == 1)
583 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
584 "Addr: %u ## ADD (operand_1=%u, operand_2=%u)",
585 current_address, operand_1, operand_2);
587 /* execute the instruction */
588 result = operand_1 + operand_2;
591 buff[result_dest] = msb;
592 buff[(result_dest+1) & 0xffff] = lsb;
594 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," Loading result %u at %u",
595 result, result_dest);
597 current_address = next_operand_address;
598 goto execute_next_instruction;
600 case SIGCOMP_INSTR_SUBTRACT: /* 7 SUBTRACT ($operand_1, %operand_2) */
601 if (show_instr_detail_level == 2 ){
602 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
603 "Addr: %u ## SUBTRACT(7) (operand_1, operand_2)",
607 operand_address = current_address + 1;
608 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &operand_1, &result_dest);
609 if (show_instr_detail_level == 2 ){
610 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_1 %u",
611 operand_address, operand_1);
613 operand_address = next_operand_address;
615 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &operand_2);
616 if (show_instr_detail_level == 2 ){
617 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_2 %u",
618 operand_address, operand_2);
620 if (show_instr_detail_level == 1)
622 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
623 "Addr: %u ## SUBTRACT (operand_1=%u, operand_2=%u)",
624 current_address, operand_1, operand_2);
626 /* execute the instruction */
627 result = operand_1 - operand_2;
630 buff[result_dest] = msb;
631 buff[(result_dest+1) & 0xffff] = lsb;
633 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," Loading result %u at %u",
634 result, result_dest);
636 current_address = next_operand_address;
637 goto execute_next_instruction;
640 case SIGCOMP_INSTR_MULTIPLY: /* 8 MULTIPLY ($operand_1, %operand_2) */
641 if (show_instr_detail_level == 2 ){
642 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
643 "Addr: %u ##MULTIPLY(8) (operand_1, operand_2)",
647 operand_address = current_address + 1;
648 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &operand_1, &result_dest);
649 if (show_instr_detail_level == 2 ){
650 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_1 %u",
651 operand_address, operand_1);
653 operand_address = next_operand_address;
655 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &operand_2);
656 if (show_instr_detail_level == 2 ){
657 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_2 %u",
658 operand_address, operand_2);
660 if (show_instr_detail_level == 1)
662 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
663 "Addr: %u ## MULTIPLY (operand_1=%u, operand_2=%u)",
664 current_address, operand_1, operand_2);
667 * execute the instruction
668 * MULTIPLY (m, n) := m * n (modulo 2^16)
670 if ( operand_2 == 0){
672 goto decompression_failure;
674 result = operand_1 * operand_2;
677 buff[result_dest] = msb;
678 buff[(result_dest+1) & 0xffff] = lsb;
680 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," Loading result %u at %u",
681 result, result_dest);
683 current_address = next_operand_address;
684 goto execute_next_instruction;
687 case SIGCOMP_INSTR_DIVIDE: /* 9 DIVIDE ($operand_1, %operand_2) */
688 if (show_instr_detail_level == 2 ){
689 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
690 "Addr: %u ## DIVIDE(9) (operand_1, operand_2)",
694 operand_address = current_address + 1;
695 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &operand_1, &result_dest);
696 if (show_instr_detail_level == 2 ){
697 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_1 %u",
698 operand_address, operand_1);
700 operand_address = next_operand_address;
702 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &operand_2);
703 if (show_instr_detail_level == 2 ){
704 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_2 %u",
705 operand_address, operand_2);
707 if (show_instr_detail_level == 1)
709 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
710 "Addr: %u ## DIVIDE (operand_1=%u, operand_2=%u)",
711 current_address, operand_1, operand_2);
714 * execute the instruction
715 * DIVIDE (m, n) := floor(m / n)
716 * Decompression failure occurs if a DIVIDE or REMAINDER instruction
717 * encounters an operand_2 that is zero.
719 if ( operand_2 == 0){
721 goto decompression_failure;
723 result = operand_1 / operand_2;
726 buff[result_dest] = msb;
727 buff[(result_dest+1) & 0xffff] = lsb;
729 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," Loading result %u at %u",
730 result, result_dest);
732 current_address = next_operand_address;
733 goto execute_next_instruction;
736 case SIGCOMP_INSTR_REMAINDER: /* 10 REMAINDER ($operand_1, %operand_2) */
737 if (show_instr_detail_level == 2 ){
738 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
739 "Addr: %u ## REMAINDER(10) (operand_1, operand_2)",
743 operand_address = current_address + 1;
744 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &operand_1, &result_dest);
745 if (show_instr_detail_level == 2 ){
746 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_1 %u",
747 operand_address, operand_1);
749 operand_address = next_operand_address;
751 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &operand_2);
752 if (show_instr_detail_level == 2 ){
753 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_2 %u",
754 operand_address, operand_2);
756 if (show_instr_detail_level == 1)
758 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
759 "Addr: %u ## REMAINDER (operand_1=%u, operand_2=%u)",
760 current_address, operand_1, operand_2);
763 * execute the instruction
764 * REMAINDER (m, n) := m - n * floor(m / n)
765 * Decompression failure occurs if a DIVIDE or REMAINDER instruction
766 * encounters an operand_2 that is zero.
768 if ( operand_2 == 0){
770 goto decompression_failure;
772 result = operand_1 - operand_2 * (operand_1 / operand_2);
775 buff[result_dest] = msb;
776 buff[(result_dest+1) & 0xffff] = lsb;
778 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," Loading result %u at %u",
779 result, result_dest);
781 current_address = next_operand_address;
782 goto execute_next_instruction;
784 case SIGCOMP_INSTR_SORT_ASCENDING: /* 11 SORT-ASCENDING (%start, %n, %k) */
786 * used_udvm_cycles = 1 + k * (ceiling(log2(k)) + n)
789 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
790 "Addr: %u ## SORT-ASCENDING(11) (start, n, k))",
793 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Execution of this instruction is NOT implemented");
795 * used_udvm_cycles = 1 + k * (ceiling(log2(k)) + n)
799 case SIGCOMP_INSTR_SORT_DESCENDING: /* 12 SORT-DESCENDING (%start, %n, %k) */
801 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
802 "Addr: %u ## SORT-DESCENDING(12) (start, n, k))",
805 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Execution of this instruction is NOT implemented");
807 * used_udvm_cycles = 1 + k * (ceiling(log2(k)) + n)
810 case SIGCOMP_INSTR_SHA_1: /* 13 SHA-1 (%position, %length, %destination) */
812 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
813 "Addr: %u ## SHA-1(13) (position, length, destination)",
816 operand_address = current_address + 1;
818 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &position);
820 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u position %u",
821 operand_address, position);
823 operand_address = next_operand_address;
826 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &length);
828 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Length %u",
829 operand_address, length);
831 operand_address = next_operand_address;
834 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &ref_destination, &result_dest);
836 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u $destination %u",
837 operand_address, ref_destination);
839 used_udvm_cycles = used_udvm_cycles + length;
843 byte_copy_right = buff[66] << 8;
844 byte_copy_right = byte_copy_right | buff[67];
845 byte_copy_left = buff[64] << 8;
846 byte_copy_left = byte_copy_left | buff[65];
849 proto_tree_add_text(udvm_tree, message_tvb, 0, -1,
850 "byte_copy_right = %u", byte_copy_right);
856 guint16 handle_now = length;
858 if ( k < byte_copy_right && byte_copy_right <= k + (length-n) ){
859 handle_now = byte_copy_right - position;
862 if (k + handle_now >= UDVM_MEMORY_SIZE)
863 goto decompression_failure;
864 sha1_update( &ctx, &buff[k], handle_now );
866 k = ( k + handle_now ) & 0xffff;
867 n = ( n + handle_now ) & 0xffff;
869 if ( k >= byte_copy_right ) {
874 sha1_finish( &ctx, sha1_digest_buf );
878 for ( n=0; n< STATE_BUFFER_SIZE; n++ ) {
880 buff[k] = sha1_digest_buf[n];
882 k = ( k + 1 ) & 0xffff;
885 if ( k == byte_copy_right ){
891 proto_tree_add_text(udvm_tree, message_tvb, 0, -1,
892 "Calculated SHA-1: %s",
893 bytes_to_ep_str(sha1_digest_buf, STATE_BUFFER_SIZE));
896 current_address = next_operand_address;
897 goto execute_next_instruction;
900 case SIGCOMP_INSTR_LOAD: /* 14 LOAD (%address, %value) */
901 if (show_instr_detail_level == 2 ){
902 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
903 "Addr: %u ## LOAD(14) (%%address, %%value)",
906 operand_address = current_address + 1;
908 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &addr);
909 if (show_instr_detail_level == 2 ){
910 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Address %u",
911 operand_address, addr);
913 operand_address = next_operand_address;
915 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &value);
916 if (show_instr_detail_level == 1)
918 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
919 "Addr: %u ## LOAD (%%address=%u, %%value=%u)",
920 current_address, addr, value);
926 buff[(addr + 1) & 0xffff] = lsb;
929 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Value %u",
930 operand_address, value);
931 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," Loading bytes at %u Value %u 0x%x",
934 current_address = next_operand_address;
935 goto execute_next_instruction;
938 case SIGCOMP_INSTR_MULTILOAD: /* 15 MULTILOAD (%address, #n, %value_0, ..., %value_n-1) */
940 * The MULTILOAD instruction sets a contiguous block of 2-byte words in
941 * the UDVM memory to specified values.
942 * Hmm what if the value to load only takes one byte ? Chose to always load two bytes.
944 if (show_instr_detail_level == 2 ){
945 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
946 "Addr: %u ## MULTILOAD(15) (%%address, #n, value_0, ..., value_n-1)",
949 operand_address = current_address + 1;
951 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &addr);
952 if (show_instr_detail_level == 2 ){
953 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Address %u",
954 operand_address, addr);
956 operand_address = next_operand_address;
959 next_operand_address = decode_udvm_literal_operand(buff,operand_address, &n);
960 if (show_instr_detail_level == 2 ){
961 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u n %u",
964 if (show_instr_detail_level == 1)
966 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
967 "Addr: %u ## MULTILOAD (%%address=%u, #n=%u, value_0, ..., value_%d)",
968 current_address, addr, n, n-1);
970 operand_address = next_operand_address;
971 used_udvm_cycles = used_udvm_cycles + n;
975 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &value);
979 if (addr >= UDVM_MEMORY_SIZE - 1)
980 goto decompression_failure;
983 buff[(addr + 1) & 0xffff] = lsb;
986 length = next_operand_address - operand_address;
989 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1, "Addr: %u Value %5u - Loading bytes at %5u Value %5u 0x%x",
990 operand_address, value, addr, value, value);
993 operand_address = next_operand_address;
995 current_address = next_operand_address;
996 goto execute_next_instruction;
1000 case SIGCOMP_INSTR_PUSH: /* 16 PUSH (%value) */
1001 if (show_instr_detail_level == 2){
1002 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1003 "Addr: %u ## PUSH(16) (value)",
1006 operand_address = current_address + 1;
1008 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &value);
1009 if (show_instr_detail_level == 2){
1010 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Value %u",
1011 operand_address, value);
1013 if (show_instr_detail_level == 1)
1015 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1016 "Addr: %u ## PUSH (value=%u)",
1017 current_address, value);
1019 current_address = next_operand_address;
1021 /* Push the value address onto the stack */
1022 stack_location = (buff[70] << 8) | buff[71];
1023 stack_fill = (buff[stack_location] << 8)
1024 | buff[(stack_location+1) & 0xFFFF];
1025 addr = (stack_location + stack_fill * 2 + 2) & 0xFFFF;
1027 if (addr >= UDVM_MEMORY_SIZE - 1)
1028 goto decompression_failure;
1030 buff[addr] = (value >> 8) & 0x00FF;
1031 buff[(addr+1) & 0xFFFF] = value & 0x00FF;
1033 if (stack_location >= UDVM_MEMORY_SIZE - 1)
1034 goto decompression_failure;
1036 stack_fill = (stack_fill + 1) & 0xFFFF;
1037 buff[stack_location] = (stack_fill >> 8) & 0x00FF;
1038 buff[(stack_location+1) & 0xFFFF] = stack_fill & 0x00FF;
1040 goto execute_next_instruction;
1044 case SIGCOMP_INSTR_POP: /* 17 POP (%address) */
1045 if (show_instr_detail_level == 2){
1046 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1047 "Addr: %u ## POP(16) (value)",
1050 operand_address = current_address + 1;
1052 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &destination);
1053 if (show_instr_detail_level == 2){
1054 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Value %u",
1055 operand_address, destination);
1057 if (show_instr_detail_level == 1)
1059 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1060 "Addr: %u ## POP (address=%u)",
1061 current_address, destination);
1063 current_address = next_operand_address;
1065 /* Pop value from the top of the stack */
1066 stack_location = (buff[70] << 8) | buff[71];
1067 stack_fill = (buff[stack_location] << 8)
1068 | buff[(stack_location+1) & 0xFFFF];
1069 if (stack_fill == 0)
1072 goto decompression_failure;
1075 if (stack_location >= UDVM_MEMORY_SIZE - 1)
1076 goto decompression_failure;
1078 stack_fill = (stack_fill - 1) & 0xFFFF;
1079 buff[stack_location] = (stack_fill >> 8) & 0x00FF;
1080 buff[(stack_location+1) & 0xFFFF] = stack_fill & 0x00FF;
1082 addr = (stack_location + stack_fill * 2 + 2) & 0xFFFF;
1084 if (addr >= UDVM_MEMORY_SIZE - 1)
1085 goto decompression_failure;
1087 value = (buff[addr] << 8)
1088 | buff[(addr+1) & 0xFFFF];
1090 /* ... and store the popped value. */
1091 if (destination >= UDVM_MEMORY_SIZE - 1)
1092 goto decompression_failure;
1093 buff[destination] = (value >> 8) & 0x00FF;
1094 buff[(destination+1) & 0xFFFF] = value & 0x00FF;
1096 goto execute_next_instruction;
1100 case SIGCOMP_INSTR_COPY: /* 18 COPY (%position, %length, %destination) */
1101 if (show_instr_detail_level == 2 ){
1102 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1103 "Addr: %u ## COPY(18) (position, length, destination)",
1106 operand_address = current_address + 1;
1108 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &position);
1109 if (show_instr_detail_level == 2 ){
1110 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u position %u",
1111 operand_address, position);
1113 operand_address = next_operand_address;
1116 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &length);
1117 if (show_instr_detail_level == 2 ){
1118 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Length %u",
1119 operand_address, length);
1121 operand_address = next_operand_address;
1124 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &destination);
1125 if (show_instr_detail_level == 2 ){
1126 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Destination %u",
1127 operand_address, destination);
1129 if (show_instr_detail_level == 1)
1131 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1132 "Addr: %u ## COPY (position=%u, length=%u, destination=%u)",
1133 current_address, position, length, destination);
1135 current_address = next_operand_address;
1139 * The string of bytes is copied in ascending order of memory address,
1140 * respecting the bounds set by byte_copy_left and byte_copy_right.
1141 * More precisely, if a byte is copied from/to Address m then the next
1142 * byte is copied from/to Address n where n is calculated as follows:
1144 * Set k := m + 1 (modulo 2^16)
1145 * If k = byte_copy_right then set n := byte_copy_left, else set n := k
1151 byte_copy_right = buff[66] << 8;
1152 byte_copy_right = byte_copy_right | buff[67];
1153 byte_copy_left = buff[64] << 8;
1154 byte_copy_left = byte_copy_left | buff[65];
1155 if (print_level_2 ){
1156 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
1157 " byte_copy_right = %u", byte_copy_right);
1160 while ( n < length ){
1161 buff[k] = buff[position];
1162 if (print_level_2 ){
1163 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
1164 " Copying value: %u (0x%x) to Addr: %u",
1165 buff[position], buff[position], k);
1167 position = ( position + 1 ) & 0xffff;
1168 k = ( k + 1 ) & 0xffff;
1172 * Check for circular buffer wrapping after the positions are
1173 * incremented. If either started at BCR then they should continue
1174 * to increment beyond BCR.
1176 if ( k == byte_copy_right ){
1179 if ( position == byte_copy_right ){
1180 position = byte_copy_left;
1183 used_udvm_cycles = used_udvm_cycles + length;
1184 goto execute_next_instruction;
1187 case SIGCOMP_INSTR_COPY_LITERAL: /* 19 COPY-LITERAL (%position, %length, $destination) */
1188 if (show_instr_detail_level == 2 ){
1189 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1190 "Addr: %u ## COPY-LITERAL(19) (position, length, $destination)",
1193 operand_address = current_address + 1;
1195 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &position);
1196 if (show_instr_detail_level == 2 ){
1197 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u position %u",
1198 operand_address, position);
1200 operand_address = next_operand_address;
1203 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &length);
1204 if (show_instr_detail_level == 2 ){
1205 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Length %u",
1206 operand_address, length);
1208 operand_address = next_operand_address;
1212 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &ref_destination, &result_dest);
1213 if (show_instr_detail_level == 2 ){
1214 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u destination %u",
1215 operand_address, ref_destination);
1217 if (show_instr_detail_level == 1)
1219 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1220 "Addr: %u ## COPY-LITERAL (position=%u, length=%u, $destination=%u)",
1221 current_address, position, length, ref_destination);
1223 current_address = next_operand_address;
1229 * The string of bytes is copied in ascending order of memory address,
1230 * respecting the bounds set by byte_copy_left and byte_copy_right.
1231 * More precisely, if a byte is copied from/to Address m then the next
1232 * byte is copied from/to Address n where n is calculated as follows:
1234 * Set k := m + 1 (modulo 2^16)
1235 * If k = byte_copy_right then set n := byte_copy_left, else set n := k
1240 k = ref_destination;
1241 byte_copy_right = buff[66] << 8;
1242 byte_copy_right = byte_copy_right | buff[67];
1243 byte_copy_left = buff[64] << 8;
1244 byte_copy_left = byte_copy_left | buff[65];
1245 if (print_level_2 ){
1246 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
1247 " byte_copy_right = %u", byte_copy_right);
1249 while ( n < length ){
1251 buff[k] = buff[position];
1252 if (print_level_2 ){
1253 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
1254 " Copying value: %u (0x%x) to Addr: %u",
1255 buff[position], buff[position], k);
1257 position = ( position + 1 ) & 0xffff;
1258 k = ( k + 1 ) & 0xffff;
1262 * Check for circular buffer wrapping after the positions are
1263 * incremented. It is important that k cannot be left set
1264 * to BCR. Also, if either started at BCR then they should continue
1265 * to increment beyond BCR.
1267 if ( k == byte_copy_right ){
1270 if ( position == byte_copy_right ){
1271 position = byte_copy_left;
1274 buff[result_dest] = k >> 8;
1275 buff[(result_dest + 1) & 0xffff] = k & 0x00ff;
1277 used_udvm_cycles = used_udvm_cycles + length;
1278 goto execute_next_instruction;
1281 case SIGCOMP_INSTR_COPY_OFFSET: /* 20 COPY-OFFSET (%offset, %length, $destination) */
1282 if (show_instr_detail_level == 2 ){
1283 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1284 "Addr: %u ## COPY-OFFSET(20) (offset, length, $destination)",
1287 operand_address = current_address + 1;
1289 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &multy_offset);
1290 if (show_instr_detail_level == 2 ){
1291 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u offset %u",
1292 operand_address, multy_offset);
1294 operand_address = next_operand_address;
1297 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &length);
1298 if (show_instr_detail_level == 2 ){
1299 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Length %u",
1300 operand_address, length);
1302 operand_address = next_operand_address;
1306 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &ref_destination, &result_dest);
1307 if (show_instr_detail_level == 2 ){
1308 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u $destination %u",
1309 operand_address, ref_destination);
1312 if (show_instr_detail_level == 1)
1314 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1315 "Addr: %u ## COPY-OFFSET (offset=%u, length=%u, $destination=%u)",
1316 current_address, multy_offset, length, result_dest);
1318 current_address = next_operand_address;
1320 /* Execute the instruction:
1321 * To derive the value of the position operand, starting at the memory
1322 * address specified by destination, the UDVM counts backwards a total
1323 * of offset memory addresses.
1325 * If the memory address specified in byte_copy_left is reached, the
1326 * next memory address is taken to be (byte_copy_right - 1) modulo 2^16.
1328 byte_copy_left = buff[64] << 8;
1329 byte_copy_left = byte_copy_left | buff[65];
1330 byte_copy_right = buff[66] << 8;
1331 byte_copy_right = byte_copy_right | buff[67];
1334 * In order to work out the position, simple arithmetic is tricky
1335 * to apply because there some nasty corner cases. A simple loop
1336 * is inefficient but the logic is simple.
1338 * FUTURE: This could be optimised.
1340 for (position = ref_destination, i = 0; i < multy_offset; i++)
1342 if ( position == byte_copy_left )
1344 position = (byte_copy_right - 1) & 0xffff;
1348 position = (position - 1) & 0xffff;
1352 if (print_level_2 ){
1353 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
1354 " byte_copy_left = %u byte_copy_right = %u position= %u",
1355 byte_copy_left, byte_copy_right, position);
1357 /* The COPY-OFFSET instruction then behaves as a COPY-LITERAL
1358 * instruction, taking the value of the position operand to be the last
1359 * memory address reached in the above step.
1365 * The string of bytes is copied in ascending order of memory address,
1366 * respecting the bounds set by byte_copy_left and byte_copy_right.
1367 * More precisely, if a byte is copied from/to Address m then the next
1368 * byte is copied from/to Address n where n is calculated as follows:
1370 * Set k := m + 1 (modulo 2^16)
1371 * If k = byte_copy_right then set n := byte_copy_left, else set n := k
1376 k = ref_destination;
1377 if (print_level_2 ){
1378 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
1379 " byte_copy_left = %u byte_copy_right = %u", byte_copy_left, byte_copy_right);
1381 while ( n < length ){
1382 buff[k] = buff[position];
1383 if (print_level_2 ){
1384 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
1385 " Copying value: %5u (0x%x) from Addr: %u to Addr: %u",
1386 buff[position], buff[position],(position), k);
1389 k = ( k + 1 ) & 0xffff;
1390 position = ( position + 1 ) & 0xffff;
1393 * Check for circular buffer wrapping after the positions are
1394 * incremented. It is important that k cannot be left set
1395 * to BCR. Also, if either started at BCR then they should continue
1396 * to increment beyond BCR.
1398 if ( k == byte_copy_right ){
1401 if ( position == byte_copy_right ){
1402 position = byte_copy_left;
1405 buff[result_dest] = k >> 8;
1406 buff[result_dest + 1] = k & 0x00ff;
1407 used_udvm_cycles = used_udvm_cycles + length;
1408 goto execute_next_instruction;
1411 case SIGCOMP_INSTR_MEMSET: /* 21 MEMSET (%address, %length, %start_value, %offset) */
1412 if (show_instr_detail_level == 2 ){
1413 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1414 "Addr: %u ## MEMSET(21) (address, length, start_value, offset)",
1417 operand_address = current_address + 1;
1420 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &addr);
1421 if (show_instr_detail_level == 2 ){
1422 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Address %u",
1423 operand_address, addr);
1425 operand_address = next_operand_address;
1428 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &length);
1429 if (show_instr_detail_level == 2 ){
1430 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Length %u",
1431 operand_address, length);
1433 operand_address = next_operand_address;
1435 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &start_value);
1436 if (show_instr_detail_level == 2 ){
1437 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u start_value %u",
1438 operand_address, start_value);
1440 operand_address = next_operand_address;
1443 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &multy_offset);
1444 if (show_instr_detail_level == 2 ){
1445 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u offset %u",
1446 operand_address, multy_offset);
1448 if (show_instr_detail_level == 1)
1450 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1451 "Addr: %u ## MEMSET (address=%u, length=%u, start_value=%u, offset=%u)",
1452 current_address, addr, length, start_value, multy_offset);
1454 current_address = next_operand_address;
1455 /* exetute the instruction
1456 * The sequence of values used by the MEMSET instruction is specified by
1457 * the following formula:
1459 * Seq[n] := (start_value + n * offset) modulo 256
1463 byte_copy_right = buff[66] << 8;
1464 byte_copy_right = byte_copy_right | buff[67];
1465 byte_copy_left = buff[64] << 8;
1466 byte_copy_left = byte_copy_left | buff[65];
1467 if (print_level_2 ){
1468 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
1469 " byte_copy_left = %u byte_copy_right = %u", byte_copy_left, byte_copy_right);
1471 while ( n < length ){
1472 if ( k == byte_copy_right ){
1475 buff[k] = (start_value + ( n * multy_offset)) & 0xff;
1476 if (print_level_2 ){
1477 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
1478 " Storing value: %u (0x%x) at Addr: %u",
1479 buff[k], buff[k], k);
1481 k = ( k + 1 ) & 0xffff;
1484 used_udvm_cycles = used_udvm_cycles + length;
1485 goto execute_next_instruction;
1489 case SIGCOMP_INSTR_JUMP: /* 22 JUMP (@address) */
1490 if (show_instr_detail_level == 2 ){
1491 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1492 "Addr: %u ## JUMP(22) (@address)",
1495 operand_address = current_address + 1;
1497 /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
1498 /*next_operand_address = */decode_udvm_address_operand(buff,operand_address, &at_address, current_address);
1499 if (show_instr_detail_level == 2 ){
1500 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u @Address %u",
1501 operand_address, at_address);
1503 if (show_instr_detail_level == 1)
1505 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1506 "Addr: %u ## JUMP (@address=%u)",
1507 current_address, at_address);
1509 current_address = at_address;
1510 goto execute_next_instruction;
1513 case SIGCOMP_INSTR_COMPARE: /* 23 */
1514 /* COMPARE (%value_1, %value_2, @address_1, @address_2, @address_3)
1516 if (show_instr_detail_level == 2 ){
1517 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1518 "Addr: %u ## COMPARE(23) (value_1, value_2, @address_1, @address_2, @address_3)",
1521 operand_address = current_address + 1;
1524 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &value_1);
1525 if (show_instr_detail_level == 2 ){
1526 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Value %u",
1527 operand_address, value_1);
1529 operand_address = next_operand_address;
1532 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &value_2);
1533 if (show_instr_detail_level == 2 ){
1534 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Value %u",
1535 operand_address, value_2);
1537 operand_address = next_operand_address;
1540 /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
1541 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &at_address_1);
1542 at_address_1 = ( current_address + at_address_1) & 0xffff;
1543 if (show_instr_detail_level == 2 ){
1544 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u @Address %u",
1545 operand_address, at_address_1);
1547 operand_address = next_operand_address;
1551 /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
1552 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &at_address_2);
1553 at_address_2 = ( current_address + at_address_2) & 0xffff;
1554 if (show_instr_detail_level == 2 ){
1555 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u @Address %u",
1556 operand_address, at_address_2);
1558 operand_address = next_operand_address;
1561 /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
1562 /*next_operand_address = */decode_udvm_multitype_operand(buff, operand_address, &at_address_3);
1563 at_address_3 = ( current_address + at_address_3) & 0xffff;
1564 if (show_instr_detail_level == 2 ){
1565 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u @Address %u",
1566 operand_address, at_address_3);
1568 if (show_instr_detail_level == 1)
1570 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1571 "Addr: %u ## COMPARE (value_1=%u, value_2=%u, @address_1=%u, @address_2=%u, @address_3=%u)",
1572 current_address, value_1, value_2, at_address_1, at_address_2, at_address_3);
1574 /* execute the instruction
1575 * If value_1 < value_2 then the UDVM continues instruction execution at
1576 * the memory address specified by address 1. If value_1 = value_2 then
1577 * it jumps to the address specified by address_2. If value_1 > value_2
1578 * then it jumps to the address specified by address_3.
1580 if ( value_1 < value_2 )
1581 current_address = at_address_1;
1582 if ( value_1 == value_2 )
1583 current_address = at_address_2;
1584 if ( value_1 > value_2 )
1585 current_address = at_address_3;
1586 goto execute_next_instruction;
1589 case SIGCOMP_INSTR_CALL: /* 24 CALL (@address) (PUSH addr )*/
1590 if (show_instr_detail_level == 2){
1591 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1592 "Addr: %u ## CALL(24) (@address) (PUSH addr )",
1595 operand_address = current_address + 1;
1597 next_operand_address = decode_udvm_address_operand(buff,operand_address, &at_address, current_address);
1598 if (show_instr_detail_level == 2 ){
1599 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u @Address %u",
1600 operand_address, at_address);
1602 if (show_instr_detail_level == 1)
1604 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1605 "Addr: %u ## CALL (@address=%u)",
1606 current_address, at_address);
1608 current_address = next_operand_address;
1610 /* Push the current address onto the stack */
1611 stack_location = (buff[70] << 8) | buff[71];
1612 stack_fill = (buff[stack_location] << 8)
1613 | buff[(stack_location+1) & 0xFFFF];
1614 addr = (stack_location + stack_fill * 2 + 2) & 0xFFFF;
1615 if (addr >= UDVM_MEMORY_SIZE - 1)
1616 goto decompression_failure;
1617 buff[addr] = (current_address >> 8) & 0x00FF;
1618 buff[(addr+1) & 0xFFFF] = current_address & 0x00FF;
1620 stack_fill = (stack_fill + 1) & 0xFFFF;
1621 if (stack_location >= UDVM_MEMORY_SIZE - 1)
1622 goto decompression_failure;
1623 buff[stack_location] = (stack_fill >> 8) & 0x00FF;
1624 buff[(stack_location+1) & 0xFFFF] = stack_fill & 0x00FF;
1626 /* ... and jump to the destination address */
1627 current_address = at_address;
1629 goto execute_next_instruction;
1633 case SIGCOMP_INSTR_RETURN: /* 25 POP and return */
1634 if (print_level_1 || show_instr_detail_level == 1){
1635 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1636 "Addr: %u ## POP(25) and return",
1640 /* Pop value from the top of the stack */
1641 stack_location = (buff[70] << 8) | buff[71];
1642 stack_fill = (buff[stack_location] << 8)
1643 | buff[(stack_location+1) & 0xFFFF];
1644 if (stack_fill == 0)
1647 goto decompression_failure;
1650 stack_fill = (stack_fill - 1) & 0xFFFF;
1651 if (stack_location >= UDVM_MEMORY_SIZE - 1)
1652 goto decompression_failure;
1653 buff[stack_location] = (stack_fill >> 8) & 0x00FF;
1654 buff[(stack_location+1) & 0xFFFF] = stack_fill & 0x00FF;
1656 addr = (stack_location + stack_fill * 2 + 2) & 0xFFFF;
1657 at_address = (buff[addr] << 8)
1658 | buff[(addr+1) & 0xFFFF];
1660 /* ... and set the PC to the popped value */
1661 current_address = at_address;
1663 goto execute_next_instruction;
1667 case SIGCOMP_INSTR_SWITCH: /* 26 SWITCH (#n, %j, @address_0, @address_1, ... , @address_n-1) */
1669 * When a SWITCH instruction is encountered the UDVM reads the value of
1670 * j. It then continues instruction execution at the address specified
1673 * Decompression failure occurs if j specifies a value of n or more, or
1674 * if the address lies beyond the overall UDVM memory size.
1676 instruction_address = current_address;
1677 if (print_level_1 ){
1678 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1679 "Addr: %u ## SWITCH (#n, j, @address_0, @address_1, ... , @address_n-1))",
1682 operand_address = current_address + 1;
1684 * Number of addresses in the instruction
1686 next_operand_address = decode_udvm_literal_operand(buff,operand_address, &n);
1687 if (print_level_1 ){
1688 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u n %u",
1689 operand_address, n);
1691 operand_address = next_operand_address;
1693 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &j);
1694 if (print_level_1 ){
1695 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u j %u",
1696 operand_address, j);
1698 operand_address = next_operand_address;
1702 /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
1703 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &at_address_1);
1704 at_address_1 = ( instruction_address + at_address_1) & 0xffff;
1705 if (print_level_1 ){
1706 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u @Address %u",
1707 operand_address, at_address_1);
1710 current_address = at_address_1;
1712 operand_address = next_operand_address;
1715 /* Check decompression failure */
1716 if ( ( j == n ) || ( j > n )){
1718 goto decompression_failure;
1720 if ( current_address > UDVM_MEMORY_SIZE ){
1722 goto decompression_failure;
1724 used_udvm_cycles = used_udvm_cycles + n;
1726 goto execute_next_instruction;
1729 case SIGCOMP_INSTR_CRC: /* 27 CRC (%value, %position, %length, @address) */
1730 if (print_level_1 ){
1731 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1732 "Addr: %u ## CRC (value, position, length, @address)",
1736 operand_address = current_address + 1;
1739 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &value);
1740 if (print_level_1 ){
1741 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Value %u",
1742 operand_address, value);
1744 operand_address = next_operand_address;
1747 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &position);
1748 if (print_level_1 ){
1749 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u position %u",
1750 operand_address, position);
1752 operand_address = next_operand_address;
1755 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &length);
1756 if (print_level_1 ){
1757 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Length %u",
1758 operand_address, length);
1760 operand_address = next_operand_address;
1763 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &at_address);
1764 at_address = ( current_address + at_address) & 0xffff;
1765 if (print_level_1 ){
1766 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u @Address %u",
1767 operand_address, at_address);
1769 /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
1770 used_udvm_cycles = used_udvm_cycles + length;
1774 byte_copy_right = buff[66] << 8;
1775 byte_copy_right = byte_copy_right | buff[67];
1776 byte_copy_left = buff[64] << 8;
1777 byte_copy_left = byte_copy_left | buff[65];
1780 if (print_level_2 ){
1781 proto_tree_add_text(udvm_tree, message_tvb, 0, -1,
1782 "byte_copy_right = %u", byte_copy_right);
1787 guint16 handle_now = length - n;
1789 if ( k < byte_copy_right && byte_copy_right <= k + (length-n) ){
1790 handle_now = byte_copy_right - k;
1793 if (k + handle_now >= UDVM_MEMORY_SIZE)
1794 goto decompression_failure;
1795 result = crc16_ccitt_seed(&buff[k], handle_now, (guint16) (result ^ 0xffff));
1797 k = ( k + handle_now ) & 0xffff;
1798 n = ( n + handle_now ) & 0xffff;
1800 if ( k >= byte_copy_right ) {
1805 result = result ^ 0xffff;
1807 if (print_level_1 ){
1808 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1, "Calculated CRC %u", result);
1810 if (result != value){
1811 current_address = at_address;
1814 current_address = next_operand_address;
1816 goto execute_next_instruction;
1820 case SIGCOMP_INSTR_INPUT_BYTES: /* 28 INPUT-BYTES (%length, %destination, @address) */
1821 if (show_instr_detail_level == 2 ){
1822 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1823 "Addr: %u ## INPUT-BYTES(28) length, destination, @address)",
1826 operand_address = current_address + 1;
1828 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &length);
1829 if (show_instr_detail_level == 2 ){
1830 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Length %u",
1831 operand_address, length);
1833 operand_address = next_operand_address;
1836 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &destination);
1837 if (show_instr_detail_level == 2 ){
1838 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Destination %u",
1839 operand_address, destination);
1841 operand_address = next_operand_address;
1844 /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
1845 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &at_address);
1846 at_address = ( current_address + at_address) & 0xffff;
1847 if (show_instr_detail_level == 2 ){
1848 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u @Address %u",
1849 operand_address, at_address);
1851 if (show_instr_detail_level == 1)
1853 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1854 "Addr: %u ## INPUT-BYTES length=%u, destination=%u, @address=%u)",
1855 current_address, length, destination, at_address);
1857 /* execute the instruction TODO insert checks
1861 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1862 * | byte_copy_left | 64 - 65
1863 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1864 * | byte_copy_right | 66 - 67
1865 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1866 * | input_bit_order | 68 - 69
1867 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1868 * | stack_location | 70 - 71
1869 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1871 * Figure 7: Memory addresses of the UDVM registers
1875 * The string of bytes is copied in ascending order of memory address,
1876 * respecting the bounds set by byte_copy_left and byte_copy_right.
1877 * More precisely, if a byte is copied from/to Address m then the next
1878 * byte is copied from/to Address n where n is calculated as follows:
1880 * Set k := m + 1 (modulo 2^16)
1881 * If k = byte_copy_right then set n := byte_copy_left, else set n := k
1887 byte_copy_right = buff[66] << 8;
1888 byte_copy_right = byte_copy_right | buff[67];
1889 byte_copy_left = buff[64] << 8;
1890 byte_copy_left = byte_copy_left | buff[65];
1891 if (print_level_1 ){
1892 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
1893 " byte_copy_right = %u", byte_copy_right);
1895 /* clear out remaining bits if any */
1898 /* operand_address used as dummy */
1899 while ( n < length ){
1900 if (input_address > ( msg_end - 1)){
1901 current_address = at_address;
1903 goto execute_next_instruction;
1906 if ( k == byte_copy_right ){
1909 octet = tvb_get_guint8(message_tvb, input_address);
1911 if (print_level_1 ){
1912 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
1913 " Loading value: %u (0x%x) at Addr: %u", octet, octet, k);
1917 * If the instruction requests data that lies beyond the end of the
1918 * SigComp message, no data is returned. Instead the UDVM moves program
1919 * execution to the address specified by the address operand.
1923 k = ( k + 1 ) & 0xffff;
1926 used_udvm_cycles = used_udvm_cycles + length;
1927 current_address = next_operand_address;
1928 goto execute_next_instruction;
1930 case SIGCOMP_INSTR_INPUT_BITS:/* 29 INPUT-BITS (%length, %destination, @address) */
1932 * The length operand indicates the requested number of bits.
1933 * Decompression failure occurs if this operand does not lie between 0
1936 * The destination operand specifies the memory address to which the
1937 * compressed data should be copied. Note that the requested bits are
1938 * interpreted as a 2-byte integer ranging from 0 to 2^length - 1, as
1939 * explained in Section 8.2.
1941 * If the instruction requests data that lies beyond the end of the
1942 * SigComp message, no data is returned. Instead the UDVM moves program
1943 * execution to the address specified by the address operand.
1946 if (show_instr_detail_level == 2 ){
1947 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1948 "Addr: %u ## INPUT-BITS(29) (length, destination, @address)",
1951 operand_address = current_address + 1;
1954 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &length);
1955 if (show_instr_detail_level == 2 ){
1956 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u length %u",
1957 operand_address, length);
1959 operand_address = next_operand_address;
1961 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &destination);
1962 if (show_instr_detail_level == 2 ){
1963 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Destination %u",
1964 operand_address, destination);
1966 operand_address = next_operand_address;
1969 /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
1970 next_operand_address = decode_udvm_address_operand(buff,operand_address, &at_address, current_address);
1971 if (show_instr_detail_level == 2 ){
1972 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u @Address %u",
1973 operand_address, at_address);
1975 if (show_instr_detail_level == 1)
1977 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1978 "Addr: %u ## INPUT-BITS length=%u, destination=%u, @address=%u)",
1979 current_address, length, destination, at_address);
1981 current_address = next_operand_address;
1984 * Execute actual instr.
1985 * The input_bit_order register contains the following three flags:
1988 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1989 * | reserved |F|H|P| 68 - 69
1990 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1992 input_bit_order = buff[68] << 8;
1993 input_bit_order = input_bit_order | buff[69];
1995 * If the instruction requests data that lies beyond the end of the
1996 * SigComp message, no data is returned. Instead the UDVM moves program
1997 * execution to the address specified by the address operand.
2002 goto decompression_failure;
2004 if ( input_bit_order > 7 ){
2006 goto decompression_failure;
2010 * Transfer F bit to bit_order to tell decomp dispatcher which bit order to use
2012 bit_order = ( input_bit_order & 0x0004 ) >> 2;
2013 value = decomp_dispatch_get_bits( message_tvb, udvm_tree, bit_order,
2014 buff, &old_input_bit_order, &remaining_bits,
2015 &input_bits, &input_address, length, &result_code, msg_end);
2016 if ( result_code == 11 ){
2017 current_address = at_address;
2018 goto execute_next_instruction;
2021 lsb = value & 0x00ff;
2022 if (destination >= UDVM_MEMORY_SIZE - 1)
2023 goto decompression_failure;
2024 buff[destination] = msb;
2025 buff[(destination + 1) & 0xffff]=lsb;
2026 if (print_level_1 ){
2027 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
2028 " Loading value: %u (0x%x) at Addr: %u, remaining_bits: %u", value, value, destination, remaining_bits);
2031 goto execute_next_instruction;
2033 case SIGCOMP_INSTR_INPUT_HUFFMAN: /* 30 */
2035 * INPUT-HUFFMAN (%destination, @address, #n, %bits_1, %lower_bound_1,
2036 * %upper_bound_1, %uncompressed_1, ... , %bits_n, %lower_bound_n,
2037 * %upper_bound_n, %uncompressed_n)
2039 if (show_instr_detail_level == 2 ){
2040 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2041 "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)",
2044 operand_address = current_address + 1;
2047 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &destination);
2048 if (show_instr_detail_level == 2 ){
2049 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Destination %u",
2050 operand_address, destination);
2052 operand_address = next_operand_address;
2055 /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
2056 next_operand_address = decode_udvm_address_operand(buff,operand_address, &at_address, current_address);
2057 if (show_instr_detail_level == 2 ){
2058 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u @Address %u",
2059 operand_address, at_address);
2061 operand_address = next_operand_address;
2064 next_operand_address = decode_udvm_literal_operand(buff,operand_address, &n);
2065 if (show_instr_detail_level == 2 ){
2066 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u n %u",
2067 operand_address, n);
2069 operand_address = next_operand_address;
2070 if (show_instr_detail_level == 1)
2072 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2073 "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)",
2074 current_address, destination, at_address, n, n, n, n, n);
2077 used_udvm_cycles = used_udvm_cycles + n;
2080 * Note that if n = 0 then the INPUT-HUFFMAN instruction is ignored and
2081 * program execution resumes at the following instruction.
2082 * Decompression failure occurs if (bits_1 + ... + bits_n) > 16.
2084 * In all other cases, the behavior of the INPUT-HUFFMAN instruction is
2087 * 1. Set j := 1 and set H := 0.
2089 * 2. Request bits_j compressed bits. Interpret the returned bits as an
2090 * integer k from 0 to 2^bits_j - 1, as explained in Section 8.2.
2092 * 3. Set H := H * 2^bits_j + k.
2094 * 4. If data is requested that lies beyond the end of the SigComp
2095 * message, terminate the INPUT-HUFFMAN instruction and move program
2096 * execution to the memory address specified by the address operand.
2098 * 5. If (H < lower_bound_j) or (H > upper_bound_j) then set j := j + 1.
2099 * Then go back to Step 2, unless j > n in which case decompression
2102 * 6. Copy (H + uncompressed_j - lower_bound_j) modulo 2^16 to the
2103 * memory address specified by the destination operand.
2107 * The input_bit_order register contains the following three flags:
2110 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2111 * | reserved |F|H|P| 68 - 69
2112 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2114 * Transfer H bit to bit_order to tell decomp dispatcher which bit order to use
2116 input_bit_order = buff[68] << 8;
2117 input_bit_order = input_bit_order | buff[69];
2118 bit_order = ( input_bit_order & 0x0002 ) >> 1;
2123 outside_huffman_boundaries = TRUE;
2124 print_in_loop = print_level_3;
2127 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &bits_n);
2128 if (print_in_loop ){
2129 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u bits_n %u",
2130 operand_address, bits_n);
2132 operand_address = next_operand_address;
2134 /* %lower_bound_n */
2135 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &lower_bound_n);
2136 if (print_in_loop ){
2137 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u lower_bound_n %u",
2138 operand_address, lower_bound_n);
2140 operand_address = next_operand_address;
2141 /* %upper_bound_n */
2142 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &upper_bound_n);
2143 if (print_in_loop ){
2144 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u upper_bound_n %u",
2145 operand_address, upper_bound_n);
2147 operand_address = next_operand_address;
2148 /* %uncompressed_n */
2149 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &uncompressed_n);
2150 if (print_in_loop ){
2151 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u uncompressed_n %u",
2152 operand_address, uncompressed_n);
2154 operand_address = next_operand_address;
2155 /* execute instruction */
2156 if ( outside_huffman_boundaries ) {
2158 * 2. Request bits_j compressed bits. Interpret the returned bits as an
2159 * integer k from 0 to 2^bits_j - 1, as explained in Section 8.2.
2161 k = decomp_dispatch_get_bits( message_tvb, udvm_tree, bit_order,
2162 buff, &old_input_bit_order, &remaining_bits,
2163 &input_bits, &input_address, bits_n, &result_code, msg_end);
2164 if ( result_code == 11 ){
2166 * 4. If data is requested that lies beyond the end of the SigComp
2167 * message, terminate the INPUT-HUFFMAN instruction and move program
2168 * execution to the memory address specified by the address operand.
2170 current_address = at_address;
2171 goto execute_next_instruction;
2175 * 3. Set H := H * 2^bits_j + k.
2176 * [In practice is a shift+OR operation.]
2179 H = (H << bits_n) | k;
2180 if (print_level_3 ){
2181 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," Set H(%u) := H(%u) * 2^bits_j(%u) + k(%u)",
2182 H ,oldH, 1<<bits_n,k);
2186 * 5. If (H < lower_bound_j) or (H > upper_bound_j) then set j := j + 1.
2187 * Then go back to Step 2, unless j > n in which case decompression
2190 if ((H < lower_bound_n) || (H > upper_bound_n)){
2191 outside_huffman_boundaries = TRUE;
2193 outside_huffman_boundaries = FALSE;
2194 print_in_loop = FALSE;
2196 * 6. Copy (H + uncompressed_j - lower_bound_j) modulo 2^16 to the
2197 * memory address specified by the destination operand.
2199 if (print_level_2 ){
2200 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2201 " H(%u) = H(%u) + uncompressed_n(%u) - lower_bound_n(%u)",
2202 (H + uncompressed_n - lower_bound_n ),H, uncompressed_n, lower_bound_n);
2204 H = H + uncompressed_n - lower_bound_n;
2207 if (destination >= UDVM_MEMORY_SIZE - 1)
2208 goto decompression_failure;
2209 buff[destination] = msb;
2210 buff[(destination + 1) & 0xffff]=lsb;
2211 if (print_level_1 ){
2212 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
2213 " Loading H: %u (0x%x) at Addr: %u,j = %u remaining_bits: %u",
2214 H, H, destination,( n - m + 1 ), remaining_bits);
2223 if ( outside_huffman_boundaries ) {
2225 goto decompression_failure;
2228 current_address = next_operand_address;
2229 goto execute_next_instruction;
2232 case SIGCOMP_INSTR_STATE_ACCESS: /* 31 */
2233 /* STATE-ACCESS (%partial_identifier_start, %partial_identifier_length,
2234 * %state_begin, %state_length, %state_address, %state_instruction)
2236 if (show_instr_detail_level == 2 ){
2237 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2238 "Addr: %u ## STATE-ACCESS(31) (partial_identifier_start, partial_identifier_length,state_begin, state_length, state_address, state_instruction)",
2241 operand_address = current_address + 1;
2244 * %partial_identifier_start
2246 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &p_id_start);
2247 if (show_instr_detail_level == 2 ){
2248 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u partial_identifier_start %u",
2249 operand_address, p_id_start);
2253 * %partial_identifier_length
2255 operand_address = next_operand_address;
2256 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &p_id_length);
2257 if (show_instr_detail_level == 2 ){
2258 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u partial_identifier_length %u",
2259 operand_address, p_id_length);
2264 operand_address = next_operand_address;
2265 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_begin);
2266 if (show_instr_detail_level == 2 ){
2267 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_begin %u",
2268 operand_address, state_begin);
2273 operand_address = next_operand_address;
2274 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_length);
2275 if (show_instr_detail_level == 2 ){
2276 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_length %u",
2277 operand_address, state_length);
2282 operand_address = next_operand_address;
2283 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_address);
2284 if (show_instr_detail_level == 2 ){
2285 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_address %u",
2286 operand_address, state_address);
2289 * %state_instruction
2291 operand_address = next_operand_address;
2292 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_instruction);
2293 if (show_instr_detail_level == 2 ){
2294 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_instruction %u",
2295 operand_address, state_instruction);
2297 if (show_instr_detail_level == 1)
2299 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2300 "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)",
2301 current_address, p_id_start, p_id_length, state_begin, state_length, state_address, state_instruction);
2303 current_address = next_operand_address;
2304 byte_copy_right = buff[66] << 8;
2305 byte_copy_right = byte_copy_right | buff[67];
2306 byte_copy_left = buff[64] << 8;
2307 byte_copy_left = byte_copy_left | buff[65];
2308 if (print_level_2 ){
2309 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
2310 " byte_copy_right = %u, byte_copy_left = %u", byte_copy_right,byte_copy_left);
2313 result_code = udvm_state_access(message_tvb, udvm_tree, buff, p_id_start, p_id_length, state_begin, &state_length,
2314 &state_address, &state_instruction, hf_id);
2315 if ( result_code != 0 ){
2316 goto decompression_failure;
2318 used_udvm_cycles = used_udvm_cycles + state_length;
2319 goto execute_next_instruction;
2321 case SIGCOMP_INSTR_STATE_CREATE: /* 32 */
2323 * STATE-CREATE (%state_length, %state_address, %state_instruction,
2324 * %minimum_access_length, %state_retention_priority)
2326 if (show_instr_detail_level == 2 ){
2327 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2328 "Addr: %u ## STATE-CREATE(32) (state_length, state_address, state_instruction,minimum_access_length, state_retention_priority)",
2331 operand_address = current_address + 1;
2336 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_length);
2337 if (show_instr_detail_level == 2 ){
2338 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_length %u",
2339 operand_address, state_length);
2344 operand_address = next_operand_address;
2345 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_address);
2346 if (show_instr_detail_level == 2 ){
2347 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_address %u",
2348 operand_address, state_address);
2351 * %state_instruction
2353 operand_address = next_operand_address;
2354 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_instruction);
2355 if (show_instr_detail_level == 2 ){
2356 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_instruction %u",
2357 operand_address, state_instruction);
2360 * %minimum_access_length
2362 operand_address = next_operand_address;
2363 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &minimum_access_length);
2364 if (show_instr_detail_level == 2 ){
2365 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u minimum_access_length %u",
2366 operand_address, minimum_access_length);
2369 * %state_retention_priority
2371 operand_address = next_operand_address;
2372 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_retention_priority);
2373 if (show_instr_detail_level == 2 ){
2374 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_retention_priority %u",
2375 operand_address, state_retention_priority);
2377 if (show_instr_detail_level == 1)
2379 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2380 "Addr: %u ## STATE-CREATE(32) (state_length=%u, state_address=%u, state_instruction=%u,minimum_access_length=%u, state_retention_priority=%u)",
2381 current_address, state_length, state_address, state_instruction,minimum_access_length, state_retention_priority);
2383 current_address = next_operand_address;
2384 /* Execute the instruction
2385 * TODO Implement the instruction
2387 * Note that the new state item cannot be created until a valid
2388 * compartment identifier has been returned by the application.
2389 * Consequently, when a STATE-CREATE instruction is encountered the UDVM
2390 * simply buffers the five supplied operands until the END-MESSAGE
2391 * instruction is reached. The steps taken at this point are described
2394 * Decompression failure MUST occur if more than four state creation
2395 * requests are made before the END-MESSAGE instruction is encountered.
2396 * Decompression failure also occurs if the minimum_access_length does
2397 * not lie between 6 and 20 inclusive, or if the
2398 * state_retention_priority is 65535.
2400 no_of_state_create++;
2401 if ( no_of_state_create > 4 ){
2403 goto decompression_failure;
2405 if (( minimum_access_length < 6 ) || ( minimum_access_length > STATE_BUFFER_SIZE )){
2407 goto decompression_failure;
2409 if ( state_retention_priority == 65535 ){
2411 goto decompression_failure;
2413 state_length_buff[no_of_state_create] = state_length;
2414 state_address_buff[no_of_state_create] = state_address;
2415 state_instruction_buff[no_of_state_create] = state_instruction;
2416 state_minimum_access_length_buff[no_of_state_create] = minimum_access_length;
2417 /* state_state_retention_priority_buff[no_of_state_create] = state_retention_priority; */
2418 used_udvm_cycles = used_udvm_cycles + state_length;
2420 byte_copy_right = buff[66] << 8;
2421 byte_copy_right = byte_copy_right | buff[67];
2422 byte_copy_left = buff[64] << 8;
2423 byte_copy_left = byte_copy_left | buff[65];
2426 while ( n < state_length ){
2427 if ( k == byte_copy_right ){
2432 if (print_level_3 ){
2433 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2434 " Addr: %5u State value: %u (0x%x) ASCII(%s)",
2435 k,buff[k],buff[k],format_text(string, 1));
2437 k = ( k + 1 ) & 0xffff;
2442 goto execute_next_instruction;
2444 case SIGCOMP_INSTR_STATE_FREE: /* 33 */
2446 * STATE-FREE (%partial_identifier_start, %partial_identifier_length)
2448 if (show_instr_detail_level == 2 ){
2449 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2450 "Addr: %u ## STATE-FREE (partial_identifier_start, partial_identifier_length)",
2453 operand_address = current_address + 1;
2455 * %partial_identifier_start
2457 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &p_id_start);
2458 if (show_instr_detail_level == 2 ){
2459 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u partial_identifier_start %u",
2460 operand_address, p_id_start);
2462 operand_address = next_operand_address;
2465 * %partial_identifier_length
2467 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &p_id_length);
2468 if (show_instr_detail_level == 2 ){
2469 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u partial_identifier_length %u",
2470 operand_address, p_id_length);
2472 if (show_instr_detail_level == 1)
2474 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2475 "Addr: %u ## STATE-FREE (partial_identifier_start=%u, partial_identifier_length=%u)",
2476 current_address, p_id_start, p_id_length);
2478 current_address = next_operand_address;
2480 /* Execute the instruction:
2483 udvm_state_free(buff,p_id_start,p_id_length);
2485 goto execute_next_instruction;
2487 case SIGCOMP_INSTR_OUTPUT: /* 34 OUTPUT (%output_start, %output_length) */
2488 if (show_instr_detail_level == 2 ){
2489 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2490 "Addr: %u ## OUTPUT(34) (output_start, output_length)",
2493 operand_address = current_address + 1;
2497 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &output_start);
2498 if (show_instr_detail_level == 2 ){
2499 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u output_start %u",
2500 operand_address, output_start);
2502 operand_address = next_operand_address;
2506 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &output_length);
2507 if (show_instr_detail_level == 2 ){
2508 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u output_length %u",
2509 operand_address, output_length);
2511 if (show_instr_detail_level == 1)
2513 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2514 "Addr: %u ## OUTPUT (output_start=%u, output_length=%u)",
2515 current_address, output_start, output_length);
2517 current_address = next_operand_address;
2520 * Execute instruction
2523 * The string of bytes is copied in ascending order of memory address,
2524 * respecting the bounds set by byte_copy_left and byte_copy_right.
2525 * More precisely, if a byte is copied from/to Address m then the next
2526 * byte is copied from/to Address n where n is calculated as follows:
2528 * Set k := m + 1 (modulo 2^16)
2529 * If k = byte_copy_right then set n := byte_copy_left, else set n := k
2535 byte_copy_right = buff[66] << 8;
2536 byte_copy_right = byte_copy_right | buff[67];
2537 byte_copy_left = buff[64] << 8;
2538 byte_copy_left = byte_copy_left | buff[65];
2539 if (print_level_3 ){
2540 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2541 " byte_copy_right = %u", byte_copy_right);
2543 while ( n < output_length ){
2545 if ( k == byte_copy_right ){
2548 out_buff[output_address] = buff[k];
2551 if (print_level_3 ){
2552 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2553 " Output value: %u (0x%x) ASCII(%s) from Addr: %u ,output to dispatcher position %u",
2554 buff[k],buff[k],format_text(string,1), k,output_address);
2556 k = ( k + 1 ) & 0xffff;
2560 used_udvm_cycles = used_udvm_cycles + output_length;
2561 goto execute_next_instruction;
2563 case SIGCOMP_INSTR_END_MESSAGE: /* 35 */
2565 * END-MESSAGE (%requested_feedback_location,
2566 * %returned_parameters_location, %state_length, %state_address,
2567 * %state_instruction, %minimum_access_length,
2568 * %state_retention_priority)
2570 if (show_instr_detail_level == 2 ){
2571 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2572 "Addr: %u ## END-MESSAGE (requested_feedback_location,state_instruction, minimum_access_length,state_retention_priority)",
2575 operand_address = current_address + 1;
2577 /* %requested_feedback_location */
2578 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &requested_feedback_location);
2579 if (show_instr_detail_level == 2 ){
2580 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u requested_feedback_location %u",
2581 operand_address, requested_feedback_location);
2583 operand_address = next_operand_address;
2584 /* returned_parameters_location */
2585 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &returned_parameters_location);
2586 if (show_instr_detail_level == 2 ){
2587 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u returned_parameters_location %u",
2588 operand_address, returned_parameters_location);
2593 operand_address = next_operand_address;
2594 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_length);
2595 if (show_instr_detail_level == 2 ){
2596 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_length %u",
2597 operand_address, state_length);
2602 operand_address = next_operand_address;
2603 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_address);
2604 if (show_instr_detail_level == 2 ){
2605 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_address %u",
2606 operand_address, state_address);
2609 * %state_instruction
2611 operand_address = next_operand_address;
2612 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_instruction);
2613 if (show_instr_detail_level == 2 ){
2614 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_instruction %u",
2615 operand_address, state_instruction);
2619 * %minimum_access_length
2621 operand_address = next_operand_address;
2622 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &minimum_access_length);
2623 if (show_instr_detail_level == 2 ){
2624 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u minimum_access_length %u",
2625 operand_address, minimum_access_length);
2629 * %state_retention_priority
2631 operand_address = next_operand_address;
2632 /*next_operand_address =*/ decode_udvm_multitype_operand(buff, operand_address, &state_retention_priority);
2633 if (show_instr_detail_level == 2 ){
2634 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_retention_priority %u",
2635 operand_address, state_retention_priority);
2637 if (show_instr_detail_level == 1)
2639 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2640 "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)",
2641 current_address, requested_feedback_location, returned_parameters_location, state_length, state_address, state_instruction, minimum_access_length,state_retention_priority);
2643 /* TODO: This isn't currently totaly correct as END_INSTRUCTION might not create state */
2644 no_of_state_create++;
2645 if ( no_of_state_create > 4 ){
2647 goto decompression_failure;
2649 state_length_buff[no_of_state_create] = state_length;
2650 state_address_buff[no_of_state_create] = state_address;
2651 state_instruction_buff[no_of_state_create] = state_instruction;
2653 state_minimum_access_length_buff[no_of_state_create] = minimum_access_length;
2654 /* state_state_retention_priority_buff[no_of_state_create] = state_retention_priority; */
2656 /* Execute the instruction
2658 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"no_of_state_create %u",no_of_state_create);
2659 if ( no_of_state_create != 0 ){
2660 memset(sha1_digest_buf, 0, STATE_BUFFER_SIZE);
2662 byte_copy_right = buff[66] << 8;
2663 byte_copy_right = byte_copy_right | buff[67];
2664 byte_copy_left = buff[64] << 8;
2665 byte_copy_left = byte_copy_left | buff[65];
2666 while ( n < no_of_state_create + 1 ){
2667 sha1buff = (guint8 *)g_malloc(state_length_buff[n]+8);
2668 sha1buff[0] = state_length_buff[n] >> 8;
2669 sha1buff[1] = state_length_buff[n] & 0xff;
2670 sha1buff[2] = state_address_buff[n] >> 8;
2671 sha1buff[3] = state_address_buff[n] & 0xff;
2672 sha1buff[4] = state_instruction_buff[n] >> 8;
2673 sha1buff[5] = state_instruction_buff[n] & 0xff;
2674 sha1buff[6] = state_minimum_access_length_buff[n] >> 8;
2675 sha1buff[7] = state_minimum_access_length_buff[n] & 0xff;
2676 if (print_level_3 ){
2677 for( x=0; x < 8; x++){
2678 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"sha1buff %u 0x%x",
2682 k = state_address_buff[n];
2683 for( x=0; x < state_length_buff[n]; x++)
2685 if ( k == byte_copy_right ){
2688 sha1buff[8+x] = buff[k];
2689 k = ( k + 1 ) & 0xffff;
2692 sha1_starts( &ctx );
2693 sha1_update( &ctx, (guint8 *) sha1buff, state_length_buff[n] + 8);
2694 sha1_finish( &ctx, sha1_digest_buf );
2695 if (print_level_3 ){
2696 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"SHA1 digest %s",bytes_to_ep_str(sha1_digest_buf, STATE_BUFFER_SIZE));
2699 /* begin partial state-id change cco@iptel.org */
2701 udvm_state_create(sha1buff, sha1_digest_buf, state_minimum_access_length_buff[n]);
2703 udvm_state_create(sha1buff, sha1_digest_buf, STATE_MIN_ACCESS_LEN);
2704 /* end partial state-id change cco@iptel.org */
2705 proto_tree_add_text(udvm_tree,bytecode_tvb, 0, -1,"### Creating state ###");
2706 proto_tree_add_string(udvm_tree,hf_id, bytecode_tvb, 0, 0, bytes_to_ep_str(sha1_digest_buf, state_minimum_access_length_buff[n]));
2715 /* At least something got decompressed, show it */
2716 decomp_tvb = tvb_new_child_real_data(message_tvb, out_buff,output_address,output_address);
2717 /* Arrange that the allocated packet data copy be freed when the
2720 tvb_set_free_cb( decomp_tvb, g_free );
2722 add_new_data_source(pinfo, decomp_tvb, "Decompressed SigComp message");
2724 proto_tree_add_text(udvm_tree, decomp_tvb, 0, -1,"SigComp message Decompressed");
2726 used_udvm_cycles = used_udvm_cycles + state_length;
2727 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"maximum_UDVM_cycles %u used_udvm_cycles %u",
2728 maximum_UDVM_cycles, used_udvm_cycles);
2733 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," ### Addr %u Invalid instruction: %u (0x%x)",
2734 current_address,current_instruction,current_instruction);
2739 decompression_failure:
2741 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"DECOMPRESSION FAILURE: %s",
2742 val_to_str(result_code, result_code_vals,"Unknown (%u)"));
2743 THROW(ReportedBoundsError);
2749 /* The simplest operand type is the literal (#), which encodes a
2750 * constant integer from 0 to 65535 inclusive. A literal operand may
2751 * require between 1 and 3 bytes depending on its value.
2752 * Bytecode: Operand value: Range:
2753 * 0nnnnnnn N 0 - 127
2754 * 10nnnnnn nnnnnnnn N 0 - 16383
2755 * 11000000 nnnnnnnn nnnnnnnn N 0 - 65535
2757 * Figure 8: Bytecode for a literal (#) operand
2761 decode_udvm_literal_operand(guint8 *buff,guint operand_address, guint16 *value)
2766 guint offset = operand_address;
2769 bytecode = buff[operand_address];
2770 test_bits = bytecode >> 7;
2771 if (test_bits == 1){
2772 test_bits = bytecode >> 6;
2773 if (test_bits == 2){
2775 * 10nnnnnn nnnnnnnn N 0 - 16383
2777 temp_data = buff[operand_address] & 0x1f;
2778 operand = temp_data << 8;
2779 temp_data = buff[(operand_address + 1) & 0xffff];
2780 operand = operand | temp_data;
2782 offset = offset + 2;
2786 * 111000000 nnnnnnnn nnnnnnnn N 0 - 65535
2789 temp_data = buff[operand_address] & 0x1f;
2790 operand = temp_data << 8;
2791 temp_data = buff[(operand_address + 1) & 0xffff];
2792 operand = operand | temp_data;
2794 offset = offset + 2;
2799 * 0nnnnnnn N 0 - 127
2801 operand = ( bytecode & 0x7f);
2811 * The second operand type is the reference ($), which is always used to
2812 * access a 2-byte value located elsewhere in the UDVM memory. The
2813 * bytecode for a reference operand is decoded to be a constant integer
2814 * from 0 to 65535 inclusive, which is interpreted as the memory address
2815 * containing the actual value of the operand.
2816 * Bytecode: Operand value: Range:
2818 * 0nnnnnnn memory[2 * N] 0 - 65535
2819 * 10nnnnnn nnnnnnnn memory[2 * N] 0 - 65535
2820 * 11000000 nnnnnnnn nnnnnnnn memory[N] 0 - 65535
2822 * Figure 9: Bytecode for a reference ($) operand
2825 dissect_udvm_reference_operand(guint8 *buff,guint operand_address, guint16 *value,guint *result_dest)
2829 guint offset = operand_address;
2832 guint16 temp_data16;
2834 bytecode = buff[operand_address];
2835 test_bits = bytecode >> 7;
2836 if (test_bits == 1){
2837 test_bits = bytecode >> 6;
2838 if (test_bits == 2){
2840 * 10nnnnnn nnnnnnnn memory[2 * N] 0 - 65535
2842 temp_data = buff[operand_address] & 0x3f;
2843 operand = temp_data << 8;
2844 temp_data = buff[(operand_address + 1) & 0xffff];
2845 operand = operand | temp_data;
2846 operand = (operand * 2);
2847 *result_dest = operand;
2848 temp_data16 = buff[operand] << 8;
2849 temp_data16 = temp_data16 | buff[(operand+1) & 0xffff];
2850 *value = temp_data16;
2851 offset = offset + 2;
2855 * 11000000 nnnnnnnn nnnnnnnn memory[N] 0 - 65535
2858 operand = buff[operand_address] << 8;
2859 operand = operand | buff[(operand_address + 1) & 0xffff];
2860 *result_dest = operand;
2861 temp_data16 = buff[operand] << 8;
2862 temp_data16 = temp_data16 | buff[(operand+1) & 0xffff];
2863 *value = temp_data16;
2864 offset = offset + 3;
2869 * 0nnnnnnn memory[2 * N] 0 - 65535
2871 operand = ( bytecode & 0x7f);
2872 operand = (operand * 2);
2873 *result_dest = operand;
2874 temp_data16 = buff[operand] << 8;
2875 temp_data16 = temp_data16 | buff[(operand+1) & 0xffff];
2876 *value = temp_data16;
2880 if (offset >= UDVM_MEMORY_SIZE || *result_dest >= UDVM_MEMORY_SIZE - 1 )
2881 THROW(ReportedBoundsError);
2887 * Figure 10: Bytecode for a multitype (%) operand
2888 * Bytecode: Operand value: Range: HEX val
2889 * 00nnnnnn N 0 - 63 0x00
2890 * 01nnnnnn memory[2 * N] 0 - 65535 0x40
2891 * 1000011n 2 ^ (N + 6) 64 , 128 0x86
2892 * 10001nnn 2 ^ (N + 8) 256 , ... , 32768 0x88
2893 * 111nnnnn N + 65504 65504 - 65535 0xe0
2894 * 1001nnnn nnnnnnnn N + 61440 61440 - 65535 0x90
2895 * 101nnnnn nnnnnnnn N 0 - 8191 0xa0
2896 * 110nnnnn nnnnnnnn memory[N] 0 - 65535 0xc0
2897 * 10000000 nnnnnnnn nnnnnnnn N 0 - 65535 0x80
2898 * 10000001 nnnnnnnn nnnnnnnn memory[N] 0 - 65535 0x81
2901 decode_udvm_multitype_operand(guint8 *buff,guint operand_address, guint16 *value)
2905 guint offset = operand_address;
2909 guint16 temp_data16;
2910 guint16 memmory_addr = 0;
2914 bytecode = buff[operand_address];
2915 test_bits = ( bytecode & 0xc0 ) >> 6;
2916 switch (test_bits ){
2921 operand = buff[operand_address];
2923 *g_warning("Reading 0x%x From address %u",operand,offset);
2930 * 01nnnnnn memory[2 * N] 0 - 65535
2932 memmory_addr = ( bytecode & 0x3f) * 2;
2933 temp_data16 = buff[memmory_addr] << 8;
2934 temp_data16 = temp_data16 | buff[(memmory_addr+1) & 0xffff];
2935 *value = temp_data16;
2939 /* Check tree most significant bits */
2940 test_bits = ( bytecode & 0xe0 ) >> 5;
2941 if ( test_bits == 5 ){
2943 * 101nnnnn nnnnnnnn N 0 - 8191
2945 temp_data = buff[operand_address] & 0x1f;
2946 operand = temp_data << 8;
2947 temp_data = buff[(operand_address + 1) & 0xffff];
2948 operand = operand | temp_data;
2950 offset = offset + 2;
2952 test_bits = ( bytecode & 0xf0 ) >> 4;
2953 if ( test_bits == 9 ){
2955 * 1001nnnn nnnnnnnn N + 61440 61440 - 65535
2957 temp_data = buff[operand_address] & 0x0f;
2958 operand = temp_data << 8;
2959 temp_data = buff[(operand_address + 1) & 0xffff];
2960 operand = operand | temp_data;
2961 operand = operand + 61440;
2963 offset = offset + 2;
2965 test_bits = ( bytecode & 0x08 ) >> 3;
2966 if ( test_bits == 1){
2968 * 10001nnn 2 ^ (N + 8) 256 , ... , 32768
2971 result = 1 << ((buff[operand_address] & 0x07) + 8);
2972 operand = result & 0xffff;
2976 test_bits = ( bytecode & 0x0e ) >> 1;
2977 if ( test_bits == 3 ){
2979 * 1000 011n 2 ^ (N + 6) 64 , 128
2981 result = 1 << ((buff[operand_address] & 0x01) + 6);
2982 operand = result & 0xffff;
2987 * 1000 0000 nnnnnnnn nnnnnnnn N 0 - 65535
2988 * 1000 0001 nnnnnnnn nnnnnnnn memory[N] 0 - 65535
2991 temp_data16 = buff[(operand_address + 1) & 0xffff] << 8;
2992 temp_data16 = temp_data16 | buff[(operand_address + 2) & 0xffff];
2994 * g_warning("Reading 0x%x From address %u",temp_data16,operand_address);
2996 if ( (bytecode & 0x01) == 1 ){
2997 memmory_addr = temp_data16;
2998 temp_data16 = buff[memmory_addr] << 8;
2999 temp_data16 = temp_data16 | buff[(memmory_addr+1) & 0xffff];
3001 *value = temp_data16;
3012 test_bits = ( bytecode & 0x20 ) >> 5;
3013 if ( test_bits == 1 ){
3015 * 111nnnnn N + 65504 65504 - 65535
3017 operand = ( buff[operand_address] & 0x1f) + 65504;
3022 * 110nnnnn nnnnnnnn memory[N] 0 - 65535
3024 memmory_addr = buff[operand_address] & 0x1f;
3025 memmory_addr = memmory_addr << 8;
3026 memmory_addr = memmory_addr | buff[(operand_address + 1) & 0xffff];
3027 temp_data16 = buff[memmory_addr] << 8;
3028 temp_data16 = temp_data16 | buff[(memmory_addr+1) & 0xffff];
3029 *value = temp_data16;
3031 * g_warning("Reading 0x%x From address %u",temp_data16,memmory_addr);
3043 * The fourth operand type is the address (@). This operand is decoded
3044 * as a multitype operand followed by a further step: the memory address
3045 * of the UDVM instruction containing the address operand is added to
3046 * obtain the correct operand value. So if the operand value from
3047 * Figure 10 is D then the actual operand value of an address is
3048 * calculated as follows:
3050 * operand_value = (memory_address_of_instruction + D) modulo 2^16
3052 * Address operands are always used in instructions that control program
3053 * flow, because they ensure that the UDVM bytecode is position-
3054 * independent code (i.e., it will run independently of where it is
3055 * placed in the UDVM memory).
3058 decode_udvm_address_operand(guint8 *buff,guint operand_address, guint16 *value,guint current_address)
3062 guint next_opreand_address;
3064 next_opreand_address = decode_udvm_multitype_operand(buff, operand_address, &value1);
3065 result = value1 & 0xffff;
3066 result = result + current_address;
3067 *value = result & 0xffff;
3068 return next_opreand_address;
3073 * This is a lookup table used to reverse the bits in a byte.
3075 static guint8 reverse [] = {
3076 0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0,
3077 0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0,
3078 0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8,
3079 0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8,
3080 0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4,
3081 0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4,
3082 0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC,
3083 0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC,
3084 0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2,
3085 0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2,
3086 0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA,
3087 0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA,
3088 0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6,
3089 0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6,
3090 0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE,
3091 0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE,
3092 0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1,
3093 0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1,
3094 0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9,
3095 0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9,
3096 0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5,
3097 0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5,
3098 0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED,
3099 0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD,
3100 0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3,
3101 0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3,
3102 0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB,
3103 0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB,
3104 0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7,
3105 0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7,
3106 0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF,
3107 0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF
3112 decomp_dispatch_get_bits(
3113 tvbuff_t *message_tvb,
3114 proto_tree *udvm_tree,
3117 guint16 *old_input_bit_order,
3118 guint16 *remaining_bits,
3119 guint16 *input_bits,
3120 guint *input_address,
3122 guint16 *result_code,
3125 guint16 input_bit_order;
3126 guint16 bits_still_required = length;
3129 gint extra_bytes_available = msg_end - *input_address;
3131 gint prev_p_bit = *old_input_bit_order & 0x0001;
3132 gint bits_to_use = 0;
3135 input_bit_order = buff[68] << 8;
3136 input_bit_order = input_bit_order | buff[69];
3138 p_bit = (input_bit_order & 0x0001) != 0;
3141 * Discard any spare bits.
3142 * Note: We take care to avoid remaining_bits having the value of 8.
3144 if (prev_p_bit != p_bit)
3146 *remaining_bits = 0;
3147 *old_input_bit_order = input_bit_order;
3151 * Check we can suppy the required number of bits now, before we alter
3152 * the input buffer's state.
3154 if (*remaining_bits + extra_bytes_available * 8 < length)
3160 /* Note: This is never called with length > 16, so the following loop
3161 * never loops more than three time. */
3162 while (bits_still_required > 0)
3165 * We only put anything into input_bits if we know we will remove
3166 * at least one bit. That ensures we can simply discard the spare
3167 * bits if the P-bit changes.
3169 if (*remaining_bits == 0)
3171 octet = tvb_get_guint8(message_tvb, *input_address);
3172 if (print_level_1 ){
3173 proto_tree_add_text(udvm_tree, message_tvb, *input_address , 1,
3174 " Getting value: %u (0x%x) From Addr: %u", octet, octet, *input_address);
3176 *input_address = *input_address + 1;
3180 octet = reverse[octet];
3182 *input_bits = octet;
3183 *remaining_bits = 8;
3186 /* Add some more bits to the accumulated value. */
3187 bits_to_use = bits_still_required < *remaining_bits ? bits_still_required : *remaining_bits;
3188 bits_still_required -= bits_to_use;
3190 *input_bits <<= bits_to_use; /* Shift bits into MSByte */
3191 value = (value << bits_to_use) /* Then add to the accumulated value */
3192 | ((*input_bits >> 8) & 0xFF);
3193 *remaining_bits -= bits_to_use;
3194 *input_bits &= 0x00FF; /* Leave just the remaining bits */
3199 /* Bit reverse the entire word. */
3200 guint16 lsb = reverse[(value >> 8) & 0xFF];
3201 guint16 msb = reverse[value & 0xFF];
3203 value = ((msb << 8) | lsb) >> (16 - length);