2 * Routines making up the Universal Decompressor Virtual Machine (UDVM) used for
3 * Signaling Compression (SigComp) dissection.
4 * Copyright 2004, Anders Broman <anders.broman@ericsson.com>
8 * Wireshark - Network traffic analyzer
9 * By Gerald Combs <gerald@wireshark.org>
10 * Copyright 1998 Gerald Combs
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
26 * http://www.ietf.org/rfc/rfc3320.txt?number=3320
27 * http://www.ietf.org/rfc/rfc3321.txt?number=3321
29 * http://www.ietf.org/internet-drafts/draft-ietf-rohc-sigcomp-impl-guide-05.txt
30 * http://www.ietf.org/internet-drafts/draft-ietf-rohc-sigcomp-sip-01.txt
40 #include <epan/emem.h>
42 #include <wsutil/sha1.h>
43 #include <wsutil/crc16.h>
48 #include "sigcomp-udvm.h"
49 #include "sigcomp_state_hdlr.h"
52 #define SIGCOMP_INSTR_DECOMPRESSION_FAILURE 0
53 #define SIGCOMP_INSTR_AND 1
54 #define SIGCOMP_INSTR_OR 2
55 #define SIGCOMP_INSTR_NOT 3
56 #define SIGCOMP_INSTR_LSHIFT 4
57 #define SIGCOMP_INSTR_RSHIFT 5
58 #define SIGCOMP_INSTR_ADD 6
59 #define SIGCOMP_INSTR_SUBTRACT 7
60 #define SIGCOMP_INSTR_MULTIPLY 8
61 #define SIGCOMP_INSTR_DIVIDE 9
62 #define SIGCOMP_INSTR_REMAINDER 10
63 #define SIGCOMP_INSTR_SORT_ASCENDING 11
64 #define SIGCOMP_INSTR_SORT_DESCENDING 12
65 #define SIGCOMP_INSTR_SHA_1 13
66 #define SIGCOMP_INSTR_LOAD 14
67 #define SIGCOMP_INSTR_MULTILOAD 15
68 #define SIGCOMP_INSTR_PUSH 16
69 #define SIGCOMP_INSTR_POP 17
70 #define SIGCOMP_INSTR_COPY 18
71 #define SIGCOMP_INSTR_COPY_LITERAL 19
72 #define SIGCOMP_INSTR_COPY_OFFSET 20
73 #define SIGCOMP_INSTR_MEMSET 21
74 #define SIGCOMP_INSTR_JUMP 22
75 #define SIGCOMP_INSTR_COMPARE 23
76 #define SIGCOMP_INSTR_CALL 24
77 #define SIGCOMP_INSTR_RETURN 25
78 #define SIGCOMP_INSTR_SWITCH 26
79 #define SIGCOMP_INSTR_CRC 27
80 #define SIGCOMP_INSTR_INPUT_BYTES 28
81 #define SIGCOMP_INSTR_INPUT_BITS 29
82 #define SIGCOMP_INSTR_INPUT_HUFFMAN 30
83 #define SIGCOMP_INSTR_STATE_ACCESS 31
84 #define SIGCOMP_INSTR_STATE_CREATE 32
85 #define SIGCOMP_INSTR_STATE_FREE 33
86 #define SIGCOMP_INSTR_OUTPUT 34
87 #define SIGCOMP_INSTR_END_MESSAGE 35
90 static gboolean print_level_1;
91 static gboolean print_level_2;
92 static gboolean print_level_3;
93 static gint show_instr_detail_level;
95 /* Internal result code values of decompression failures */
96 const value_string result_code_vals[] = {
97 { 0, "No decompression failure" },
98 { 1, "Partial state length less than 6 or greater than 20 bytes long" },
99 { 2, "No state match" },
100 { 3, "state_begin + state_length > size of state" },
101 { 4, "Operand_2 is Zero" },
102 { 5, "Switch statement failed j >= n" },
103 { 6, "Attempt to jump outside of UDVM memory" },
104 { 7, "L in input-bits > 16" },
105 { 8, "input_bit_order > 7" },
106 { 9, "Instruction Decompression failure encountered" },
107 {10, "Input huffman failed j > n" },
108 {11, "Input bits requested beyond end of message" },
109 {12, "more than four state creation requests are made before the END-MESSAGE instruction" },
110 {13, "state_retention_priority is 65535" },
111 {14, "Input bytes requested beyond end of message" },
112 {15, "Maximum number of UDVM cycles reached" },
113 {16, "UDVM stack underflow" },
114 { 255, "This branch isn't coded yet" },
118 static int decode_udvm_literal_operand(guint8 *buff,guint operand_address, guint16 *value);
119 static int dissect_udvm_reference_operand(guint8 *buff,guint operand_address, guint16 *value, guint *result_dest);
120 static int decode_udvm_multitype_operand(guint8 *buff,guint operand_address,guint16 *value);
121 static int decode_udvm_address_operand(guint8 *buff,guint operand_address, guint16 *value,guint current_address);
122 static int decomp_dispatch_get_bits(tvbuff_t *message_tvb,proto_tree *udvm_tree,guint8 bit_order,
123 guint8 *buff,guint16 *old_input_bit_order, guint16 *remaining_bits,
124 guint16 *input_bits, guint *input_address, guint16 length, guint16 *result_code,guint msg_end);
128 decompress_sigcomp_message(tvbuff_t *bytecode_tvb, tvbuff_t *message_tvb, packet_info *pinfo,
129 proto_tree *udvm_tree, gint udvm_mem_dest,
130 gint print_flags, gint hf_id,
132 gint byte_code_state_len, gint byte_code_id_len,
135 tvbuff_t *decomp_tvb;
136 /* UDVM memory must be initialised to zero */
137 guint8 *buff = (guint8 *)ep_alloc0(UDVM_MEMORY_SIZE);
139 guint8 *out_buff; /* Largest allowed size for a message is UDVM_MEMORY_SIZE = 65536 */
149 guint code_length =0;
150 guint8 current_instruction;
151 guint current_address;
152 guint operand_address;
154 guint16 output_address = 0;
155 guint next_operand_address;
159 guint16 byte_copy_right;
160 guint16 byte_copy_left;
161 guint16 input_bit_order;
162 guint16 stack_location;
165 guint msg_end = tvb_reported_length_remaining(message_tvb, 0);
166 guint16 result_code = 0;
167 guint16 old_input_bit_order = 0;
168 guint16 remaining_bits = 0;
169 guint16 input_bits = 0;
170 guint8 bit_order = 0;
171 gboolean outside_huffman_boundaries = TRUE;
172 gboolean print_in_loop = FALSE;
173 guint16 instruction_address;
174 guint8 no_of_state_create = 0;
175 guint16 state_length_buff[5];
176 guint16 state_address_buff[5];
177 guint16 state_instruction_buff[5];
178 guint16 state_minimum_access_length_buff[5];
179 /* guint16 state_state_retention_priority_buff[5]; */
180 guint32 used_udvm_cycles = 0;
181 guint cycles_per_bit;
182 guint maximum_UDVM_cycles;
184 unsigned char sha1_digest_buf[STATE_BUFFER_SIZE];
188 /* UDVM operand variables */
197 guint16 state_length;
198 guint16 state_address;
199 guint16 state_instruction;
204 guint16 at_address_1;
205 guint16 at_address_2;
206 guint16 at_address_3;
209 guint16 lower_bound_n;
210 guint16 upper_bound_n;
211 guint16 uncompressed_n;
213 guint16 ref_destination; /* could I have used $destination ? */
214 guint16 multy_offset;
215 guint16 output_start;
216 guint16 output_length;
217 guint16 minimum_access_length;
218 guint16 state_retention_priority;
219 guint16 requested_feedback_location;
220 guint16 returned_parameters_location;
224 /* Set print parameters */
225 print_level_1 = FALSE;
226 print_level_2 = FALSE;
227 print_level_3 = FALSE;
228 show_instr_detail_level = 0;
232 switch( print_flags ) {
237 print_level_1 = TRUE;
238 show_instr_detail_level = 1;
241 print_level_1 = TRUE;
242 print_level_2 = TRUE;
243 show_instr_detail_level = 1;
246 print_level_1 = TRUE;
247 print_level_2 = TRUE;
248 print_level_3 = TRUE;
249 show_instr_detail_level = 2;
252 print_level_1 = TRUE;
253 show_instr_detail_level = 1;
257 /* Set initial UDVM data
258 * The first 32 bytes of UDVM memory are then initialized to special
259 * values as illustrated in Figure 5.
262 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
263 * | UDVM_memory_size | 0 - 1
264 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
265 * | cycles_per_bit | 2 - 3
266 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
267 * | SigComp_version | 4 - 5
268 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
269 * | partial_state_ID_length | 6 - 7
270 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
271 * | state_length | 8 - 9
272 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
274 * : reserved : 10 - 31
276 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
278 * Figure 5: Initializing Useful Values in UDVM memory
280 /* UDVM_memory_size */
281 buff[0] = (UDVM_MEMORY_SIZE >> 8) & 0x00FF;
282 buff[1] = UDVM_MEMORY_SIZE & 0x00FF;
286 /* SigComp_version */
289 /* partial_state_ID_length */
290 buff[6] = (byte_code_id_len >> 8) & 0x00FF;
291 buff[7] = byte_code_id_len & 0x00FF;
293 buff[8] = (byte_code_state_len >> 8) & 0x00FF;
294 buff[9] = byte_code_state_len & 0x00FF;
296 code_length = tvb_reported_length_remaining(bytecode_tvb, 0);
298 cycles_per_bit = buff[2] << 8;
299 cycles_per_bit = cycles_per_bit | buff[3];
301 * maximum_UDVM_cycles = (8 * n + 1000) * cycles_per_bit
303 maximum_UDVM_cycles = (( 8 * (header_len + msg_end) ) + 1000) * cycles_per_bit;
305 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);
306 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);
308 /* Load bytecode into UDVM starting at "udvm_mem_dest" */
311 proto_tree_add_text(udvm_tree, bytecode_tvb, offset, 1,"Load bytecode into UDVM starting at %u",i);
312 while ( code_length > offset && i < UDVM_MEMORY_SIZE ) {
313 buff[i] = tvb_get_guint8(bytecode_tvb, offset);
315 proto_tree_add_text(udvm_tree, bytecode_tvb, offset, 1,
316 " Addr: %u Instruction code(0x%0x) ", i, buff[i]);
322 /* Largest allowed size for a message is UDVM_MEMORY_SIZE = 65536 */
323 out_buff = (guint8 *)g_malloc(UDVM_MEMORY_SIZE);
324 /* Start executing code */
325 current_address = udvm_start_ip;
328 proto_tree_add_text(udvm_tree, bytecode_tvb, offset, 1,"UDVM EXECUTION STARTED at Address: %u Message size %u",
329 current_address, msg_end);
331 execute_next_instruction:
333 if ( used_udvm_cycles > maximum_UDVM_cycles ){
335 goto decompression_failure;
338 current_instruction = buff[current_address & 0xffff];
340 switch ( current_instruction ) {
341 case SIGCOMP_INSTR_DECOMPRESSION_FAILURE:
342 if ( result_code == 0 )
344 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
345 "Addr: %u ## DECOMPRESSION-FAILURE(0)",
347 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Wireshark UDVM diagnostic: %s.",
348 val_to_str(result_code, result_code_vals,"Unknown (%u)"));
349 if ( output_address > 0 ){
350 /* At least something got decompressed, show it */
351 decomp_tvb = tvb_new_child_real_data(message_tvb, out_buff,output_address,output_address);
352 /* Arrange that the allocated packet data copy be freed when the
355 tvb_set_free_cb( decomp_tvb, g_free );
356 /* Add the tvbuff to the list of tvbuffs to which the tvbuff we
357 * were handed refers, so it'll get cleaned up when that tvbuff
360 add_new_data_source(pinfo, decomp_tvb, "Decompressed SigComp message(Incomplete)");
361 proto_tree_add_text(udvm_tree, decomp_tvb, 0, -1,"SigComp message Decompression failure");
368 case SIGCOMP_INSTR_AND: /* 1 AND ($operand_1, %operand_2) */
369 if (show_instr_detail_level == 2 ){
370 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
371 "Addr: %u ## AND(1) (operand_1, operand_2)",
375 operand_address = current_address + 1;
376 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &operand_1, &result_dest);
377 if (show_instr_detail_level == 2 ){
378 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_1 %u",
379 operand_address, operand_1);
381 operand_address = next_operand_address;
383 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &operand_2);
384 if (show_instr_detail_level == 2 ){
385 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_2 %u",
386 operand_address, operand_2);
388 if (show_instr_detail_level == 1)
390 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
391 "Addr: %u ## AND (operand_1=%u, operand_2=%u)",
392 current_address, operand_1, operand_2);
394 /* execute the instruction */
395 result = operand_1 & operand_2;
398 buff[result_dest] = msb;
399 buff[(result_dest+1) & 0xffff] = lsb;
401 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," Loading result %u at %u",
402 result, result_dest);
404 current_address = next_operand_address;
405 goto execute_next_instruction;
409 case SIGCOMP_INSTR_OR: /* 2 OR ($operand_1, %operand_2) */
410 if (show_instr_detail_level == 2 ){
411 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
412 "Addr: %u ## OR(2) (operand_1, operand_2)",
416 operand_address = current_address + 1;
417 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &operand_1, &result_dest);
418 if (show_instr_detail_level == 2 ){
419 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_1 %u",
420 operand_address, operand_1);
422 operand_address = next_operand_address;
424 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &operand_2);
425 if (show_instr_detail_level == 2 ){
426 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_2 %u",
427 operand_address, operand_2);
429 if (show_instr_detail_level == 1)
431 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
432 "Addr: %u ## OR (operand_1=%u, operand_2=%u)",
433 current_address, operand_1, operand_2);
435 /* execute the instruction */
436 result = operand_1 | operand_2;
439 buff[result_dest] = msb;
440 buff[(result_dest+1) & 0xffff] = lsb;
442 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," Loading result %u at %u",
443 result, result_dest);
445 current_address = next_operand_address;
446 goto execute_next_instruction;
450 case SIGCOMP_INSTR_NOT: /* 3 NOT ($operand_1) */
451 if (show_instr_detail_level == 2 ){
452 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
453 "Addr: %u ## NOT(3) ($operand_1)",
457 operand_address = current_address + 1;
458 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &operand_1, &result_dest);
459 if (show_instr_detail_level == 2 ){
460 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_1 %u",
461 operand_address, operand_1);
463 if (show_instr_detail_level == 1)
465 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
466 "Addr: %u ## NOT (operand_1=%u)",
467 current_address, operand_1);
469 /* execute the instruction */
470 result = operand_1 ^ 0xffff;
473 buff[result_dest] = msb;
474 buff[(result_dest+1) & 0xffff] = lsb;
476 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," Loading result %u at %u",
477 result, result_dest);
479 current_address = next_operand_address;
480 goto execute_next_instruction;
483 case SIGCOMP_INSTR_LSHIFT: /* 4 LSHIFT ($operand_1, %operand_2) */
484 if (show_instr_detail_level == 2 ){
485 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
486 "Addr: %u ## LSHIFT(4) ($operand_1, operand_2)",
490 operand_address = current_address + 1;
491 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &operand_1, &result_dest);
492 if (show_instr_detail_level == 2 ){
493 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_1 %u",
494 operand_address, operand_1);
496 operand_address = next_operand_address;
498 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &operand_2);
499 if (show_instr_detail_level == 2 ){
500 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_2 %u",
501 operand_address, operand_2);
503 if (show_instr_detail_level == 1)
505 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
506 "Addr: %u ## LSHIFT (operand_1=%u, operand_2=%u)",
507 current_address, operand_1, operand_2);
509 /* execute the instruction */
510 result = operand_1 << operand_2;
513 buff[result_dest] = msb;
514 buff[(result_dest+1) & 0xffff] = lsb;
516 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," Loading result %u at %u",
517 result, result_dest);
519 current_address = next_operand_address;
520 goto execute_next_instruction;
523 case SIGCOMP_INSTR_RSHIFT: /* 5 RSHIFT ($operand_1, %operand_2) */
524 if (show_instr_detail_level == 2 ){
525 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
526 "Addr: %u ## RSHIFT(5) (operand_1, operand_2)",
530 operand_address = current_address + 1;
531 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &operand_1, &result_dest);
532 if (show_instr_detail_level == 2 ){
533 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_1 %u",
534 operand_address, operand_1);
536 operand_address = next_operand_address;
538 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &operand_2);
539 if (show_instr_detail_level == 2 ){
540 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_2 %u",
541 operand_address, operand_2);
543 if (show_instr_detail_level == 1)
545 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
546 "Addr: %u ## RSHIFT (operand_1=%u, operand_2=%u)",
547 current_address, operand_1, operand_2);
549 /* execute the instruction */
550 result = operand_1 >> operand_2;
553 buff[result_dest] = msb;
554 buff[(result_dest+1) & 0xffff] = lsb;
556 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," Loading result %u at %u",
557 result, result_dest);
559 current_address = next_operand_address;
560 goto execute_next_instruction;
562 case SIGCOMP_INSTR_ADD: /* 6 ADD ($operand_1, %operand_2) */
563 if (show_instr_detail_level == 2 ){
564 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
565 "Addr: %u ## ADD(6) (operand_1, operand_2)",
569 operand_address = current_address + 1;
570 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &operand_1, &result_dest);
571 if (show_instr_detail_level == 2 ){
572 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_1 %u",
573 operand_address, operand_1);
575 operand_address = next_operand_address;
577 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &operand_2);
578 if (show_instr_detail_level == 2 ){
579 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_2 %u",
580 operand_address, operand_2);
582 if (show_instr_detail_level == 1)
584 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
585 "Addr: %u ## ADD (operand_1=%u, operand_2=%u)",
586 current_address, operand_1, operand_2);
588 /* execute the instruction */
589 result = operand_1 + operand_2;
592 buff[result_dest] = msb;
593 buff[(result_dest+1) & 0xffff] = lsb;
595 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," Loading result %u at %u",
596 result, result_dest);
598 current_address = next_operand_address;
599 goto execute_next_instruction;
601 case SIGCOMP_INSTR_SUBTRACT: /* 7 SUBTRACT ($operand_1, %operand_2) */
602 if (show_instr_detail_level == 2 ){
603 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
604 "Addr: %u ## SUBTRACT(7) (operand_1, operand_2)",
608 operand_address = current_address + 1;
609 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &operand_1, &result_dest);
610 if (show_instr_detail_level == 2 ){
611 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_1 %u",
612 operand_address, operand_1);
614 operand_address = next_operand_address;
616 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &operand_2);
617 if (show_instr_detail_level == 2 ){
618 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_2 %u",
619 operand_address, operand_2);
621 if (show_instr_detail_level == 1)
623 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
624 "Addr: %u ## SUBTRACT (operand_1=%u, operand_2=%u)",
625 current_address, operand_1, operand_2);
627 /* execute the instruction */
628 result = operand_1 - operand_2;
631 buff[result_dest] = msb;
632 buff[(result_dest+1) & 0xffff] = lsb;
634 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," Loading result %u at %u",
635 result, result_dest);
637 current_address = next_operand_address;
638 goto execute_next_instruction;
641 case SIGCOMP_INSTR_MULTIPLY: /* 8 MULTIPLY ($operand_1, %operand_2) */
642 if (show_instr_detail_level == 2 ){
643 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
644 "Addr: %u ##MULTIPLY(8) (operand_1, operand_2)",
648 operand_address = current_address + 1;
649 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &operand_1, &result_dest);
650 if (show_instr_detail_level == 2 ){
651 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_1 %u",
652 operand_address, operand_1);
654 operand_address = next_operand_address;
656 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &operand_2);
657 if (show_instr_detail_level == 2 ){
658 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_2 %u",
659 operand_address, operand_2);
661 if (show_instr_detail_level == 1)
663 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
664 "Addr: %u ## MULTIPLY (operand_1=%u, operand_2=%u)",
665 current_address, operand_1, operand_2);
668 * execute the instruction
669 * MULTIPLY (m, n) := m * n (modulo 2^16)
671 if ( operand_2 == 0){
673 goto decompression_failure;
675 result = operand_1 * operand_2;
678 buff[result_dest] = msb;
679 buff[(result_dest+1) & 0xffff] = lsb;
681 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," Loading result %u at %u",
682 result, result_dest);
684 current_address = next_operand_address;
685 goto execute_next_instruction;
688 case SIGCOMP_INSTR_DIVIDE: /* 9 DIVIDE ($operand_1, %operand_2) */
689 if (show_instr_detail_level == 2 ){
690 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
691 "Addr: %u ## DIVIDE(9) (operand_1, operand_2)",
695 operand_address = current_address + 1;
696 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &operand_1, &result_dest);
697 if (show_instr_detail_level == 2 ){
698 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_1 %u",
699 operand_address, operand_1);
701 operand_address = next_operand_address;
703 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &operand_2);
704 if (show_instr_detail_level == 2 ){
705 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_2 %u",
706 operand_address, operand_2);
708 if (show_instr_detail_level == 1)
710 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
711 "Addr: %u ## DIVIDE (operand_1=%u, operand_2=%u)",
712 current_address, operand_1, operand_2);
715 * execute the instruction
716 * DIVIDE (m, n) := floor(m / n)
717 * Decompression failure occurs if a DIVIDE or REMAINDER instruction
718 * encounters an operand_2 that is zero.
720 if ( operand_2 == 0){
722 goto decompression_failure;
724 result = operand_1 / operand_2;
727 buff[result_dest] = msb;
728 buff[(result_dest+1) & 0xffff] = lsb;
730 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," Loading result %u at %u",
731 result, result_dest);
733 current_address = next_operand_address;
734 goto execute_next_instruction;
737 case SIGCOMP_INSTR_REMAINDER: /* 10 REMAINDER ($operand_1, %operand_2) */
738 if (show_instr_detail_level == 2 ){
739 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
740 "Addr: %u ## REMAINDER(10) (operand_1, operand_2)",
744 operand_address = current_address + 1;
745 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &operand_1, &result_dest);
746 if (show_instr_detail_level == 2 ){
747 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_1 %u",
748 operand_address, operand_1);
750 operand_address = next_operand_address;
752 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &operand_2);
753 if (show_instr_detail_level == 2 ){
754 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_2 %u",
755 operand_address, operand_2);
757 if (show_instr_detail_level == 1)
759 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
760 "Addr: %u ## REMAINDER (operand_1=%u, operand_2=%u)",
761 current_address, operand_1, operand_2);
764 * execute the instruction
765 * REMAINDER (m, n) := m - n * floor(m / n)
766 * Decompression failure occurs if a DIVIDE or REMAINDER instruction
767 * encounters an operand_2 that is zero.
769 if ( operand_2 == 0){
771 goto decompression_failure;
773 result = operand_1 - operand_2 * (operand_1 / operand_2);
776 buff[result_dest] = msb;
777 buff[(result_dest+1) & 0xffff] = lsb;
779 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," Loading result %u at %u",
780 result, result_dest);
782 current_address = next_operand_address;
783 goto execute_next_instruction;
785 case SIGCOMP_INSTR_SORT_ASCENDING: /* 11 SORT-ASCENDING (%start, %n, %k) */
787 * used_udvm_cycles = 1 + k * (ceiling(log2(k)) + n)
790 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
791 "Addr: %u ## SORT-ASCENDING(11) (start, n, k))",
794 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Execution of this instruction is NOT implemented");
796 * used_udvm_cycles = 1 + k * (ceiling(log2(k)) + n)
800 case SIGCOMP_INSTR_SORT_DESCENDING: /* 12 SORT-DESCENDING (%start, %n, %k) */
802 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
803 "Addr: %u ## SORT-DESCENDING(12) (start, n, k))",
806 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Execution of this instruction is NOT implemented");
808 * used_udvm_cycles = 1 + k * (ceiling(log2(k)) + n)
811 case SIGCOMP_INSTR_SHA_1: /* 13 SHA-1 (%position, %length, %destination) */
813 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
814 "Addr: %u ## SHA-1(13) (position, length, destination)",
817 operand_address = current_address + 1;
819 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &position);
821 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u position %u",
822 operand_address, position);
824 operand_address = next_operand_address;
827 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &length);
829 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Length %u",
830 operand_address, length);
832 operand_address = next_operand_address;
835 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &ref_destination, &result_dest);
837 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u $destination %u",
838 operand_address, ref_destination);
840 used_udvm_cycles = used_udvm_cycles + length;
844 byte_copy_right = buff[66] << 8;
845 byte_copy_right = byte_copy_right | buff[67];
846 byte_copy_left = buff[64] << 8;
847 byte_copy_left = byte_copy_left | buff[65];
850 proto_tree_add_text(udvm_tree, message_tvb, 0, -1,
851 "byte_copy_right = %u", byte_copy_right);
857 guint16 handle_now = length;
859 if ( k < byte_copy_right && byte_copy_right <= k + (length-n) ){
860 handle_now = byte_copy_right - position;
863 if (k + handle_now >= UDVM_MEMORY_SIZE)
864 goto decompression_failure;
865 sha1_update( &ctx, &buff[k], handle_now );
867 k = ( k + handle_now ) & 0xffff;
868 n = ( n + handle_now ) & 0xffff;
870 if ( k >= byte_copy_right ) {
875 sha1_finish( &ctx, sha1_digest_buf );
879 for ( n=0; n< STATE_BUFFER_SIZE; n++ ) {
881 buff[k] = sha1_digest_buf[n];
883 k = ( k + 1 ) & 0xffff;
886 if ( k == byte_copy_right ){
892 proto_tree_add_text(udvm_tree, message_tvb, 0, -1,
893 "Calculated SHA-1: %s",
894 bytes_to_str(sha1_digest_buf, STATE_BUFFER_SIZE));
897 current_address = next_operand_address;
898 goto execute_next_instruction;
901 case SIGCOMP_INSTR_LOAD: /* 14 LOAD (%address, %value) */
902 if (show_instr_detail_level == 2 ){
903 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
904 "Addr: %u ## LOAD(14) (%%address, %%value)",
907 operand_address = current_address + 1;
909 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &addr);
910 if (show_instr_detail_level == 2 ){
911 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Address %u",
912 operand_address, addr);
914 operand_address = next_operand_address;
916 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &value);
917 if (show_instr_detail_level == 1)
919 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
920 "Addr: %u ## LOAD (%%address=%u, %%value=%u)",
921 current_address, addr, value);
927 buff[(addr + 1) & 0xffff] = lsb;
930 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Value %u",
931 operand_address, value);
932 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," Loading bytes at %u Value %u 0x%x",
935 current_address = next_operand_address;
936 goto execute_next_instruction;
939 case SIGCOMP_INSTR_MULTILOAD: /* 15 MULTILOAD (%address, #n, %value_0, ..., %value_n-1) */
941 * The MULTILOAD instruction sets a contiguous block of 2-byte words in
942 * the UDVM memory to specified values.
943 * Hmm what if the value to load only takes one byte ? Chose to always load two bytes.
945 if (show_instr_detail_level == 2 ){
946 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
947 "Addr: %u ## MULTILOAD(15) (%%address, #n, value_0, ..., value_n-1)",
950 operand_address = current_address + 1;
952 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &addr);
953 if (show_instr_detail_level == 2 ){
954 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Address %u",
955 operand_address, addr);
957 operand_address = next_operand_address;
960 next_operand_address = decode_udvm_literal_operand(buff,operand_address, &n);
961 if (show_instr_detail_level == 2 ){
962 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u n %u",
965 if (show_instr_detail_level == 1)
967 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
968 "Addr: %u ## MULTILOAD (%%address=%u, #n=%u, value_0, ..., value_%d)",
969 current_address, addr, n, n-1);
971 operand_address = next_operand_address;
972 used_udvm_cycles = used_udvm_cycles + n;
976 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &value);
980 if (addr >= UDVM_MEMORY_SIZE - 1)
981 goto decompression_failure;
984 buff[(addr + 1) & 0xffff] = lsb;
987 length = next_operand_address - operand_address;
990 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1, "Addr: %u Value %5u - Loading bytes at %5u Value %5u 0x%x",
991 operand_address, value, addr, value, value);
994 operand_address = next_operand_address;
996 current_address = next_operand_address;
997 goto execute_next_instruction;
1001 case SIGCOMP_INSTR_PUSH: /* 16 PUSH (%value) */
1002 if (show_instr_detail_level == 2){
1003 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1004 "Addr: %u ## PUSH(16) (value)",
1007 operand_address = current_address + 1;
1009 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &value);
1010 if (show_instr_detail_level == 2){
1011 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Value %u",
1012 operand_address, value);
1014 if (show_instr_detail_level == 1)
1016 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1017 "Addr: %u ## PUSH (value=%u)",
1018 current_address, value);
1020 current_address = next_operand_address;
1022 /* Push the value address onto the stack */
1023 stack_location = (buff[70] << 8) | buff[71];
1024 stack_fill = (buff[stack_location] << 8)
1025 | buff[(stack_location+1) & 0xFFFF];
1026 addr = (stack_location + stack_fill * 2 + 2) & 0xFFFF;
1028 if (addr >= UDVM_MEMORY_SIZE - 1)
1029 goto decompression_failure;
1031 buff[addr] = (value >> 8) & 0x00FF;
1032 buff[(addr+1) & 0xFFFF] = value & 0x00FF;
1034 if (stack_location >= UDVM_MEMORY_SIZE - 1)
1035 goto decompression_failure;
1037 stack_fill = (stack_fill + 1) & 0xFFFF;
1038 buff[stack_location] = (stack_fill >> 8) & 0x00FF;
1039 buff[(stack_location+1) & 0xFFFF] = stack_fill & 0x00FF;
1041 goto execute_next_instruction;
1045 case SIGCOMP_INSTR_POP: /* 17 POP (%address) */
1046 if (show_instr_detail_level == 2){
1047 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1048 "Addr: %u ## POP(16) (value)",
1051 operand_address = current_address + 1;
1053 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &destination);
1054 if (show_instr_detail_level == 2){
1055 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Value %u",
1056 operand_address, destination);
1058 if (show_instr_detail_level == 1)
1060 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1061 "Addr: %u ## POP (address=%u)",
1062 current_address, destination);
1064 current_address = next_operand_address;
1066 /* Pop value from the top of the stack */
1067 stack_location = (buff[70] << 8) | buff[71];
1068 stack_fill = (buff[stack_location] << 8)
1069 | buff[(stack_location+1) & 0xFFFF];
1070 if (stack_fill == 0)
1073 goto decompression_failure;
1076 if (stack_location >= UDVM_MEMORY_SIZE - 1)
1077 goto decompression_failure;
1079 stack_fill = (stack_fill - 1) & 0xFFFF;
1080 buff[stack_location] = (stack_fill >> 8) & 0x00FF;
1081 buff[(stack_location+1) & 0xFFFF] = stack_fill & 0x00FF;
1083 addr = (stack_location + stack_fill * 2 + 2) & 0xFFFF;
1085 if (addr >= UDVM_MEMORY_SIZE - 1)
1086 goto decompression_failure;
1088 value = (buff[addr] << 8)
1089 | buff[(addr+1) & 0xFFFF];
1091 /* ... and store the popped value. */
1092 if (destination >= UDVM_MEMORY_SIZE - 1)
1093 goto decompression_failure;
1094 buff[destination] = (value >> 8) & 0x00FF;
1095 buff[(destination+1) & 0xFFFF] = value & 0x00FF;
1097 goto execute_next_instruction;
1101 case SIGCOMP_INSTR_COPY: /* 18 COPY (%position, %length, %destination) */
1102 if (show_instr_detail_level == 2 ){
1103 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1104 "Addr: %u ## COPY(18) (position, length, destination)",
1107 operand_address = current_address + 1;
1109 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &position);
1110 if (show_instr_detail_level == 2 ){
1111 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u position %u",
1112 operand_address, position);
1114 operand_address = next_operand_address;
1117 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &length);
1118 if (show_instr_detail_level == 2 ){
1119 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Length %u",
1120 operand_address, length);
1122 operand_address = next_operand_address;
1125 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &destination);
1126 if (show_instr_detail_level == 2 ){
1127 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Destination %u",
1128 operand_address, destination);
1130 if (show_instr_detail_level == 1)
1132 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1133 "Addr: %u ## COPY (position=%u, length=%u, destination=%u)",
1134 current_address, position, length, destination);
1136 current_address = next_operand_address;
1140 * The string of bytes is copied in ascending order of memory address,
1141 * respecting the bounds set by byte_copy_left and byte_copy_right.
1142 * More precisely, if a byte is copied from/to Address m then the next
1143 * byte is copied from/to Address n where n is calculated as follows:
1145 * Set k := m + 1 (modulo 2^16)
1146 * If k = byte_copy_right then set n := byte_copy_left, else set n := k
1152 byte_copy_right = buff[66] << 8;
1153 byte_copy_right = byte_copy_right | buff[67];
1154 byte_copy_left = buff[64] << 8;
1155 byte_copy_left = byte_copy_left | buff[65];
1156 if (print_level_2 ){
1157 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
1158 " byte_copy_right = %u", byte_copy_right);
1161 while ( n < length ){
1162 buff[k] = buff[position];
1163 if (print_level_2 ){
1164 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
1165 " Copying value: %u (0x%x) to Addr: %u",
1166 buff[position], buff[position], k);
1168 position = ( position + 1 ) & 0xffff;
1169 k = ( k + 1 ) & 0xffff;
1173 * Check for circular buffer wrapping after the positions are
1174 * incremented. If either started at BCR then they should continue
1175 * to increment beyond BCR.
1177 if ( k == byte_copy_right ){
1180 if ( position == byte_copy_right ){
1181 position = byte_copy_left;
1184 used_udvm_cycles = used_udvm_cycles + length;
1185 goto execute_next_instruction;
1188 case SIGCOMP_INSTR_COPY_LITERAL: /* 19 COPY-LITERAL (%position, %length, $destination) */
1189 if (show_instr_detail_level == 2 ){
1190 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1191 "Addr: %u ## COPY-LITERAL(19) (position, length, $destination)",
1194 operand_address = current_address + 1;
1196 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &position);
1197 if (show_instr_detail_level == 2 ){
1198 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u position %u",
1199 operand_address, position);
1201 operand_address = next_operand_address;
1204 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &length);
1205 if (show_instr_detail_level == 2 ){
1206 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Length %u",
1207 operand_address, length);
1209 operand_address = next_operand_address;
1213 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &ref_destination, &result_dest);
1214 if (show_instr_detail_level == 2 ){
1215 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u destination %u",
1216 operand_address, ref_destination);
1218 if (show_instr_detail_level == 1)
1220 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1221 "Addr: %u ## COPY-LITERAL (position=%u, length=%u, $destination=%u)",
1222 current_address, position, length, ref_destination);
1224 current_address = next_operand_address;
1230 * The string of bytes is copied in ascending order of memory address,
1231 * respecting the bounds set by byte_copy_left and byte_copy_right.
1232 * More precisely, if a byte is copied from/to Address m then the next
1233 * byte is copied from/to Address n where n is calculated as follows:
1235 * Set k := m + 1 (modulo 2^16)
1236 * If k = byte_copy_right then set n := byte_copy_left, else set n := k
1241 k = ref_destination;
1242 byte_copy_right = buff[66] << 8;
1243 byte_copy_right = byte_copy_right | buff[67];
1244 byte_copy_left = buff[64] << 8;
1245 byte_copy_left = byte_copy_left | buff[65];
1246 if (print_level_2 ){
1247 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
1248 " byte_copy_right = %u", byte_copy_right);
1250 while ( n < length ){
1252 buff[k] = buff[position];
1253 if (print_level_2 ){
1254 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
1255 " Copying value: %u (0x%x) to Addr: %u",
1256 buff[position], buff[position], k);
1258 position = ( position + 1 ) & 0xffff;
1259 k = ( k + 1 ) & 0xffff;
1263 * Check for circular buffer wrapping after the positions are
1264 * incremented. It is important that k cannot be left set
1265 * to BCR. Also, if either started at BCR then they should continue
1266 * to increment beyond BCR.
1268 if ( k == byte_copy_right ){
1271 if ( position == byte_copy_right ){
1272 position = byte_copy_left;
1275 buff[result_dest] = k >> 8;
1276 buff[(result_dest + 1) & 0xffff] = k & 0x00ff;
1278 used_udvm_cycles = used_udvm_cycles + length;
1279 goto execute_next_instruction;
1282 case SIGCOMP_INSTR_COPY_OFFSET: /* 20 COPY-OFFSET (%offset, %length, $destination) */
1283 if (show_instr_detail_level == 2 ){
1284 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1285 "Addr: %u ## COPY-OFFSET(20) (offset, length, $destination)",
1288 operand_address = current_address + 1;
1290 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &multy_offset);
1291 if (show_instr_detail_level == 2 ){
1292 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u offset %u",
1293 operand_address, multy_offset);
1295 operand_address = next_operand_address;
1298 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &length);
1299 if (show_instr_detail_level == 2 ){
1300 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Length %u",
1301 operand_address, length);
1303 operand_address = next_operand_address;
1307 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &ref_destination, &result_dest);
1308 if (show_instr_detail_level == 2 ){
1309 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u $destination %u",
1310 operand_address, ref_destination);
1313 if (show_instr_detail_level == 1)
1315 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1316 "Addr: %u ## COPY-OFFSET (offset=%u, length=%u, $destination=%u)",
1317 current_address, multy_offset, length, result_dest);
1319 current_address = next_operand_address;
1321 /* Execute the instruction:
1322 * To derive the value of the position operand, starting at the memory
1323 * address specified by destination, the UDVM counts backwards a total
1324 * of offset memory addresses.
1326 * If the memory address specified in byte_copy_left is reached, the
1327 * next memory address is taken to be (byte_copy_right - 1) modulo 2^16.
1329 byte_copy_left = buff[64] << 8;
1330 byte_copy_left = byte_copy_left | buff[65];
1331 byte_copy_right = buff[66] << 8;
1332 byte_copy_right = byte_copy_right | buff[67];
1335 * In order to work out the position, simple arithmetic is tricky
1336 * to apply because there some nasty corner cases. A simple loop
1337 * is inefficient but the logic is simple.
1339 * FUTURE: This could be optimised.
1341 for (position = ref_destination, i = 0; i < multy_offset; i++)
1343 if ( position == byte_copy_left )
1345 position = (byte_copy_right - 1) & 0xffff;
1349 position = (position - 1) & 0xffff;
1353 if (print_level_2 ){
1354 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
1355 " byte_copy_left = %u byte_copy_right = %u position= %u",
1356 byte_copy_left, byte_copy_right, position);
1358 /* The COPY-OFFSET instruction then behaves as a COPY-LITERAL
1359 * instruction, taking the value of the position operand to be the last
1360 * memory address reached in the above step.
1366 * The string of bytes is copied in ascending order of memory address,
1367 * respecting the bounds set by byte_copy_left and byte_copy_right.
1368 * More precisely, if a byte is copied from/to Address m then the next
1369 * byte is copied from/to Address n where n is calculated as follows:
1371 * Set k := m + 1 (modulo 2^16)
1372 * If k = byte_copy_right then set n := byte_copy_left, else set n := k
1377 k = ref_destination;
1378 if (print_level_2 ){
1379 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
1380 " byte_copy_left = %u byte_copy_right = %u", byte_copy_left, byte_copy_right);
1382 while ( n < length ){
1383 buff[k] = buff[position];
1384 if (print_level_2 ){
1385 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
1386 " Copying value: %5u (0x%x) from Addr: %u to Addr: %u",
1387 buff[position], buff[position],(position), k);
1390 k = ( k + 1 ) & 0xffff;
1391 position = ( position + 1 ) & 0xffff;
1394 * Check for circular buffer wrapping after the positions are
1395 * incremented. It is important that k cannot be left set
1396 * to BCR. Also, if either started at BCR then they should continue
1397 * to increment beyond BCR.
1399 if ( k == byte_copy_right ){
1402 if ( position == byte_copy_right ){
1403 position = byte_copy_left;
1406 buff[result_dest] = k >> 8;
1407 buff[result_dest + 1] = k & 0x00ff;
1408 used_udvm_cycles = used_udvm_cycles + length;
1409 goto execute_next_instruction;
1412 case SIGCOMP_INSTR_MEMSET: /* 21 MEMSET (%address, %length, %start_value, %offset) */
1413 if (show_instr_detail_level == 2 ){
1414 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1415 "Addr: %u ## MEMSET(21) (address, length, start_value, offset)",
1418 operand_address = current_address + 1;
1421 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &addr);
1422 if (show_instr_detail_level == 2 ){
1423 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Address %u",
1424 operand_address, addr);
1426 operand_address = next_operand_address;
1429 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &length);
1430 if (show_instr_detail_level == 2 ){
1431 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Length %u",
1432 operand_address, length);
1434 operand_address = next_operand_address;
1436 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &start_value);
1437 if (show_instr_detail_level == 2 ){
1438 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u start_value %u",
1439 operand_address, start_value);
1441 operand_address = next_operand_address;
1444 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &multy_offset);
1445 if (show_instr_detail_level == 2 ){
1446 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u offset %u",
1447 operand_address, multy_offset);
1449 if (show_instr_detail_level == 1)
1451 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1452 "Addr: %u ## MEMSET (address=%u, length=%u, start_value=%u, offset=%u)",
1453 current_address, addr, length, start_value, multy_offset);
1455 current_address = next_operand_address;
1456 /* exetute the instruction
1457 * The sequence of values used by the MEMSET instruction is specified by
1458 * the following formula:
1460 * Seq[n] := (start_value + n * offset) modulo 256
1464 byte_copy_right = buff[66] << 8;
1465 byte_copy_right = byte_copy_right | buff[67];
1466 byte_copy_left = buff[64] << 8;
1467 byte_copy_left = byte_copy_left | buff[65];
1468 if (print_level_2 ){
1469 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
1470 " byte_copy_left = %u byte_copy_right = %u", byte_copy_left, byte_copy_right);
1472 while ( n < length ){
1473 if ( k == byte_copy_right ){
1476 buff[k] = (start_value + ( n * multy_offset)) & 0xff;
1477 if (print_level_2 ){
1478 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
1479 " Storing value: %u (0x%x) at Addr: %u",
1480 buff[k], buff[k], k);
1482 k = ( k + 1 ) & 0xffff;
1485 used_udvm_cycles = used_udvm_cycles + length;
1486 goto execute_next_instruction;
1490 case SIGCOMP_INSTR_JUMP: /* 22 JUMP (@address) */
1491 if (show_instr_detail_level == 2 ){
1492 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1493 "Addr: %u ## JUMP(22) (@address)",
1496 operand_address = current_address + 1;
1498 /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
1499 /*next_operand_address = */decode_udvm_address_operand(buff,operand_address, &at_address, current_address);
1500 if (show_instr_detail_level == 2 ){
1501 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u @Address %u",
1502 operand_address, at_address);
1504 if (show_instr_detail_level == 1)
1506 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1507 "Addr: %u ## JUMP (@address=%u)",
1508 current_address, at_address);
1510 current_address = at_address;
1511 goto execute_next_instruction;
1514 case SIGCOMP_INSTR_COMPARE: /* 23 */
1515 /* COMPARE (%value_1, %value_2, @address_1, @address_2, @address_3)
1517 if (show_instr_detail_level == 2 ){
1518 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1519 "Addr: %u ## COMPARE(23) (value_1, value_2, @address_1, @address_2, @address_3)",
1522 operand_address = current_address + 1;
1525 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &value_1);
1526 if (show_instr_detail_level == 2 ){
1527 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Value %u",
1528 operand_address, value_1);
1530 operand_address = next_operand_address;
1533 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &value_2);
1534 if (show_instr_detail_level == 2 ){
1535 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Value %u",
1536 operand_address, value_2);
1538 operand_address = next_operand_address;
1541 /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
1542 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &at_address_1);
1543 at_address_1 = ( current_address + at_address_1) & 0xffff;
1544 if (show_instr_detail_level == 2 ){
1545 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u @Address %u",
1546 operand_address, at_address_1);
1548 operand_address = next_operand_address;
1552 /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
1553 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &at_address_2);
1554 at_address_2 = ( current_address + at_address_2) & 0xffff;
1555 if (show_instr_detail_level == 2 ){
1556 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u @Address %u",
1557 operand_address, at_address_2);
1559 operand_address = next_operand_address;
1562 /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
1563 /*next_operand_address = */decode_udvm_multitype_operand(buff, operand_address, &at_address_3);
1564 at_address_3 = ( current_address + at_address_3) & 0xffff;
1565 if (show_instr_detail_level == 2 ){
1566 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u @Address %u",
1567 operand_address, at_address_3);
1569 if (show_instr_detail_level == 1)
1571 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1572 "Addr: %u ## COMPARE (value_1=%u, value_2=%u, @address_1=%u, @address_2=%u, @address_3=%u)",
1573 current_address, value_1, value_2, at_address_1, at_address_2, at_address_3);
1575 /* execute the instruction
1576 * If value_1 < value_2 then the UDVM continues instruction execution at
1577 * the memory address specified by address 1. If value_1 = value_2 then
1578 * it jumps to the address specified by address_2. If value_1 > value_2
1579 * then it jumps to the address specified by address_3.
1581 if ( value_1 < value_2 )
1582 current_address = at_address_1;
1583 if ( value_1 == value_2 )
1584 current_address = at_address_2;
1585 if ( value_1 > value_2 )
1586 current_address = at_address_3;
1587 goto execute_next_instruction;
1590 case SIGCOMP_INSTR_CALL: /* 24 CALL (@address) (PUSH addr )*/
1591 if (show_instr_detail_level == 2){
1592 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1593 "Addr: %u ## CALL(24) (@address) (PUSH addr )",
1596 operand_address = current_address + 1;
1598 next_operand_address = decode_udvm_address_operand(buff,operand_address, &at_address, current_address);
1599 if (show_instr_detail_level == 2 ){
1600 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u @Address %u",
1601 operand_address, at_address);
1603 if (show_instr_detail_level == 1)
1605 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1606 "Addr: %u ## CALL (@address=%u)",
1607 current_address, at_address);
1609 current_address = next_operand_address;
1611 /* Push the current address onto the stack */
1612 stack_location = (buff[70] << 8) | buff[71];
1613 stack_fill = (buff[stack_location] << 8)
1614 | buff[(stack_location+1) & 0xFFFF];
1615 addr = (stack_location + stack_fill * 2 + 2) & 0xFFFF;
1616 if (addr >= UDVM_MEMORY_SIZE - 1)
1617 goto decompression_failure;
1618 buff[addr] = (current_address >> 8) & 0x00FF;
1619 buff[(addr+1) & 0xFFFF] = current_address & 0x00FF;
1621 stack_fill = (stack_fill + 1) & 0xFFFF;
1622 if (stack_location >= UDVM_MEMORY_SIZE - 1)
1623 goto decompression_failure;
1624 buff[stack_location] = (stack_fill >> 8) & 0x00FF;
1625 buff[(stack_location+1) & 0xFFFF] = stack_fill & 0x00FF;
1627 /* ... and jump to the destination address */
1628 current_address = at_address;
1630 goto execute_next_instruction;
1634 case SIGCOMP_INSTR_RETURN: /* 25 POP and return */
1635 if (print_level_1 || show_instr_detail_level == 1){
1636 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1637 "Addr: %u ## POP(25) and return",
1641 /* Pop value from the top of the stack */
1642 stack_location = (buff[70] << 8) | buff[71];
1643 stack_fill = (buff[stack_location] << 8)
1644 | buff[(stack_location+1) & 0xFFFF];
1645 if (stack_fill == 0)
1648 goto decompression_failure;
1651 stack_fill = (stack_fill - 1) & 0xFFFF;
1652 if (stack_location >= UDVM_MEMORY_SIZE - 1)
1653 goto decompression_failure;
1654 buff[stack_location] = (stack_fill >> 8) & 0x00FF;
1655 buff[(stack_location+1) & 0xFFFF] = stack_fill & 0x00FF;
1657 addr = (stack_location + stack_fill * 2 + 2) & 0xFFFF;
1658 at_address = (buff[addr] << 8)
1659 | buff[(addr+1) & 0xFFFF];
1661 /* ... and set the PC to the popped value */
1662 current_address = at_address;
1664 goto execute_next_instruction;
1668 case SIGCOMP_INSTR_SWITCH: /* 26 SWITCH (#n, %j, @address_0, @address_1, ... , @address_n-1) */
1670 * When a SWITCH instruction is encountered the UDVM reads the value of
1671 * j. It then continues instruction execution at the address specified
1674 * Decompression failure occurs if j specifies a value of n or more, or
1675 * if the address lies beyond the overall UDVM memory size.
1677 instruction_address = current_address;
1678 if (print_level_1 ){
1679 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1680 "Addr: %u ## SWITCH (#n, j, @address_0, @address_1, ... , @address_n-1))",
1683 operand_address = current_address + 1;
1685 * Number of addresses in the instruction
1687 next_operand_address = decode_udvm_literal_operand(buff,operand_address, &n);
1688 if (print_level_1 ){
1689 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u n %u",
1690 operand_address, n);
1692 operand_address = next_operand_address;
1694 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &j);
1695 if (print_level_1 ){
1696 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u j %u",
1697 operand_address, j);
1699 operand_address = next_operand_address;
1703 /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
1704 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &at_address_1);
1705 at_address_1 = ( instruction_address + at_address_1) & 0xffff;
1706 if (print_level_1 ){
1707 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u @Address %u",
1708 operand_address, at_address_1);
1711 current_address = at_address_1;
1713 operand_address = next_operand_address;
1716 /* Check decompression failure */
1717 if ( ( j == n ) || ( j > n )){
1719 goto decompression_failure;
1721 if ( current_address > UDVM_MEMORY_SIZE ){
1723 goto decompression_failure;
1725 used_udvm_cycles = used_udvm_cycles + n;
1727 goto execute_next_instruction;
1730 case SIGCOMP_INSTR_CRC: /* 27 CRC (%value, %position, %length, @address) */
1731 if (print_level_1 ){
1732 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1733 "Addr: %u ## CRC (value, position, length, @address)",
1737 operand_address = current_address + 1;
1740 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &value);
1741 if (print_level_1 ){
1742 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Value %u",
1743 operand_address, value);
1745 operand_address = next_operand_address;
1748 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &position);
1749 if (print_level_1 ){
1750 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u position %u",
1751 operand_address, position);
1753 operand_address = next_operand_address;
1756 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &length);
1757 if (print_level_1 ){
1758 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Length %u",
1759 operand_address, length);
1761 operand_address = next_operand_address;
1764 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &at_address);
1765 at_address = ( current_address + at_address) & 0xffff;
1766 if (print_level_1 ){
1767 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u @Address %u",
1768 operand_address, at_address);
1770 /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
1771 used_udvm_cycles = used_udvm_cycles + length;
1775 byte_copy_right = buff[66] << 8;
1776 byte_copy_right = byte_copy_right | buff[67];
1777 byte_copy_left = buff[64] << 8;
1778 byte_copy_left = byte_copy_left | buff[65];
1781 if (print_level_2 ){
1782 proto_tree_add_text(udvm_tree, message_tvb, 0, -1,
1783 "byte_copy_right = %u", byte_copy_right);
1788 guint16 handle_now = length - n;
1790 if ( k < byte_copy_right && byte_copy_right <= k + (length-n) ){
1791 handle_now = byte_copy_right - k;
1794 if (k + handle_now >= UDVM_MEMORY_SIZE)
1795 goto decompression_failure;
1796 result = crc16_ccitt_seed(&buff[k], handle_now, (guint16) (result ^ 0xffff));
1798 k = ( k + handle_now ) & 0xffff;
1799 n = ( n + handle_now ) & 0xffff;
1801 if ( k >= byte_copy_right ) {
1806 result = result ^ 0xffff;
1808 if (print_level_1 ){
1809 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1, "Calculated CRC %u", result);
1811 if (result != value){
1812 current_address = at_address;
1815 current_address = next_operand_address;
1817 goto execute_next_instruction;
1821 case SIGCOMP_INSTR_INPUT_BYTES: /* 28 INPUT-BYTES (%length, %destination, @address) */
1822 if (show_instr_detail_level == 2 ){
1823 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1824 "Addr: %u ## INPUT-BYTES(28) length, destination, @address)",
1827 operand_address = current_address + 1;
1829 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &length);
1830 if (show_instr_detail_level == 2 ){
1831 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Length %u",
1832 operand_address, length);
1834 operand_address = next_operand_address;
1837 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &destination);
1838 if (show_instr_detail_level == 2 ){
1839 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Destination %u",
1840 operand_address, destination);
1842 operand_address = next_operand_address;
1845 /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
1846 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &at_address);
1847 at_address = ( current_address + at_address) & 0xffff;
1848 if (show_instr_detail_level == 2 ){
1849 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u @Address %u",
1850 operand_address, at_address);
1852 if (show_instr_detail_level == 1)
1854 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1855 "Addr: %u ## INPUT-BYTES length=%u, destination=%u, @address=%u)",
1856 current_address, length, destination, at_address);
1858 /* execute the instruction TODO insert checks
1862 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1863 * | byte_copy_left | 64 - 65
1864 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1865 * | byte_copy_right | 66 - 67
1866 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1867 * | input_bit_order | 68 - 69
1868 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1869 * | stack_location | 70 - 71
1870 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1872 * Figure 7: Memory addresses of the UDVM registers
1876 * The string of bytes is copied in ascending order of memory address,
1877 * respecting the bounds set by byte_copy_left and byte_copy_right.
1878 * More precisely, if a byte is copied from/to Address m then the next
1879 * byte is copied from/to Address n where n is calculated as follows:
1881 * Set k := m + 1 (modulo 2^16)
1882 * If k = byte_copy_right then set n := byte_copy_left, else set n := k
1888 byte_copy_right = buff[66] << 8;
1889 byte_copy_right = byte_copy_right | buff[67];
1890 byte_copy_left = buff[64] << 8;
1891 byte_copy_left = byte_copy_left | buff[65];
1892 if (print_level_1 ){
1893 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
1894 " byte_copy_right = %u", byte_copy_right);
1896 /* clear out remaining bits if any */
1899 /* operand_address used as dummy */
1900 while ( n < length ){
1901 if (input_address > ( msg_end - 1)){
1902 current_address = at_address;
1904 goto execute_next_instruction;
1907 if ( k == byte_copy_right ){
1910 octet = tvb_get_guint8(message_tvb, input_address);
1912 if (print_level_1 ){
1913 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
1914 " Loading value: %u (0x%x) at Addr: %u", octet, octet, k);
1918 * If the instruction requests data that lies beyond the end of the
1919 * SigComp message, no data is returned. Instead the UDVM moves program
1920 * execution to the address specified by the address operand.
1924 k = ( k + 1 ) & 0xffff;
1927 used_udvm_cycles = used_udvm_cycles + length;
1928 current_address = next_operand_address;
1929 goto execute_next_instruction;
1931 case SIGCOMP_INSTR_INPUT_BITS:/* 29 INPUT-BITS (%length, %destination, @address) */
1933 * The length operand indicates the requested number of bits.
1934 * Decompression failure occurs if this operand does not lie between 0
1937 * The destination operand specifies the memory address to which the
1938 * compressed data should be copied. Note that the requested bits are
1939 * interpreted as a 2-byte integer ranging from 0 to 2^length - 1, as
1940 * explained in Section 8.2.
1942 * If the instruction requests data that lies beyond the end of the
1943 * SigComp message, no data is returned. Instead the UDVM moves program
1944 * execution to the address specified by the address operand.
1947 if (show_instr_detail_level == 2 ){
1948 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1949 "Addr: %u ## INPUT-BITS(29) (length, destination, @address)",
1952 operand_address = current_address + 1;
1955 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &length);
1956 if (show_instr_detail_level == 2 ){
1957 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u length %u",
1958 operand_address, length);
1960 operand_address = next_operand_address;
1962 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &destination);
1963 if (show_instr_detail_level == 2 ){
1964 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Destination %u",
1965 operand_address, destination);
1967 operand_address = next_operand_address;
1970 /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
1971 next_operand_address = decode_udvm_address_operand(buff,operand_address, &at_address, current_address);
1972 if (show_instr_detail_level == 2 ){
1973 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u @Address %u",
1974 operand_address, at_address);
1976 if (show_instr_detail_level == 1)
1978 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1979 "Addr: %u ## INPUT-BITS length=%u, destination=%u, @address=%u)",
1980 current_address, length, destination, at_address);
1982 current_address = next_operand_address;
1985 * Execute actual instr.
1986 * The input_bit_order register contains the following three flags:
1989 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1990 * | reserved |F|H|P| 68 - 69
1991 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1993 input_bit_order = buff[68] << 8;
1994 input_bit_order = input_bit_order | buff[69];
1996 * If the instruction requests data that lies beyond the end of the
1997 * SigComp message, no data is returned. Instead the UDVM moves program
1998 * execution to the address specified by the address operand.
2003 goto decompression_failure;
2005 if ( input_bit_order > 7 ){
2007 goto decompression_failure;
2011 * Transfer F bit to bit_order to tell decomp dispatcher which bit order to use
2013 bit_order = ( input_bit_order & 0x0004 ) >> 2;
2014 value = decomp_dispatch_get_bits( message_tvb, udvm_tree, bit_order,
2015 buff, &old_input_bit_order, &remaining_bits,
2016 &input_bits, &input_address, length, &result_code, msg_end);
2017 if ( result_code == 11 ){
2018 current_address = at_address;
2019 goto execute_next_instruction;
2022 lsb = value & 0x00ff;
2023 if (destination >= UDVM_MEMORY_SIZE - 1)
2024 goto decompression_failure;
2025 buff[destination] = msb;
2026 buff[(destination + 1) & 0xffff]=lsb;
2027 if (print_level_1 ){
2028 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
2029 " Loading value: %u (0x%x) at Addr: %u, remaining_bits: %u", value, value, destination, remaining_bits);
2032 goto execute_next_instruction;
2034 case SIGCOMP_INSTR_INPUT_HUFFMAN: /* 30 */
2036 * INPUT-HUFFMAN (%destination, @address, #n, %bits_1, %lower_bound_1,
2037 * %upper_bound_1, %uncompressed_1, ... , %bits_n, %lower_bound_n,
2038 * %upper_bound_n, %uncompressed_n)
2040 if (show_instr_detail_level == 2 ){
2041 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2042 "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)",
2045 operand_address = current_address + 1;
2048 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &destination);
2049 if (show_instr_detail_level == 2 ){
2050 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Destination %u",
2051 operand_address, destination);
2053 operand_address = next_operand_address;
2056 /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
2057 next_operand_address = decode_udvm_address_operand(buff,operand_address, &at_address, current_address);
2058 if (show_instr_detail_level == 2 ){
2059 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u @Address %u",
2060 operand_address, at_address);
2062 operand_address = next_operand_address;
2065 next_operand_address = decode_udvm_literal_operand(buff,operand_address, &n);
2066 if (show_instr_detail_level == 2 ){
2067 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u n %u",
2068 operand_address, n);
2070 operand_address = next_operand_address;
2071 if (show_instr_detail_level == 1)
2073 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2074 "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)",
2075 current_address, destination, at_address, n, n, n, n, n);
2078 used_udvm_cycles = used_udvm_cycles + n;
2081 * Note that if n = 0 then the INPUT-HUFFMAN instruction is ignored and
2082 * program execution resumes at the following instruction.
2083 * Decompression failure occurs if (bits_1 + ... + bits_n) > 16.
2085 * In all other cases, the behavior of the INPUT-HUFFMAN instruction is
2088 * 1. Set j := 1 and set H := 0.
2090 * 2. Request bits_j compressed bits. Interpret the returned bits as an
2091 * integer k from 0 to 2^bits_j - 1, as explained in Section 8.2.
2093 * 3. Set H := H * 2^bits_j + k.
2095 * 4. If data is requested that lies beyond the end of the SigComp
2096 * message, terminate the INPUT-HUFFMAN instruction and move program
2097 * execution to the memory address specified by the address operand.
2099 * 5. If (H < lower_bound_j) or (H > upper_bound_j) then set j := j + 1.
2100 * Then go back to Step 2, unless j > n in which case decompression
2103 * 6. Copy (H + uncompressed_j - lower_bound_j) modulo 2^16 to the
2104 * memory address specified by the destination operand.
2108 * The input_bit_order register contains the following three flags:
2111 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2112 * | reserved |F|H|P| 68 - 69
2113 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2115 * Transfer H bit to bit_order to tell decomp dispatcher which bit order to use
2117 input_bit_order = buff[68] << 8;
2118 input_bit_order = input_bit_order | buff[69];
2119 bit_order = ( input_bit_order & 0x0002 ) >> 1;
2124 outside_huffman_boundaries = TRUE;
2125 print_in_loop = print_level_3;
2128 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &bits_n);
2129 if (print_in_loop ){
2130 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u bits_n %u",
2131 operand_address, bits_n);
2133 operand_address = next_operand_address;
2135 /* %lower_bound_n */
2136 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &lower_bound_n);
2137 if (print_in_loop ){
2138 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u lower_bound_n %u",
2139 operand_address, lower_bound_n);
2141 operand_address = next_operand_address;
2142 /* %upper_bound_n */
2143 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &upper_bound_n);
2144 if (print_in_loop ){
2145 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u upper_bound_n %u",
2146 operand_address, upper_bound_n);
2148 operand_address = next_operand_address;
2149 /* %uncompressed_n */
2150 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &uncompressed_n);
2151 if (print_in_loop ){
2152 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u uncompressed_n %u",
2153 operand_address, uncompressed_n);
2155 operand_address = next_operand_address;
2156 /* execute instruction */
2157 if ( outside_huffman_boundaries ) {
2159 * 2. Request bits_j compressed bits. Interpret the returned bits as an
2160 * integer k from 0 to 2^bits_j - 1, as explained in Section 8.2.
2162 k = decomp_dispatch_get_bits( message_tvb, udvm_tree, bit_order,
2163 buff, &old_input_bit_order, &remaining_bits,
2164 &input_bits, &input_address, bits_n, &result_code, msg_end);
2165 if ( result_code == 11 ){
2167 * 4. If data is requested that lies beyond the end of the SigComp
2168 * message, terminate the INPUT-HUFFMAN instruction and move program
2169 * execution to the memory address specified by the address operand.
2171 current_address = at_address;
2172 goto execute_next_instruction;
2176 * 3. Set H := H * 2^bits_j + k.
2177 * [In practice is a shift+OR operation.]
2180 H = (H << bits_n) | k;
2181 if (print_level_3 ){
2182 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," Set H(%u) := H(%u) * 2^bits_j(%u) + k(%u)",
2183 H ,oldH, 1<<bits_n,k);
2187 * 5. If (H < lower_bound_j) or (H > upper_bound_j) then set j := j + 1.
2188 * Then go back to Step 2, unless j > n in which case decompression
2191 if ((H < lower_bound_n) || (H > upper_bound_n)){
2192 outside_huffman_boundaries = TRUE;
2194 outside_huffman_boundaries = FALSE;
2195 print_in_loop = FALSE;
2197 * 6. Copy (H + uncompressed_j - lower_bound_j) modulo 2^16 to the
2198 * memory address specified by the destination operand.
2200 if (print_level_2 ){
2201 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2202 " H(%u) = H(%u) + uncompressed_n(%u) - lower_bound_n(%u)",
2203 (H + uncompressed_n - lower_bound_n ),H, uncompressed_n, lower_bound_n);
2205 H = H + uncompressed_n - lower_bound_n;
2208 if (destination >= UDVM_MEMORY_SIZE - 1)
2209 goto decompression_failure;
2210 buff[destination] = msb;
2211 buff[(destination + 1) & 0xffff]=lsb;
2212 if (print_level_1 ){
2213 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
2214 " Loading H: %u (0x%x) at Addr: %u,j = %u remaining_bits: %u",
2215 H, H, destination,( n - m + 1 ), remaining_bits);
2224 if ( outside_huffman_boundaries ) {
2226 goto decompression_failure;
2229 current_address = next_operand_address;
2230 goto execute_next_instruction;
2233 case SIGCOMP_INSTR_STATE_ACCESS: /* 31 */
2234 /* STATE-ACCESS (%partial_identifier_start, %partial_identifier_length,
2235 * %state_begin, %state_length, %state_address, %state_instruction)
2237 if (show_instr_detail_level == 2 ){
2238 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2239 "Addr: %u ## STATE-ACCESS(31) (partial_identifier_start, partial_identifier_length,state_begin, state_length, state_address, state_instruction)",
2242 operand_address = current_address + 1;
2245 * %partial_identifier_start
2247 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &p_id_start);
2248 if (show_instr_detail_level == 2 ){
2249 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u partial_identifier_start %u",
2250 operand_address, p_id_start);
2254 * %partial_identifier_length
2256 operand_address = next_operand_address;
2257 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &p_id_length);
2258 if (show_instr_detail_level == 2 ){
2259 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u partial_identifier_length %u",
2260 operand_address, p_id_length);
2265 operand_address = next_operand_address;
2266 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_begin);
2267 if (show_instr_detail_level == 2 ){
2268 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_begin %u",
2269 operand_address, state_begin);
2274 operand_address = next_operand_address;
2275 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_length);
2276 if (show_instr_detail_level == 2 ){
2277 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_length %u",
2278 operand_address, state_length);
2283 operand_address = next_operand_address;
2284 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_address);
2285 if (show_instr_detail_level == 2 ){
2286 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_address %u",
2287 operand_address, state_address);
2290 * %state_instruction
2292 operand_address = next_operand_address;
2293 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_instruction);
2294 if (show_instr_detail_level == 2 ){
2295 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_instruction %u",
2296 operand_address, state_instruction);
2298 if (show_instr_detail_level == 1)
2300 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2301 "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)",
2302 current_address, p_id_start, p_id_length, state_begin, state_length, state_address, state_instruction);
2304 current_address = next_operand_address;
2305 byte_copy_right = buff[66] << 8;
2306 byte_copy_right = byte_copy_right | buff[67];
2307 byte_copy_left = buff[64] << 8;
2308 byte_copy_left = byte_copy_left | buff[65];
2309 if (print_level_2 ){
2310 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
2311 " byte_copy_right = %u, byte_copy_left = %u", byte_copy_right,byte_copy_left);
2314 result_code = udvm_state_access(message_tvb, udvm_tree, buff, p_id_start, p_id_length, state_begin, &state_length,
2315 &state_address, &state_instruction, hf_id);
2316 if ( result_code != 0 ){
2317 goto decompression_failure;
2319 used_udvm_cycles = used_udvm_cycles + state_length;
2320 goto execute_next_instruction;
2322 case SIGCOMP_INSTR_STATE_CREATE: /* 32 */
2324 * STATE-CREATE (%state_length, %state_address, %state_instruction,
2325 * %minimum_access_length, %state_retention_priority)
2327 if (show_instr_detail_level == 2 ){
2328 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2329 "Addr: %u ## STATE-CREATE(32) (state_length, state_address, state_instruction,minimum_access_length, state_retention_priority)",
2332 operand_address = current_address + 1;
2337 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_length);
2338 if (show_instr_detail_level == 2 ){
2339 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_length %u",
2340 operand_address, state_length);
2345 operand_address = next_operand_address;
2346 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_address);
2347 if (show_instr_detail_level == 2 ){
2348 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_address %u",
2349 operand_address, state_address);
2352 * %state_instruction
2354 operand_address = next_operand_address;
2355 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_instruction);
2356 if (show_instr_detail_level == 2 ){
2357 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_instruction %u",
2358 operand_address, state_instruction);
2361 * %minimum_access_length
2363 operand_address = next_operand_address;
2364 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &minimum_access_length);
2365 if (show_instr_detail_level == 2 ){
2366 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u minimum_access_length %u",
2367 operand_address, minimum_access_length);
2370 * %state_retention_priority
2372 operand_address = next_operand_address;
2373 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_retention_priority);
2374 if (show_instr_detail_level == 2 ){
2375 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_retention_priority %u",
2376 operand_address, state_retention_priority);
2378 if (show_instr_detail_level == 1)
2380 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2381 "Addr: %u ## STATE-CREATE(32) (state_length=%u, state_address=%u, state_instruction=%u,minimum_access_length=%u, state_retention_priority=%u)",
2382 current_address, state_length, state_address, state_instruction,minimum_access_length, state_retention_priority);
2384 current_address = next_operand_address;
2385 /* Execute the instruction
2386 * TODO Implement the instruction
2388 * Note that the new state item cannot be created until a valid
2389 * compartment identifier has been returned by the application.
2390 * Consequently, when a STATE-CREATE instruction is encountered the UDVM
2391 * simply buffers the five supplied operands until the END-MESSAGE
2392 * instruction is reached. The steps taken at this point are described
2395 * Decompression failure MUST occur if more than four state creation
2396 * requests are made before the END-MESSAGE instruction is encountered.
2397 * Decompression failure also occurs if the minimum_access_length does
2398 * not lie between 6 and 20 inclusive, or if the
2399 * state_retention_priority is 65535.
2401 no_of_state_create++;
2402 if ( no_of_state_create > 4 ){
2404 goto decompression_failure;
2406 if (( minimum_access_length < 6 ) || ( minimum_access_length > STATE_BUFFER_SIZE )){
2408 goto decompression_failure;
2410 if ( state_retention_priority == 65535 ){
2412 goto decompression_failure;
2414 state_length_buff[no_of_state_create] = state_length;
2415 state_address_buff[no_of_state_create] = state_address;
2416 state_instruction_buff[no_of_state_create] = state_instruction;
2417 state_minimum_access_length_buff[no_of_state_create] = minimum_access_length;
2418 /* state_state_retention_priority_buff[no_of_state_create] = state_retention_priority; */
2419 used_udvm_cycles = used_udvm_cycles + state_length;
2421 byte_copy_right = buff[66] << 8;
2422 byte_copy_right = byte_copy_right | buff[67];
2423 byte_copy_left = buff[64] << 8;
2424 byte_copy_left = byte_copy_left | buff[65];
2427 while ( n < state_length ){
2428 if ( k == byte_copy_right ){
2433 if (print_level_3 ){
2434 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2435 " Addr: %5u State value: %u (0x%x) ASCII(%s)",
2436 k,buff[k],buff[k],format_text(string, 1));
2438 k = ( k + 1 ) & 0xffff;
2443 goto execute_next_instruction;
2445 case SIGCOMP_INSTR_STATE_FREE: /* 33 */
2447 * STATE-FREE (%partial_identifier_start, %partial_identifier_length)
2449 if (show_instr_detail_level == 2 ){
2450 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2451 "Addr: %u ## STATE-FREE (partial_identifier_start, partial_identifier_length)",
2454 operand_address = current_address + 1;
2456 * %partial_identifier_start
2458 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &p_id_start);
2459 if (show_instr_detail_level == 2 ){
2460 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u partial_identifier_start %u",
2461 operand_address, p_id_start);
2463 operand_address = next_operand_address;
2466 * %partial_identifier_length
2468 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &p_id_length);
2469 if (show_instr_detail_level == 2 ){
2470 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u partial_identifier_length %u",
2471 operand_address, p_id_length);
2473 if (show_instr_detail_level == 1)
2475 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2476 "Addr: %u ## STATE-FREE (partial_identifier_start=%u, partial_identifier_length=%u)",
2477 current_address, p_id_start, p_id_length);
2479 current_address = next_operand_address;
2481 /* Execute the instruction:
2484 udvm_state_free(buff,p_id_start,p_id_length);
2486 goto execute_next_instruction;
2488 case SIGCOMP_INSTR_OUTPUT: /* 34 OUTPUT (%output_start, %output_length) */
2489 if (show_instr_detail_level == 2 ){
2490 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2491 "Addr: %u ## OUTPUT(34) (output_start, output_length)",
2494 operand_address = current_address + 1;
2498 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &output_start);
2499 if (show_instr_detail_level == 2 ){
2500 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u output_start %u",
2501 operand_address, output_start);
2503 operand_address = next_operand_address;
2507 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &output_length);
2508 if (show_instr_detail_level == 2 ){
2509 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u output_length %u",
2510 operand_address, output_length);
2512 if (show_instr_detail_level == 1)
2514 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2515 "Addr: %u ## OUTPUT (output_start=%u, output_length=%u)",
2516 current_address, output_start, output_length);
2518 current_address = next_operand_address;
2521 * Execute instruction
2524 * The string of bytes is copied in ascending order of memory address,
2525 * respecting the bounds set by byte_copy_left and byte_copy_right.
2526 * More precisely, if a byte is copied from/to Address m then the next
2527 * byte is copied from/to Address n where n is calculated as follows:
2529 * Set k := m + 1 (modulo 2^16)
2530 * If k = byte_copy_right then set n := byte_copy_left, else set n := k
2536 byte_copy_right = buff[66] << 8;
2537 byte_copy_right = byte_copy_right | buff[67];
2538 byte_copy_left = buff[64] << 8;
2539 byte_copy_left = byte_copy_left | buff[65];
2540 if (print_level_3 ){
2541 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2542 " byte_copy_right = %u", byte_copy_right);
2544 while ( n < output_length ){
2546 if ( k == byte_copy_right ){
2549 out_buff[output_address] = buff[k];
2552 if (print_level_3 ){
2553 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2554 " Output value: %u (0x%x) ASCII(%s) from Addr: %u ,output to dispatcher position %u",
2555 buff[k],buff[k],format_text(string,1), k,output_address);
2557 k = ( k + 1 ) & 0xffff;
2561 used_udvm_cycles = used_udvm_cycles + output_length;
2562 goto execute_next_instruction;
2564 case SIGCOMP_INSTR_END_MESSAGE: /* 35 */
2566 * END-MESSAGE (%requested_feedback_location,
2567 * %returned_parameters_location, %state_length, %state_address,
2568 * %state_instruction, %minimum_access_length,
2569 * %state_retention_priority)
2571 if (show_instr_detail_level == 2 ){
2572 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2573 "Addr: %u ## END-MESSAGE (requested_feedback_location,state_instruction, minimum_access_length,state_retention_priority)",
2576 operand_address = current_address + 1;
2578 /* %requested_feedback_location */
2579 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &requested_feedback_location);
2580 if (show_instr_detail_level == 2 ){
2581 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u requested_feedback_location %u",
2582 operand_address, requested_feedback_location);
2584 operand_address = next_operand_address;
2585 /* returned_parameters_location */
2586 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &returned_parameters_location);
2587 if (show_instr_detail_level == 2 ){
2588 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u returned_parameters_location %u",
2589 operand_address, returned_parameters_location);
2594 operand_address = next_operand_address;
2595 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_length);
2596 if (show_instr_detail_level == 2 ){
2597 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_length %u",
2598 operand_address, state_length);
2603 operand_address = next_operand_address;
2604 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_address);
2605 if (show_instr_detail_level == 2 ){
2606 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_address %u",
2607 operand_address, state_address);
2610 * %state_instruction
2612 operand_address = next_operand_address;
2613 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_instruction);
2614 if (show_instr_detail_level == 2 ){
2615 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_instruction %u",
2616 operand_address, state_instruction);
2620 * %minimum_access_length
2622 operand_address = next_operand_address;
2623 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &minimum_access_length);
2624 if (show_instr_detail_level == 2 ){
2625 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u minimum_access_length %u",
2626 operand_address, minimum_access_length);
2630 * %state_retention_priority
2632 operand_address = next_operand_address;
2633 /*next_operand_address =*/ decode_udvm_multitype_operand(buff, operand_address, &state_retention_priority);
2634 if (show_instr_detail_level == 2 ){
2635 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_retention_priority %u",
2636 operand_address, state_retention_priority);
2638 if (show_instr_detail_level == 1)
2640 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2641 "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)",
2642 current_address, requested_feedback_location, returned_parameters_location, state_length, state_address, state_instruction, minimum_access_length,state_retention_priority);
2644 /* TODO: This isn't currently totaly correct as END_INSTRUCTION might not create state */
2645 no_of_state_create++;
2646 if ( no_of_state_create > 4 ){
2648 goto decompression_failure;
2650 state_length_buff[no_of_state_create] = state_length;
2651 state_address_buff[no_of_state_create] = state_address;
2652 state_instruction_buff[no_of_state_create] = state_instruction;
2654 state_minimum_access_length_buff[no_of_state_create] = minimum_access_length;
2655 /* state_state_retention_priority_buff[no_of_state_create] = state_retention_priority; */
2657 /* Execute the instruction
2659 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"no_of_state_create %u",no_of_state_create);
2660 if ( no_of_state_create != 0 ){
2661 memset(sha1_digest_buf, 0, STATE_BUFFER_SIZE);
2663 byte_copy_right = buff[66] << 8;
2664 byte_copy_right = byte_copy_right | buff[67];
2665 byte_copy_left = buff[64] << 8;
2666 byte_copy_left = byte_copy_left | buff[65];
2667 while ( n < no_of_state_create + 1 ){
2668 sha1buff = (guint8 *)g_malloc(state_length_buff[n]+8);
2669 sha1buff[0] = state_length_buff[n] >> 8;
2670 sha1buff[1] = state_length_buff[n] & 0xff;
2671 sha1buff[2] = state_address_buff[n] >> 8;
2672 sha1buff[3] = state_address_buff[n] & 0xff;
2673 sha1buff[4] = state_instruction_buff[n] >> 8;
2674 sha1buff[5] = state_instruction_buff[n] & 0xff;
2675 sha1buff[6] = state_minimum_access_length_buff[n] >> 8;
2676 sha1buff[7] = state_minimum_access_length_buff[n] & 0xff;
2677 if (print_level_3 ){
2678 for( x=0; x < 8; x++){
2679 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"sha1buff %u 0x%x",
2683 k = state_address_buff[n];
2684 for( x=0; x < state_length_buff[n]; x++)
2686 if ( k == byte_copy_right ){
2689 sha1buff[8+x] = buff[k];
2690 k = ( k + 1 ) & 0xffff;
2693 sha1_starts( &ctx );
2694 sha1_update( &ctx, (guint8 *) sha1buff, state_length_buff[n] + 8);
2695 sha1_finish( &ctx, sha1_digest_buf );
2696 if (print_level_3 ){
2697 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"SHA1 digest %s",bytes_to_str(sha1_digest_buf, STATE_BUFFER_SIZE));
2700 /* begin partial state-id change cco@iptel.org */
2702 udvm_state_create(sha1buff, sha1_digest_buf, state_minimum_access_length_buff[n]);
2704 udvm_state_create(sha1buff, sha1_digest_buf, STATE_MIN_ACCESS_LEN);
2705 /* end partial state-id change cco@iptel.org */
2706 proto_tree_add_text(udvm_tree,bytecode_tvb, 0, -1,"### Creating state ###");
2707 proto_tree_add_string(udvm_tree,hf_id, bytecode_tvb, 0, 0, bytes_to_str(sha1_digest_buf, state_minimum_access_length_buff[n]));
2716 /* At least something got decompressed, show it */
2717 decomp_tvb = tvb_new_child_real_data(message_tvb, out_buff,output_address,output_address);
2718 /* Arrange that the allocated packet data copy be freed when the
2721 tvb_set_free_cb( decomp_tvb, g_free );
2723 add_new_data_source(pinfo, decomp_tvb, "Decompressed SigComp message");
2725 proto_tree_add_text(udvm_tree, decomp_tvb, 0, -1,"SigComp message Decompressed");
2727 used_udvm_cycles = used_udvm_cycles + state_length;
2728 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"maximum_UDVM_cycles %u used_udvm_cycles %u",
2729 maximum_UDVM_cycles, used_udvm_cycles);
2734 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," ### Addr %u Invalid instruction: %u (0x%x)",
2735 current_address,current_instruction,current_instruction);
2740 decompression_failure:
2742 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"DECOMPRESSION FAILURE: %s",
2743 val_to_str(result_code, result_code_vals,"Unknown (%u)"));
2744 THROW(ReportedBoundsError);
2750 /* The simplest operand type is the literal (#), which encodes a
2751 * constant integer from 0 to 65535 inclusive. A literal operand may
2752 * require between 1 and 3 bytes depending on its value.
2753 * Bytecode: Operand value: Range:
2754 * 0nnnnnnn N 0 - 127
2755 * 10nnnnnn nnnnnnnn N 0 - 16383
2756 * 11000000 nnnnnnnn nnnnnnnn N 0 - 65535
2758 * Figure 8: Bytecode for a literal (#) operand
2762 decode_udvm_literal_operand(guint8 *buff,guint operand_address, guint16 *value)
2767 guint offset = operand_address;
2770 bytecode = buff[operand_address];
2771 test_bits = bytecode >> 7;
2772 if (test_bits == 1){
2773 test_bits = bytecode >> 6;
2774 if (test_bits == 2){
2776 * 10nnnnnn nnnnnnnn N 0 - 16383
2778 temp_data = buff[operand_address] & 0x1f;
2779 operand = temp_data << 8;
2780 temp_data = buff[(operand_address + 1) & 0xffff];
2781 operand = operand | temp_data;
2783 offset = offset + 2;
2787 * 111000000 nnnnnnnn nnnnnnnn N 0 - 65535
2790 temp_data = buff[operand_address] & 0x1f;
2791 operand = temp_data << 8;
2792 temp_data = buff[(operand_address + 1) & 0xffff];
2793 operand = operand | temp_data;
2795 offset = offset + 2;
2800 * 0nnnnnnn N 0 - 127
2802 operand = ( bytecode & 0x7f);
2812 * The second operand type is the reference ($), which is always used to
2813 * access a 2-byte value located elsewhere in the UDVM memory. The
2814 * bytecode for a reference operand is decoded to be a constant integer
2815 * from 0 to 65535 inclusive, which is interpreted as the memory address
2816 * containing the actual value of the operand.
2817 * Bytecode: Operand value: Range:
2819 * 0nnnnnnn memory[2 * N] 0 - 65535
2820 * 10nnnnnn nnnnnnnn memory[2 * N] 0 - 65535
2821 * 11000000 nnnnnnnn nnnnnnnn memory[N] 0 - 65535
2823 * Figure 9: Bytecode for a reference ($) operand
2826 dissect_udvm_reference_operand(guint8 *buff,guint operand_address, guint16 *value,guint *result_dest)
2830 guint offset = operand_address;
2833 guint16 temp_data16;
2835 bytecode = buff[operand_address];
2836 test_bits = bytecode >> 7;
2837 if (test_bits == 1){
2838 test_bits = bytecode >> 6;
2839 if (test_bits == 2){
2841 * 10nnnnnn nnnnnnnn memory[2 * N] 0 - 65535
2843 temp_data = buff[operand_address] & 0x3f;
2844 operand = temp_data << 8;
2845 temp_data = buff[(operand_address + 1) & 0xffff];
2846 operand = operand | temp_data;
2847 operand = (operand * 2);
2848 *result_dest = operand;
2849 temp_data16 = buff[operand] << 8;
2850 temp_data16 = temp_data16 | buff[(operand+1) & 0xffff];
2851 *value = temp_data16;
2852 offset = offset + 2;
2856 * 11000000 nnnnnnnn nnnnnnnn memory[N] 0 - 65535
2859 operand = buff[operand_address] << 8;
2860 operand = operand | buff[(operand_address + 1) & 0xffff];
2861 *result_dest = operand;
2862 temp_data16 = buff[operand] << 8;
2863 temp_data16 = temp_data16 | buff[(operand+1) & 0xffff];
2864 *value = temp_data16;
2865 offset = offset + 3;
2870 * 0nnnnnnn memory[2 * N] 0 - 65535
2872 operand = ( bytecode & 0x7f);
2873 operand = (operand * 2);
2874 *result_dest = operand;
2875 temp_data16 = buff[operand] << 8;
2876 temp_data16 = temp_data16 | buff[(operand+1) & 0xffff];
2877 *value = temp_data16;
2881 if (offset >= UDVM_MEMORY_SIZE || *result_dest >= UDVM_MEMORY_SIZE - 1 )
2882 THROW(ReportedBoundsError);
2888 * Figure 10: Bytecode for a multitype (%) operand
2889 * Bytecode: Operand value: Range: HEX val
2890 * 00nnnnnn N 0 - 63 0x00
2891 * 01nnnnnn memory[2 * N] 0 - 65535 0x40
2892 * 1000011n 2 ^ (N + 6) 64 , 128 0x86
2893 * 10001nnn 2 ^ (N + 8) 256 , ... , 32768 0x88
2894 * 111nnnnn N + 65504 65504 - 65535 0xe0
2895 * 1001nnnn nnnnnnnn N + 61440 61440 - 65535 0x90
2896 * 101nnnnn nnnnnnnn N 0 - 8191 0xa0
2897 * 110nnnnn nnnnnnnn memory[N] 0 - 65535 0xc0
2898 * 10000000 nnnnnnnn nnnnnnnn N 0 - 65535 0x80
2899 * 10000001 nnnnnnnn nnnnnnnn memory[N] 0 - 65535 0x81
2902 decode_udvm_multitype_operand(guint8 *buff,guint operand_address, guint16 *value)
2906 guint offset = operand_address;
2910 guint16 temp_data16;
2911 guint16 memmory_addr = 0;
2915 bytecode = buff[operand_address];
2916 test_bits = ( bytecode & 0xc0 ) >> 6;
2917 switch (test_bits ){
2922 operand = buff[operand_address];
2924 *g_warning("Reading 0x%x From address %u",operand,offset);
2931 * 01nnnnnn memory[2 * N] 0 - 65535
2933 memmory_addr = ( bytecode & 0x3f) * 2;
2934 temp_data16 = buff[memmory_addr] << 8;
2935 temp_data16 = temp_data16 | buff[(memmory_addr+1) & 0xffff];
2936 *value = temp_data16;
2940 /* Check tree most significant bits */
2941 test_bits = ( bytecode & 0xe0 ) >> 5;
2942 if ( test_bits == 5 ){
2944 * 101nnnnn nnnnnnnn N 0 - 8191
2946 temp_data = buff[operand_address] & 0x1f;
2947 operand = temp_data << 8;
2948 temp_data = buff[(operand_address + 1) & 0xffff];
2949 operand = operand | temp_data;
2951 offset = offset + 2;
2953 test_bits = ( bytecode & 0xf0 ) >> 4;
2954 if ( test_bits == 9 ){
2956 * 1001nnnn nnnnnnnn N + 61440 61440 - 65535
2958 temp_data = buff[operand_address] & 0x0f;
2959 operand = temp_data << 8;
2960 temp_data = buff[(operand_address + 1) & 0xffff];
2961 operand = operand | temp_data;
2962 operand = operand + 61440;
2964 offset = offset + 2;
2966 test_bits = ( bytecode & 0x08 ) >> 3;
2967 if ( test_bits == 1){
2969 * 10001nnn 2 ^ (N + 8) 256 , ... , 32768
2972 result = 1 << ((buff[operand_address] & 0x07) + 8);
2973 operand = result & 0xffff;
2977 test_bits = ( bytecode & 0x0e ) >> 1;
2978 if ( test_bits == 3 ){
2980 * 1000 011n 2 ^ (N + 6) 64 , 128
2982 result = 1 << ((buff[operand_address] & 0x01) + 6);
2983 operand = result & 0xffff;
2988 * 1000 0000 nnnnnnnn nnnnnnnn N 0 - 65535
2989 * 1000 0001 nnnnnnnn nnnnnnnn memory[N] 0 - 65535
2992 temp_data16 = buff[(operand_address + 1) & 0xffff] << 8;
2993 temp_data16 = temp_data16 | buff[(operand_address + 2) & 0xffff];
2995 * g_warning("Reading 0x%x From address %u",temp_data16,operand_address);
2997 if ( (bytecode & 0x01) == 1 ){
2998 memmory_addr = temp_data16;
2999 temp_data16 = buff[memmory_addr] << 8;
3000 temp_data16 = temp_data16 | buff[(memmory_addr+1) & 0xffff];
3002 *value = temp_data16;
3013 test_bits = ( bytecode & 0x20 ) >> 5;
3014 if ( test_bits == 1 ){
3016 * 111nnnnn N + 65504 65504 - 65535
3018 operand = ( buff[operand_address] & 0x1f) + 65504;
3023 * 110nnnnn nnnnnnnn memory[N] 0 - 65535
3025 memmory_addr = buff[operand_address] & 0x1f;
3026 memmory_addr = memmory_addr << 8;
3027 memmory_addr = memmory_addr | buff[(operand_address + 1) & 0xffff];
3028 temp_data16 = buff[memmory_addr] << 8;
3029 temp_data16 = temp_data16 | buff[(memmory_addr+1) & 0xffff];
3030 *value = temp_data16;
3032 * g_warning("Reading 0x%x From address %u",temp_data16,memmory_addr);
3044 * The fourth operand type is the address (@). This operand is decoded
3045 * as a multitype operand followed by a further step: the memory address
3046 * of the UDVM instruction containing the address operand is added to
3047 * obtain the correct operand value. So if the operand value from
3048 * Figure 10 is D then the actual operand value of an address is
3049 * calculated as follows:
3051 * operand_value = (memory_address_of_instruction + D) modulo 2^16
3053 * Address operands are always used in instructions that control program
3054 * flow, because they ensure that the UDVM bytecode is position-
3055 * independent code (i.e., it will run independently of where it is
3056 * placed in the UDVM memory).
3059 decode_udvm_address_operand(guint8 *buff,guint operand_address, guint16 *value,guint current_address)
3063 guint next_opreand_address;
3065 next_opreand_address = decode_udvm_multitype_operand(buff, operand_address, &value1);
3066 result = value1 & 0xffff;
3067 result = result + current_address;
3068 *value = result & 0xffff;
3069 return next_opreand_address;
3074 * This is a lookup table used to reverse the bits in a byte.
3076 static guint8 reverse [] = {
3077 0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0,
3078 0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0,
3079 0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8,
3080 0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8,
3081 0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4,
3082 0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4,
3083 0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC,
3084 0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC,
3085 0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2,
3086 0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2,
3087 0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA,
3088 0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA,
3089 0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6,
3090 0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6,
3091 0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE,
3092 0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE,
3093 0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1,
3094 0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1,
3095 0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9,
3096 0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9,
3097 0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5,
3098 0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5,
3099 0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED,
3100 0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD,
3101 0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3,
3102 0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3,
3103 0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB,
3104 0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB,
3105 0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7,
3106 0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7,
3107 0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF,
3108 0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF
3113 decomp_dispatch_get_bits(
3114 tvbuff_t *message_tvb,
3115 proto_tree *udvm_tree,
3118 guint16 *old_input_bit_order,
3119 guint16 *remaining_bits,
3120 guint16 *input_bits,
3121 guint *input_address,
3123 guint16 *result_code,
3126 guint16 input_bit_order;
3127 guint16 bits_still_required = length;
3130 gint extra_bytes_available = msg_end - *input_address;
3132 gint prev_p_bit = *old_input_bit_order & 0x0001;
3133 gint bits_to_use = 0;
3136 input_bit_order = buff[68] << 8;
3137 input_bit_order = input_bit_order | buff[69];
3139 p_bit = (input_bit_order & 0x0001) != 0;
3142 * Discard any spare bits.
3143 * Note: We take care to avoid remaining_bits having the value of 8.
3145 if (prev_p_bit != p_bit)
3147 *remaining_bits = 0;
3148 *old_input_bit_order = input_bit_order;
3152 * Check we can suppy the required number of bits now, before we alter
3153 * the input buffer's state.
3155 if (*remaining_bits + extra_bytes_available * 8 < length)
3161 /* Note: This is never called with length > 16, so the following loop
3162 * never loops more than three time. */
3163 while (bits_still_required > 0)
3166 * We only put anything into input_bits if we know we will remove
3167 * at least one bit. That ensures we can simply discard the spare
3168 * bits if the P-bit changes.
3170 if (*remaining_bits == 0)
3172 octet = tvb_get_guint8(message_tvb, *input_address);
3173 if (print_level_1 ){
3174 proto_tree_add_text(udvm_tree, message_tvb, *input_address , 1,
3175 " Getting value: %u (0x%x) From Addr: %u", octet, octet, *input_address);
3177 *input_address = *input_address + 1;
3181 octet = reverse[octet];
3183 *input_bits = octet;
3184 *remaining_bits = 8;
3187 /* Add some more bits to the accumulated value. */
3188 bits_to_use = bits_still_required < *remaining_bits ? bits_still_required : *remaining_bits;
3189 bits_still_required -= bits_to_use;
3191 *input_bits <<= bits_to_use; /* Shift bits into MSByte */
3192 value = (value << bits_to_use) /* Then add to the accumulated value */
3193 | ((*input_bits >> 8) & 0xFF);
3194 *remaining_bits -= bits_to_use;
3195 *input_bits &= 0x00FF; /* Leave just the remaining bits */
3200 /* Bit reverse the entire word. */
3201 guint16 lsb = reverse[(value >> 8) & 0xFF];
3202 guint16 msb = reverse[value & 0xFF];
3204 value = ((msb << 8) | lsb) >> (16 - length);