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