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 * Ethereal - Network traffic analyzer
9 * By Gerald Combs <gerald@ethereal.com>
10 * Copyright 1998 Gerald Combs
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
26 * http://www.ietf.org/rfc/rfc3320.txt?number=3320
27 * http://www.ietf.org/rfc/rfc3321.txt?number=3321
29 * http://www.ietf.org/internet-drafts/draft-ietf-rohc-sigcomp-impl-guide-05.txt
30 * http://www.ietf.org/internet-drafts/draft-ietf-rohc-sigcomp-sip-01.txt
44 #include "sigcomp-udvm.h"
45 #include "sigcomp_state_hdlr.h"
50 #define SIGCOMP_INSTR_DECOMPRESSION_FAILURE 0
51 #define SIGCOMP_INSTR_AND 1
52 #define SIGCOMP_INSTR_OR 2
53 #define SIGCOMP_INSTR_NOT 3
54 #define SIGCOMP_INSTR_LSHIFT 4
55 #define SIGCOMP_INSTR_RSHIFT 5
56 #define SIGCOMP_INSTR_ADD 6
57 #define SIGCOMP_INSTR_SUBTRACT 7
58 #define SIGCOMP_INSTR_MULTIPLY 8
59 #define SIGCOMP_INSTR_DIVIDE 9
60 #define SIGCOMP_INSTR_REMAINDER 10
61 #define SIGCOMP_INSTR_SORT_ASCENDING 11
62 #define SIGCOMP_INSTR_SORT_DESCENDING 12
63 #define SIGCOMP_INSTR_SHA_1 13
64 #define SIGCOMP_INSTR_LOAD 14
65 #define SIGCOMP_INSTR_MULTILOAD 15
66 #define SIGCOMP_INSTR_PUSH 16
67 #define SIGCOMP_INSTR_POP 17
68 #define SIGCOMP_INSTR_COPY 18
69 #define SIGCOMP_INSTR_COPY_LITERAL 19
70 #define SIGCOMP_INSTR_COPY_OFFSET 20
71 #define SIGCOMP_INSTR_MEMSET 21
72 #define SIGCOMP_INSTR_JUMP 22
73 #define SIGCOMP_INSTR_COMPARE 23
74 #define SIGCOMP_INSTR_CALL 24
75 #define SIGCOMP_INSTR_RETURN 25
76 #define SIGCOMP_INSTR_SWITCH 26
77 #define SIGCOMP_INSTR_CRC 27
78 #define SIGCOMP_INSTR_INPUT_BYTES 28
79 #define SIGCOMP_INSTR_INPUT_BITS 29
80 #define SIGCOMP_INSTR_INPUT_HUFFMAN 30
81 #define SIGCOMP_INSTR_STATE_ACCESS 31
82 #define SIGCOMP_INSTR_STATE_CREATE 32
83 #define SIGCOMP_INSTR_STATE_FREE 33
84 #define SIGCOMP_INSTR_OUTPUT 34
85 #define SIGCOMP_INSTR_END_MESSAGE 35
88 static gboolean print_level_1;
89 static gboolean print_level_2;
90 static gboolean print_level_3;
91 static gint show_instr_detail_level;
93 /* Internal result code values of decompression failures */
94 const value_string result_code_vals[] = {
95 { 0, "No decomprssion failure" },
96 { 1, "Partial state length less than 6 or greater than 20 bytes long" },
97 { 2, "No state match" },
98 { 3, "state_begin + state_length > size of state" },
99 { 4, "Operand_2 is Zero" },
100 { 5, "Switch statement failed j >= n" },
101 { 6, "Atempt to jump outside of UDVM memory" },
102 { 7, "L in input-bits > 16" },
103 { 8, "input_bit_order > 7" },
104 { 9, "Instruction Decompression failure encountered" },
105 {10, "Input huffman failed j > n" },
106 {11, "Input bits requested beyond end of message" },
107 {12, "more than four state creation requests are made before the END-MESSAGE instruction" },
108 {13, "state_retention_priority is 65535" },
109 {14, "Input bytes requested beond end of message" },
110 {15, "Maximum number of UDVM cycles reached" },
111 {16, "UDVM stack underflow" },
112 { 255, "This branch isn't coded yet" },
116 static int decode_udvm_literal_operand(guint8 *buff,guint operand_address, guint16 *value);
117 static int dissect_udvm_reference_operand(guint8 *buff,guint operand_address, guint16 *value, guint *result_dest);
118 static int decode_udvm_multitype_operand(guint8 *buff,guint operand_address,guint16 *value);
119 static int decode_udvm_address_operand(guint8 *buff,guint operand_address, guint16 *value,guint current_address);
120 static int decomp_dispatch_get_bits(tvbuff_t *message_tvb,proto_tree *udvm_tree,guint8 bit_order,
121 guint8 *buff,guint16 *old_input_bit_order, guint16 *remaining_bits,
122 guint16 *input_bits, guint *input_address, guint16 length, guint16 *result_code,guint msg_end);
126 decompress_sigcomp_message(tvbuff_t *bytecode_tvb, tvbuff_t *message_tvb, packet_info *pinfo,
127 proto_tree *udvm_tree, gint udvm_mem_dest,
128 gint print_flags, gint hf_id,
130 gint byte_code_state_len, gint byte_code_id_len,
133 tvbuff_t *decomp_tvb;
134 guint8 buff[UDVM_MEMORY_SIZE];
136 guint8 *out_buff; /* Largest allowed size for a message is 65535 */
146 guint code_length =0;
147 guint8 current_instruction;
148 guint current_address;
149 guint operand_address;
151 guint16 output_address = 0;
152 guint next_operand_address;
156 guint16 byte_copy_right;
157 guint16 byte_copy_left;
158 guint16 input_bit_order;
159 guint16 stack_location;
162 guint msg_end = tvb_reported_length_remaining(message_tvb, 0);
163 guint16 result_code = 0;
164 guint16 old_input_bit_order = 0;
165 guint16 remaining_bits = 0;
166 guint16 input_bits = 0;
167 guint8 bit_order = 0;
168 gboolean outside_huffman_boundaries = TRUE;
169 gboolean print_in_loop = FALSE;
170 guint16 instruction_address;
171 guint8 no_of_state_create = 0;
172 guint16 state_length_buff[5];
173 guint16 state_address_buff[5];
174 guint16 state_instruction_buff[5];
175 guint16 state_minimum_access_length_buff[5];
176 guint16 state_state_retention_priority_buff[5];
177 guint32 used_udvm_cycles = 0;
178 guint cycles_per_bit;
179 guint maximum_UDVM_cycles;
181 unsigned char sha1_digest_buf[STATE_BUFFER_SIZE];
185 /* UDVM operand variables */
194 guint16 state_length;
195 guint16 state_address;
196 guint16 state_instruction;
201 guint16 at_address_1;
202 guint16 at_address_2;
203 guint16 at_address_3;
206 guint16 lower_bound_n;
207 guint16 upper_bound_n;
208 guint16 uncompressed_n;
210 guint16 ref_destination; /* could I have used $destination ? */
211 guint16 multy_offset;
212 guint16 output_start;
213 guint16 output_length;
214 guint16 minimum_access_length;
215 guint16 state_retention_priority;
216 guint16 requested_feedback_location;
217 guint16 returned_parameters_location;
221 /* Set print parameters */
222 print_level_1 = FALSE;
223 print_level_2 = FALSE;
224 print_level_3 = FALSE;
225 show_instr_detail_level = 0;
229 switch( print_flags ) {
234 print_level_1 = TRUE;
235 show_instr_detail_level = 1;
238 print_level_1 = TRUE;
239 print_level_2 = TRUE;
240 show_instr_detail_level = 1;
243 print_level_1 = TRUE;
244 print_level_2 = TRUE;
245 print_level_3 = TRUE;
246 show_instr_detail_level = 2;
249 print_level_1 = TRUE;
250 show_instr_detail_level = 1;
258 /* UDVM memory must be initialised to zero */
259 memset(buff, 0, UDVM_MEMORY_SIZE);
260 /* Set initial UDVM data
261 * The first 32 bytes of UDVM memory are then initialized to special
262 * values as illustrated in Figure 5.
265 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
266 * | UDVM_memory_size | 0 - 1
267 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
268 * | cycles_per_bit | 2 - 3
269 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
270 * | SigComp_version | 4 - 5
271 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
272 * | partial_state_ID_length | 6 - 7
273 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
274 * | state_length | 8 - 9
275 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
277 * : reserved : 10 - 31
279 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
281 * Figure 5: Initializing Useful Values in UDVM memory
283 /* UDVM_memory_size */
284 buff[0] = (UDVM_MEMORY_SIZE >> 8) & 0x00FF;
285 buff[1] = UDVM_MEMORY_SIZE & 0x00FF;
289 /* SigComp_version */
292 /* partial_state_ID_length */
293 buff[6] = (byte_code_id_len >> 8) & 0x00FF;
294 buff[7] = byte_code_id_len & 0x00FF;
296 buff[8] = (byte_code_state_len >> 8) & 0x00FF;
297 buff[9] = byte_code_state_len & 0x00FF;
299 code_length = tvb_reported_length_remaining(bytecode_tvb, 0);
301 cycles_per_bit = buff[2] << 8;
302 cycles_per_bit = cycles_per_bit | buff[3];
304 * maximum_UDVM_cycles = (8 * n + 1000) * cycles_per_bit
306 maximum_UDVM_cycles = (( 8 * (header_len + msg_end) ) + 1000) * cycles_per_bit;
308 proto_tree_add_text(udvm_tree, bytecode_tvb, offset, 1,"maximum_UDVM_cycles(%u) = (( 8 * msg_end(%u) ) + 1000) * cycles_per_bit(%u)",maximum_UDVM_cycles,msg_end,cycles_per_bit);
309 proto_tree_add_text(udvm_tree, bytecode_tvb, offset, 1,"Message Length: %u,Byte code length: %u, Maximum UDVM cycles: %u",msg_end,code_length,maximum_UDVM_cycles);
311 /* Load bytecode into UDVM starting at "udvm_mem_dest" */
314 proto_tree_add_text(udvm_tree, bytecode_tvb, offset, 1,"Load bytecode into UDVM starting at %u",i);
315 while ( code_length > offset && i < UDVM_MEMORY_SIZE ) {
316 buff[i] = tvb_get_guint8(bytecode_tvb, offset);
318 proto_tree_add_text(udvm_tree, bytecode_tvb, offset, 1,
319 " Addr: %u Instruction code(0x%0x) ", i, buff[i]);
325 /* Largest allowed size for a message is 65535 */
326 out_buff = g_malloc(65535);
327 /* Start executing code */
328 current_address = udvm_start_ip;
332 proto_tree_add_text(udvm_tree, bytecode_tvb, offset, 1,"UDVM EXECUTION STARTED at Address: %u Message size %u",
333 current_address, msg_end);
335 execute_next_instruction:
337 if ( used_udvm_cycles > maximum_UDVM_cycles ){
339 goto decompression_failure;
341 current_instruction = buff[current_address];
343 switch ( current_instruction ) {
344 case SIGCOMP_INSTR_DECOMPRESSION_FAILURE:
346 if ( result_code == 0 )
348 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
349 "Addr: %u ## DECOMPRESSION-FAILURE(0)",
351 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Ethereal UDVM diagnostic: %s.",
352 val_to_str(result_code, result_code_vals,"Unknown (%u)"));
353 if ( output_address > 0 ){
354 /* At least something got decompressed, show it */
355 decomp_tvb = tvb_new_real_data(out_buff,output_address,output_address);
356 /* Arrange that the allocated packet data copy be freed when the
359 tvb_set_free_cb( decomp_tvb, g_free );
360 /* Add the tvbuff to the list of tvbuffs to which the tvbuff we
361 * were handed refers, so it'll get cleaned up when that tvbuff
364 tvb_set_child_real_data_tvbuff(message_tvb,decomp_tvb);
365 add_new_data_source(pinfo, decomp_tvb, "Decompressed SigComp message(Incomplete)");
366 proto_tree_add_text(udvm_tree, decomp_tvb, 0, -1,"SigComp message Decompression failure");
373 case SIGCOMP_INSTR_AND: /* 1 AND ($operand_1, %operand_2) */
375 if (show_instr_detail_level == 2 ){
376 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
377 "Addr: %u ## AND(1) (operand_1, operand_2)",
381 operand_address = current_address + 1;
382 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &operand_1, &result_dest);
383 if (show_instr_detail_level == 2 ){
384 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_1 %u",
385 operand_address, operand_1);
387 operand_address = next_operand_address;
389 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &operand_2);
390 if (show_instr_detail_level == 2 ){
391 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_2 %u",
392 operand_address, operand_2);
394 if (show_instr_detail_level == 1)
396 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
397 "Addr: %u ## AND (operand_1=%u, operand_2=%u)",
398 current_address, operand_1, operand_2);
400 /* execute the instruction */
401 result = operand_1 & operand_2;
404 buff[result_dest] = msb;
405 buff[result_dest+1] = lsb;
407 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," Loading result %u at %u",
408 result, result_dest);
410 current_address = next_operand_address;
411 goto execute_next_instruction;
415 case SIGCOMP_INSTR_OR: /* 2 OR ($operand_1, %operand_2) */
417 if (show_instr_detail_level == 2 ){
418 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
419 "Addr: %u ## OR(2) (operand_1, operand_2)",
423 operand_address = current_address + 1;
424 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &operand_1, &result_dest);
425 if (show_instr_detail_level == 2 ){
426 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_1 %u",
427 operand_address, operand_1);
429 operand_address = next_operand_address;
431 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &operand_2);
432 if (show_instr_detail_level == 2 ){
433 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_2 %u",
434 operand_address, operand_2);
436 if (show_instr_detail_level == 1)
438 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
439 "Addr: %u ## OR (operand_1=%u, operand_2=%u)",
440 current_address, operand_1, operand_2);
442 /* execute the instruction */
443 result = operand_1 | operand_2;
446 buff[result_dest] = msb;
447 buff[result_dest+1] = lsb;
449 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," Loading result %u at %u",
450 result, result_dest);
452 current_address = next_operand_address;
453 goto execute_next_instruction;
457 case SIGCOMP_INSTR_NOT: /* 3 NOT ($operand_1) */
459 if (show_instr_detail_level == 2 ){
460 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
461 "Addr: %u ## NOT(3) ($operand_1)",
465 operand_address = current_address + 1;
466 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &operand_1, &result_dest);
467 if (show_instr_detail_level == 2 ){
468 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_1 %u",
469 operand_address, operand_1);
471 if (show_instr_detail_level == 1)
473 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
474 "Addr: %u ## NOT (operand_1=%u)",
475 current_address, operand_1);
477 /* execute the instruction */
478 result = operand_1 ^ 0xffff;
481 buff[result_dest] = msb;
482 buff[result_dest+1] = lsb;
484 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," Loading result %u at %u",
485 result, result_dest);
487 current_address = next_operand_address;
488 goto execute_next_instruction;
491 case SIGCOMP_INSTR_LSHIFT: /* 4 LSHIFT ($operand_1, %operand_2) */
493 if (show_instr_detail_level == 2 ){
494 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
495 "Addr: %u ## LSHIFT(4) ($operand_1, operand_2)",
499 operand_address = current_address + 1;
500 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &operand_1, &result_dest);
501 if (show_instr_detail_level == 2 ){
502 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_1 %u",
503 operand_address, operand_1);
505 operand_address = next_operand_address;
507 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &operand_2);
508 if (show_instr_detail_level == 2 ){
509 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_2 %u",
510 operand_address, operand_2);
512 if (show_instr_detail_level == 1)
514 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
515 "Addr: %u ## LSHIFT (operand_1=%u, operand_2=%u)",
516 current_address, operand_1, operand_2);
518 /* execute the instruction */
519 result = operand_1 << operand_2;
522 buff[result_dest] = msb;
523 buff[result_dest+1] = lsb;
525 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," Loading result %u at %u",
526 result, result_dest);
528 current_address = next_operand_address;
529 goto execute_next_instruction;
532 case SIGCOMP_INSTR_RSHIFT: /* 5 RSHIFT ($operand_1, %operand_2) */
534 if (show_instr_detail_level == 2 ){
535 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
536 "Addr: %u ## RSHIFT(5) (operand_1, operand_2)",
540 operand_address = current_address + 1;
541 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &operand_1, &result_dest);
542 if (show_instr_detail_level == 2 ){
543 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_1 %u",
544 operand_address, operand_1);
546 operand_address = next_operand_address;
548 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &operand_2);
549 if (show_instr_detail_level == 2 ){
550 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_2 %u",
551 operand_address, operand_2);
553 if (show_instr_detail_level == 1)
555 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
556 "Addr: %u ## RSHIFT (operand_1=%u, operand_2=%u)",
557 current_address, operand_1, operand_2);
559 /* execute the instruction */
560 result = operand_1 >> operand_2;
563 buff[result_dest] = msb;
564 buff[result_dest+1] = lsb;
566 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," Loading result %u at %u",
567 result, result_dest);
569 current_address = next_operand_address;
570 goto execute_next_instruction;
572 case SIGCOMP_INSTR_ADD: /* 6 ADD ($operand_1, %operand_2) */
574 if (show_instr_detail_level == 2 ){
575 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
576 "Addr: %u ## ADD(6) (operand_1, operand_2)",
580 operand_address = current_address + 1;
581 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &operand_1, &result_dest);
582 if (show_instr_detail_level == 2 ){
583 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_1 %u",
584 operand_address, operand_1);
586 operand_address = next_operand_address;
588 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &operand_2);
589 if (show_instr_detail_level == 2 ){
590 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_2 %u",
591 operand_address, operand_2);
593 if (show_instr_detail_level == 1)
595 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
596 "Addr: %u ## ADD (operand_1=%u, operand_2=%u)",
597 current_address, operand_1, operand_2);
599 /* execute the instruction */
600 result = operand_1 + operand_2;
603 buff[result_dest] = msb;
604 buff[result_dest+1] = lsb;
606 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," Loading result %u at %u",
607 result, result_dest);
609 current_address = next_operand_address;
610 goto execute_next_instruction;
612 case SIGCOMP_INSTR_SUBTRACT: /* 7 SUBTRACT ($operand_1, %operand_2) */
614 if (show_instr_detail_level == 2 ){
615 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
616 "Addr: %u ## SUBTRACT(7) (operand_1, operand_2)",
620 operand_address = current_address + 1;
621 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &operand_1, &result_dest);
622 if (show_instr_detail_level == 2 ){
623 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_1 %u",
624 operand_address, operand_1);
626 operand_address = next_operand_address;
628 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &operand_2);
629 if (show_instr_detail_level == 2 ){
630 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_2 %u",
631 operand_address, operand_2);
633 if (show_instr_detail_level == 1)
635 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
636 "Addr: %u ## SUBTRACT (operand_1=%u, operand_2=%u)",
637 current_address, operand_1, operand_2);
639 /* execute the instruction */
640 result = operand_1 - operand_2;
643 buff[result_dest] = msb;
644 buff[result_dest+1] = lsb;
646 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," Loading result %u at %u",
647 result, result_dest);
649 current_address = next_operand_address;
650 goto execute_next_instruction;
653 case SIGCOMP_INSTR_MULTIPLY: /* 8 MULTIPLY ($operand_1, %operand_2) */
655 if (show_instr_detail_level == 2 ){
656 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
657 "Addr: %u ##MULTIPLY(8) (operand_1, operand_2)",
661 operand_address = current_address + 1;
662 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &operand_1, &result_dest);
663 if (show_instr_detail_level == 2 ){
664 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_1 %u",
665 operand_address, operand_1);
667 operand_address = next_operand_address;
669 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &operand_2);
670 if (show_instr_detail_level == 2 ){
671 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_2 %u",
672 operand_address, operand_2);
674 if (show_instr_detail_level == 1)
676 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
677 "Addr: %u ## MULTIPLY (operand_1=%u, operand_2=%u)",
678 current_address, operand_1, operand_2);
681 * execute the instruction
682 * MULTIPLY (m, n) := m * n (modulo 2^16)
684 if ( operand_2 == 0){
686 goto decompression_failure;
688 result = operand_1 * operand_2;
691 buff[result_dest] = msb;
692 buff[result_dest+1] = lsb;
694 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," Loading result %u at %u",
695 result, result_dest);
697 current_address = next_operand_address;
698 goto execute_next_instruction;
701 case SIGCOMP_INSTR_DIVIDE: /* 9 DIVIDE ($operand_1, %operand_2) */
703 if (show_instr_detail_level == 2 ){
704 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
705 "Addr: %u ## DIVIDE(9) (operand_1, operand_2)",
709 operand_address = current_address + 1;
710 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &operand_1, &result_dest);
711 if (show_instr_detail_level == 2 ){
712 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_1 %u",
713 operand_address, operand_1);
715 operand_address = next_operand_address;
717 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &operand_2);
718 if (show_instr_detail_level == 2 ){
719 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_2 %u",
720 operand_address, operand_2);
722 if (show_instr_detail_level == 1)
724 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
725 "Addr: %u ## DIVIDE (operand_1=%u, operand_2=%u)",
726 current_address, operand_1, operand_2);
729 * execute the instruction
730 * DIVIDE (m, n) := floor(m / n)
731 * Decompression failure occurs if a DIVIDE or REMAINDER instruction
732 * encounters an operand_2 that is zero.
734 if ( operand_2 == 0){
736 goto decompression_failure;
738 result = operand_1 / operand_2;
741 buff[result_dest] = msb;
742 buff[result_dest+1] = lsb;
744 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," Loading result %u at %u",
745 result, result_dest);
747 current_address = next_operand_address;
748 goto execute_next_instruction;
751 case SIGCOMP_INSTR_REMAINDER: /* 10 REMAINDER ($operand_1, %operand_2) */
753 if (show_instr_detail_level == 2 ){
754 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
755 "Addr: %u ## REMAINDER(10) (operand_1, operand_2)",
759 operand_address = current_address + 1;
760 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &operand_1, &result_dest);
761 if (show_instr_detail_level == 2 ){
762 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_1 %u",
763 operand_address, operand_1);
765 operand_address = next_operand_address;
767 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &operand_2);
768 if (show_instr_detail_level == 2 ){
769 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_2 %u",
770 operand_address, operand_2);
772 if (show_instr_detail_level == 1)
774 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
775 "Addr: %u ## REMAINDER (operand_1=%u, operand_2=%u)",
776 current_address, operand_1, operand_2);
779 * execute the instruction
780 * REMAINDER (m, n) := m - n * floor(m / n)
781 * Decompression failure occurs if a DIVIDE or REMAINDER instruction
782 * encounters an operand_2 that is zero.
784 if ( operand_2 == 0){
786 goto decompression_failure;
788 result = operand_1 - operand_2 * (operand_1 / operand_2);
791 buff[result_dest] = msb;
792 buff[result_dest+1] = lsb;
794 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," Loading result %u at %u",
795 result, result_dest);
797 current_address = next_operand_address;
798 goto execute_next_instruction;
800 case SIGCOMP_INSTR_SORT_ASCENDING: /* 11 SORT-ASCENDING (%start, %n, %k) */
802 * used_udvm_cycles = 1 + k * (ceiling(log2(k)) + n)
805 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
806 "Addr: %u ## SORT-ASCENDING(11) (start, n, k))",
809 operand_address = current_address + 1;
810 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Execution of this instruction is NOT implemented");
812 * used_udvm_cycles = 1 + k * (ceiling(log2(k)) + n)
816 case SIGCOMP_INSTR_SORT_DESCENDING: /* 12 SORT-DESCENDING (%start, %n, %k) */
818 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
819 "Addr: %u ## SORT-DESCENDING(12) (start, n, k))",
822 operand_address = current_address + 1;
823 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Execution of this instruction is NOT implemented");
825 * used_udvm_cycles = 1 + k * (ceiling(log2(k)) + n)
828 case SIGCOMP_INSTR_SHA_1: /* 13 SHA-1 (%position, %length, %destination) */
830 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
831 "Addr: %u ## SHA-1(13) (position, length, destination)",
834 operand_address = current_address + 1;
836 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &position);
838 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u position %u",
839 operand_address, position);
841 operand_address = next_operand_address;
844 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &length);
846 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Length %u",
847 operand_address, length);
849 operand_address = next_operand_address;
852 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &ref_destination, &result_dest);
854 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u $destination %u",
855 operand_address, ref_destination);
857 current_address = next_operand_address;
858 used_udvm_cycles = used_udvm_cycles + 1 + length;
862 byte_copy_right = buff[66] << 8;
863 byte_copy_right = byte_copy_right | buff[67];
864 byte_copy_left = buff[64] << 8;
865 byte_copy_left = byte_copy_left | buff[65];
868 proto_tree_add_text(udvm_tree, message_tvb, 0, -1,
869 "byte_copy_right = %u", byte_copy_right);
875 guint16 handle_now = length;
877 if ( k < byte_copy_right && byte_copy_right <= k + (length-n) ){
878 handle_now = byte_copy_right - position;
881 if (k + handle_now >= UDVM_MEMORY_SIZE)
882 goto decompression_failure;
883 sha1_update( &ctx, &buff[k], handle_now );
885 k = ( k + handle_now ) & 0xffff;
886 n = ( n + handle_now ) & 0xffff;
888 if ( k >= byte_copy_right ) {
893 sha1_finish( &ctx, sha1_digest_buf );
897 for ( n=0; n< STATE_BUFFER_SIZE; n++ ) {
899 buff[k] = sha1_digest_buf[n];
901 k = ( k + 1 ) & 0xffff;
904 if ( k == byte_copy_right ){
910 proto_tree_add_text(udvm_tree, message_tvb, 0, -1,
911 "Calculated SHA-1: %s",
912 bytes_to_str(sha1_digest_buf, STATE_BUFFER_SIZE));
915 current_address = next_operand_address;
916 goto execute_next_instruction;
919 case SIGCOMP_INSTR_LOAD: /* 14 LOAD (%address, %value) */
920 if (show_instr_detail_level == 2 ){
921 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
922 "Addr: %u ## LOAD(14) (%%address, %%value)",
925 operand_address = current_address + 1;
927 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &address);
928 if (show_instr_detail_level == 2 ){
929 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Address %u",
930 operand_address, address);
932 operand_address = next_operand_address;
934 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &value);
935 if (show_instr_detail_level == 1)
937 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
938 "Addr: %u ## LOAD (%%address=%u, %%value=%u)",
939 current_address, address, value);
945 buff[address + 1] = lsb;
948 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Value %u",
949 operand_address, value);
950 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," Loading bytes at %u Value %u 0x%x",
951 address, value, value);
954 current_address = next_operand_address;
955 goto execute_next_instruction;
958 case SIGCOMP_INSTR_MULTILOAD: /* 15 MULTILOAD (%address, #n, %value_0, ..., %value_n-1) */
960 * The MULTILOAD instruction sets a contiguous block of 2-byte words in
961 * the UDVM memory to specified values.
962 * Hmm what if the value to load only takes one byte ? Chose to always load two bytes.
964 if (show_instr_detail_level == 2 ){
965 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
966 "Addr: %u ## MULTILOAD(15) (%%address, #n, value_0, ..., value_n-1)",
969 operand_address = current_address + 1;
971 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &address);
972 if (show_instr_detail_level == 2 ){
973 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Address %u",
974 operand_address, address);
976 operand_address = next_operand_address;
979 next_operand_address = decode_udvm_literal_operand(buff,operand_address, &n);
980 if (show_instr_detail_level == 2 ){
981 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u n %u",
984 if (show_instr_detail_level == 1)
986 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
987 "Addr: %u ## MULTILOAD (%%address=%u, #n=%u, value_0, ..., value_%d)",
988 current_address, address, n, n-1);
990 operand_address = next_operand_address;
991 used_udvm_cycles = used_udvm_cycles + 1 + n;
995 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &value);
999 if (address >= UDVM_MEMORY_SIZE - 1)
1000 goto decompression_failure;
1002 buff[address] = msb;
1003 buff[address + 1] = lsb;
1006 length = next_operand_address - operand_address;
1008 if (print_level_1 ){
1009 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1, "Addr: %u Value %5u - Loading bytes at %5u Value %5u 0x%x",
1010 operand_address, value, address, value, value);
1012 address = address + 2;
1013 operand_address = next_operand_address;
1015 current_address = next_operand_address;
1016 goto execute_next_instruction;
1020 case SIGCOMP_INSTR_PUSH: /* 16 PUSH (%value) */
1021 if (show_instr_detail_level == 2){
1022 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1023 "Addr: %u ## PUSH(16) (value)",
1026 operand_address = current_address + 1;
1028 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &value);
1029 if (show_instr_detail_level == 2){
1030 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Value %u",
1031 operand_address, value);
1033 if (show_instr_detail_level == 1)
1035 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1036 "Addr: %u ## PUSH (value=%u)",
1037 current_address, value);
1039 current_address = next_operand_address;
1041 /* Push the value address onto the stack */
1042 stack_location = (buff[70] << 8) | buff[71];
1043 stack_fill = (buff[stack_location] << 8)
1044 | buff[(stack_location+1) & 0xFFFF];
1045 address = (stack_location + stack_fill * 2 + 2) & 0xFFFF;
1047 if (address >= UDVM_MEMORY_SIZE - 1)
1048 goto decompression_failure;
1050 buff[address] = (value >> 8) & 0x00FF;
1051 buff[(address+1) & 0xFFFF] = value & 0x00FF;
1053 if (stack_location >= UDVM_MEMORY_SIZE - 1)
1054 goto decompression_failure;
1056 stack_fill = (stack_fill + 1) & 0xFFFF;
1057 buff[stack_location] = (stack_fill >> 8) & 0x00FF;
1058 buff[(stack_location+1) & 0xFFFF] = stack_fill & 0x00FF;
1061 goto execute_next_instruction;
1065 case SIGCOMP_INSTR_POP: /* 17 POP (%address) */
1066 if (show_instr_detail_level == 2){
1067 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1068 "Addr: %u ## POP(16) (value)",
1071 operand_address = current_address + 1;
1073 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &destination);
1074 if (show_instr_detail_level == 2){
1075 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Value %u",
1076 operand_address, destination);
1078 if (show_instr_detail_level == 1)
1080 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1081 "Addr: %u ## POP (address=%u)",
1082 current_address, destination);
1084 current_address = next_operand_address;
1086 /* Pop value from the top of the stack */
1087 stack_location = (buff[70] << 8) | buff[71];
1088 stack_fill = (buff[stack_location] << 8)
1089 | buff[(stack_location+1) & 0xFFFF];
1090 if (stack_fill == 0)
1093 goto decompression_failure;
1096 if (stack_location >= UDVM_MEMORY_SIZE - 1)
1097 goto decompression_failure;
1099 stack_fill = (stack_fill - 1) & 0xFFFF;
1100 buff[stack_location] = (stack_fill >> 8) & 0x00FF;
1101 buff[(stack_location+1) & 0xFFFF] = stack_fill & 0x00FF;
1103 if (address >= UDVM_MEMORY_SIZE - 1)
1104 goto decompression_failure;
1106 address = (stack_location + stack_fill * 2 + 2) & 0xFFFF;
1107 value = (buff[address] << 8)
1108 | buff[(address+1) & 0xFFFF];
1110 /* ... and store the popped value. */
1111 if (destination >= UDVM_MEMORY_SIZE - 1)
1112 goto decompression_failure;
1113 buff[destination] = (value >> 8) & 0x00FF;
1114 buff[(destination+1) & 0xFFFF] = value & 0x00FF;
1117 goto execute_next_instruction;
1121 case SIGCOMP_INSTR_COPY: /* 18 COPY (%position, %length, %destination) */
1122 if (show_instr_detail_level == 2 ){
1123 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1124 "Addr: %u ## COPY(18) (position, length, destination)",
1127 operand_address = current_address + 1;
1129 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &position);
1130 if (show_instr_detail_level == 2 ){
1131 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u position %u",
1132 operand_address, position);
1134 operand_address = next_operand_address;
1137 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &length);
1138 if (show_instr_detail_level == 2 ){
1139 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Length %u",
1140 operand_address, length);
1142 operand_address = next_operand_address;
1145 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &destination);
1146 if (show_instr_detail_level == 2 ){
1147 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Destination %u",
1148 operand_address, destination);
1150 if (show_instr_detail_level == 1)
1152 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1153 "Addr: %u ## COPY (position=%u, length=%u, destination=%u)",
1154 current_address, position, length, destination);
1156 current_address = next_operand_address;
1160 * The string of bytes is copied in ascending order of memory address,
1161 * respecting the bounds set by byte_copy_left and byte_copy_right.
1162 * More precisely, if a byte is copied from/to Address m then the next
1163 * byte is copied from/to Address n where n is calculated as follows:
1165 * Set k := m + 1 (modulo 2^16)
1166 * If k = byte_copy_right then set n := byte_copy_left, else set n := k
1172 byte_copy_right = buff[66] << 8;
1173 byte_copy_right = byte_copy_right | buff[67];
1174 byte_copy_left = buff[64] << 8;
1175 byte_copy_left = byte_copy_left | buff[65];
1176 if (print_level_2 ){
1177 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
1178 " byte_copy_right = %u", byte_copy_right);
1181 while ( n < length ){
1182 buff[k] = buff[position];
1183 if (print_level_2 ){
1184 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
1185 " Copying value: %u (0x%x) to Addr: %u",
1186 buff[position], buff[position], k);
1188 position = ( position + 1 ) & 0xffff;
1189 k = ( k + 1 ) & 0xffff;
1193 * Check for circular buffer wrapping after the positions are
1194 * incremented. If either started at BCR then they should continue
1195 * to increment beyond BCR.
1197 if ( k == byte_copy_right ){
1200 if ( position == byte_copy_right ){
1201 position = byte_copy_left;
1204 used_udvm_cycles = used_udvm_cycles + 1 + length;
1205 goto execute_next_instruction;
1208 case SIGCOMP_INSTR_COPY_LITERAL: /* 19 COPY-LITERAL (%position, %length, $destination) */
1209 if (show_instr_detail_level == 2 ){
1210 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1211 "Addr: %u ## COPY-LITERAL(19) (position, length, $destination)",
1214 operand_address = current_address + 1;
1216 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &position);
1217 if (show_instr_detail_level == 2 ){
1218 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u position %u",
1219 operand_address, position);
1221 operand_address = next_operand_address;
1224 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &length);
1225 if (show_instr_detail_level == 2 ){
1226 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Length %u",
1227 operand_address, length);
1229 operand_address = next_operand_address;
1233 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &ref_destination, &result_dest);
1234 if (show_instr_detail_level == 2 ){
1235 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u destination %u",
1236 operand_address, ref_destination);
1238 if (show_instr_detail_level == 1)
1240 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1241 "Addr: %u ## COPY-LITERAL (position=%u, length=%u, $destination=%u)",
1242 current_address, position, length, destination);
1244 current_address = next_operand_address;
1250 * The string of bytes is copied in ascending order of memory address,
1251 * respecting the bounds set by byte_copy_left and byte_copy_right.
1252 * More precisely, if a byte is copied from/to Address m then the next
1253 * byte is copied from/to Address n where n is calculated as follows:
1255 * Set k := m + 1 (modulo 2^16)
1256 * If k = byte_copy_right then set n := byte_copy_left, else set n := k
1261 k = ref_destination;
1262 byte_copy_right = buff[66] << 8;
1263 byte_copy_right = byte_copy_right | buff[67];
1264 byte_copy_left = buff[64] << 8;
1265 byte_copy_left = byte_copy_left | buff[65];
1266 if (print_level_2 ){
1267 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
1268 " byte_copy_right = %u", byte_copy_right);
1270 while ( n < length ){
1272 buff[k] = buff[position];
1273 if (print_level_2 ){
1274 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
1275 " Copying value: %u (0x%x) to Addr: %u",
1276 buff[position], buff[position], k);
1278 position = ( position + 1 ) & 0xffff;
1279 k = ( k + 1 ) & 0xffff;
1283 * Check for circular buffer wrapping after the positions are
1284 * incremented. It is important that k cannot be left set
1285 * to BCR. Also, if either started at BCR then they should continue
1286 * to increment beyond BCR.
1288 if ( k == byte_copy_right ){
1291 if ( position == byte_copy_right ){
1292 position = byte_copy_left;
1295 buff[result_dest] = k >> 8;
1296 buff[result_dest + 1] = k & 0x00ff;
1298 used_udvm_cycles = used_udvm_cycles + 1 + length;
1299 goto execute_next_instruction;
1302 case SIGCOMP_INSTR_COPY_OFFSET: /* 20 COPY-OFFSET (%offset, %length, $destination) */
1303 if (show_instr_detail_level == 2 ){
1304 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1305 "Addr: %u ## COPY-OFFSET(20) (offset, length, $destination)",
1308 operand_address = current_address + 1;
1310 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &multy_offset);
1311 if (show_instr_detail_level == 2 ){
1312 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u offset %u",
1313 operand_address, multy_offset);
1315 operand_address = next_operand_address;
1318 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &length);
1319 if (show_instr_detail_level == 2 ){
1320 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Length %u",
1321 operand_address, length);
1323 operand_address = next_operand_address;
1327 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &ref_destination, &result_dest);
1328 if (show_instr_detail_level == 2 ){
1329 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u $destination %u",
1330 operand_address, ref_destination);
1333 if (show_instr_detail_level == 1)
1335 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1336 "Addr: %u ## COPY-OFFSET (offset=%u, length=%u, $destination=%u)",
1337 current_address, multy_offset, length, result_dest);
1339 current_address = next_operand_address;
1341 /* Execute the instruction:
1342 * To derive the value of the position operand, starting at the memory
1343 * address specified by destination, the UDVM counts backwards a total
1344 * of offset memory addresses.
1346 * If the memory address specified in byte_copy_left is reached, the
1347 * next memory address is taken to be (byte_copy_right - 1) modulo 2^16.
1349 byte_copy_left = buff[64] << 8;
1350 byte_copy_left = byte_copy_left | buff[65];
1351 byte_copy_right = buff[66] << 8;
1352 byte_copy_right = byte_copy_right | buff[67];
1355 * In order to work out the position, simple arithmetic is tricky
1356 * to apply because there some nasty corner cases. A simple loop
1357 * is inefficient but the logic is simple.
1359 * FUTURE: This could be optimised.
1361 for (position = ref_destination, i = 0; i < multy_offset; i++)
1363 if ( position == byte_copy_left )
1365 position = (byte_copy_right - 1) & 0xffff;
1369 position = (position - 1) & 0xffff;
1373 if (print_level_2 ){
1374 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
1375 " byte_copy_left = %u byte_copy_right = %u position= %u",
1376 byte_copy_left, byte_copy_right, position);
1378 /* The COPY-OFFSET instruction then behaves as a COPY-LITERAL
1379 * instruction, taking the value of the position operand to be the last
1380 * memory address reached in the above step.
1386 * The string of bytes is copied in ascending order of memory address,
1387 * respecting the bounds set by byte_copy_left and byte_copy_right.
1388 * More precisely, if a byte is copied from/to Address m then the next
1389 * byte is copied from/to Address n where n is calculated as follows:
1391 * Set k := m + 1 (modulo 2^16)
1392 * If k = byte_copy_right then set n := byte_copy_left, else set n := k
1397 k = ref_destination;
1398 if (print_level_2 ){
1399 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
1400 " byte_copy_left = %u byte_copy_right = %u", byte_copy_left, byte_copy_right);
1402 while ( n < length ){
1403 buff[k] = buff[position];
1404 if (print_level_2 ){
1405 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
1406 " Copying value: %5u (0x%x) from Addr: %u to Addr: %u",
1407 buff[position], buff[position],(position), k);
1410 k = ( k + 1 ) & 0xffff;
1411 position = ( position + 1 ) & 0xffff;
1414 * Check for circular buffer wrapping after the positions are
1415 * incremented. It is important that k cannot be left set
1416 * to BCR. Also, if either started at BCR then they should continue
1417 * to increment beyond BCR.
1419 if ( k == byte_copy_right ){
1422 if ( position == byte_copy_right ){
1423 position = byte_copy_left;
1426 buff[result_dest] = k >> 8;
1427 buff[result_dest + 1] = k & 0x00ff;
1428 used_udvm_cycles = used_udvm_cycles + 1 + length;
1429 goto execute_next_instruction;
1432 case SIGCOMP_INSTR_MEMSET: /* 21 MEMSET (%address, %length, %start_value, %offset) */
1433 if (show_instr_detail_level == 2 ){
1434 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1435 "Addr: %u ## MEMSET(21) (address, length, start_value, offset)",
1438 operand_address = current_address + 1;
1441 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &address);
1442 if (show_instr_detail_level == 2 ){
1443 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Address %u",
1444 operand_address, address);
1446 operand_address = next_operand_address;
1449 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &length);
1450 if (show_instr_detail_level == 2 ){
1451 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Length %u",
1452 operand_address, length);
1454 operand_address = next_operand_address;
1456 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &start_value);
1457 if (show_instr_detail_level == 2 ){
1458 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u start_value %u",
1459 operand_address, start_value);
1461 operand_address = next_operand_address;
1464 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &multy_offset);
1465 if (show_instr_detail_level == 2 ){
1466 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u offset %u",
1467 operand_address, multy_offset);
1469 if (show_instr_detail_level == 1)
1471 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1472 "Addr: %u ## MEMSET (address=%u, length=%u, start_value=%u, offset=%u)",
1473 current_address, address, length, start_value, multy_offset);
1475 current_address = next_operand_address;
1476 /* exetute the instruction
1477 * The sequence of values used by the MEMSET instruction is specified by
1478 * the following formula:
1480 * Seq[n] := (start_value + n * offset) modulo 256
1484 byte_copy_right = buff[66] << 8;
1485 byte_copy_right = byte_copy_right | buff[67];
1486 byte_copy_left = buff[64] << 8;
1487 byte_copy_left = byte_copy_left | buff[65];
1488 if (print_level_2 ){
1489 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
1490 " byte_copy_left = %u byte_copy_right = %u", byte_copy_left, byte_copy_right);
1492 while ( n < length ){
1493 if ( k == byte_copy_right ){
1496 buff[k] = (start_value + ( n * multy_offset)) & 0xff;
1497 if (print_level_2 ){
1498 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
1499 " Storing value: %u (0x%x) at Addr: %u",
1500 buff[k], buff[k], k);
1502 k = ( k + 1 ) & 0xffff;
1505 used_udvm_cycles = used_udvm_cycles + 1 + length;
1506 goto execute_next_instruction;
1510 case SIGCOMP_INSTR_JUMP: /* 22 JUMP (@address) */
1511 if (show_instr_detail_level == 2 ){
1512 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1513 "Addr: %u ## JUMP(22) (@address)",
1516 operand_address = current_address + 1;
1518 /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
1519 next_operand_address = decode_udvm_address_operand(buff,operand_address, &at_address, current_address);
1520 if (show_instr_detail_level == 2 ){
1521 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u @Address %u",
1522 operand_address, at_address);
1524 if (show_instr_detail_level == 1)
1526 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1527 "Addr: %u ## JUMP (@address=%u)",
1528 current_address, at_address);
1530 current_address = at_address;
1532 goto execute_next_instruction;
1535 case SIGCOMP_INSTR_COMPARE: /* 23 */
1536 /* COMPARE (%value_1, %value_2, @address_1, @address_2, @address_3)
1538 if (show_instr_detail_level == 2 ){
1539 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1540 "Addr: %u ## COMPARE(23) (value_1, value_2, @address_1, @address_2, @address_3)",
1543 operand_address = current_address + 1;
1546 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &value_1);
1547 if (show_instr_detail_level == 2 ){
1548 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Value %u",
1549 operand_address, value_1);
1551 operand_address = next_operand_address;
1554 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &value_2);
1555 if (show_instr_detail_level == 2 ){
1556 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Value %u",
1557 operand_address, value_2);
1559 operand_address = next_operand_address;
1562 /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
1563 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &at_address_1);
1564 at_address_1 = ( current_address + at_address_1) & 0xffff;
1565 if (show_instr_detail_level == 2 ){
1566 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u @Address %u",
1567 operand_address, at_address_1);
1569 operand_address = next_operand_address;
1573 /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
1574 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &at_address_2);
1575 at_address_2 = ( current_address + at_address_2) & 0xffff;
1576 if (show_instr_detail_level == 2 ){
1577 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u @Address %u",
1578 operand_address, at_address_2);
1580 operand_address = next_operand_address;
1583 /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
1584 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &at_address_3);
1585 at_address_3 = ( current_address + at_address_3) & 0xffff;
1586 if (show_instr_detail_level == 2 ){
1587 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u @Address %u",
1588 operand_address, at_address_3);
1590 if (show_instr_detail_level == 1)
1592 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1593 "Addr: %u ## COMPARE (value_1=%u, value_2=%u, @address_1=%u, @address_2=%u, @address_3=%u)",
1594 current_address, value_1, value_2, at_address_1, at_address_2, at_address_3);
1596 /* execute the instruction
1597 * If value_1 < value_2 then the UDVM continues instruction execution at
1598 * the memory address specified by address 1. If value_1 = value_2 then
1599 * it jumps to the address specified by address_2. If value_1 > value_2
1600 * then it jumps to the address specified by address_3.
1602 if ( value_1 < value_2 )
1603 current_address = at_address_1;
1604 if ( value_1 == value_2 )
1605 current_address = at_address_2;
1606 if ( value_1 > value_2 )
1607 current_address = at_address_3;
1609 goto execute_next_instruction;
1612 case SIGCOMP_INSTR_CALL: /* 24 CALL (@address) (PUSH addr )*/
1613 if (show_instr_detail_level == 2){
1614 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1615 "Addr: %u ## CALL(24) (@address) (PUSH addr )",
1618 operand_address = current_address + 1;
1620 next_operand_address = decode_udvm_address_operand(buff,operand_address, &at_address, current_address);
1621 if (show_instr_detail_level == 2 ){
1622 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u @Address %u",
1623 operand_address, at_address);
1625 if (show_instr_detail_level == 1)
1627 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1628 "Addr: %u ## CALL (@address=%u)",
1629 current_address, at_address);
1631 current_address = next_operand_address;
1633 /* Push the current address onto the stack */
1634 stack_location = (buff[70] << 8) | buff[71];
1635 stack_fill = (buff[stack_location] << 8)
1636 | buff[(stack_location+1) & 0xFFFF];
1637 address = (stack_location + stack_fill * 2 + 2) & 0xFFFF;
1638 if (address >= UDVM_MEMORY_SIZE - 1)
1639 goto decompression_failure;
1640 buff[address] = (current_address >> 8) & 0x00FF;
1641 buff[(address+1) & 0xFFFF] = current_address & 0x00FF;
1643 stack_fill = (stack_fill + 1) & 0xFFFF;
1644 if (stack_location >= UDVM_MEMORY_SIZE - 1)
1645 goto decompression_failure;
1646 buff[stack_location] = (stack_fill >> 8) & 0x00FF;
1647 buff[(stack_location+1) & 0xFFFF] = stack_fill & 0x00FF;
1649 /* ... and jump to the destination address */
1650 current_address = at_address;
1653 goto execute_next_instruction;
1657 case SIGCOMP_INSTR_RETURN: /* 25 POP and return */
1658 if (print_level_1 || show_instr_detail_level == 1){
1659 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1660 "Addr: %u ## POP(25) and return",
1664 /* Pop value from the top of the stack */
1665 stack_location = (buff[70] << 8) | buff[71];
1666 stack_fill = (buff[stack_location] << 8)
1667 | buff[(stack_location+1) & 0xFFFF];
1668 if (stack_fill == 0)
1671 goto decompression_failure;
1674 stack_fill = (stack_fill - 1) & 0xFFFF;
1675 if (stack_location >= UDVM_MEMORY_SIZE - 1)
1676 goto decompression_failure;
1677 buff[stack_location] = (stack_fill >> 8) & 0x00FF;
1678 buff[(stack_location+1) & 0xFFFF] = stack_fill & 0x00FF;
1680 address = (stack_location + stack_fill * 2 + 2) & 0xFFFF;
1681 at_address = (buff[address] << 8)
1682 | buff[(address+1) & 0xFFFF];
1684 /* ... and set the PC to the popped value */
1685 current_address = at_address;
1688 goto execute_next_instruction;
1692 case SIGCOMP_INSTR_SWITCH: /* 26 SWITCH (#n, %j, @address_0, @address_1, ... , @address_n-1) */
1694 * When a SWITCH instruction is encountered the UDVM reads the value of
1695 * j. It then continues instruction execution at the address specified
1698 * Decompression failure occurs if j specifies a value of n or more, or
1699 * if the address lies beyond the overall UDVM memory size.
1701 instruction_address = current_address;
1702 if (print_level_1 ){
1703 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1704 "Addr: %u ## SWITCH (#n, j, @address_0, @address_1, ... , @address_n-1))",
1707 operand_address = current_address + 1;
1709 * Number of addresses in the instruction
1711 next_operand_address = decode_udvm_literal_operand(buff,operand_address, &n);
1712 if (print_level_1 ){
1713 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u n %u",
1714 operand_address, n);
1716 operand_address = next_operand_address;
1718 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &j);
1719 if (print_level_1 ){
1720 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u j %u",
1721 operand_address, j);
1723 operand_address = next_operand_address;
1727 /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
1728 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &at_address_1);
1729 at_address_1 = ( instruction_address + at_address_1) & 0xffff;
1730 if (print_level_1 ){
1731 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u @Address %u",
1732 operand_address, at_address_1);
1735 current_address = at_address_1;
1737 operand_address = next_operand_address;
1740 /* Check decompression failure */
1741 if ( ( j == n ) || ( j > n )){
1743 goto decompression_failure;
1745 if ( current_address > UDVM_MEMORY_SIZE ){
1747 goto decompression_failure;
1749 used_udvm_cycles = used_udvm_cycles + 1 + n;
1751 goto execute_next_instruction;
1754 case SIGCOMP_INSTR_CRC: /* 27 CRC (%value, %position, %length, @address) */
1755 if (print_level_1 ){
1756 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1757 "Addr: %u ## CRC (value, position, length, @address)",
1761 operand_address = current_address + 1;
1764 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &value);
1765 if (print_level_1 ){
1766 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Value %u",
1767 operand_address, value);
1769 operand_address = next_operand_address;
1772 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &position);
1773 if (print_level_1 ){
1774 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u position %u",
1775 operand_address, position);
1777 operand_address = next_operand_address;
1780 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &length);
1781 if (print_level_1 ){
1782 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Length %u",
1783 operand_address, length);
1785 operand_address = next_operand_address;
1788 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &at_address);
1789 at_address = ( current_address + at_address) & 0xffff;
1790 if (print_level_1 ){
1791 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u @Address %u",
1792 operand_address, at_address);
1794 /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
1795 used_udvm_cycles = used_udvm_cycles + 1 + length;
1799 byte_copy_right = buff[66] << 8;
1800 byte_copy_right = byte_copy_right | buff[67];
1801 byte_copy_left = buff[64] << 8;
1802 byte_copy_left = byte_copy_left | buff[65];
1805 if (print_level_2 ){
1806 proto_tree_add_text(udvm_tree, message_tvb, 0, -1,
1807 "byte_copy_right = %u", byte_copy_right);
1812 guint16 handle_now = length - n;
1814 if ( k < byte_copy_right && byte_copy_right <= k + (length-n) ){
1815 handle_now = byte_copy_right - k;
1818 if (k + handle_now >= UDVM_MEMORY_SIZE)
1819 goto decompression_failure;
1820 result = crc16_ccitt_seed(&buff[k], handle_now, result ^ 0xffff);
1822 k = ( k + handle_now ) & 0xffff;
1823 n = ( n + handle_now ) & 0xffff;
1825 if ( k >= byte_copy_right ) {
1830 result = result ^ 0xffff;
1832 if (print_level_1 ){
1833 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1, "Calculated CRC %u", result);
1835 if (result != value){
1836 current_address = at_address;
1839 current_address = next_operand_address;
1841 goto execute_next_instruction;
1845 case SIGCOMP_INSTR_INPUT_BYTES: /* 28 INPUT-BYTES (%length, %destination, @address) */
1846 if (show_instr_detail_level == 2 ){
1847 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1848 "Addr: %u ## INPUT-BYTES(28) length, destination, @address)",
1851 operand_address = current_address + 1;
1853 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &length);
1854 if (show_instr_detail_level == 2 ){
1855 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Length %u",
1856 operand_address, length);
1858 operand_address = next_operand_address;
1861 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &destination);
1862 if (show_instr_detail_level == 2 ){
1863 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Destination %u",
1864 operand_address, destination);
1866 operand_address = next_operand_address;
1869 /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
1870 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &at_address);
1871 at_address = ( current_address + at_address) & 0xffff;
1872 if (show_instr_detail_level == 2 ){
1873 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u @Address %u",
1874 operand_address, at_address);
1876 if (show_instr_detail_level == 1)
1878 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1879 "Addr: %u ## INPUT-BYTES length=%u, destination=%u, @address=%u)",
1880 current_address, length, destination, at_address);
1882 /* execute the instruction TODO insert checks
1886 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1887 * | byte_copy_left | 64 - 65
1888 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1889 * | byte_copy_right | 66 - 67
1890 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1891 * | input_bit_order | 68 - 69
1892 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1893 * | stack_location | 70 - 71
1894 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1896 * Figure 7: Memory addresses of the UDVM registers
1900 * The string of bytes is copied in ascending order of memory address,
1901 * respecting the bounds set by byte_copy_left and byte_copy_right.
1902 * More precisely, if a byte is copied from/to Address m then the next
1903 * byte is copied from/to Address n where n is calculated as follows:
1905 * Set k := m + 1 (modulo 2^16)
1906 * If k = byte_copy_right then set n := byte_copy_left, else set n := k
1912 byte_copy_right = buff[66] << 8;
1913 byte_copy_right = byte_copy_right | buff[67];
1914 byte_copy_left = buff[64] << 8;
1915 byte_copy_left = byte_copy_left | buff[65];
1916 if (print_level_1 ){
1917 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
1918 " byte_copy_right = %u", byte_copy_right);
1920 /* clear out remaining bits if any */
1923 /* operand_address used as dummy */
1924 while ( n < length ){
1925 if (input_address > ( msg_end - 1)){
1926 current_address = at_address;
1928 goto execute_next_instruction;
1931 if ( k == byte_copy_right ){
1934 octet = tvb_get_guint8(message_tvb, input_address);
1936 if (print_level_1 ){
1937 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
1938 " Loading value: %u (0x%x) at Addr: %u", octet, octet, k);
1942 * If the instruction requests data that lies beyond the end of the
1943 * SigComp message, no data is returned. Instead the UDVM moves program
1944 * execution to the address specified by the address operand.
1948 k = ( k + 1 ) & 0xffff;
1951 used_udvm_cycles = used_udvm_cycles + 1 + length;
1952 current_address = next_operand_address;
1953 goto execute_next_instruction;
1955 case SIGCOMP_INSTR_INPUT_BITS:/* 29 INPUT-BITS (%length, %destination, @address) */
1957 * The length operand indicates the requested number of bits.
1958 * Decompression failure occurs if this operand does not lie between 0
1961 * The destination operand specifies the memory address to which the
1962 * compressed data should be copied. Note that the requested bits are
1963 * interpreted as a 2-byte integer ranging from 0 to 2^length - 1, as
1964 * explained in Section 8.2.
1966 * If the instruction requests data that lies beyond the end of the
1967 * SigComp message, no data is returned. Instead the UDVM moves program
1968 * execution to the address specified by the address operand.
1971 if (show_instr_detail_level == 2 ){
1972 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
1973 "Addr: %u ## INPUT-BITS(29) (length, destination, @address)",
1976 operand_address = current_address + 1;
1979 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &length);
1980 if (show_instr_detail_level == 2 ){
1981 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u length %u",
1982 operand_address, length);
1984 operand_address = next_operand_address;
1986 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &destination);
1987 if (show_instr_detail_level == 2 ){
1988 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Destination %u",
1989 operand_address, destination);
1991 operand_address = next_operand_address;
1994 /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
1995 next_operand_address = decode_udvm_address_operand(buff,operand_address, &at_address, current_address);
1996 if (show_instr_detail_level == 2 ){
1997 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u @Address %u",
1998 operand_address, at_address);
2000 if (show_instr_detail_level == 1)
2002 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2003 "Addr: %u ## INPUT-BITS length=%u, destination=%u, @address=%u)",
2004 current_address, length, destination, at_address);
2006 current_address = next_operand_address;
2009 * Execute actual instr.
2010 * The input_bit_order register contains the following three flags:
2013 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2014 * | reserved |F|H|P| 68 - 69
2015 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2017 input_bit_order = buff[68] << 8;
2018 input_bit_order = input_bit_order | buff[69];
2020 * If the instruction requests data that lies beyond the end of the
2021 * SigComp message, no data is returned. Instead the UDVM moves program
2022 * execution to the address specified by the address operand.
2027 goto decompression_failure;
2029 if ( input_bit_order > 7 ){
2031 goto decompression_failure;
2035 * Transfer F bit to bit_order to tell decomp dispatcher which bit order to use
2037 bit_order = ( input_bit_order & 0x0004 ) >> 2;
2038 value = decomp_dispatch_get_bits( message_tvb, udvm_tree, bit_order,
2039 buff, &old_input_bit_order, &remaining_bits,
2040 &input_bits, &input_address, length, &result_code, msg_end);
2041 if ( result_code == 11 ){
2042 used_udvm_cycles = used_udvm_cycles + 1;
2043 current_address = at_address;
2044 goto execute_next_instruction;
2047 lsb = value & 0x00ff;
2048 if (destination >= UDVM_MEMORY_SIZE - 1)
2049 goto decompression_failure;
2050 buff[destination] = msb;
2051 buff[destination + 1]=lsb;
2052 if (print_level_1 ){
2053 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
2054 " Loading value: %u (0x%x) at Addr: %u, remaining_bits: %u", value, value, destination, remaining_bits);
2057 used_udvm_cycles = used_udvm_cycles + 1;
2058 goto execute_next_instruction;
2060 case SIGCOMP_INSTR_INPUT_HUFFMAN: /* 30 */
2062 * INPUT-HUFFMAN (%destination, @address, #n, %bits_1, %lower_bound_1,
2063 * %upper_bound_1, %uncompressed_1, ... , %bits_n, %lower_bound_n,
2064 * %upper_bound_n, %uncompressed_n)
2066 if (show_instr_detail_level == 2 ){
2067 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2068 "Addr: %u ## INPUT-HUFFMAN (destination, @address, #n, bits_1, lower_bound_1,upper_bound_1, uncompressed_1, ... , bits_n, lower_bound_n,upper_bound_n, uncompressed_n)",
2071 operand_address = current_address + 1;
2074 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &destination);
2075 if (show_instr_detail_level == 2 ){
2076 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Destination %u",
2077 operand_address, destination);
2079 operand_address = next_operand_address;
2082 /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
2083 next_operand_address = decode_udvm_address_operand(buff,operand_address, &at_address, current_address);
2084 if (show_instr_detail_level == 2 ){
2085 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u @Address %u",
2086 operand_address, at_address);
2088 operand_address = next_operand_address;
2091 next_operand_address = decode_udvm_literal_operand(buff,operand_address, &n);
2092 if (show_instr_detail_level == 2 ){
2093 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u n %u",
2094 operand_address, n);
2096 operand_address = next_operand_address;
2097 if (show_instr_detail_level == 1)
2099 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2100 "Addr: %u ## INPUT-HUFFMAN (destination=%u, @address=%u, #n=%u, bits_1, lower_1,upper_1, unc_1, ... , bits_%d, lower_%d,upper_%d, unc_%d)",
2101 current_address, destination, at_address, n, n, n, n, n);
2104 used_udvm_cycles = used_udvm_cycles + 1 + n;
2107 * Note that if n = 0 then the INPUT-HUFFMAN instruction is ignored and
2108 * program execution resumes at the following instruction.
2109 * Decompression failure occurs if (bits_1 + ... + bits_n) > 16.
2111 * In all other cases, the behavior of the INPUT-HUFFMAN instruction is
2114 * 1. Set j := 1 and set H := 0.
2116 * 2. Request bits_j compressed bits. Interpret the returned bits as an
2117 * integer k from 0 to 2^bits_j - 1, as explained in Section 8.2.
2119 * 3. Set H := H * 2^bits_j + k.
2121 * 4. If data is requested that lies beyond the end of the SigComp
2122 * message, terminate the INPUT-HUFFMAN instruction and move program
2123 * execution to the memory address specified by the address operand.
2125 * 5. If (H < lower_bound_j) or (H > upper_bound_j) then set j := j + 1.
2126 * Then go back to Step 2, unless j > n in which case decompression
2129 * 6. Copy (H + uncompressed_j - lower_bound_j) modulo 2^16 to the
2130 * memory address specified by the destination operand.
2134 * The input_bit_order register contains the following three flags:
2137 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2138 * | reserved |F|H|P| 68 - 69
2139 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2141 * Transfer H bit to bit_order to tell decomp dispatcher which bit order to use
2143 input_bit_order = buff[68] << 8;
2144 input_bit_order = input_bit_order | buff[69];
2145 bit_order = ( input_bit_order & 0x0002 ) >> 1;
2150 outside_huffman_boundaries = TRUE;
2151 print_in_loop = print_level_3;
2154 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &bits_n);
2155 if (print_in_loop ){
2156 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u bits_n %u",
2157 operand_address, bits_n);
2159 operand_address = next_operand_address;
2161 /* %lower_bound_n */
2162 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &lower_bound_n);
2163 if (print_in_loop ){
2164 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u lower_bound_n %u",
2165 operand_address, lower_bound_n);
2167 operand_address = next_operand_address;
2168 /* %upper_bound_n */
2169 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &upper_bound_n);
2170 if (print_in_loop ){
2171 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u upper_bound_n %u",
2172 operand_address, upper_bound_n);
2174 operand_address = next_operand_address;
2175 /* %uncompressed_n */
2176 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &uncompressed_n);
2177 if (print_in_loop ){
2178 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u uncompressed_n %u",
2179 operand_address, uncompressed_n);
2181 operand_address = next_operand_address;
2182 /* execute instruction */
2183 if ( outside_huffman_boundaries ) {
2185 * 2. Request bits_j compressed bits. Interpret the returned bits as an
2186 * integer k from 0 to 2^bits_j - 1, as explained in Section 8.2.
2188 k = decomp_dispatch_get_bits( message_tvb, udvm_tree, bit_order,
2189 buff, &old_input_bit_order, &remaining_bits,
2190 &input_bits, &input_address, bits_n, &result_code, msg_end);
2191 if ( result_code == 11 ){
2193 * 4. If data is requested that lies beyond the end of the SigComp
2194 * message, terminate the INPUT-HUFFMAN instruction and move program
2195 * execution to the memory address specified by the address operand.
2197 current_address = at_address;
2198 goto execute_next_instruction;
2202 * 3. Set H := H * 2^bits_j + k.
2203 * [In practice is a shift+OR operation.]
2206 H = (H << bits_n) | k;
2207 if (print_level_3 ){
2208 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," Set H(%u) := H(%u) * 2^bits_j(%u) + k(%u)",
2209 H ,oldH, 1<<bits_n,k);
2213 * 5. If (H < lower_bound_j) or (H > upper_bound_j) then set j := j + 1.
2214 * Then go back to Step 2, unless j > n in which case decompression
2217 if ((H < lower_bound_n) || (H > upper_bound_n)){
2218 outside_huffman_boundaries = TRUE;
2220 outside_huffman_boundaries = FALSE;
2221 print_in_loop = FALSE;
2223 * 6. Copy (H + uncompressed_j - lower_bound_j) modulo 2^16 to the
2224 * memory address specified by the destination operand.
2226 if (print_level_2 ){
2227 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2228 " H(%u) = H(%u) + uncompressed_n(%u) - lower_bound_n(%u)",
2229 (H + uncompressed_n - lower_bound_n ),H, uncompressed_n, lower_bound_n);
2231 H = H + uncompressed_n - lower_bound_n;
2234 if (destination >= UDVM_MEMORY_SIZE - 1)
2235 goto decompression_failure;
2236 buff[destination] = msb;
2237 buff[destination + 1]=lsb;
2238 if (print_level_1 ){
2239 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
2240 " Loading H: %u (0x%x) at Addr: %u,j = %u remaining_bits: %u",
2241 H, H, destination,( n - m + 1 ), remaining_bits);
2250 if ( outside_huffman_boundaries ) {
2252 goto decompression_failure;
2255 current_address = next_operand_address;
2256 goto execute_next_instruction;
2259 case SIGCOMP_INSTR_STATE_ACCESS: /* 31 */
2260 /* STATE-ACCESS (%partial_identifier_start, %partial_identifier_length,
2261 * %state_begin, %state_length, %state_address, %state_instruction)
2263 if (show_instr_detail_level == 2 ){
2264 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2265 "Addr: %u ## STATE-ACCESS(31) (partial_identifier_start, partial_identifier_length,state_begin, state_length, state_address, state_instruction)",
2268 operand_address = current_address + 1;
2271 * %partial_identifier_start
2273 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &p_id_start);
2274 if (show_instr_detail_level == 2 ){
2275 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u partial_identifier_start %u",
2276 operand_address, p_id_start);
2278 operand_address = next_operand_address;
2281 * %partial_identifier_length
2283 operand_address = next_operand_address;
2284 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &p_id_length);
2285 if (show_instr_detail_level == 2 ){
2286 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u partial_identifier_length %u",
2287 operand_address, p_id_length);
2292 operand_address = next_operand_address;
2293 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_begin);
2294 if (show_instr_detail_level == 2 ){
2295 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_begin %u",
2296 operand_address, state_begin);
2301 operand_address = next_operand_address;
2302 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_length);
2303 if (show_instr_detail_level == 2 ){
2304 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_length %u",
2305 operand_address, state_length);
2310 operand_address = next_operand_address;
2311 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_address);
2312 if (show_instr_detail_level == 2 ){
2313 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_address %u",
2314 operand_address, state_address);
2317 * %state_instruction
2319 operand_address = next_operand_address;
2320 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_instruction);
2321 if (show_instr_detail_level == 2 ){
2322 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_instruction %u",
2323 operand_address, state_instruction);
2325 if (show_instr_detail_level == 1)
2327 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2328 "Addr: %u ## STATE-ACCESS(31) (partial_identifier_start=%u, partial_identifier_length=%u,state_begin=%u, state_length=%u, state_address=%u, state_instruction=%u)",
2329 current_address, p_id_start, p_id_length, state_begin, state_length, state_address, state_instruction);
2331 current_address = next_operand_address;
2332 byte_copy_right = buff[66] << 8;
2333 byte_copy_right = byte_copy_right | buff[67];
2334 byte_copy_left = buff[64] << 8;
2335 byte_copy_left = byte_copy_left | buff[65];
2336 if (print_level_2 ){
2337 proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
2338 " byte_copy_right = %u, byte_copy_left = %u", byte_copy_right,byte_copy_left);
2341 result_code = udvm_state_access(message_tvb, udvm_tree, buff, p_id_start, p_id_length, state_begin, &state_length,
2342 &state_address, &state_instruction, hf_id);
2343 if ( result_code != 0 ){
2344 goto decompression_failure;
2346 used_udvm_cycles = used_udvm_cycles + 1 + state_length;
2347 goto execute_next_instruction;
2349 case SIGCOMP_INSTR_STATE_CREATE: /* 32 */
2351 * STATE-CREATE (%state_length, %state_address, %state_instruction,
2352 * %minimum_access_length, %state_retention_priority)
2354 if (show_instr_detail_level == 2 ){
2355 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2356 "Addr: %u ## STATE-CREATE(32) (state_length, state_address, state_instruction,minimum_access_length, state_retention_priority)",
2359 operand_address = current_address + 1;
2364 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_length);
2365 if (show_instr_detail_level == 2 ){
2366 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_length %u",
2367 operand_address, state_length);
2372 operand_address = next_operand_address;
2373 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_address);
2374 if (show_instr_detail_level == 2 ){
2375 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_address %u",
2376 operand_address, state_address);
2379 * %state_instruction
2381 operand_address = next_operand_address;
2382 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_instruction);
2383 if (show_instr_detail_level == 2 ){
2384 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_instruction %u",
2385 operand_address, state_instruction);
2387 operand_address = next_operand_address;
2389 * %minimum_access_length
2391 operand_address = next_operand_address;
2392 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &minimum_access_length);
2393 if (show_instr_detail_level == 2 ){
2394 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u minimum_access_length %u",
2395 operand_address, minimum_access_length);
2397 operand_address = next_operand_address;
2399 * %state_retention_priority
2401 operand_address = next_operand_address;
2402 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_retention_priority);
2403 if (show_instr_detail_level == 2 ){
2404 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_retention_priority %u",
2405 operand_address, state_retention_priority);
2407 if (show_instr_detail_level == 1)
2409 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2410 "Addr: %u ## STATE-CREATE(32) (state_length=%u, state_address=%u, state_instruction=%u,minimum_access_length=%u, state_retention_priority=%u)",
2411 current_address, state_length, state_address, state_instruction,minimum_access_length, state_retention_priority);
2413 current_address = next_operand_address;
2414 /* Execute the instruction
2415 * TODO Implement the instruction
2417 * Note that the new state item cannot be created until a valid
2418 * compartment identifier has been returned by the application.
2419 * Consequently, when a STATE-CREATE instruction is encountered the UDVM
2420 * simply buffers the five supplied operands until the END-MESSAGE
2421 * instruction is reached. The steps taken at this point are described
2424 * Decompression failure MUST occur if more than four state creation
2425 * requests are made before the END-MESSAGE instruction is encountered.
2426 * Decompression failure also occurs if the minimum_access_length does
2427 * not lie between 6 and 20 inclusive, or if the
2428 * state_retention_priority is 65535.
2430 no_of_state_create++;
2431 if ( no_of_state_create > 4 ){
2433 goto decompression_failure;
2435 if (( minimum_access_length < 6 ) || ( minimum_access_length > STATE_BUFFER_SIZE )){
2437 goto decompression_failure;
2439 if ( state_retention_priority == 65535 ){
2441 goto decompression_failure;
2443 state_length_buff[no_of_state_create] = state_length;
2444 state_address_buff[no_of_state_create] = state_address;
2445 state_instruction_buff[no_of_state_create] = state_instruction;
2446 state_minimum_access_length_buff[no_of_state_create] = minimum_access_length;
2447 state_state_retention_priority_buff[no_of_state_create] = state_retention_priority;
2448 used_udvm_cycles = used_udvm_cycles + 1 + state_length;
2450 byte_copy_right = buff[66] << 8;
2451 byte_copy_right = byte_copy_right | buff[67];
2452 byte_copy_left = buff[64] << 8;
2453 byte_copy_left = byte_copy_left | buff[65];
2456 while ( n < state_length ){
2457 if ( k == byte_copy_right ){
2462 if (print_level_3 ){
2463 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2464 " Addr: %5u State value: %u (0x%x) ASCII(%s)",
2465 k,buff[k],buff[k],format_text(string, 1));
2467 k = ( k + 1 ) & 0xffff;
2472 goto execute_next_instruction;
2474 case SIGCOMP_INSTR_STATE_FREE: /* 33 */
2476 * STATE-FREE (%partial_identifier_start, %partial_identifier_length)
2478 if (show_instr_detail_level == 2 ){
2479 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2480 "Addr: %u ## STATE-FREE (partial_identifier_start, partial_identifier_length)",
2483 operand_address = current_address + 1;
2485 * %partial_identifier_start
2487 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &p_id_start);
2488 if (show_instr_detail_level == 2 ){
2489 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u partial_identifier_start %u",
2490 operand_address, p_id_start);
2492 operand_address = next_operand_address;
2495 * %partial_identifier_length
2497 operand_address = next_operand_address;
2498 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &p_id_length);
2499 if (show_instr_detail_level == 2 ){
2500 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u partial_identifier_length %u",
2501 operand_address, p_id_length);
2503 if (show_instr_detail_level == 1)
2505 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2506 "Addr: %u ## STATE-FREE (partial_identifier_start=%u, partial_identifier_length=%u)",
2507 current_address, p_id_start, p_id_length);
2509 current_address = next_operand_address;
2511 /* Execute the instruction:
2514 udvm_state_free(buff,p_id_start,p_id_length);
2517 goto execute_next_instruction;
2519 case SIGCOMP_INSTR_OUTPUT: /* 34 OUTPUT (%output_start, %output_length) */
2520 if (show_instr_detail_level == 2 ){
2521 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2522 "Addr: %u ## OUTPUT(34) (output_start, output_length)",
2525 operand_address = current_address + 1;
2529 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &output_start);
2530 if (show_instr_detail_level == 2 ){
2531 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u output_start %u",
2532 operand_address, output_start);
2534 operand_address = next_operand_address;
2538 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &output_length);
2539 if (show_instr_detail_level == 2 ){
2540 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u output_length %u",
2541 operand_address, output_length);
2543 if (show_instr_detail_level == 1)
2545 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2546 "Addr: %u ## OUTPUT (output_start=%u, output_length=%u)",
2547 current_address, output_start, output_length);
2549 current_address = next_operand_address;
2552 * Execute instruction
2555 * The string of bytes is copied in ascending order of memory address,
2556 * respecting the bounds set by byte_copy_left and byte_copy_right.
2557 * More precisely, if a byte is copied from/to Address m then the next
2558 * byte is copied from/to Address n where n is calculated as follows:
2560 * Set k := m + 1 (modulo 2^16)
2561 * If k = byte_copy_right then set n := byte_copy_left, else set n := k
2567 byte_copy_right = buff[66] << 8;
2568 byte_copy_right = byte_copy_right | buff[67];
2569 byte_copy_left = buff[64] << 8;
2570 byte_copy_left = byte_copy_left | buff[65];
2571 if (print_level_3 ){
2572 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2573 " byte_copy_right = %u", byte_copy_right);
2575 while ( n < output_length ){
2577 if ( k == byte_copy_right ){
2580 out_buff[output_address] = buff[k];
2583 if (print_level_3 ){
2584 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2585 " Output value: %u (0x%x) ASCII(%s) from Addr: %u ,output to dispatcher position %u",
2586 buff[k],buff[k],format_text(string,1), k,output_address);
2588 k = ( k + 1 ) & 0xffff;
2592 used_udvm_cycles = used_udvm_cycles + 1 + output_length;
2593 goto execute_next_instruction;
2595 case SIGCOMP_INSTR_END_MESSAGE: /* 35 */
2597 * END-MESSAGE (%requested_feedback_location,
2598 * %returned_parameters_location, %state_length, %state_address,
2599 * %state_instruction, %minimum_access_length,
2600 * %state_retention_priority)
2602 if (show_instr_detail_level == 2 ){
2603 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2604 "Addr: %u ## END-MESSAGE (requested_feedback_location,state_instruction, minimum_access_length,state_retention_priority)",
2607 operand_address = current_address + 1;
2609 /* %requested_feedback_location */
2610 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &requested_feedback_location);
2611 if (show_instr_detail_level == 2 ){
2612 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u requested_feedback_location %u",
2613 operand_address, requested_feedback_location);
2615 operand_address = next_operand_address;
2616 /* returned_parameters_location */
2617 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &returned_parameters_location);
2618 if (show_instr_detail_level == 2 ){
2619 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u returned_parameters_location %u",
2620 operand_address, returned_parameters_location);
2622 operand_address = next_operand_address;
2626 operand_address = next_operand_address;
2627 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_length);
2628 if (show_instr_detail_level == 2 ){
2629 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_length %u",
2630 operand_address, state_length);
2635 operand_address = next_operand_address;
2636 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_address);
2637 if (show_instr_detail_level == 2 ){
2638 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_address %u",
2639 operand_address, state_address);
2642 * %state_instruction
2644 operand_address = next_operand_address;
2645 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_instruction);
2646 if (show_instr_detail_level == 2 ){
2647 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_instruction %u",
2648 operand_address, state_instruction);
2652 * %minimum_access_length
2654 operand_address = next_operand_address;
2655 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &minimum_access_length);
2656 if (show_instr_detail_level == 2 ){
2657 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u minimum_access_length %u",
2658 operand_address, minimum_access_length);
2662 * %state_retention_priority
2664 operand_address = next_operand_address;
2665 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_retention_priority);
2666 if (show_instr_detail_level == 2 ){
2667 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_retention_priority %u",
2668 operand_address, state_retention_priority);
2670 if (show_instr_detail_level == 1)
2672 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
2673 "Addr: %u ## END-MESSAGE (requested_feedback_location=%u, returned_parameters_location=%u, state_length=%u, state_address=%u, state_instruction=%u, minimum_access_length=%u, state_retention_priority=%u)",
2674 current_address, requested_feedback_location, returned_parameters_location, state_length, state_address, state_instruction, minimum_access_length,state_retention_priority);
2676 current_address = next_operand_address;
2677 /* TODO: This isn't currently totaly correct as END_INSTRUCTION might not create state */
2678 no_of_state_create++;
2679 if ( no_of_state_create > 4 ){
2681 goto decompression_failure;
2683 state_length_buff[no_of_state_create] = state_length;
2684 state_address_buff[no_of_state_create] = state_address;
2685 state_instruction_buff[no_of_state_create] = state_instruction;
2687 state_minimum_access_length_buff[no_of_state_create] = minimum_access_length;
2688 state_state_retention_priority_buff[no_of_state_create] = state_retention_priority;
2690 /* Execute the instruction
2692 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"no_of_state_create %u",no_of_state_create);
2693 if ( no_of_state_create != 0 ){
2694 memset(sha1_digest_buf, 0, STATE_BUFFER_SIZE);
2696 byte_copy_right = buff[66] << 8;
2697 byte_copy_right = byte_copy_right | buff[67];
2698 byte_copy_left = buff[64] << 8;
2699 byte_copy_left = byte_copy_left | buff[65];
2700 while ( n < no_of_state_create + 1 ){
2701 sha1buff = g_malloc(state_length_buff[n]+8);
2702 sha1buff[0] = state_length_buff[n] >> 8;
2703 sha1buff[1] = state_length_buff[n] & 0xff;
2704 sha1buff[2] = state_address_buff[n] >> 8;
2705 sha1buff[3] = state_address_buff[n] & 0xff;
2706 sha1buff[4] = state_instruction_buff[n] >> 8;
2707 sha1buff[5] = state_instruction_buff[n] & 0xff;
2708 sha1buff[6] = state_minimum_access_length_buff[n] >> 8;
2709 sha1buff[7] = state_minimum_access_length_buff[n] & 0xff;
2710 if (print_level_3 ){
2711 for( x=0; x < 8; x++){
2712 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"sha1buff %u 0x%x",
2716 k = state_address_buff[n];
2717 for( x=0; x < state_length_buff[n]; x++)
2719 if ( k == byte_copy_right ){
2722 sha1buff[8+x] = buff[k];
2723 k = ( k + 1 ) & 0xffff;
2726 sha1_starts( &ctx );
2727 sha1_update( &ctx, (guint8 *) sha1buff, state_length_buff[n] + 8);
2728 sha1_finish( &ctx, sha1_digest_buf );
2729 if (print_level_3 ){
2730 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"SHA1 digest %s",bytes_to_str(sha1_digest_buf, STATE_BUFFER_SIZE));
2733 udvm_state_create(sha1buff, sha1_digest_buf, state_minimum_access_length_buff[n]);
2734 proto_tree_add_text(udvm_tree,bytecode_tvb, 0, -1,"### Creating state ###");
2735 proto_tree_add_string(udvm_tree,hf_id, bytecode_tvb, 0, 0, bytes_to_str(sha1_digest_buf, state_minimum_access_length_buff[n]));
2744 /* At least something got decompressed, show it */
2745 decomp_tvb = tvb_new_real_data(out_buff,output_address,output_address);
2746 /* Arrange that the allocated packet data copy be freed when the
2749 tvb_set_free_cb( decomp_tvb, g_free );
2751 tvb_set_child_real_data_tvbuff(message_tvb,decomp_tvb);
2752 add_new_data_source(pinfo, decomp_tvb, "Decompressed SigComp message");
2754 proto_tree_add_text(udvm_tree, decomp_tvb, 0, -1,"SigComp message Decompressed");
2756 used_udvm_cycles = used_udvm_cycles + 1 + state_length;
2757 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"maximum_UDVM_cycles %u used_udvm_cycles %u",
2758 maximum_UDVM_cycles, used_udvm_cycles);
2763 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," ### Addr %u Invalid instruction: %u (0x%x)",
2764 current_address,current_instruction,current_instruction);
2769 decompression_failure:
2771 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"DECOMPRESSION FAILURE: %s",
2772 val_to_str(result_code, result_code_vals,"Unknown (%u)"));
2773 THROW(ReportedBoundsError);
2779 /* The simplest operand type is the literal (#), which encodes a
2780 * constant integer from 0 to 65535 inclusive. A literal operand may
2781 * require between 1 and 3 bytes depending on its value.
2782 * Bytecode: Operand value: Range:
2783 * 0nnnnnnn N 0 - 127
2784 * 10nnnnnn nnnnnnnn N 0 - 16383
2785 * 11000000 nnnnnnnn nnnnnnnn N 0 - 65535
2787 * Figure 8: Bytecode for a literal (#) operand
2791 decode_udvm_literal_operand(guint8 *buff,guint operand_address, guint16 *value)
2796 guint offset = operand_address;
2799 bytecode = buff[operand_address];
2800 test_bits = bytecode >> 7;
2801 if (test_bits == 1){
2802 test_bits = bytecode >> 6;
2803 if (test_bits == 2){
2805 * 10nnnnnn nnnnnnnn N 0 - 16383
2807 temp_data = buff[operand_address] & 0x1f;
2808 operand = temp_data << 8;
2809 temp_data = buff[operand_address + 1];
2810 operand = operand | temp_data;
2812 offset = offset + 2;
2816 * 111000000 nnnnnnnn nnnnnnnn N 0 - 65535
2819 temp_data = buff[operand_address] & 0x1f;
2820 operand = temp_data << 8;
2821 temp_data = buff[operand_address + 1];
2822 operand = operand | temp_data;
2824 offset = offset + 2;
2829 * 0nnnnnnn N 0 - 127
2831 operand = ( bytecode & 0x7f);
2841 * The second operand type is the reference ($), which is always used to
2842 * access a 2-byte value located elsewhere in the UDVM memory. The
2843 * bytecode for a reference operand is decoded to be a constant integer
2844 * from 0 to 65535 inclusive, which is interpreted as the memory address
2845 * containing the actual value of the operand.
2846 * Bytecode: Operand value: Range:
2848 * 0nnnnnnn memory[2 * N] 0 - 65535
2849 * 10nnnnnn nnnnnnnn memory[2 * N] 0 - 65535
2850 * 11000000 nnnnnnnn nnnnnnnn memory[N] 0 - 65535
2852 * Figure 9: Bytecode for a reference ($) operand
2855 dissect_udvm_reference_operand(guint8 *buff,guint operand_address, guint16 *value,guint *result_dest)
2859 guint offset = operand_address;
2862 guint16 temp_data16;
2864 bytecode = buff[operand_address];
2865 test_bits = bytecode >> 7;
2866 if (test_bits == 1){
2867 test_bits = bytecode >> 6;
2868 if (test_bits == 2){
2870 * 10nnnnnn nnnnnnnn memory[2 * N] 0 - 65535
2872 temp_data = buff[operand_address] & 0x3f;
2873 operand = temp_data << 8;
2874 temp_data = buff[operand_address + 1];
2875 operand = operand | temp_data;
2876 operand = (operand * 2);
2877 *result_dest = operand;
2878 temp_data16 = buff[operand] << 8;
2879 temp_data16 = temp_data16 | buff[operand+1];
2880 *value = temp_data16;
2881 offset = offset + 2;
2885 * 11000000 nnnnnnnn nnnnnnnn memory[N] 0 - 65535
2888 operand = buff[operand_address] << 8;
2889 operand = operand | buff[operand_address + 1];
2890 *result_dest = operand;
2891 temp_data16 = buff[operand] << 8;
2892 temp_data16 = temp_data16 | buff[operand+1];
2893 *value = temp_data16;
2894 offset = offset + 3;
2899 * 0nnnnnnn memory[2 * N] 0 - 65535
2901 operand = ( bytecode & 0x7f);
2902 operand = (operand * 2);
2903 *result_dest = operand;
2904 temp_data16 = buff[operand] << 8;
2905 temp_data16 = temp_data16 | buff[operand+1];
2906 *value = temp_data16;
2910 if (offset >= UDVM_MEMORY_SIZE || *result_dest >= UDVM_MEMORY_SIZE - 1 )
2911 THROW(ReportedBoundsError);
2917 * Figure 10: Bytecode for a multitype (%) operand
2918 * Bytecode: Operand value: Range: HEX val
2919 * 00nnnnnn N 0 - 63 0x00
2920 * 01nnnnnn memory[2 * N] 0 - 65535 0x40
2921 * 1000011n 2 ^ (N + 6) 64 , 128 0x86
2922 * 10001nnn 2 ^ (N + 8) 256 , ... , 32768 0x88
2923 * 111nnnnn N + 65504 65504 - 65535 0xe0
2924 * 1001nnnn nnnnnnnn N + 61440 61440 - 65535 0x90
2925 * 101nnnnn nnnnnnnn N 0 - 8191 0xa0
2926 * 110nnnnn nnnnnnnn memory[N] 0 - 65535 0xc0
2927 * 10000000 nnnnnnnn nnnnnnnn N 0 - 65535 0x80
2928 * 10000001 nnnnnnnn nnnnnnnn memory[N] 0 - 65535 0x81
2931 decode_udvm_multitype_operand(guint8 *buff,guint operand_address, guint16 *value)
2935 guint offset = operand_address;
2939 guint16 temp_data16;
2940 guint16 memmory_addr = 0;
2942 bytecode = buff[operand_address];
2943 test_bits = ( bytecode & 0xc0 ) >> 6;
2944 switch (test_bits ){
2949 operand = buff[operand_address];
2951 *g_warning("Reading 0x%x From address %u",operand,offset);
2958 * 01nnnnnn memory[2 * N] 0 - 65535
2960 memmory_addr = ( bytecode & 0x3f) * 2;
2961 temp_data16 = buff[memmory_addr] << 8;
2962 temp_data16 = temp_data16 | buff[memmory_addr+1];
2963 *value = temp_data16;
2967 /* Check tree most significant bits */
2968 test_bits = ( bytecode & 0xe0 ) >> 5;
2969 if ( test_bits == 5 ){
2971 * 101nnnnn nnnnnnnn N 0 - 8191
2973 temp_data = buff[operand_address] & 0x1f;
2974 operand = temp_data << 8;
2975 temp_data = buff[operand_address + 1];
2976 operand = operand | temp_data;
2978 offset = offset + 2;
2980 test_bits = ( bytecode & 0xf0 ) >> 4;
2981 if ( test_bits == 9 ){
2983 * 1001nnnn nnnnnnnn N + 61440 61440 - 65535
2985 temp_data = buff[operand_address] & 0x0f;
2986 operand = temp_data << 8;
2987 temp_data = buff[operand_address + 1];
2988 operand = operand | temp_data;
2989 operand = operand + 61440;
2991 offset = offset + 2;
2993 test_bits = ( bytecode & 0x08 ) >> 3;
2994 if ( test_bits == 1){
2996 * 10001nnn 2 ^ (N + 8) 256 , ... , 32768
2999 result = 1 << ((buff[operand_address] & 0x07) + 8);
3000 operand = result & 0xffff;
3004 test_bits = ( bytecode & 0x0e ) >> 1;
3005 if ( test_bits == 3 ){
3007 * 1000 011n 2 ^ (N + 6) 64 , 128
3009 result = 1 << ((buff[operand_address] & 0x01) + 6);
3010 operand = result & 0xffff;
3015 * 1000 0000 nnnnnnnn nnnnnnnn N 0 - 65535
3016 * 1000 0001 nnnnnnnn nnnnnnnn memory[N] 0 - 65535
3019 temp_data16 = buff[operand_address + 1] << 8;
3020 temp_data16 = temp_data16 | buff[operand_address + 2];
3022 * g_warning("Reading 0x%x From address %u",temp_data16,operand_address);
3024 if ( (bytecode & 0x01) == 1 ){
3025 memmory_addr = temp_data16;
3026 temp_data16 = buff[memmory_addr] << 8;
3027 temp_data16 = temp_data16 | buff[memmory_addr+1];
3029 *value = temp_data16;
3040 test_bits = ( bytecode & 0x20 ) >> 5;
3041 if ( test_bits == 1 ){
3043 * 111nnnnn N + 65504 65504 - 65535
3045 operand = ( buff[operand_address] & 0x1f) + 65504;
3050 * 110nnnnn nnnnnnnn memory[N] 0 - 65535
3052 memmory_addr = buff[operand_address] & 0x1f;
3053 memmory_addr = memmory_addr << 8;
3054 memmory_addr = memmory_addr | buff[operand_address + 1];
3055 temp_data16 = buff[memmory_addr] << 8;
3056 temp_data16 = temp_data16 | buff[memmory_addr+1];
3057 *value = temp_data16;
3059 * g_warning("Reading 0x%x From address %u",temp_data16,memmory_addr);
3071 * The fourth operand type is the address (@). This operand is decoded
3072 * as a multitype operand followed by a further step: the memory address
3073 * of the UDVM instruction containing the address operand is added to
3074 * obtain the correct operand value. So if the operand value from
3075 * Figure 10 is D then the actual operand value of an address is
3076 * calculated as follows:
3078 * operand_value = (memory_address_of_instruction + D) modulo 2^16
3080 * Address operands are always used in instructions that control program
3081 * flow, because they ensure that the UDVM bytecode is position-
3082 * independent code (i.e., it will run independently of where it is
3083 * placed in the UDVM memory).
3086 decode_udvm_address_operand(guint8 *buff,guint operand_address, guint16 *value,guint current_address)
3090 guint next_opreand_address;
3092 next_opreand_address = decode_udvm_multitype_operand(buff, operand_address, &value1);
3093 result = value1 & 0xffff;
3094 result = result + current_address;
3095 *value = result & 0xffff;
3096 return next_opreand_address;
3101 * This is a lookup table used to reverse the bits in a byte.
3103 static guint8 reverse [] = {
3104 0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0,
3105 0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0,
3106 0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8,
3107 0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8,
3108 0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4,
3109 0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4,
3110 0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC,
3111 0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC,
3112 0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2,
3113 0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2,
3114 0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA,
3115 0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA,
3116 0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6,
3117 0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6,
3118 0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE,
3119 0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE,
3120 0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1,
3121 0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1,
3122 0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9,
3123 0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9,
3124 0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5,
3125 0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5,
3126 0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED,
3127 0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD,
3128 0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3,
3129 0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3,
3130 0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB,
3131 0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB,
3132 0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7,
3133 0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7,
3134 0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF,
3135 0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF
3140 decomp_dispatch_get_bits(
3141 tvbuff_t *message_tvb,
3142 proto_tree *udvm_tree,
3145 guint16 *old_input_bit_order,
3146 guint16 *remaining_bits,
3147 guint16 *input_bits,
3148 guint *input_address,
3150 guint16 *result_code,
3153 guint16 input_bit_order;
3154 guint16 bits_still_required = length;
3157 gint extra_bytes_available = msg_end - *input_address;
3159 gint prev_p_bit = *old_input_bit_order & 0x0001;
3160 gint bits_to_use = 0;
3163 input_bit_order = buff[68] << 8;
3164 input_bit_order = input_bit_order | buff[69];
3166 p_bit = (input_bit_order & 0x0001) != 0;
3169 * Discard any spare bits.
3170 * Note: We take care to avoid remaining_bits having the value of 8.
3172 if (prev_p_bit != p_bit)
3174 *remaining_bits = 0;
3175 *old_input_bit_order = input_bit_order;
3179 * Check we can suppy the required number of bits now, before we alter
3180 * the input buffer's state.
3182 if (*remaining_bits + extra_bytes_available * 8 < length)
3188 /* Note: This is never called with length > 16, so the following loop
3189 * never loops more than three time. */
3190 while (bits_still_required > 0)
3193 * We only put anything into input_bits if we know we will remove
3194 * at least one bit. That ensures we can simply discard the spare
3195 * bits if the P-bit changes.
3197 if (*remaining_bits == 0)
3199 octet = tvb_get_guint8(message_tvb, *input_address);
3200 if (print_level_1 ){
3201 proto_tree_add_text(udvm_tree, message_tvb, *input_address , 1,
3202 " Geting value: %u (0x%x) From Addr: %u", octet, octet, *input_address);
3204 *input_address = *input_address + 1;
3208 octet = reverse[octet];
3210 *input_bits = octet;
3211 *remaining_bits = 8;
3214 /* Add some more bits to the accumulated value. */
3215 bits_to_use = bits_still_required < *remaining_bits ? bits_still_required : *remaining_bits;
3216 bits_still_required -= bits_to_use;
3218 *input_bits <<= bits_to_use; /* Shift bits into MSByte */
3219 value = (value << bits_to_use) /* Then add to the accumulated value */
3220 | ((*input_bits >> 8) & 0xFF);
3221 *remaining_bits -= bits_to_use;
3222 *input_bits &= 0x00FF; /* Leave just the remaining bits */
3227 /* Bit reverse the entire word. */
3228 guint16 lsb = reverse[(value >> 8) & 0xFF];
3229 guint16 msb = reverse[value & 0xFF];
3231 value = ((msb << 8) | lsb) >> (16 - length);