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 <wsutil/sha1.h>
41 #include <wsutil/crc16.h>
45 #include "sigcomp-udvm.h"
46 #include "sigcomp_state_hdlr.h"
49 #define SIGCOMP_INSTR_DECOMPRESSION_FAILURE 0
50 #define SIGCOMP_INSTR_AND 1
51 #define SIGCOMP_INSTR_OR 2
52 #define SIGCOMP_INSTR_NOT 3
53 #define SIGCOMP_INSTR_LSHIFT 4
54 #define SIGCOMP_INSTR_RSHIFT 5
55 #define SIGCOMP_INSTR_ADD 6
56 #define SIGCOMP_INSTR_SUBTRACT 7
57 #define SIGCOMP_INSTR_MULTIPLY 8
58 #define SIGCOMP_INSTR_DIVIDE 9
59 #define SIGCOMP_INSTR_REMAINDER 10
60 #define SIGCOMP_INSTR_SORT_ASCENDING 11
61 #define SIGCOMP_INSTR_SORT_DESCENDING 12
62 #define SIGCOMP_INSTR_SHA_1 13
63 #define SIGCOMP_INSTR_LOAD 14
64 #define SIGCOMP_INSTR_MULTILOAD 15
65 #define SIGCOMP_INSTR_PUSH 16
66 #define SIGCOMP_INSTR_POP 17
67 #define SIGCOMP_INSTR_COPY 18
68 #define SIGCOMP_INSTR_COPY_LITERAL 19
69 #define SIGCOMP_INSTR_COPY_OFFSET 20
70 #define SIGCOMP_INSTR_MEMSET 21
71 #define SIGCOMP_INSTR_JUMP 22
72 #define SIGCOMP_INSTR_COMPARE 23
73 #define SIGCOMP_INSTR_CALL 24
74 #define SIGCOMP_INSTR_RETURN 25
75 #define SIGCOMP_INSTR_SWITCH 26
76 #define SIGCOMP_INSTR_CRC 27
77 #define SIGCOMP_INSTR_INPUT_BYTES 28
78 #define SIGCOMP_INSTR_INPUT_BITS 29
79 #define SIGCOMP_INSTR_INPUT_HUFFMAN 30
80 #define SIGCOMP_INSTR_STATE_ACCESS 31
81 #define SIGCOMP_INSTR_STATE_CREATE 32
82 #define SIGCOMP_INSTR_STATE_FREE 33
83 #define SIGCOMP_INSTR_OUTPUT 34
84 #define SIGCOMP_INSTR_END_MESSAGE 35
87 static gboolean print_level_1;
88 static gboolean print_level_2;
89 static gboolean print_level_3;
90 static gint show_instr_detail_level;
92 /* Internal result code values of decompression failures */
93 const value_string result_code_vals[] = {
94 { 0, "No decompression failure" },
95 { 1, "Partial state length less than 6 or greater than 20 bytes long" },
96 { 2, "No state match" },
97 { 3, "state_begin + state_length > size of state" },
98 { 4, "Operand_2 is Zero" },
99 { 5, "Switch statement failed j >= n" },
100 { 6, "Attempt to jump outside of UDVM memory" },
101 { 7, "L in input-bits > 16" },
102 { 8, "input_bit_order > 7" },
103 { 9, "Instruction Decompression failure encountered" },
104 {10, "Input huffman failed j > n" },
105 {11, "Input bits requested beyond end of message" },
106 {12, "more than four state creation requests are made before the END-MESSAGE instruction" },
107 {13, "state_retention_priority is 65535" },
108 {14, "Input bytes requested beyond end of message" },
109 {15, "Maximum number of UDVM cycles reached" },
110 {16, "UDVM stack underflow" },
111 { 255, "This branch isn't coded yet" },
115 static int decode_udvm_literal_operand(guint8 *buff,guint operand_address, guint16 *value);
116 static int dissect_udvm_reference_operand(guint8 *buff,guint operand_address, guint16 *value, guint *result_dest);
117 static int decode_udvm_multitype_operand(guint8 *buff,guint operand_address,guint16 *value);
118 static int decode_udvm_address_operand(guint8 *buff,guint operand_address, guint16 *value,guint current_address);
119 static int decomp_dispatch_get_bits(tvbuff_t *message_tvb,proto_tree *udvm_tree,guint8 bit_order,
120 guint8 *buff,guint16 *old_input_bit_order, guint16 *remaining_bits,
121 guint16 *input_bits, guint *input_address, guint16 length, guint16 *result_code,guint msg_end);
125 decompress_sigcomp_message(tvbuff_t *bytecode_tvb, tvbuff_t *message_tvb, packet_info *pinfo,
126 proto_tree *udvm_tree, gint udvm_mem_dest,
127 gint print_flags, gint hf_id,
129 gint byte_code_state_len, gint byte_code_id_len,
132 tvbuff_t *decomp_tvb;
133 /* UDVM memory must be initialised to zero */
134 guint8 *buff = (guint8 *)ep_alloc0(UDVM_MEMORY_SIZE);
136 guint8 *out_buff; /* Largest allowed size for a message is UDVM_MEMORY_SIZE = 65536 */
146 guint code_length =0;
147 guint8 current_instruction;
148 guint current_address;
149 guint operand_address;
151 guint16 output_address = 0;
152 guint next_operand_address;
156 guint16 byte_copy_right;
157 guint16 byte_copy_left;
158 guint16 input_bit_order;
159 guint16 stack_location;
162 guint msg_end = tvb_reported_length_remaining(message_tvb, 0);
163 guint16 result_code = 0;
164 guint16 old_input_bit_order = 0;
165 guint16 remaining_bits = 0;
166 guint16 input_bits = 0;
167 guint8 bit_order = 0;
168 gboolean outside_huffman_boundaries = TRUE;
169 gboolean print_in_loop = FALSE;
170 guint16 instruction_address;
171 guint8 no_of_state_create = 0;
172 guint16 state_length_buff[5];
173 guint16 state_address_buff[5];
174 guint16 state_instruction_buff[5];
175 guint16 state_minimum_access_length_buff[5];
176 /* guint16 state_state_retention_priority_buff[5]; */
177 guint32 used_udvm_cycles = 0;
178 guint cycles_per_bit;
179 guint maximum_UDVM_cycles;
181 unsigned char sha1_digest_buf[STATE_BUFFER_SIZE];
185 /* UDVM operand variables */
194 guint16 state_length;
195 guint16 state_address;
196 guint16 state_instruction;
201 guint16 at_address_1;
202 guint16 at_address_2;
203 guint16 at_address_3;
206 guint16 lower_bound_n;
207 guint16 upper_bound_n;
208 guint16 uncompressed_n;
210 guint16 ref_destination; /* could I have used $destination ? */
211 guint16 multy_offset;
212 guint16 output_start;
213 guint16 output_length;
214 guint16 minimum_access_length;
215 guint16 state_retention_priority;
216 guint16 requested_feedback_location;
217 guint16 returned_parameters_location;
221 /* Set print parameters */
222 print_level_1 = FALSE;
223 print_level_2 = FALSE;
224 print_level_3 = FALSE;
225 show_instr_detail_level = 0;
229 switch( print_flags ) {
234 print_level_1 = TRUE;
235 show_instr_detail_level = 1;
238 print_level_1 = TRUE;
239 print_level_2 = TRUE;
240 show_instr_detail_level = 1;
243 print_level_1 = TRUE;
244 print_level_2 = TRUE;
245 print_level_3 = TRUE;
246 show_instr_detail_level = 2;
249 print_level_1 = TRUE;
250 show_instr_detail_level = 1;
254 /* Set initial UDVM data
255 * The first 32 bytes of UDVM memory are then initialized to special
256 * values as illustrated in Figure 5.
259 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
260 * | UDVM_memory_size | 0 - 1
261 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
262 * | cycles_per_bit | 2 - 3
263 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
264 * | SigComp_version | 4 - 5
265 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
266 * | partial_state_ID_length | 6 - 7
267 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
268 * | state_length | 8 - 9
269 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
271 * : reserved : 10 - 31
273 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
275 * Figure 5: Initializing Useful Values in UDVM memory
277 /* UDVM_memory_size */
278 buff[0] = (UDVM_MEMORY_SIZE >> 8) & 0x00FF;
279 buff[1] = UDVM_MEMORY_SIZE & 0x00FF;
283 /* SigComp_version */
286 /* partial_state_ID_length */
287 buff[6] = (byte_code_id_len >> 8) & 0x00FF;
288 buff[7] = byte_code_id_len & 0x00FF;
290 buff[8] = (byte_code_state_len >> 8) & 0x00FF;
291 buff[9] = byte_code_state_len & 0x00FF;
293 code_length = tvb_reported_length_remaining(bytecode_tvb, 0);
295 cycles_per_bit = buff[2] << 8;
296 cycles_per_bit = cycles_per_bit | buff[3];
298 * maximum_UDVM_cycles = (8 * n + 1000) * cycles_per_bit
300 maximum_UDVM_cycles = (( 8 * (header_len + msg_end) ) + 1000) * cycles_per_bit;
302 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);
303 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);
305 /* Load bytecode into UDVM starting at "udvm_mem_dest" */
308 proto_tree_add_text(udvm_tree, bytecode_tvb, offset, 1,"Load bytecode into UDVM starting at %u",i);
309 while ( code_length > offset && i < UDVM_MEMORY_SIZE ) {
310 buff[i] = tvb_get_guint8(bytecode_tvb, offset);
312 proto_tree_add_text(udvm_tree, bytecode_tvb, offset, 1,
313 " Addr: %u Instruction code(0x%0x) ", i, buff[i]);
319 /* Largest allowed size for a message is UDVM_MEMORY_SIZE = 65536 */
320 out_buff = (guint8 *)g_malloc(UDVM_MEMORY_SIZE);
321 /* Start executing code */
322 current_address = udvm_start_ip;
325 proto_tree_add_text(udvm_tree, bytecode_tvb, offset, 1,"UDVM EXECUTION STARTED at Address: %u Message size %u",
326 current_address, msg_end);
328 execute_next_instruction:
330 if ( used_udvm_cycles > maximum_UDVM_cycles ){
332 goto decompression_failure;
335 current_instruction = buff[current_address & 0xffff];
337 switch ( current_instruction ) {
338 case SIGCOMP_INSTR_DECOMPRESSION_FAILURE:
339 if ( result_code == 0 )
341 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
342 "Addr: %u ## DECOMPRESSION-FAILURE(0)",
344 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Wireshark UDVM diagnostic: %s.",
345 val_to_str(result_code, result_code_vals,"Unknown (%u)"));
346 if ( output_address > 0 ){
347 /* At least something got decompressed, show it */
348 decomp_tvb = tvb_new_child_real_data(message_tvb, out_buff,output_address,output_address);
349 /* Arrange that the allocated packet data copy be freed when the
352 tvb_set_free_cb( decomp_tvb, g_free );
353 /* Add the tvbuff to the list of tvbuffs to which the tvbuff we
354 * were handed refers, so it'll get cleaned up when that tvbuff
357 add_new_data_source(pinfo, decomp_tvb, "Decompressed SigComp message(Incomplete)");
358 proto_tree_add_text(udvm_tree, decomp_tvb, 0, -1,"SigComp message Decompression failure");
365 case SIGCOMP_INSTR_AND: /* 1 AND ($operand_1, %operand_2) */
366 if (show_instr_detail_level == 2 ){
367 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
368 "Addr: %u ## AND(1) (operand_1, operand_2)",
372 operand_address = current_address + 1;
373 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &operand_1, &result_dest);
374 if (show_instr_detail_level == 2 ){
375 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_1 %u",
376 operand_address, operand_1);
378 operand_address = next_operand_address;
380 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &operand_2);
381 if (show_instr_detail_level == 2 ){
382 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_2 %u",
383 operand_address, operand_2);
385 if (show_instr_detail_level == 1)
387 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
388 "Addr: %u ## AND (operand_1=%u, operand_2=%u)",
389 current_address, operand_1, operand_2);
391 /* execute the instruction */
392 result = operand_1 & operand_2;
395 buff[result_dest] = msb;
396 buff[(result_dest+1) & 0xffff] = lsb;
398 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," Loading result %u at %u",
399 result, result_dest);
401 current_address = next_operand_address;
402 goto execute_next_instruction;
406 case SIGCOMP_INSTR_OR: /* 2 OR ($operand_1, %operand_2) */
407 if (show_instr_detail_level == 2 ){
408 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
409 "Addr: %u ## OR(2) (operand_1, operand_2)",
413 operand_address = current_address + 1;
414 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &operand_1, &result_dest);
415 if (show_instr_detail_level == 2 ){
416 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_1 %u",
417 operand_address, operand_1);
419 operand_address = next_operand_address;
421 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &operand_2);
422 if (show_instr_detail_level == 2 ){
423 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_2 %u",
424 operand_address, operand_2);
426 if (show_instr_detail_level == 1)
428 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
429 "Addr: %u ## OR (operand_1=%u, operand_2=%u)",
430 current_address, operand_1, operand_2);
432 /* execute the instruction */
433 result = operand_1 | operand_2;
436 buff[result_dest] = msb;
437 buff[(result_dest+1) & 0xffff] = lsb;
439 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," Loading result %u at %u",
440 result, result_dest);
442 current_address = next_operand_address;
443 goto execute_next_instruction;
447 case SIGCOMP_INSTR_NOT: /* 3 NOT ($operand_1) */
448 if (show_instr_detail_level == 2 ){
449 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
450 "Addr: %u ## NOT(3) ($operand_1)",
454 operand_address = current_address + 1;
455 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &operand_1, &result_dest);
456 if (show_instr_detail_level == 2 ){
457 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_1 %u",
458 operand_address, operand_1);
460 if (show_instr_detail_level == 1)
462 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
463 "Addr: %u ## NOT (operand_1=%u)",
464 current_address, operand_1);
466 /* execute the instruction */
467 result = operand_1 ^ 0xffff;
470 buff[result_dest] = msb;
471 buff[(result_dest+1) & 0xffff] = lsb;
473 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," Loading result %u at %u",
474 result, result_dest);
476 current_address = next_operand_address;
477 goto execute_next_instruction;
480 case SIGCOMP_INSTR_LSHIFT: /* 4 LSHIFT ($operand_1, %operand_2) */
481 if (show_instr_detail_level == 2 ){
482 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
483 "Addr: %u ## LSHIFT(4) ($operand_1, operand_2)",
487 operand_address = current_address + 1;
488 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &operand_1, &result_dest);
489 if (show_instr_detail_level == 2 ){
490 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_1 %u",
491 operand_address, operand_1);
493 operand_address = next_operand_address;
495 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &operand_2);
496 if (show_instr_detail_level == 2 ){
497 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_2 %u",
498 operand_address, operand_2);
500 if (show_instr_detail_level == 1)
502 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
503 "Addr: %u ## LSHIFT (operand_1=%u, operand_2=%u)",
504 current_address, operand_1, operand_2);
506 /* execute the instruction */
507 result = operand_1 << operand_2;
510 buff[result_dest] = msb;
511 buff[(result_dest+1) & 0xffff] = lsb;
513 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," Loading result %u at %u",
514 result, result_dest);
516 current_address = next_operand_address;
517 goto execute_next_instruction;
520 case SIGCOMP_INSTR_RSHIFT: /* 5 RSHIFT ($operand_1, %operand_2) */
521 if (show_instr_detail_level == 2 ){
522 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
523 "Addr: %u ## RSHIFT(5) (operand_1, operand_2)",
527 operand_address = current_address + 1;
528 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &operand_1, &result_dest);
529 if (show_instr_detail_level == 2 ){
530 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_1 %u",
531 operand_address, operand_1);
533 operand_address = next_operand_address;
535 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &operand_2);
536 if (show_instr_detail_level == 2 ){
537 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_2 %u",
538 operand_address, operand_2);
540 if (show_instr_detail_level == 1)
542 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
543 "Addr: %u ## RSHIFT (operand_1=%u, operand_2=%u)",
544 current_address, operand_1, operand_2);
546 /* execute the instruction */
547 result = operand_1 >> operand_2;
550 buff[result_dest] = msb;
551 buff[(result_dest+1) & 0xffff] = lsb;
553 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," Loading result %u at %u",
554 result, result_dest);
556 current_address = next_operand_address;
557 goto execute_next_instruction;
559 case SIGCOMP_INSTR_ADD: /* 6 ADD ($operand_1, %operand_2) */
560 if (show_instr_detail_level == 2 ){
561 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
562 "Addr: %u ## ADD(6) (operand_1, operand_2)",
566 operand_address = current_address + 1;
567 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &operand_1, &result_dest);
568 if (show_instr_detail_level == 2 ){
569 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_1 %u",
570 operand_address, operand_1);
572 operand_address = next_operand_address;
574 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &operand_2);
575 if (show_instr_detail_level == 2 ){
576 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_2 %u",
577 operand_address, operand_2);
579 if (show_instr_detail_level == 1)
581 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
582 "Addr: %u ## ADD (operand_1=%u, operand_2=%u)",
583 current_address, operand_1, operand_2);
585 /* execute the instruction */
586 result = operand_1 + operand_2;
589 buff[result_dest] = msb;
590 buff[(result_dest+1) & 0xffff] = lsb;
592 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," Loading result %u at %u",
593 result, result_dest);
595 current_address = next_operand_address;
596 goto execute_next_instruction;
598 case SIGCOMP_INSTR_SUBTRACT: /* 7 SUBTRACT ($operand_1, %operand_2) */
599 if (show_instr_detail_level == 2 ){
600 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
601 "Addr: %u ## SUBTRACT(7) (operand_1, operand_2)",
605 operand_address = current_address + 1;
606 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &operand_1, &result_dest);
607 if (show_instr_detail_level == 2 ){
608 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_1 %u",
609 operand_address, operand_1);
611 operand_address = next_operand_address;
613 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &operand_2);
614 if (show_instr_detail_level == 2 ){
615 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_2 %u",
616 operand_address, operand_2);
618 if (show_instr_detail_level == 1)
620 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
621 "Addr: %u ## SUBTRACT (operand_1=%u, operand_2=%u)",
622 current_address, operand_1, operand_2);
624 /* execute the instruction */
625 result = operand_1 - operand_2;
628 buff[result_dest] = msb;
629 buff[(result_dest+1) & 0xffff] = lsb;
631 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," Loading result %u at %u",
632 result, result_dest);
634 current_address = next_operand_address;
635 goto execute_next_instruction;
638 case SIGCOMP_INSTR_MULTIPLY: /* 8 MULTIPLY ($operand_1, %operand_2) */
639 if (show_instr_detail_level == 2 ){
640 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
641 "Addr: %u ##MULTIPLY(8) (operand_1, operand_2)",
645 operand_address = current_address + 1;
646 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &operand_1, &result_dest);
647 if (show_instr_detail_level == 2 ){
648 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_1 %u",
649 operand_address, operand_1);
651 operand_address = next_operand_address;
653 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &operand_2);
654 if (show_instr_detail_level == 2 ){
655 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_2 %u",
656 operand_address, operand_2);
658 if (show_instr_detail_level == 1)
660 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
661 "Addr: %u ## MULTIPLY (operand_1=%u, operand_2=%u)",
662 current_address, operand_1, operand_2);
665 * execute the instruction
666 * MULTIPLY (m, n) := m * n (modulo 2^16)
668 if ( operand_2 == 0){
670 goto decompression_failure;
672 result = operand_1 * operand_2;
675 buff[result_dest] = msb;
676 buff[(result_dest+1) & 0xffff] = lsb;
678 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," Loading result %u at %u",
679 result, result_dest);
681 current_address = next_operand_address;
682 goto execute_next_instruction;
685 case SIGCOMP_INSTR_DIVIDE: /* 9 DIVIDE ($operand_1, %operand_2) */
686 if (show_instr_detail_level == 2 ){
687 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
688 "Addr: %u ## DIVIDE(9) (operand_1, operand_2)",
692 operand_address = current_address + 1;
693 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &operand_1, &result_dest);
694 if (show_instr_detail_level == 2 ){
695 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_1 %u",
696 operand_address, operand_1);
698 operand_address = next_operand_address;
700 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &operand_2);
701 if (show_instr_detail_level == 2 ){
702 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_2 %u",
703 operand_address, operand_2);
705 if (show_instr_detail_level == 1)
707 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
708 "Addr: %u ## DIVIDE (operand_1=%u, operand_2=%u)",
709 current_address, operand_1, operand_2);
712 * execute the instruction
713 * DIVIDE (m, n) := floor(m / n)
714 * Decompression failure occurs if a DIVIDE or REMAINDER instruction
715 * encounters an operand_2 that is zero.
717 if ( operand_2 == 0){
719 goto decompression_failure;
721 result = operand_1 / operand_2;
724 buff[result_dest] = msb;
725 buff[(result_dest+1) & 0xffff] = lsb;
727 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," Loading result %u at %u",
728 result, result_dest);
730 current_address = next_operand_address;
731 goto execute_next_instruction;
734 case SIGCOMP_INSTR_REMAINDER: /* 10 REMAINDER ($operand_1, %operand_2) */
735 if (show_instr_detail_level == 2 ){
736 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
737 "Addr: %u ## REMAINDER(10) (operand_1, operand_2)",
741 operand_address = current_address + 1;
742 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &operand_1, &result_dest);
743 if (show_instr_detail_level == 2 ){
744 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_1 %u",
745 operand_address, operand_1);
747 operand_address = next_operand_address;
749 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &operand_2);
750 if (show_instr_detail_level == 2 ){
751 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_2 %u",
752 operand_address, operand_2);
754 if (show_instr_detail_level == 1)
756 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
757 "Addr: %u ## REMAINDER (operand_1=%u, operand_2=%u)",
758 current_address, operand_1, operand_2);
761 * execute the instruction
762 * REMAINDER (m, n) := m - n * floor(m / n)
763 * Decompression failure occurs if a DIVIDE or REMAINDER instruction
764 * encounters an operand_2 that is zero.
766 if ( operand_2 == 0){
768 goto decompression_failure;
770 result = operand_1 - operand_2 * (operand_1 / operand_2);
773 buff[result_dest] = msb;
774 buff[(result_dest+1) & 0xffff] = lsb;
776 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," Loading result %u at %u",
777 result, result_dest);
779 current_address = next_operand_address;
780 goto execute_next_instruction;
782 case SIGCOMP_INSTR_SORT_ASCENDING: /* 11 SORT-ASCENDING (%start, %n, %k) */
784 * used_udvm_cycles = 1 + k * (ceiling(log2(k)) + n)
787 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
788 "Addr: %u ## SORT-ASCENDING(11) (start, n, k))",
791 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Execution of this instruction is NOT implemented");
793 * used_udvm_cycles = 1 + k * (ceiling(log2(k)) + n)
797 case SIGCOMP_INSTR_SORT_DESCENDING: /* 12 SORT-DESCENDING (%start, %n, %k) */
799 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
800 "Addr: %u ## SORT-DESCENDING(12) (start, n, k))",
803 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Execution of this instruction is NOT implemented");
805 * used_udvm_cycles = 1 + k * (ceiling(log2(k)) + n)
808 case SIGCOMP_INSTR_SHA_1: /* 13 SHA-1 (%position, %length, %destination) */
810 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
811 "Addr: %u ## SHA-1(13) (position, length, destination)",
814 operand_address = current_address + 1;
816 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &position);
818 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u position %u",
819 operand_address, position);
821 operand_address = next_operand_address;
824 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &length);
826 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Length %u",
827 operand_address, length);
829 operand_address = next_operand_address;
832 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &ref_destination, &result_dest);
834 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u $destination %u",
835 operand_address, ref_destination);
837 used_udvm_cycles = used_udvm_cycles + length;
841 byte_copy_right = buff[66] << 8;
842 byte_copy_right = byte_copy_right | buff[67];
843 byte_copy_left = buff[64] << 8;
844 byte_copy_left = byte_copy_left | buff[65];
847 proto_tree_add_text(udvm_tree, message_tvb, 0, -1,
848 "byte_copy_right = %u", byte_copy_right);
854 guint16 handle_now = length;
856 if ( k < byte_copy_right && byte_copy_right <= k + (length-n) ){
857 handle_now = byte_copy_right - position;
860 if (k + handle_now >= UDVM_MEMORY_SIZE)
861 goto decompression_failure;
862 sha1_update( &ctx, &buff[k], handle_now );
864 k = ( k + handle_now ) & 0xffff;
865 n = ( n + handle_now ) & 0xffff;
867 if ( k >= byte_copy_right ) {
872 sha1_finish( &ctx, sha1_digest_buf );
876 for ( n=0; n< STATE_BUFFER_SIZE; n++ ) {
878 buff[k] = sha1_digest_buf[n];
880 k = ( k + 1 ) & 0xffff;
883 if ( k == byte_copy_right ){
889 proto_tree_add_text(udvm_tree, message_tvb, 0, -1,
890 "Calculated SHA-1: %s",
891 bytes_to_str(sha1_digest_buf, STATE_BUFFER_SIZE));
894 current_address = next_operand_address;
895 goto execute_next_instruction;
898 case SIGCOMP_INSTR_LOAD: /* 14 LOAD (%address, %value) */
899 if (show_instr_detail_level == 2 ){
900 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
901 "Addr: %u ## LOAD(14) (%%address, %%value)",
904 operand_address = current_address + 1;
906 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &addr);
907 if (show_instr_detail_level == 2 ){
908 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Address %u",
909 operand_address, addr);
911 operand_address = next_operand_address;
913 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &value);
914 if (show_instr_detail_level == 1)
916 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
917 "Addr: %u ## LOAD (%%address=%u, %%value=%u)",
918 current_address, addr, value);
924 buff[(addr + 1) & 0xffff] = lsb;
927 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Value %u",
928 operand_address, value);
929 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," Loading bytes at %u Value %u 0x%x",
932 current_address = next_operand_address;
933 goto execute_next_instruction;
936 case SIGCOMP_INSTR_MULTILOAD: /* 15 MULTILOAD (%address, #n, %value_0, ..., %value_n-1) */
938 * The MULTILOAD instruction sets a contiguous block of 2-byte words in
939 * the UDVM memory to specified values.
940 * Hmm what if the value to load only takes one byte ? Chose to always load two bytes.
942 if (show_instr_detail_level == 2 ){
943 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
944 "Addr: %u ## MULTILOAD(15) (%%address, #n, value_0, ..., value_n-1)",
947 operand_address = current_address + 1;
949 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &addr);
950 if (show_instr_detail_level == 2 ){
951 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Address %u",
952 operand_address, addr);
954 operand_address = next_operand_address;
957 next_operand_address = decode_udvm_literal_operand(buff,operand_address, &n);
958 if (show_instr_detail_level == 2 ){
959 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u n %u",
962 if (show_instr_detail_level == 1)
964 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
965 "Addr: %u ## MULTILOAD (%%address=%u, #n=%u, value_0, ..., value_%d)",
966 current_address, addr, n, n-1);
968 operand_address = next_operand_address;
969 used_udvm_cycles = used_udvm_cycles + n;
973 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &value);
977 if (addr >= UDVM_MEMORY_SIZE - 1)
978 goto decompression_failure;
981 buff[(addr + 1) & 0xffff] = lsb;
984 length = next_operand_address - operand_address;
987 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1, "Addr: %u Value %5u - Loading bytes at %5u Value %5u 0x%x",
988 operand_address, value, addr, value, value);
991 operand_address = next_operand_address;
993 current_address = next_operand_address;
994 goto execute_next_instruction;
998 case SIGCOMP_INSTR_PUSH: /* 16 PUSH (%value) */
999 if (show_instr_detail_level == 2){
1000 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1001 "Addr: %u ## PUSH(16) (value)",
1004 operand_address = current_address + 1;
1006 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &value);
1007 if (show_instr_detail_level == 2){
1008 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Value %u",
1009 operand_address, value);
1011 if (show_instr_detail_level == 1)
1013 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1014 "Addr: %u ## PUSH (value=%u)",
1015 current_address, value);
1017 current_address = next_operand_address;
1019 /* Push the value address onto the stack */
1020 stack_location = (buff[70] << 8) | buff[71];
1021 stack_fill = (buff[stack_location] << 8)
1022 | buff[(stack_location+1) & 0xFFFF];
1023 addr = (stack_location + stack_fill * 2 + 2) & 0xFFFF;
1025 if (addr >= UDVM_MEMORY_SIZE - 1)
1026 goto decompression_failure;
1028 buff[addr] = (value >> 8) & 0x00FF;
1029 buff[(addr+1) & 0xFFFF] = value & 0x00FF;
1031 if (stack_location >= UDVM_MEMORY_SIZE - 1)
1032 goto decompression_failure;
1034 stack_fill = (stack_fill + 1) & 0xFFFF;
1035 buff[stack_location] = (stack_fill >> 8) & 0x00FF;
1036 buff[(stack_location+1) & 0xFFFF] = stack_fill & 0x00FF;
1038 goto execute_next_instruction;
1042 case SIGCOMP_INSTR_POP: /* 17 POP (%address) */
1043 if (show_instr_detail_level == 2){
1044 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1045 "Addr: %u ## POP(16) (value)",
1048 operand_address = current_address + 1;
1050 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &destination);
1051 if (show_instr_detail_level == 2){
1052 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Value %u",
1053 operand_address, destination);
1055 if (show_instr_detail_level == 1)
1057 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1058 "Addr: %u ## POP (address=%u)",
1059 current_address, destination);
1061 current_address = next_operand_address;
1063 /* Pop value from the top of the stack */
1064 stack_location = (buff[70] << 8) | buff[71];
1065 stack_fill = (buff[stack_location] << 8)
1066 | buff[(stack_location+1) & 0xFFFF];
1067 if (stack_fill == 0)
1070 goto decompression_failure;
1073 if (stack_location >= UDVM_MEMORY_SIZE - 1)
1074 goto decompression_failure;
1076 stack_fill = (stack_fill - 1) & 0xFFFF;
1077 buff[stack_location] = (stack_fill >> 8) & 0x00FF;
1078 buff[(stack_location+1) & 0xFFFF] = stack_fill & 0x00FF;
1080 addr = (stack_location + stack_fill * 2 + 2) & 0xFFFF;
1082 if (addr >= UDVM_MEMORY_SIZE - 1)
1083 goto decompression_failure;
1085 value = (buff[addr] << 8)
1086 | buff[(addr+1) & 0xFFFF];
1088 /* ... and store the popped value. */
1089 if (destination >= UDVM_MEMORY_SIZE - 1)
1090 goto decompression_failure;
1091 buff[destination] = (value >> 8) & 0x00FF;
1092 buff[(destination+1) & 0xFFFF] = value & 0x00FF;
1094 goto execute_next_instruction;
1098 case SIGCOMP_INSTR_COPY: /* 18 COPY (%position, %length, %destination) */
1099 if (show_instr_detail_level == 2 ){
1100 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1101 "Addr: %u ## COPY(18) (position, length, destination)",
1104 operand_address = current_address + 1;
1106 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &position);
1107 if (show_instr_detail_level == 2 ){
1108 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u position %u",
1109 operand_address, position);
1111 operand_address = next_operand_address;
1114 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &length);
1115 if (show_instr_detail_level == 2 ){
1116 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Length %u",
1117 operand_address, length);
1119 operand_address = next_operand_address;
1122 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &destination);
1123 if (show_instr_detail_level == 2 ){
1124 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Destination %u",
1125 operand_address, destination);
1127 if (show_instr_detail_level == 1)
1129 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1130 "Addr: %u ## COPY (position=%u, length=%u, destination=%u)",
1131 current_address, position, length, destination);
1133 current_address = next_operand_address;
1137 * The string of bytes is copied in ascending order of memory address,
1138 * respecting the bounds set by byte_copy_left and byte_copy_right.
1139 * More precisely, if a byte is copied from/to Address m then the next
1140 * byte is copied from/to Address n where n is calculated as follows:
1142 * Set k := m + 1 (modulo 2^16)
1143 * If k = byte_copy_right then set n := byte_copy_left, else set n := k
1149 byte_copy_right = buff[66] << 8;
1150 byte_copy_right = byte_copy_right | buff[67];
1151 byte_copy_left = buff[64] << 8;
1152 byte_copy_left = byte_copy_left | buff[65];
1153 if (print_level_2 ){
1154 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
1155 " byte_copy_right = %u", byte_copy_right);
1158 while ( n < length ){
1159 buff[k] = buff[position];
1160 if (print_level_2 ){
1161 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
1162 " Copying value: %u (0x%x) to Addr: %u",
1163 buff[position], buff[position], k);
1165 position = ( position + 1 ) & 0xffff;
1166 k = ( k + 1 ) & 0xffff;
1170 * Check for circular buffer wrapping after the positions are
1171 * incremented. If either started at BCR then they should continue
1172 * to increment beyond BCR.
1174 if ( k == byte_copy_right ){
1177 if ( position == byte_copy_right ){
1178 position = byte_copy_left;
1181 used_udvm_cycles = used_udvm_cycles + length;
1182 goto execute_next_instruction;
1185 case SIGCOMP_INSTR_COPY_LITERAL: /* 19 COPY-LITERAL (%position, %length, $destination) */
1186 if (show_instr_detail_level == 2 ){
1187 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1188 "Addr: %u ## COPY-LITERAL(19) (position, length, $destination)",
1191 operand_address = current_address + 1;
1193 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &position);
1194 if (show_instr_detail_level == 2 ){
1195 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u position %u",
1196 operand_address, position);
1198 operand_address = next_operand_address;
1201 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &length);
1202 if (show_instr_detail_level == 2 ){
1203 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Length %u",
1204 operand_address, length);
1206 operand_address = next_operand_address;
1210 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &ref_destination, &result_dest);
1211 if (show_instr_detail_level == 2 ){
1212 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u destination %u",
1213 operand_address, ref_destination);
1215 if (show_instr_detail_level == 1)
1217 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1218 "Addr: %u ## COPY-LITERAL (position=%u, length=%u, $destination=%u)",
1219 current_address, position, length, ref_destination);
1221 current_address = next_operand_address;
1227 * The string of bytes is copied in ascending order of memory address,
1228 * respecting the bounds set by byte_copy_left and byte_copy_right.
1229 * More precisely, if a byte is copied from/to Address m then the next
1230 * byte is copied from/to Address n where n is calculated as follows:
1232 * Set k := m + 1 (modulo 2^16)
1233 * If k = byte_copy_right then set n := byte_copy_left, else set n := k
1238 k = ref_destination;
1239 byte_copy_right = buff[66] << 8;
1240 byte_copy_right = byte_copy_right | buff[67];
1241 byte_copy_left = buff[64] << 8;
1242 byte_copy_left = byte_copy_left | buff[65];
1243 if (print_level_2 ){
1244 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
1245 " byte_copy_right = %u", byte_copy_right);
1247 while ( n < length ){
1249 buff[k] = buff[position];
1250 if (print_level_2 ){
1251 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
1252 " Copying value: %u (0x%x) to Addr: %u",
1253 buff[position], buff[position], k);
1255 position = ( position + 1 ) & 0xffff;
1256 k = ( k + 1 ) & 0xffff;
1260 * Check for circular buffer wrapping after the positions are
1261 * incremented. It is important that k cannot be left set
1262 * to BCR. Also, if either started at BCR then they should continue
1263 * to increment beyond BCR.
1265 if ( k == byte_copy_right ){
1268 if ( position == byte_copy_right ){
1269 position = byte_copy_left;
1272 buff[result_dest] = k >> 8;
1273 buff[(result_dest + 1) & 0xffff] = k & 0x00ff;
1275 used_udvm_cycles = used_udvm_cycles + length;
1276 goto execute_next_instruction;
1279 case SIGCOMP_INSTR_COPY_OFFSET: /* 20 COPY-OFFSET (%offset, %length, $destination) */
1280 if (show_instr_detail_level == 2 ){
1281 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1282 "Addr: %u ## COPY-OFFSET(20) (offset, length, $destination)",
1285 operand_address = current_address + 1;
1287 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &multy_offset);
1288 if (show_instr_detail_level == 2 ){
1289 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u offset %u",
1290 operand_address, multy_offset);
1292 operand_address = next_operand_address;
1295 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &length);
1296 if (show_instr_detail_level == 2 ){
1297 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Length %u",
1298 operand_address, length);
1300 operand_address = next_operand_address;
1304 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &ref_destination, &result_dest);
1305 if (show_instr_detail_level == 2 ){
1306 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u $destination %u",
1307 operand_address, ref_destination);
1310 if (show_instr_detail_level == 1)
1312 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1313 "Addr: %u ## COPY-OFFSET (offset=%u, length=%u, $destination=%u)",
1314 current_address, multy_offset, length, result_dest);
1316 current_address = next_operand_address;
1318 /* Execute the instruction:
1319 * To derive the value of the position operand, starting at the memory
1320 * address specified by destination, the UDVM counts backwards a total
1321 * of offset memory addresses.
1323 * If the memory address specified in byte_copy_left is reached, the
1324 * next memory address is taken to be (byte_copy_right - 1) modulo 2^16.
1326 byte_copy_left = buff[64] << 8;
1327 byte_copy_left = byte_copy_left | buff[65];
1328 byte_copy_right = buff[66] << 8;
1329 byte_copy_right = byte_copy_right | buff[67];
1332 * In order to work out the position, simple arithmetic is tricky
1333 * to apply because there some nasty corner cases. A simple loop
1334 * is inefficient but the logic is simple.
1336 * FUTURE: This could be optimised.
1338 for (position = ref_destination, i = 0; i < multy_offset; i++)
1340 if ( position == byte_copy_left )
1342 position = (byte_copy_right - 1) & 0xffff;
1346 position = (position - 1) & 0xffff;
1350 if (print_level_2 ){
1351 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
1352 " byte_copy_left = %u byte_copy_right = %u position= %u",
1353 byte_copy_left, byte_copy_right, position);
1355 /* The COPY-OFFSET instruction then behaves as a COPY-LITERAL
1356 * instruction, taking the value of the position operand to be the last
1357 * memory address reached in the above step.
1363 * The string of bytes is copied in ascending order of memory address,
1364 * respecting the bounds set by byte_copy_left and byte_copy_right.
1365 * More precisely, if a byte is copied from/to Address m then the next
1366 * byte is copied from/to Address n where n is calculated as follows:
1368 * Set k := m + 1 (modulo 2^16)
1369 * If k = byte_copy_right then set n := byte_copy_left, else set n := k
1374 k = ref_destination;
1375 if (print_level_2 ){
1376 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
1377 " byte_copy_left = %u byte_copy_right = %u", byte_copy_left, byte_copy_right);
1379 while ( n < length ){
1380 buff[k] = buff[position];
1381 if (print_level_2 ){
1382 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
1383 " Copying value: %5u (0x%x) from Addr: %u to Addr: %u",
1384 buff[position], buff[position],(position), k);
1387 k = ( k + 1 ) & 0xffff;
1388 position = ( position + 1 ) & 0xffff;
1391 * Check for circular buffer wrapping after the positions are
1392 * incremented. It is important that k cannot be left set
1393 * to BCR. Also, if either started at BCR then they should continue
1394 * to increment beyond BCR.
1396 if ( k == byte_copy_right ){
1399 if ( position == byte_copy_right ){
1400 position = byte_copy_left;
1403 buff[result_dest] = k >> 8;
1404 buff[result_dest + 1] = k & 0x00ff;
1405 used_udvm_cycles = used_udvm_cycles + length;
1406 goto execute_next_instruction;
1409 case SIGCOMP_INSTR_MEMSET: /* 21 MEMSET (%address, %length, %start_value, %offset) */
1410 if (show_instr_detail_level == 2 ){
1411 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1412 "Addr: %u ## MEMSET(21) (address, length, start_value, offset)",
1415 operand_address = current_address + 1;
1418 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &addr);
1419 if (show_instr_detail_level == 2 ){
1420 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Address %u",
1421 operand_address, addr);
1423 operand_address = next_operand_address;
1426 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &length);
1427 if (show_instr_detail_level == 2 ){
1428 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Length %u",
1429 operand_address, length);
1431 operand_address = next_operand_address;
1433 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &start_value);
1434 if (show_instr_detail_level == 2 ){
1435 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u start_value %u",
1436 operand_address, start_value);
1438 operand_address = next_operand_address;
1441 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &multy_offset);
1442 if (show_instr_detail_level == 2 ){
1443 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u offset %u",
1444 operand_address, multy_offset);
1446 if (show_instr_detail_level == 1)
1448 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1449 "Addr: %u ## MEMSET (address=%u, length=%u, start_value=%u, offset=%u)",
1450 current_address, addr, length, start_value, multy_offset);
1452 current_address = next_operand_address;
1453 /* exetute the instruction
1454 * The sequence of values used by the MEMSET instruction is specified by
1455 * the following formula:
1457 * Seq[n] := (start_value + n * offset) modulo 256
1461 byte_copy_right = buff[66] << 8;
1462 byte_copy_right = byte_copy_right | buff[67];
1463 byte_copy_left = buff[64] << 8;
1464 byte_copy_left = byte_copy_left | buff[65];
1465 if (print_level_2 ){
1466 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
1467 " byte_copy_left = %u byte_copy_right = %u", byte_copy_left, byte_copy_right);
1469 while ( n < length ){
1470 if ( k == byte_copy_right ){
1473 buff[k] = (start_value + ( n * multy_offset)) & 0xff;
1474 if (print_level_2 ){
1475 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
1476 " Storing value: %u (0x%x) at Addr: %u",
1477 buff[k], buff[k], k);
1479 k = ( k + 1 ) & 0xffff;
1482 used_udvm_cycles = used_udvm_cycles + length;
1483 goto execute_next_instruction;
1487 case SIGCOMP_INSTR_JUMP: /* 22 JUMP (@address) */
1488 if (show_instr_detail_level == 2 ){
1489 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1490 "Addr: %u ## JUMP(22) (@address)",
1493 operand_address = current_address + 1;
1495 /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
1496 /*next_operand_address = */decode_udvm_address_operand(buff,operand_address, &at_address, current_address);
1497 if (show_instr_detail_level == 2 ){
1498 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u @Address %u",
1499 operand_address, at_address);
1501 if (show_instr_detail_level == 1)
1503 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1504 "Addr: %u ## JUMP (@address=%u)",
1505 current_address, at_address);
1507 current_address = at_address;
1508 goto execute_next_instruction;
1511 case SIGCOMP_INSTR_COMPARE: /* 23 */
1512 /* COMPARE (%value_1, %value_2, @address_1, @address_2, @address_3)
1514 if (show_instr_detail_level == 2 ){
1515 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1516 "Addr: %u ## COMPARE(23) (value_1, value_2, @address_1, @address_2, @address_3)",
1519 operand_address = current_address + 1;
1522 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &value_1);
1523 if (show_instr_detail_level == 2 ){
1524 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Value %u",
1525 operand_address, value_1);
1527 operand_address = next_operand_address;
1530 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &value_2);
1531 if (show_instr_detail_level == 2 ){
1532 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Value %u",
1533 operand_address, value_2);
1535 operand_address = next_operand_address;
1538 /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
1539 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &at_address_1);
1540 at_address_1 = ( current_address + at_address_1) & 0xffff;
1541 if (show_instr_detail_level == 2 ){
1542 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u @Address %u",
1543 operand_address, at_address_1);
1545 operand_address = next_operand_address;
1549 /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
1550 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &at_address_2);
1551 at_address_2 = ( current_address + at_address_2) & 0xffff;
1552 if (show_instr_detail_level == 2 ){
1553 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u @Address %u",
1554 operand_address, at_address_2);
1556 operand_address = next_operand_address;
1559 /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
1560 /*next_operand_address = */decode_udvm_multitype_operand(buff, operand_address, &at_address_3);
1561 at_address_3 = ( current_address + at_address_3) & 0xffff;
1562 if (show_instr_detail_level == 2 ){
1563 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u @Address %u",
1564 operand_address, at_address_3);
1566 if (show_instr_detail_level == 1)
1568 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1569 "Addr: %u ## COMPARE (value_1=%u, value_2=%u, @address_1=%u, @address_2=%u, @address_3=%u)",
1570 current_address, value_1, value_2, at_address_1, at_address_2, at_address_3);
1572 /* execute the instruction
1573 * If value_1 < value_2 then the UDVM continues instruction execution at
1574 * the memory address specified by address 1. If value_1 = value_2 then
1575 * it jumps to the address specified by address_2. If value_1 > value_2
1576 * then it jumps to the address specified by address_3.
1578 if ( value_1 < value_2 )
1579 current_address = at_address_1;
1580 if ( value_1 == value_2 )
1581 current_address = at_address_2;
1582 if ( value_1 > value_2 )
1583 current_address = at_address_3;
1584 goto execute_next_instruction;
1587 case SIGCOMP_INSTR_CALL: /* 24 CALL (@address) (PUSH addr )*/
1588 if (show_instr_detail_level == 2){
1589 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1590 "Addr: %u ## CALL(24) (@address) (PUSH addr )",
1593 operand_address = current_address + 1;
1595 next_operand_address = decode_udvm_address_operand(buff,operand_address, &at_address, current_address);
1596 if (show_instr_detail_level == 2 ){
1597 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u @Address %u",
1598 operand_address, at_address);
1600 if (show_instr_detail_level == 1)
1602 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1603 "Addr: %u ## CALL (@address=%u)",
1604 current_address, at_address);
1606 current_address = next_operand_address;
1608 /* Push the current address onto the stack */
1609 stack_location = (buff[70] << 8) | buff[71];
1610 stack_fill = (buff[stack_location] << 8)
1611 | buff[(stack_location+1) & 0xFFFF];
1612 addr = (stack_location + stack_fill * 2 + 2) & 0xFFFF;
1613 if (addr >= UDVM_MEMORY_SIZE - 1)
1614 goto decompression_failure;
1615 buff[addr] = (current_address >> 8) & 0x00FF;
1616 buff[(addr+1) & 0xFFFF] = current_address & 0x00FF;
1618 stack_fill = (stack_fill + 1) & 0xFFFF;
1619 if (stack_location >= UDVM_MEMORY_SIZE - 1)
1620 goto decompression_failure;
1621 buff[stack_location] = (stack_fill >> 8) & 0x00FF;
1622 buff[(stack_location+1) & 0xFFFF] = stack_fill & 0x00FF;
1624 /* ... and jump to the destination address */
1625 current_address = at_address;
1627 goto execute_next_instruction;
1631 case SIGCOMP_INSTR_RETURN: /* 25 POP and return */
1632 if (print_level_1 || show_instr_detail_level == 1){
1633 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1634 "Addr: %u ## POP(25) and return",
1638 /* Pop value from the top of the stack */
1639 stack_location = (buff[70] << 8) | buff[71];
1640 stack_fill = (buff[stack_location] << 8)
1641 | buff[(stack_location+1) & 0xFFFF];
1642 if (stack_fill == 0)
1645 goto decompression_failure;
1648 stack_fill = (stack_fill - 1) & 0xFFFF;
1649 if (stack_location >= UDVM_MEMORY_SIZE - 1)
1650 goto decompression_failure;
1651 buff[stack_location] = (stack_fill >> 8) & 0x00FF;
1652 buff[(stack_location+1) & 0xFFFF] = stack_fill & 0x00FF;
1654 addr = (stack_location + stack_fill * 2 + 2) & 0xFFFF;
1655 at_address = (buff[addr] << 8)
1656 | buff[(addr+1) & 0xFFFF];
1658 /* ... and set the PC to the popped value */
1659 current_address = at_address;
1661 goto execute_next_instruction;
1665 case SIGCOMP_INSTR_SWITCH: /* 26 SWITCH (#n, %j, @address_0, @address_1, ... , @address_n-1) */
1667 * When a SWITCH instruction is encountered the UDVM reads the value of
1668 * j. It then continues instruction execution at the address specified
1671 * Decompression failure occurs if j specifies a value of n or more, or
1672 * if the address lies beyond the overall UDVM memory size.
1674 instruction_address = current_address;
1675 if (print_level_1 ){
1676 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1677 "Addr: %u ## SWITCH (#n, j, @address_0, @address_1, ... , @address_n-1))",
1680 operand_address = current_address + 1;
1682 * Number of addresses in the instruction
1684 next_operand_address = decode_udvm_literal_operand(buff,operand_address, &n);
1685 if (print_level_1 ){
1686 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u n %u",
1687 operand_address, n);
1689 operand_address = next_operand_address;
1691 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &j);
1692 if (print_level_1 ){
1693 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u j %u",
1694 operand_address, j);
1696 operand_address = next_operand_address;
1700 /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
1701 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &at_address_1);
1702 at_address_1 = ( instruction_address + at_address_1) & 0xffff;
1703 if (print_level_1 ){
1704 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u @Address %u",
1705 operand_address, at_address_1);
1708 current_address = at_address_1;
1710 operand_address = next_operand_address;
1713 /* Check decompression failure */
1714 if ( ( j == n ) || ( j > n )){
1716 goto decompression_failure;
1718 if ( current_address > UDVM_MEMORY_SIZE ){
1720 goto decompression_failure;
1722 used_udvm_cycles = used_udvm_cycles + n;
1724 goto execute_next_instruction;
1727 case SIGCOMP_INSTR_CRC: /* 27 CRC (%value, %position, %length, @address) */
1728 if (print_level_1 ){
1729 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1730 "Addr: %u ## CRC (value, position, length, @address)",
1734 operand_address = current_address + 1;
1737 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &value);
1738 if (print_level_1 ){
1739 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Value %u",
1740 operand_address, value);
1742 operand_address = next_operand_address;
1745 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &position);
1746 if (print_level_1 ){
1747 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u position %u",
1748 operand_address, position);
1750 operand_address = next_operand_address;
1753 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &length);
1754 if (print_level_1 ){
1755 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Length %u",
1756 operand_address, length);
1758 operand_address = next_operand_address;
1761 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &at_address);
1762 at_address = ( current_address + at_address) & 0xffff;
1763 if (print_level_1 ){
1764 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u @Address %u",
1765 operand_address, at_address);
1767 /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
1768 used_udvm_cycles = used_udvm_cycles + length;
1772 byte_copy_right = buff[66] << 8;
1773 byte_copy_right = byte_copy_right | buff[67];
1774 byte_copy_left = buff[64] << 8;
1775 byte_copy_left = byte_copy_left | buff[65];
1778 if (print_level_2 ){
1779 proto_tree_add_text(udvm_tree, message_tvb, 0, -1,
1780 "byte_copy_right = %u", byte_copy_right);
1785 guint16 handle_now = length - n;
1787 if ( k < byte_copy_right && byte_copy_right <= k + (length-n) ){
1788 handle_now = byte_copy_right - k;
1791 if (k + handle_now >= UDVM_MEMORY_SIZE)
1792 goto decompression_failure;
1793 result = crc16_ccitt_seed(&buff[k], handle_now, (guint16) (result ^ 0xffff));
1795 k = ( k + handle_now ) & 0xffff;
1796 n = ( n + handle_now ) & 0xffff;
1798 if ( k >= byte_copy_right ) {
1803 result = result ^ 0xffff;
1805 if (print_level_1 ){
1806 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1, "Calculated CRC %u", result);
1808 if (result != value){
1809 current_address = at_address;
1812 current_address = next_operand_address;
1814 goto execute_next_instruction;
1818 case SIGCOMP_INSTR_INPUT_BYTES: /* 28 INPUT-BYTES (%length, %destination, @address) */
1819 if (show_instr_detail_level == 2 ){
1820 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1821 "Addr: %u ## INPUT-BYTES(28) length, destination, @address)",
1824 operand_address = current_address + 1;
1826 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &length);
1827 if (show_instr_detail_level == 2 ){
1828 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Length %u",
1829 operand_address, length);
1831 operand_address = next_operand_address;
1834 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &destination);
1835 if (show_instr_detail_level == 2 ){
1836 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Destination %u",
1837 operand_address, destination);
1839 operand_address = next_operand_address;
1842 /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
1843 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &at_address);
1844 at_address = ( current_address + at_address) & 0xffff;
1845 if (show_instr_detail_level == 2 ){
1846 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u @Address %u",
1847 operand_address, at_address);
1849 if (show_instr_detail_level == 1)
1851 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1852 "Addr: %u ## INPUT-BYTES length=%u, destination=%u, @address=%u)",
1853 current_address, length, destination, at_address);
1855 /* execute the instruction TODO insert checks
1859 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1860 * | byte_copy_left | 64 - 65
1861 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1862 * | byte_copy_right | 66 - 67
1863 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1864 * | input_bit_order | 68 - 69
1865 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1866 * | stack_location | 70 - 71
1867 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1869 * Figure 7: Memory addresses of the UDVM registers
1873 * The string of bytes is copied in ascending order of memory address,
1874 * respecting the bounds set by byte_copy_left and byte_copy_right.
1875 * More precisely, if a byte is copied from/to Address m then the next
1876 * byte is copied from/to Address n where n is calculated as follows:
1878 * Set k := m + 1 (modulo 2^16)
1879 * If k = byte_copy_right then set n := byte_copy_left, else set n := k
1885 byte_copy_right = buff[66] << 8;
1886 byte_copy_right = byte_copy_right | buff[67];
1887 byte_copy_left = buff[64] << 8;
1888 byte_copy_left = byte_copy_left | buff[65];
1889 if (print_level_1 ){
1890 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
1891 " byte_copy_right = %u", byte_copy_right);
1893 /* clear out remaining bits if any */
1896 /* operand_address used as dummy */
1897 while ( n < length ){
1898 if (input_address > ( msg_end - 1)){
1899 current_address = at_address;
1901 goto execute_next_instruction;
1904 if ( k == byte_copy_right ){
1907 octet = tvb_get_guint8(message_tvb, input_address);
1909 if (print_level_1 ){
1910 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
1911 " Loading value: %u (0x%x) at Addr: %u", octet, octet, k);
1915 * If the instruction requests data that lies beyond the end of the
1916 * SigComp message, no data is returned. Instead the UDVM moves program
1917 * execution to the address specified by the address operand.
1921 k = ( k + 1 ) & 0xffff;
1924 used_udvm_cycles = used_udvm_cycles + length;
1925 current_address = next_operand_address;
1926 goto execute_next_instruction;
1928 case SIGCOMP_INSTR_INPUT_BITS:/* 29 INPUT-BITS (%length, %destination, @address) */
1930 * The length operand indicates the requested number of bits.
1931 * Decompression failure occurs if this operand does not lie between 0
1934 * The destination operand specifies the memory address to which the
1935 * compressed data should be copied. Note that the requested bits are
1936 * interpreted as a 2-byte integer ranging from 0 to 2^length - 1, as
1937 * explained in Section 8.2.
1939 * If the instruction requests data that lies beyond the end of the
1940 * SigComp message, no data is returned. Instead the UDVM moves program
1941 * execution to the address specified by the address operand.
1944 if (show_instr_detail_level == 2 ){
1945 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1946 "Addr: %u ## INPUT-BITS(29) (length, destination, @address)",
1949 operand_address = current_address + 1;
1952 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &length);
1953 if (show_instr_detail_level == 2 ){
1954 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u length %u",
1955 operand_address, length);
1957 operand_address = next_operand_address;
1959 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &destination);
1960 if (show_instr_detail_level == 2 ){
1961 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Destination %u",
1962 operand_address, destination);
1964 operand_address = next_operand_address;
1967 /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
1968 next_operand_address = decode_udvm_address_operand(buff,operand_address, &at_address, current_address);
1969 if (show_instr_detail_level == 2 ){
1970 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u @Address %u",
1971 operand_address, at_address);
1973 if (show_instr_detail_level == 1)
1975 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1976 "Addr: %u ## INPUT-BITS length=%u, destination=%u, @address=%u)",
1977 current_address, length, destination, at_address);
1979 current_address = next_operand_address;
1982 * Execute actual instr.
1983 * The input_bit_order register contains the following three flags:
1986 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1987 * | reserved |F|H|P| 68 - 69
1988 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1990 input_bit_order = buff[68] << 8;
1991 input_bit_order = input_bit_order | buff[69];
1993 * If the instruction requests data that lies beyond the end of the
1994 * SigComp message, no data is returned. Instead the UDVM moves program
1995 * execution to the address specified by the address operand.
2000 goto decompression_failure;
2002 if ( input_bit_order > 7 ){
2004 goto decompression_failure;
2008 * Transfer F bit to bit_order to tell decomp dispatcher which bit order to use
2010 bit_order = ( input_bit_order & 0x0004 ) >> 2;
2011 value = decomp_dispatch_get_bits( message_tvb, udvm_tree, bit_order,
2012 buff, &old_input_bit_order, &remaining_bits,
2013 &input_bits, &input_address, length, &result_code, msg_end);
2014 if ( result_code == 11 ){
2015 current_address = at_address;
2016 goto execute_next_instruction;
2019 lsb = value & 0x00ff;
2020 if (destination >= UDVM_MEMORY_SIZE - 1)
2021 goto decompression_failure;
2022 buff[destination] = msb;
2023 buff[(destination + 1) & 0xffff]=lsb;
2024 if (print_level_1 ){
2025 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
2026 " Loading value: %u (0x%x) at Addr: %u, remaining_bits: %u", value, value, destination, remaining_bits);
2029 goto execute_next_instruction;
2031 case SIGCOMP_INSTR_INPUT_HUFFMAN: /* 30 */
2033 * INPUT-HUFFMAN (%destination, @address, #n, %bits_1, %lower_bound_1,
2034 * %upper_bound_1, %uncompressed_1, ... , %bits_n, %lower_bound_n,
2035 * %upper_bound_n, %uncompressed_n)
2037 if (show_instr_detail_level == 2 ){
2038 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2039 "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)",
2042 operand_address = current_address + 1;
2045 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &destination);
2046 if (show_instr_detail_level == 2 ){
2047 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Destination %u",
2048 operand_address, destination);
2050 operand_address = next_operand_address;
2053 /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
2054 next_operand_address = decode_udvm_address_operand(buff,operand_address, &at_address, current_address);
2055 if (show_instr_detail_level == 2 ){
2056 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u @Address %u",
2057 operand_address, at_address);
2059 operand_address = next_operand_address;
2062 next_operand_address = decode_udvm_literal_operand(buff,operand_address, &n);
2063 if (show_instr_detail_level == 2 ){
2064 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u n %u",
2065 operand_address, n);
2067 operand_address = next_operand_address;
2068 if (show_instr_detail_level == 1)
2070 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2071 "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)",
2072 current_address, destination, at_address, n, n, n, n, n);
2075 used_udvm_cycles = used_udvm_cycles + n;
2078 * Note that if n = 0 then the INPUT-HUFFMAN instruction is ignored and
2079 * program execution resumes at the following instruction.
2080 * Decompression failure occurs if (bits_1 + ... + bits_n) > 16.
2082 * In all other cases, the behavior of the INPUT-HUFFMAN instruction is
2085 * 1. Set j := 1 and set H := 0.
2087 * 2. Request bits_j compressed bits. Interpret the returned bits as an
2088 * integer k from 0 to 2^bits_j - 1, as explained in Section 8.2.
2090 * 3. Set H := H * 2^bits_j + k.
2092 * 4. If data is requested that lies beyond the end of the SigComp
2093 * message, terminate the INPUT-HUFFMAN instruction and move program
2094 * execution to the memory address specified by the address operand.
2096 * 5. If (H < lower_bound_j) or (H > upper_bound_j) then set j := j + 1.
2097 * Then go back to Step 2, unless j > n in which case decompression
2100 * 6. Copy (H + uncompressed_j - lower_bound_j) modulo 2^16 to the
2101 * memory address specified by the destination operand.
2105 * The input_bit_order register contains the following three flags:
2108 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2109 * | reserved |F|H|P| 68 - 69
2110 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2112 * Transfer H bit to bit_order to tell decomp dispatcher which bit order to use
2114 input_bit_order = buff[68] << 8;
2115 input_bit_order = input_bit_order | buff[69];
2116 bit_order = ( input_bit_order & 0x0002 ) >> 1;
2121 outside_huffman_boundaries = TRUE;
2122 print_in_loop = print_level_3;
2125 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &bits_n);
2126 if (print_in_loop ){
2127 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u bits_n %u",
2128 operand_address, bits_n);
2130 operand_address = next_operand_address;
2132 /* %lower_bound_n */
2133 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &lower_bound_n);
2134 if (print_in_loop ){
2135 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u lower_bound_n %u",
2136 operand_address, lower_bound_n);
2138 operand_address = next_operand_address;
2139 /* %upper_bound_n */
2140 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &upper_bound_n);
2141 if (print_in_loop ){
2142 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u upper_bound_n %u",
2143 operand_address, upper_bound_n);
2145 operand_address = next_operand_address;
2146 /* %uncompressed_n */
2147 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &uncompressed_n);
2148 if (print_in_loop ){
2149 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u uncompressed_n %u",
2150 operand_address, uncompressed_n);
2152 operand_address = next_operand_address;
2153 /* execute instruction */
2154 if ( outside_huffman_boundaries ) {
2156 * 2. Request bits_j compressed bits. Interpret the returned bits as an
2157 * integer k from 0 to 2^bits_j - 1, as explained in Section 8.2.
2159 k = decomp_dispatch_get_bits( message_tvb, udvm_tree, bit_order,
2160 buff, &old_input_bit_order, &remaining_bits,
2161 &input_bits, &input_address, bits_n, &result_code, msg_end);
2162 if ( result_code == 11 ){
2164 * 4. If data is requested that lies beyond the end of the SigComp
2165 * message, terminate the INPUT-HUFFMAN instruction and move program
2166 * execution to the memory address specified by the address operand.
2168 current_address = at_address;
2169 goto execute_next_instruction;
2173 * 3. Set H := H * 2^bits_j + k.
2174 * [In practice is a shift+OR operation.]
2177 H = (H << bits_n) | k;
2178 if (print_level_3 ){
2179 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," Set H(%u) := H(%u) * 2^bits_j(%u) + k(%u)",
2180 H ,oldH, 1<<bits_n,k);
2184 * 5. If (H < lower_bound_j) or (H > upper_bound_j) then set j := j + 1.
2185 * Then go back to Step 2, unless j > n in which case decompression
2188 if ((H < lower_bound_n) || (H > upper_bound_n)){
2189 outside_huffman_boundaries = TRUE;
2191 outside_huffman_boundaries = FALSE;
2192 print_in_loop = FALSE;
2194 * 6. Copy (H + uncompressed_j - lower_bound_j) modulo 2^16 to the
2195 * memory address specified by the destination operand.
2197 if (print_level_2 ){
2198 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2199 " H(%u) = H(%u) + uncompressed_n(%u) - lower_bound_n(%u)",
2200 (H + uncompressed_n - lower_bound_n ),H, uncompressed_n, lower_bound_n);
2202 H = H + uncompressed_n - lower_bound_n;
2205 if (destination >= UDVM_MEMORY_SIZE - 1)
2206 goto decompression_failure;
2207 buff[destination] = msb;
2208 buff[(destination + 1) & 0xffff]=lsb;
2209 if (print_level_1 ){
2210 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
2211 " Loading H: %u (0x%x) at Addr: %u,j = %u remaining_bits: %u",
2212 H, H, destination,( n - m + 1 ), remaining_bits);
2221 if ( outside_huffman_boundaries ) {
2223 goto decompression_failure;
2226 current_address = next_operand_address;
2227 goto execute_next_instruction;
2230 case SIGCOMP_INSTR_STATE_ACCESS: /* 31 */
2231 /* STATE-ACCESS (%partial_identifier_start, %partial_identifier_length,
2232 * %state_begin, %state_length, %state_address, %state_instruction)
2234 if (show_instr_detail_level == 2 ){
2235 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2236 "Addr: %u ## STATE-ACCESS(31) (partial_identifier_start, partial_identifier_length,state_begin, state_length, state_address, state_instruction)",
2239 operand_address = current_address + 1;
2242 * %partial_identifier_start
2244 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &p_id_start);
2245 if (show_instr_detail_level == 2 ){
2246 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u partial_identifier_start %u",
2247 operand_address, p_id_start);
2251 * %partial_identifier_length
2253 operand_address = next_operand_address;
2254 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &p_id_length);
2255 if (show_instr_detail_level == 2 ){
2256 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u partial_identifier_length %u",
2257 operand_address, p_id_length);
2262 operand_address = next_operand_address;
2263 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_begin);
2264 if (show_instr_detail_level == 2 ){
2265 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_begin %u",
2266 operand_address, state_begin);
2271 operand_address = next_operand_address;
2272 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_length);
2273 if (show_instr_detail_level == 2 ){
2274 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_length %u",
2275 operand_address, state_length);
2280 operand_address = next_operand_address;
2281 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_address);
2282 if (show_instr_detail_level == 2 ){
2283 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_address %u",
2284 operand_address, state_address);
2287 * %state_instruction
2289 operand_address = next_operand_address;
2290 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_instruction);
2291 if (show_instr_detail_level == 2 ){
2292 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_instruction %u",
2293 operand_address, state_instruction);
2295 if (show_instr_detail_level == 1)
2297 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2298 "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)",
2299 current_address, p_id_start, p_id_length, state_begin, state_length, state_address, state_instruction);
2301 current_address = next_operand_address;
2302 byte_copy_right = buff[66] << 8;
2303 byte_copy_right = byte_copy_right | buff[67];
2304 byte_copy_left = buff[64] << 8;
2305 byte_copy_left = byte_copy_left | buff[65];
2306 if (print_level_2 ){
2307 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
2308 " byte_copy_right = %u, byte_copy_left = %u", byte_copy_right,byte_copy_left);
2311 result_code = udvm_state_access(message_tvb, udvm_tree, buff, p_id_start, p_id_length, state_begin, &state_length,
2312 &state_address, &state_instruction, hf_id);
2313 if ( result_code != 0 ){
2314 goto decompression_failure;
2316 used_udvm_cycles = used_udvm_cycles + state_length;
2317 goto execute_next_instruction;
2319 case SIGCOMP_INSTR_STATE_CREATE: /* 32 */
2321 * STATE-CREATE (%state_length, %state_address, %state_instruction,
2322 * %minimum_access_length, %state_retention_priority)
2324 if (show_instr_detail_level == 2 ){
2325 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2326 "Addr: %u ## STATE-CREATE(32) (state_length, state_address, state_instruction,minimum_access_length, state_retention_priority)",
2329 operand_address = current_address + 1;
2334 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_length);
2335 if (show_instr_detail_level == 2 ){
2336 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_length %u",
2337 operand_address, state_length);
2342 operand_address = next_operand_address;
2343 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_address);
2344 if (show_instr_detail_level == 2 ){
2345 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_address %u",
2346 operand_address, state_address);
2349 * %state_instruction
2351 operand_address = next_operand_address;
2352 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_instruction);
2353 if (show_instr_detail_level == 2 ){
2354 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_instruction %u",
2355 operand_address, state_instruction);
2358 * %minimum_access_length
2360 operand_address = next_operand_address;
2361 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &minimum_access_length);
2362 if (show_instr_detail_level == 2 ){
2363 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u minimum_access_length %u",
2364 operand_address, minimum_access_length);
2367 * %state_retention_priority
2369 operand_address = next_operand_address;
2370 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_retention_priority);
2371 if (show_instr_detail_level == 2 ){
2372 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_retention_priority %u",
2373 operand_address, state_retention_priority);
2375 if (show_instr_detail_level == 1)
2377 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2378 "Addr: %u ## STATE-CREATE(32) (state_length=%u, state_address=%u, state_instruction=%u,minimum_access_length=%u, state_retention_priority=%u)",
2379 current_address, state_length, state_address, state_instruction,minimum_access_length, state_retention_priority);
2381 current_address = next_operand_address;
2382 /* Execute the instruction
2383 * TODO Implement the instruction
2385 * Note that the new state item cannot be created until a valid
2386 * compartment identifier has been returned by the application.
2387 * Consequently, when a STATE-CREATE instruction is encountered the UDVM
2388 * simply buffers the five supplied operands until the END-MESSAGE
2389 * instruction is reached. The steps taken at this point are described
2392 * Decompression failure MUST occur if more than four state creation
2393 * requests are made before the END-MESSAGE instruction is encountered.
2394 * Decompression failure also occurs if the minimum_access_length does
2395 * not lie between 6 and 20 inclusive, or if the
2396 * state_retention_priority is 65535.
2398 no_of_state_create++;
2399 if ( no_of_state_create > 4 ){
2401 goto decompression_failure;
2403 if (( minimum_access_length < 6 ) || ( minimum_access_length > STATE_BUFFER_SIZE )){
2405 goto decompression_failure;
2407 if ( state_retention_priority == 65535 ){
2409 goto decompression_failure;
2411 state_length_buff[no_of_state_create] = state_length;
2412 state_address_buff[no_of_state_create] = state_address;
2413 state_instruction_buff[no_of_state_create] = state_instruction;
2414 state_minimum_access_length_buff[no_of_state_create] = minimum_access_length;
2415 /* state_state_retention_priority_buff[no_of_state_create] = state_retention_priority; */
2416 used_udvm_cycles = used_udvm_cycles + state_length;
2418 byte_copy_right = buff[66] << 8;
2419 byte_copy_right = byte_copy_right | buff[67];
2420 byte_copy_left = buff[64] << 8;
2421 byte_copy_left = byte_copy_left | buff[65];
2424 while ( n < state_length ){
2425 if ( k == byte_copy_right ){
2430 if (print_level_3 ){
2431 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2432 " Addr: %5u State value: %u (0x%x) ASCII(%s)",
2433 k,buff[k],buff[k],format_text(string, 1));
2435 k = ( k + 1 ) & 0xffff;
2440 goto execute_next_instruction;
2442 case SIGCOMP_INSTR_STATE_FREE: /* 33 */
2444 * STATE-FREE (%partial_identifier_start, %partial_identifier_length)
2446 if (show_instr_detail_level == 2 ){
2447 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2448 "Addr: %u ## STATE-FREE (partial_identifier_start, partial_identifier_length)",
2451 operand_address = current_address + 1;
2453 * %partial_identifier_start
2455 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &p_id_start);
2456 if (show_instr_detail_level == 2 ){
2457 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u partial_identifier_start %u",
2458 operand_address, p_id_start);
2460 operand_address = next_operand_address;
2463 * %partial_identifier_length
2465 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &p_id_length);
2466 if (show_instr_detail_level == 2 ){
2467 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u partial_identifier_length %u",
2468 operand_address, p_id_length);
2470 if (show_instr_detail_level == 1)
2472 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2473 "Addr: %u ## STATE-FREE (partial_identifier_start=%u, partial_identifier_length=%u)",
2474 current_address, p_id_start, p_id_length);
2476 current_address = next_operand_address;
2478 /* Execute the instruction:
2481 udvm_state_free(buff,p_id_start,p_id_length);
2483 goto execute_next_instruction;
2485 case SIGCOMP_INSTR_OUTPUT: /* 34 OUTPUT (%output_start, %output_length) */
2486 if (show_instr_detail_level == 2 ){
2487 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2488 "Addr: %u ## OUTPUT(34) (output_start, output_length)",
2491 operand_address = current_address + 1;
2495 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &output_start);
2496 if (show_instr_detail_level == 2 ){
2497 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u output_start %u",
2498 operand_address, output_start);
2500 operand_address = next_operand_address;
2504 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &output_length);
2505 if (show_instr_detail_level == 2 ){
2506 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u output_length %u",
2507 operand_address, output_length);
2509 if (show_instr_detail_level == 1)
2511 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2512 "Addr: %u ## OUTPUT (output_start=%u, output_length=%u)",
2513 current_address, output_start, output_length);
2515 current_address = next_operand_address;
2518 * Execute instruction
2521 * The string of bytes is copied in ascending order of memory address,
2522 * respecting the bounds set by byte_copy_left and byte_copy_right.
2523 * More precisely, if a byte is copied from/to Address m then the next
2524 * byte is copied from/to Address n where n is calculated as follows:
2526 * Set k := m + 1 (modulo 2^16)
2527 * If k = byte_copy_right then set n := byte_copy_left, else set n := k
2533 byte_copy_right = buff[66] << 8;
2534 byte_copy_right = byte_copy_right | buff[67];
2535 byte_copy_left = buff[64] << 8;
2536 byte_copy_left = byte_copy_left | buff[65];
2537 if (print_level_3 ){
2538 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2539 " byte_copy_right = %u", byte_copy_right);
2541 while ( n < output_length ){
2543 if ( k == byte_copy_right ){
2546 out_buff[output_address] = buff[k];
2549 if (print_level_3 ){
2550 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2551 " Output value: %u (0x%x) ASCII(%s) from Addr: %u ,output to dispatcher position %u",
2552 buff[k],buff[k],format_text(string,1), k,output_address);
2554 k = ( k + 1 ) & 0xffff;
2558 used_udvm_cycles = used_udvm_cycles + output_length;
2559 goto execute_next_instruction;
2561 case SIGCOMP_INSTR_END_MESSAGE: /* 35 */
2563 * END-MESSAGE (%requested_feedback_location,
2564 * %returned_parameters_location, %state_length, %state_address,
2565 * %state_instruction, %minimum_access_length,
2566 * %state_retention_priority)
2568 if (show_instr_detail_level == 2 ){
2569 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2570 "Addr: %u ## END-MESSAGE (requested_feedback_location,state_instruction, minimum_access_length,state_retention_priority)",
2573 operand_address = current_address + 1;
2575 /* %requested_feedback_location */
2576 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &requested_feedback_location);
2577 if (show_instr_detail_level == 2 ){
2578 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u requested_feedback_location %u",
2579 operand_address, requested_feedback_location);
2581 operand_address = next_operand_address;
2582 /* returned_parameters_location */
2583 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &returned_parameters_location);
2584 if (show_instr_detail_level == 2 ){
2585 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u returned_parameters_location %u",
2586 operand_address, returned_parameters_location);
2591 operand_address = next_operand_address;
2592 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_length);
2593 if (show_instr_detail_level == 2 ){
2594 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_length %u",
2595 operand_address, state_length);
2600 operand_address = next_operand_address;
2601 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_address);
2602 if (show_instr_detail_level == 2 ){
2603 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_address %u",
2604 operand_address, state_address);
2607 * %state_instruction
2609 operand_address = next_operand_address;
2610 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_instruction);
2611 if (show_instr_detail_level == 2 ){
2612 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_instruction %u",
2613 operand_address, state_instruction);
2617 * %minimum_access_length
2619 operand_address = next_operand_address;
2620 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &minimum_access_length);
2621 if (show_instr_detail_level == 2 ){
2622 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u minimum_access_length %u",
2623 operand_address, minimum_access_length);
2627 * %state_retention_priority
2629 operand_address = next_operand_address;
2630 /*next_operand_address =*/ decode_udvm_multitype_operand(buff, operand_address, &state_retention_priority);
2631 if (show_instr_detail_level == 2 ){
2632 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_retention_priority %u",
2633 operand_address, state_retention_priority);
2635 if (show_instr_detail_level == 1)
2637 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2638 "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)",
2639 current_address, requested_feedback_location, returned_parameters_location, state_length, state_address, state_instruction, minimum_access_length,state_retention_priority);
2641 /* TODO: This isn't currently totaly correct as END_INSTRUCTION might not create state */
2642 no_of_state_create++;
2643 if ( no_of_state_create > 4 ){
2645 goto decompression_failure;
2647 state_length_buff[no_of_state_create] = state_length;
2648 state_address_buff[no_of_state_create] = state_address;
2649 state_instruction_buff[no_of_state_create] = state_instruction;
2651 state_minimum_access_length_buff[no_of_state_create] = minimum_access_length;
2652 /* state_state_retention_priority_buff[no_of_state_create] = state_retention_priority; */
2654 /* Execute the instruction
2656 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"no_of_state_create %u",no_of_state_create);
2657 if ( no_of_state_create != 0 ){
2658 memset(sha1_digest_buf, 0, STATE_BUFFER_SIZE);
2660 byte_copy_right = buff[66] << 8;
2661 byte_copy_right = byte_copy_right | buff[67];
2662 byte_copy_left = buff[64] << 8;
2663 byte_copy_left = byte_copy_left | buff[65];
2664 while ( n < no_of_state_create + 1 ){
2665 sha1buff = (guint8 *)g_malloc(state_length_buff[n]+8);
2666 sha1buff[0] = state_length_buff[n] >> 8;
2667 sha1buff[1] = state_length_buff[n] & 0xff;
2668 sha1buff[2] = state_address_buff[n] >> 8;
2669 sha1buff[3] = state_address_buff[n] & 0xff;
2670 sha1buff[4] = state_instruction_buff[n] >> 8;
2671 sha1buff[5] = state_instruction_buff[n] & 0xff;
2672 sha1buff[6] = state_minimum_access_length_buff[n] >> 8;
2673 sha1buff[7] = state_minimum_access_length_buff[n] & 0xff;
2674 if (print_level_3 ){
2675 for( x=0; x < 8; x++){
2676 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"sha1buff %u 0x%x",
2680 k = state_address_buff[n];
2681 for( x=0; x < state_length_buff[n]; x++)
2683 if ( k == byte_copy_right ){
2686 sha1buff[8+x] = buff[k];
2687 k = ( k + 1 ) & 0xffff;
2690 sha1_starts( &ctx );
2691 sha1_update( &ctx, (guint8 *) sha1buff, state_length_buff[n] + 8);
2692 sha1_finish( &ctx, sha1_digest_buf );
2693 if (print_level_3 ){
2694 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"SHA1 digest %s",bytes_to_str(sha1_digest_buf, STATE_BUFFER_SIZE));
2697 /* begin partial state-id change cco@iptel.org */
2699 udvm_state_create(sha1buff, sha1_digest_buf, state_minimum_access_length_buff[n]);
2701 udvm_state_create(sha1buff, sha1_digest_buf, STATE_MIN_ACCESS_LEN);
2702 /* end partial state-id change cco@iptel.org */
2703 proto_tree_add_text(udvm_tree,bytecode_tvb, 0, -1,"### Creating state ###");
2704 proto_tree_add_string(udvm_tree,hf_id, bytecode_tvb, 0, 0, bytes_to_str(sha1_digest_buf, state_minimum_access_length_buff[n]));
2713 /* At least something got decompressed, show it */
2714 decomp_tvb = tvb_new_child_real_data(message_tvb, out_buff,output_address,output_address);
2715 /* Arrange that the allocated packet data copy be freed when the
2718 tvb_set_free_cb( decomp_tvb, g_free );
2720 add_new_data_source(pinfo, decomp_tvb, "Decompressed SigComp message");
2722 proto_tree_add_text(udvm_tree, decomp_tvb, 0, -1,"SigComp message Decompressed");
2724 used_udvm_cycles = used_udvm_cycles + state_length;
2725 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"maximum_UDVM_cycles %u used_udvm_cycles %u",
2726 maximum_UDVM_cycles, used_udvm_cycles);
2731 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," ### Addr %u Invalid instruction: %u (0x%x)",
2732 current_address,current_instruction,current_instruction);
2737 decompression_failure:
2739 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"DECOMPRESSION FAILURE: %s",
2740 val_to_str(result_code, result_code_vals,"Unknown (%u)"));
2741 THROW(ReportedBoundsError);
2747 /* The simplest operand type is the literal (#), which encodes a
2748 * constant integer from 0 to 65535 inclusive. A literal operand may
2749 * require between 1 and 3 bytes depending on its value.
2750 * Bytecode: Operand value: Range:
2751 * 0nnnnnnn N 0 - 127
2752 * 10nnnnnn nnnnnnnn N 0 - 16383
2753 * 11000000 nnnnnnnn nnnnnnnn N 0 - 65535
2755 * Figure 8: Bytecode for a literal (#) operand
2759 decode_udvm_literal_operand(guint8 *buff,guint operand_address, guint16 *value)
2764 guint offset = operand_address;
2767 bytecode = buff[operand_address];
2768 test_bits = bytecode >> 7;
2769 if (test_bits == 1){
2770 test_bits = bytecode >> 6;
2771 if (test_bits == 2){
2773 * 10nnnnnn nnnnnnnn N 0 - 16383
2775 temp_data = buff[operand_address] & 0x1f;
2776 operand = temp_data << 8;
2777 temp_data = buff[(operand_address + 1) & 0xffff];
2778 operand = operand | temp_data;
2780 offset = offset + 2;
2784 * 111000000 nnnnnnnn nnnnnnnn N 0 - 65535
2787 temp_data = buff[operand_address] & 0x1f;
2788 operand = temp_data << 8;
2789 temp_data = buff[(operand_address + 1) & 0xffff];
2790 operand = operand | temp_data;
2792 offset = offset + 2;
2797 * 0nnnnnnn N 0 - 127
2799 operand = ( bytecode & 0x7f);
2809 * The second operand type is the reference ($), which is always used to
2810 * access a 2-byte value located elsewhere in the UDVM memory. The
2811 * bytecode for a reference operand is decoded to be a constant integer
2812 * from 0 to 65535 inclusive, which is interpreted as the memory address
2813 * containing the actual value of the operand.
2814 * Bytecode: Operand value: Range:
2816 * 0nnnnnnn memory[2 * N] 0 - 65535
2817 * 10nnnnnn nnnnnnnn memory[2 * N] 0 - 65535
2818 * 11000000 nnnnnnnn nnnnnnnn memory[N] 0 - 65535
2820 * Figure 9: Bytecode for a reference ($) operand
2823 dissect_udvm_reference_operand(guint8 *buff,guint operand_address, guint16 *value,guint *result_dest)
2827 guint offset = operand_address;
2830 guint16 temp_data16;
2832 bytecode = buff[operand_address];
2833 test_bits = bytecode >> 7;
2834 if (test_bits == 1){
2835 test_bits = bytecode >> 6;
2836 if (test_bits == 2){
2838 * 10nnnnnn nnnnnnnn memory[2 * N] 0 - 65535
2840 temp_data = buff[operand_address] & 0x3f;
2841 operand = temp_data << 8;
2842 temp_data = buff[(operand_address + 1) & 0xffff];
2843 operand = operand | temp_data;
2844 operand = (operand * 2);
2845 *result_dest = operand;
2846 temp_data16 = buff[operand] << 8;
2847 temp_data16 = temp_data16 | buff[(operand+1) & 0xffff];
2848 *value = temp_data16;
2849 offset = offset + 2;
2853 * 11000000 nnnnnnnn nnnnnnnn memory[N] 0 - 65535
2856 operand = buff[operand_address] << 8;
2857 operand = operand | buff[(operand_address + 1) & 0xffff];
2858 *result_dest = operand;
2859 temp_data16 = buff[operand] << 8;
2860 temp_data16 = temp_data16 | buff[(operand+1) & 0xffff];
2861 *value = temp_data16;
2862 offset = offset + 3;
2867 * 0nnnnnnn memory[2 * N] 0 - 65535
2869 operand = ( bytecode & 0x7f);
2870 operand = (operand * 2);
2871 *result_dest = operand;
2872 temp_data16 = buff[operand] << 8;
2873 temp_data16 = temp_data16 | buff[(operand+1) & 0xffff];
2874 *value = temp_data16;
2878 if (offset >= UDVM_MEMORY_SIZE || *result_dest >= UDVM_MEMORY_SIZE - 1 )
2879 THROW(ReportedBoundsError);
2885 * Figure 10: Bytecode for a multitype (%) operand
2886 * Bytecode: Operand value: Range: HEX val
2887 * 00nnnnnn N 0 - 63 0x00
2888 * 01nnnnnn memory[2 * N] 0 - 65535 0x40
2889 * 1000011n 2 ^ (N + 6) 64 , 128 0x86
2890 * 10001nnn 2 ^ (N + 8) 256 , ... , 32768 0x88
2891 * 111nnnnn N + 65504 65504 - 65535 0xe0
2892 * 1001nnnn nnnnnnnn N + 61440 61440 - 65535 0x90
2893 * 101nnnnn nnnnnnnn N 0 - 8191 0xa0
2894 * 110nnnnn nnnnnnnn memory[N] 0 - 65535 0xc0
2895 * 10000000 nnnnnnnn nnnnnnnn N 0 - 65535 0x80
2896 * 10000001 nnnnnnnn nnnnnnnn memory[N] 0 - 65535 0x81
2899 decode_udvm_multitype_operand(guint8 *buff,guint operand_address, guint16 *value)
2903 guint offset = operand_address;
2907 guint16 temp_data16;
2908 guint16 memmory_addr = 0;
2912 bytecode = buff[operand_address];
2913 test_bits = ( bytecode & 0xc0 ) >> 6;
2914 switch (test_bits ){
2919 operand = buff[operand_address];
2921 *g_warning("Reading 0x%x From address %u",operand,offset);
2928 * 01nnnnnn memory[2 * N] 0 - 65535
2930 memmory_addr = ( bytecode & 0x3f) * 2;
2931 temp_data16 = buff[memmory_addr] << 8;
2932 temp_data16 = temp_data16 | buff[(memmory_addr+1) & 0xffff];
2933 *value = temp_data16;
2937 /* Check tree most significant bits */
2938 test_bits = ( bytecode & 0xe0 ) >> 5;
2939 if ( test_bits == 5 ){
2941 * 101nnnnn nnnnnnnn N 0 - 8191
2943 temp_data = buff[operand_address] & 0x1f;
2944 operand = temp_data << 8;
2945 temp_data = buff[(operand_address + 1) & 0xffff];
2946 operand = operand | temp_data;
2948 offset = offset + 2;
2950 test_bits = ( bytecode & 0xf0 ) >> 4;
2951 if ( test_bits == 9 ){
2953 * 1001nnnn nnnnnnnn N + 61440 61440 - 65535
2955 temp_data = buff[operand_address] & 0x0f;
2956 operand = temp_data << 8;
2957 temp_data = buff[(operand_address + 1) & 0xffff];
2958 operand = operand | temp_data;
2959 operand = operand + 61440;
2961 offset = offset + 2;
2963 test_bits = ( bytecode & 0x08 ) >> 3;
2964 if ( test_bits == 1){
2966 * 10001nnn 2 ^ (N + 8) 256 , ... , 32768
2969 result = 1 << ((buff[operand_address] & 0x07) + 8);
2970 operand = result & 0xffff;
2974 test_bits = ( bytecode & 0x0e ) >> 1;
2975 if ( test_bits == 3 ){
2977 * 1000 011n 2 ^ (N + 6) 64 , 128
2979 result = 1 << ((buff[operand_address] & 0x01) + 6);
2980 operand = result & 0xffff;
2985 * 1000 0000 nnnnnnnn nnnnnnnn N 0 - 65535
2986 * 1000 0001 nnnnnnnn nnnnnnnn memory[N] 0 - 65535
2989 temp_data16 = buff[(operand_address + 1) & 0xffff] << 8;
2990 temp_data16 = temp_data16 | buff[(operand_address + 2) & 0xffff];
2992 * g_warning("Reading 0x%x From address %u",temp_data16,operand_address);
2994 if ( (bytecode & 0x01) == 1 ){
2995 memmory_addr = temp_data16;
2996 temp_data16 = buff[memmory_addr] << 8;
2997 temp_data16 = temp_data16 | buff[(memmory_addr+1) & 0xffff];
2999 *value = temp_data16;
3010 test_bits = ( bytecode & 0x20 ) >> 5;
3011 if ( test_bits == 1 ){
3013 * 111nnnnn N + 65504 65504 - 65535
3015 operand = ( buff[operand_address] & 0x1f) + 65504;
3020 * 110nnnnn nnnnnnnn memory[N] 0 - 65535
3022 memmory_addr = buff[operand_address] & 0x1f;
3023 memmory_addr = memmory_addr << 8;
3024 memmory_addr = memmory_addr | buff[(operand_address + 1) & 0xffff];
3025 temp_data16 = buff[memmory_addr] << 8;
3026 temp_data16 = temp_data16 | buff[(memmory_addr+1) & 0xffff];
3027 *value = temp_data16;
3029 * g_warning("Reading 0x%x From address %u",temp_data16,memmory_addr);
3041 * The fourth operand type is the address (@). This operand is decoded
3042 * as a multitype operand followed by a further step: the memory address
3043 * of the UDVM instruction containing the address operand is added to
3044 * obtain the correct operand value. So if the operand value from
3045 * Figure 10 is D then the actual operand value of an address is
3046 * calculated as follows:
3048 * operand_value = (memory_address_of_instruction + D) modulo 2^16
3050 * Address operands are always used in instructions that control program
3051 * flow, because they ensure that the UDVM bytecode is position-
3052 * independent code (i.e., it will run independently of where it is
3053 * placed in the UDVM memory).
3056 decode_udvm_address_operand(guint8 *buff,guint operand_address, guint16 *value,guint current_address)
3060 guint next_opreand_address;
3062 next_opreand_address = decode_udvm_multitype_operand(buff, operand_address, &value1);
3063 result = value1 & 0xffff;
3064 result = result + current_address;
3065 *value = result & 0xffff;
3066 return next_opreand_address;
3071 * This is a lookup table used to reverse the bits in a byte.
3073 static guint8 reverse [] = {
3074 0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0,
3075 0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0,
3076 0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8,
3077 0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8,
3078 0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4,
3079 0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4,
3080 0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC,
3081 0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC,
3082 0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2,
3083 0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2,
3084 0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA,
3085 0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA,
3086 0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6,
3087 0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6,
3088 0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE,
3089 0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE,
3090 0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1,
3091 0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1,
3092 0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9,
3093 0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9,
3094 0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5,
3095 0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5,
3096 0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED,
3097 0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD,
3098 0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3,
3099 0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3,
3100 0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB,
3101 0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB,
3102 0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7,
3103 0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7,
3104 0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF,
3105 0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF
3110 decomp_dispatch_get_bits(
3111 tvbuff_t *message_tvb,
3112 proto_tree *udvm_tree,
3115 guint16 *old_input_bit_order,
3116 guint16 *remaining_bits,
3117 guint16 *input_bits,
3118 guint *input_address,
3120 guint16 *result_code,
3123 guint16 input_bit_order;
3124 guint16 bits_still_required = length;
3127 gint extra_bytes_available = msg_end - *input_address;
3129 gint prev_p_bit = *old_input_bit_order & 0x0001;
3130 gint bits_to_use = 0;
3133 input_bit_order = buff[68] << 8;
3134 input_bit_order = input_bit_order | buff[69];
3136 p_bit = (input_bit_order & 0x0001) != 0;
3139 * Discard any spare bits.
3140 * Note: We take care to avoid remaining_bits having the value of 8.
3142 if (prev_p_bit != p_bit)
3144 *remaining_bits = 0;
3145 *old_input_bit_order = input_bit_order;
3149 * Check we can suppy the required number of bits now, before we alter
3150 * the input buffer's state.
3152 if (*remaining_bits + extra_bytes_available * 8 < length)
3158 /* Note: This is never called with length > 16, so the following loop
3159 * never loops more than three time. */
3160 while (bits_still_required > 0)
3163 * We only put anything into input_bits if we know we will remove
3164 * at least one bit. That ensures we can simply discard the spare
3165 * bits if the P-bit changes.
3167 if (*remaining_bits == 0)
3169 octet = tvb_get_guint8(message_tvb, *input_address);
3170 if (print_level_1 ){
3171 proto_tree_add_text(udvm_tree, message_tvb, *input_address , 1,
3172 " Getting value: %u (0x%x) From Addr: %u", octet, octet, *input_address);
3174 *input_address = *input_address + 1;
3178 octet = reverse[octet];
3180 *input_bits = octet;
3181 *remaining_bits = 8;
3184 /* Add some more bits to the accumulated value. */
3185 bits_to_use = bits_still_required < *remaining_bits ? bits_still_required : *remaining_bits;
3186 bits_still_required -= bits_to_use;
3188 *input_bits <<= bits_to_use; /* Shift bits into MSByte */
3189 value = (value << bits_to_use) /* Then add to the accumulated value */
3190 | ((*input_bits >> 8) & 0xFF);
3191 *remaining_bits -= bits_to_use;
3192 *input_bits &= 0x00FF; /* Leave just the remaining bits */
3197 /* Bit reverse the entire word. */
3198 guint16 lsb = reverse[(value >> 8) & 0xFF];
3199 guint16 msb = reverse[value & 0xFF];
3201 value = ((msb << 8) | lsb) >> (16 - length);