2 * Routines making up the Universal Decompressor Virtual Machine (UDVM) used for
3 * Signaling Compression (SigComp) dissection.
4 * Copyright 2004, Anders Broman <anders.broman@ericsson.com>
8 * Wireshark - Network traffic analyzer
9 * By Gerald Combs <gerald@wireshark.org>
10 * Copyright 1998 Gerald Combs
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
26 * http://www.ietf.org/rfc/rfc3320.txt?number=3320
27 * http://www.ietf.org/rfc/rfc3321.txt?number=3321
29 * http://www.ietf.org/internet-drafts/draft-ietf-rohc-sigcomp-impl-guide-05.txt
30 * http://www.ietf.org/internet-drafts/draft-ietf-rohc-sigcomp-sip-01.txt
40 #include <epan/emem.h>
42 #include <wsutil/sha1.h>
43 #include <wsutil/crc16.h>
46 #include "exceptions.h"
49 #include "sigcomp-udvm.h"
50 #include "sigcomp_state_hdlr.h"
53 #define SIGCOMP_INSTR_DECOMPRESSION_FAILURE 0
54 #define SIGCOMP_INSTR_AND 1
55 #define SIGCOMP_INSTR_OR 2
56 #define SIGCOMP_INSTR_NOT 3
57 #define SIGCOMP_INSTR_LSHIFT 4
58 #define SIGCOMP_INSTR_RSHIFT 5
59 #define SIGCOMP_INSTR_ADD 6
60 #define SIGCOMP_INSTR_SUBTRACT 7
61 #define SIGCOMP_INSTR_MULTIPLY 8
62 #define SIGCOMP_INSTR_DIVIDE 9
63 #define SIGCOMP_INSTR_REMAINDER 10
64 #define SIGCOMP_INSTR_SORT_ASCENDING 11
65 #define SIGCOMP_INSTR_SORT_DESCENDING 12
66 #define SIGCOMP_INSTR_SHA_1 13
67 #define SIGCOMP_INSTR_LOAD 14
68 #define SIGCOMP_INSTR_MULTILOAD 15
69 #define SIGCOMP_INSTR_PUSH 16
70 #define SIGCOMP_INSTR_POP 17
71 #define SIGCOMP_INSTR_COPY 18
72 #define SIGCOMP_INSTR_COPY_LITERAL 19
73 #define SIGCOMP_INSTR_COPY_OFFSET 20
74 #define SIGCOMP_INSTR_MEMSET 21
75 #define SIGCOMP_INSTR_JUMP 22
76 #define SIGCOMP_INSTR_COMPARE 23
77 #define SIGCOMP_INSTR_CALL 24
78 #define SIGCOMP_INSTR_RETURN 25
79 #define SIGCOMP_INSTR_SWITCH 26
80 #define SIGCOMP_INSTR_CRC 27
81 #define SIGCOMP_INSTR_INPUT_BYTES 28
82 #define SIGCOMP_INSTR_INPUT_BITS 29
83 #define SIGCOMP_INSTR_INPUT_HUFFMAN 30
84 #define SIGCOMP_INSTR_STATE_ACCESS 31
85 #define SIGCOMP_INSTR_STATE_CREATE 32
86 #define SIGCOMP_INSTR_STATE_FREE 33
87 #define SIGCOMP_INSTR_OUTPUT 34
88 #define SIGCOMP_INSTR_END_MESSAGE 35
91 static gboolean print_level_1
;
92 static gboolean print_level_2
;
93 static gboolean print_level_3
;
94 static gint show_instr_detail_level
;
96 /* Internal result code values of decompression failures */
97 const value_string result_code_vals
[] = {
98 { 0, "No decompression failure" },
99 { 1, "Partial state length less than 6 or greater than 20 bytes long" },
100 { 2, "No state match" },
101 { 3, "state_begin + state_length > size of state" },
102 { 4, "Operand_2 is Zero" },
103 { 5, "Switch statement failed j >= n" },
104 { 6, "Attempt to jump outside of UDVM memory" },
105 { 7, "L in input-bits > 16" },
106 { 8, "input_bit_order > 7" },
107 { 9, "Instruction Decompression failure encountered" },
108 {10, "Input huffman failed j > n" },
109 {11, "Input bits requested beyond end of message" },
110 {12, "more than four state creation requests are made before the END-MESSAGE instruction" },
111 {13, "state_retention_priority is 65535" },
112 {14, "Input bytes requested beyond end of message" },
113 {15, "Maximum number of UDVM cycles reached" },
114 {16, "UDVM stack underflow" },
115 { 255, "This branch isn't coded yet" },
119 static int decode_udvm_literal_operand(guint8
*buff
,guint operand_address
, guint16
*value
);
120 static int dissect_udvm_reference_operand(guint8
*buff
,guint operand_address
, guint16
*value
, guint
*result_dest
);
121 static int decode_udvm_multitype_operand(guint8
*buff
,guint operand_address
,guint16
*value
);
122 static int decode_udvm_address_operand(guint8
*buff
,guint operand_address
, guint16
*value
,guint current_address
);
123 static int decomp_dispatch_get_bits(tvbuff_t
*message_tvb
,proto_tree
*udvm_tree
,guint8 bit_order
,
124 guint8
*buff
,guint16
*old_input_bit_order
, guint16
*remaining_bits
,
125 guint16
*input_bits
, guint
*input_address
, guint16 length
, guint16
*result_code
,guint msg_end
);
129 decompress_sigcomp_message(tvbuff_t
*bytecode_tvb
, tvbuff_t
*message_tvb
, packet_info
*pinfo
,
130 proto_tree
*udvm_tree
, gint udvm_mem_dest
,
131 gint print_flags
, gint hf_id
,
133 gint byte_code_state_len
, gint byte_code_id_len
,
136 tvbuff_t
*decomp_tvb
;
137 /* UDVM memory must be initialised to zero */
138 guint8
*buff
= (guint8
*)ep_alloc0(UDVM_MEMORY_SIZE
);
140 guint8
*out_buff
; /* Largest allowed size for a message is UDVM_MEMORY_SIZE = 65536 */
150 guint code_length
=0;
151 guint8 current_instruction
;
152 guint current_address
;
153 guint operand_address
;
155 guint16 output_address
= 0;
156 guint next_operand_address
;
160 guint16 byte_copy_right
;
161 guint16 byte_copy_left
;
162 guint16 input_bit_order
;
163 guint16 stack_location
;
166 guint msg_end
= tvb_reported_length_remaining(message_tvb
, 0);
167 guint16 result_code
= 0;
168 guint16 old_input_bit_order
= 0;
169 guint16 remaining_bits
= 0;
170 guint16 input_bits
= 0;
171 guint8 bit_order
= 0;
172 gboolean outside_huffman_boundaries
= TRUE
;
173 gboolean print_in_loop
= FALSE
;
174 guint16 instruction_address
;
175 guint8 no_of_state_create
= 0;
176 guint16 state_length_buff
[5];
177 guint16 state_address_buff
[5];
178 guint16 state_instruction_buff
[5];
179 guint16 state_minimum_access_length_buff
[5];
180 /* guint16 state_state_retention_priority_buff[5]; */
181 guint32 used_udvm_cycles
= 0;
182 guint cycles_per_bit
;
183 guint maximum_UDVM_cycles
;
185 unsigned char sha1_digest_buf
[STATE_BUFFER_SIZE
];
189 /* UDVM operand variables */
198 guint16 state_length
;
199 guint16 state_address
;
200 guint16 state_instruction
;
205 guint16 at_address_1
;
206 guint16 at_address_2
;
207 guint16 at_address_3
;
210 guint16 lower_bound_n
;
211 guint16 upper_bound_n
;
212 guint16 uncompressed_n
;
214 guint16 ref_destination
; /* could I have used $destination ? */
215 guint16 multy_offset
;
216 guint16 output_start
;
217 guint16 output_length
;
218 guint16 minimum_access_length
;
219 guint16 state_retention_priority
;
220 guint16 requested_feedback_location
;
221 guint16 returned_parameters_location
;
225 /* Set print parameters */
226 print_level_1
= FALSE
;
227 print_level_2
= FALSE
;
228 print_level_3
= FALSE
;
229 show_instr_detail_level
= 0;
233 switch( print_flags
) {
238 print_level_1
= TRUE
;
239 show_instr_detail_level
= 1;
242 print_level_1
= TRUE
;
243 print_level_2
= TRUE
;
244 show_instr_detail_level
= 1;
247 print_level_1
= TRUE
;
248 print_level_2
= TRUE
;
249 print_level_3
= TRUE
;
250 show_instr_detail_level
= 2;
253 print_level_1
= TRUE
;
254 show_instr_detail_level
= 1;
258 /* Set initial UDVM data
259 * The first 32 bytes of UDVM memory are then initialized to special
260 * values as illustrated in Figure 5.
263 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
264 * | UDVM_memory_size | 0 - 1
265 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
266 * | cycles_per_bit | 2 - 3
267 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
268 * | SigComp_version | 4 - 5
269 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
270 * | partial_state_ID_length | 6 - 7
271 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
272 * | state_length | 8 - 9
273 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
275 * : reserved : 10 - 31
277 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
279 * Figure 5: Initializing Useful Values in UDVM memory
281 /* UDVM_memory_size */
282 buff
[0] = (UDVM_MEMORY_SIZE
>> 8) & 0x00FF;
283 buff
[1] = UDVM_MEMORY_SIZE
& 0x00FF;
287 /* SigComp_version */
290 /* partial_state_ID_length */
291 buff
[6] = (byte_code_id_len
>> 8) & 0x00FF;
292 buff
[7] = byte_code_id_len
& 0x00FF;
294 buff
[8] = (byte_code_state_len
>> 8) & 0x00FF;
295 buff
[9] = byte_code_state_len
& 0x00FF;
297 code_length
= tvb_reported_length_remaining(bytecode_tvb
, 0);
299 cycles_per_bit
= buff
[2] << 8;
300 cycles_per_bit
= cycles_per_bit
| buff
[3];
302 * maximum_UDVM_cycles = (8 * n + 1000) * cycles_per_bit
304 maximum_UDVM_cycles
= (( 8 * (header_len
+ msg_end
) ) + 1000) * cycles_per_bit
;
306 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
);
307 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
);
309 /* Load bytecode into UDVM starting at "udvm_mem_dest" */
312 proto_tree_add_text(udvm_tree
, bytecode_tvb
, offset
, 1,"Load bytecode into UDVM starting at %u",i
);
313 while ( code_length
> offset
&& i
< UDVM_MEMORY_SIZE
) {
314 buff
[i
] = tvb_get_guint8(bytecode_tvb
, offset
);
316 proto_tree_add_text(udvm_tree
, bytecode_tvb
, offset
, 1,
317 " Addr: %u Instruction code(0x%0x) ", i
, buff
[i
]);
323 /* Largest allowed size for a message is UDVM_MEMORY_SIZE = 65536 */
324 out_buff
= (guint8
*)g_malloc(UDVM_MEMORY_SIZE
);
325 /* Start executing code */
326 current_address
= udvm_start_ip
;
329 proto_tree_add_text(udvm_tree
, bytecode_tvb
, offset
, 1,"UDVM EXECUTION STARTED at Address: %u Message size %u",
330 current_address
, msg_end
);
332 execute_next_instruction
:
334 if ( used_udvm_cycles
> maximum_UDVM_cycles
){
336 goto decompression_failure
;
339 current_instruction
= buff
[current_address
& 0xffff];
341 switch ( current_instruction
) {
342 case SIGCOMP_INSTR_DECOMPRESSION_FAILURE
:
343 if ( result_code
== 0 )
345 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,
346 "Addr: %u ## DECOMPRESSION-FAILURE(0)",
348 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,"Wireshark UDVM diagnostic: %s.",
349 val_to_str(result_code
, result_code_vals
,"Unknown (%u)"));
350 if ( output_address
> 0 ){
351 /* At least something got decompressed, show it */
352 decomp_tvb
= tvb_new_child_real_data(message_tvb
, out_buff
,output_address
,output_address
);
353 /* Arrange that the allocated packet data copy be freed when the
356 tvb_set_free_cb( decomp_tvb
, g_free
);
357 /* Add the tvbuff to the list of tvbuffs to which the tvbuff we
358 * were handed refers, so it'll get cleaned up when that tvbuff
361 add_new_data_source(pinfo
, decomp_tvb
, "Decompressed SigComp message(Incomplete)");
362 proto_tree_add_text(udvm_tree
, decomp_tvb
, 0, -1,"SigComp message Decompression failure");
369 case SIGCOMP_INSTR_AND
: /* 1 AND ($operand_1, %operand_2) */
370 if (show_instr_detail_level
== 2 ){
371 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,
372 "Addr: %u ## AND(1) (operand_1, operand_2)",
376 operand_address
= current_address
+ 1;
377 next_operand_address
= dissect_udvm_reference_operand(buff
, operand_address
, &operand_1
, &result_dest
);
378 if (show_instr_detail_level
== 2 ){
379 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,"Addr: %u operand_1 %u",
380 operand_address
, operand_1
);
382 operand_address
= next_operand_address
;
384 next_operand_address
= decode_udvm_multitype_operand(buff
, operand_address
, &operand_2
);
385 if (show_instr_detail_level
== 2 ){
386 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,"Addr: %u operand_2 %u",
387 operand_address
, operand_2
);
389 if (show_instr_detail_level
== 1)
391 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,
392 "Addr: %u ## AND (operand_1=%u, operand_2=%u)",
393 current_address
, operand_1
, operand_2
);
395 /* execute the instruction */
396 result
= operand_1
& operand_2
;
399 buff
[result_dest
] = msb
;
400 buff
[(result_dest
+1) & 0xffff] = lsb
;
402 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1," Loading result %u at %u",
403 result
, result_dest
);
405 current_address
= next_operand_address
;
406 goto execute_next_instruction
;
410 case SIGCOMP_INSTR_OR
: /* 2 OR ($operand_1, %operand_2) */
411 if (show_instr_detail_level
== 2 ){
412 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,
413 "Addr: %u ## OR(2) (operand_1, operand_2)",
417 operand_address
= current_address
+ 1;
418 next_operand_address
= dissect_udvm_reference_operand(buff
, operand_address
, &operand_1
, &result_dest
);
419 if (show_instr_detail_level
== 2 ){
420 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,"Addr: %u operand_1 %u",
421 operand_address
, operand_1
);
423 operand_address
= next_operand_address
;
425 next_operand_address
= decode_udvm_multitype_operand(buff
, operand_address
, &operand_2
);
426 if (show_instr_detail_level
== 2 ){
427 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,"Addr: %u operand_2 %u",
428 operand_address
, operand_2
);
430 if (show_instr_detail_level
== 1)
432 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,
433 "Addr: %u ## OR (operand_1=%u, operand_2=%u)",
434 current_address
, operand_1
, operand_2
);
436 /* execute the instruction */
437 result
= operand_1
| operand_2
;
440 buff
[result_dest
] = msb
;
441 buff
[(result_dest
+1) & 0xffff] = lsb
;
443 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1," Loading result %u at %u",
444 result
, result_dest
);
446 current_address
= next_operand_address
;
447 goto execute_next_instruction
;
451 case SIGCOMP_INSTR_NOT
: /* 3 NOT ($operand_1) */
452 if (show_instr_detail_level
== 2 ){
453 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,
454 "Addr: %u ## NOT(3) ($operand_1)",
458 operand_address
= current_address
+ 1;
459 next_operand_address
= dissect_udvm_reference_operand(buff
, operand_address
, &operand_1
, &result_dest
);
460 if (show_instr_detail_level
== 2 ){
461 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,"Addr: %u operand_1 %u",
462 operand_address
, operand_1
);
464 if (show_instr_detail_level
== 1)
466 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,
467 "Addr: %u ## NOT (operand_1=%u)",
468 current_address
, operand_1
);
470 /* execute the instruction */
471 result
= operand_1
^ 0xffff;
474 buff
[result_dest
] = msb
;
475 buff
[(result_dest
+1) & 0xffff] = lsb
;
477 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1," Loading result %u at %u",
478 result
, result_dest
);
480 current_address
= next_operand_address
;
481 goto execute_next_instruction
;
484 case SIGCOMP_INSTR_LSHIFT
: /* 4 LSHIFT ($operand_1, %operand_2) */
485 if (show_instr_detail_level
== 2 ){
486 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,
487 "Addr: %u ## LSHIFT(4) ($operand_1, operand_2)",
491 operand_address
= current_address
+ 1;
492 next_operand_address
= dissect_udvm_reference_operand(buff
, operand_address
, &operand_1
, &result_dest
);
493 if (show_instr_detail_level
== 2 ){
494 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,"Addr: %u operand_1 %u",
495 operand_address
, operand_1
);
497 operand_address
= next_operand_address
;
499 next_operand_address
= decode_udvm_multitype_operand(buff
, operand_address
, &operand_2
);
500 if (show_instr_detail_level
== 2 ){
501 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,"Addr: %u operand_2 %u",
502 operand_address
, operand_2
);
504 if (show_instr_detail_level
== 1)
506 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,
507 "Addr: %u ## LSHIFT (operand_1=%u, operand_2=%u)",
508 current_address
, operand_1
, operand_2
);
510 /* execute the instruction */
511 result
= operand_1
<< operand_2
;
514 buff
[result_dest
] = msb
;
515 buff
[(result_dest
+1) & 0xffff] = lsb
;
517 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1," Loading result %u at %u",
518 result
, result_dest
);
520 current_address
= next_operand_address
;
521 goto execute_next_instruction
;
524 case SIGCOMP_INSTR_RSHIFT
: /* 5 RSHIFT ($operand_1, %operand_2) */
525 if (show_instr_detail_level
== 2 ){
526 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,
527 "Addr: %u ## RSHIFT(5) (operand_1, operand_2)",
531 operand_address
= current_address
+ 1;
532 next_operand_address
= dissect_udvm_reference_operand(buff
, operand_address
, &operand_1
, &result_dest
);
533 if (show_instr_detail_level
== 2 ){
534 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,"Addr: %u operand_1 %u",
535 operand_address
, operand_1
);
537 operand_address
= next_operand_address
;
539 next_operand_address
= decode_udvm_multitype_operand(buff
, operand_address
, &operand_2
);
540 if (show_instr_detail_level
== 2 ){
541 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,"Addr: %u operand_2 %u",
542 operand_address
, operand_2
);
544 if (show_instr_detail_level
== 1)
546 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,
547 "Addr: %u ## RSHIFT (operand_1=%u, operand_2=%u)",
548 current_address
, operand_1
, operand_2
);
550 /* execute the instruction */
551 result
= operand_1
>> operand_2
;
554 buff
[result_dest
] = msb
;
555 buff
[(result_dest
+1) & 0xffff] = lsb
;
557 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1," Loading result %u at %u",
558 result
, result_dest
);
560 current_address
= next_operand_address
;
561 goto execute_next_instruction
;
563 case SIGCOMP_INSTR_ADD
: /* 6 ADD ($operand_1, %operand_2) */
564 if (show_instr_detail_level
== 2 ){
565 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,
566 "Addr: %u ## ADD(6) (operand_1, operand_2)",
570 operand_address
= current_address
+ 1;
571 next_operand_address
= dissect_udvm_reference_operand(buff
, operand_address
, &operand_1
, &result_dest
);
572 if (show_instr_detail_level
== 2 ){
573 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,"Addr: %u operand_1 %u",
574 operand_address
, operand_1
);
576 operand_address
= next_operand_address
;
578 next_operand_address
= decode_udvm_multitype_operand(buff
, operand_address
, &operand_2
);
579 if (show_instr_detail_level
== 2 ){
580 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,"Addr: %u operand_2 %u",
581 operand_address
, operand_2
);
583 if (show_instr_detail_level
== 1)
585 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,
586 "Addr: %u ## ADD (operand_1=%u, operand_2=%u)",
587 current_address
, operand_1
, operand_2
);
589 /* execute the instruction */
590 result
= operand_1
+ operand_2
;
593 buff
[result_dest
] = msb
;
594 buff
[(result_dest
+1) & 0xffff] = lsb
;
596 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1," Loading result %u at %u",
597 result
, result_dest
);
599 current_address
= next_operand_address
;
600 goto execute_next_instruction
;
602 case SIGCOMP_INSTR_SUBTRACT
: /* 7 SUBTRACT ($operand_1, %operand_2) */
603 if (show_instr_detail_level
== 2 ){
604 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,
605 "Addr: %u ## SUBTRACT(7) (operand_1, operand_2)",
609 operand_address
= current_address
+ 1;
610 next_operand_address
= dissect_udvm_reference_operand(buff
, operand_address
, &operand_1
, &result_dest
);
611 if (show_instr_detail_level
== 2 ){
612 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,"Addr: %u operand_1 %u",
613 operand_address
, operand_1
);
615 operand_address
= next_operand_address
;
617 next_operand_address
= decode_udvm_multitype_operand(buff
, operand_address
, &operand_2
);
618 if (show_instr_detail_level
== 2 ){
619 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,"Addr: %u operand_2 %u",
620 operand_address
, operand_2
);
622 if (show_instr_detail_level
== 1)
624 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,
625 "Addr: %u ## SUBTRACT (operand_1=%u, operand_2=%u)",
626 current_address
, operand_1
, operand_2
);
628 /* execute the instruction */
629 result
= operand_1
- operand_2
;
632 buff
[result_dest
] = msb
;
633 buff
[(result_dest
+1) & 0xffff] = lsb
;
635 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1," Loading result %u at %u",
636 result
, result_dest
);
638 current_address
= next_operand_address
;
639 goto execute_next_instruction
;
642 case SIGCOMP_INSTR_MULTIPLY
: /* 8 MULTIPLY ($operand_1, %operand_2) */
643 if (show_instr_detail_level
== 2 ){
644 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,
645 "Addr: %u ##MULTIPLY(8) (operand_1, operand_2)",
649 operand_address
= current_address
+ 1;
650 next_operand_address
= dissect_udvm_reference_operand(buff
, operand_address
, &operand_1
, &result_dest
);
651 if (show_instr_detail_level
== 2 ){
652 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,"Addr: %u operand_1 %u",
653 operand_address
, operand_1
);
655 operand_address
= next_operand_address
;
657 next_operand_address
= decode_udvm_multitype_operand(buff
, operand_address
, &operand_2
);
658 if (show_instr_detail_level
== 2 ){
659 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,"Addr: %u operand_2 %u",
660 operand_address
, operand_2
);
662 if (show_instr_detail_level
== 1)
664 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,
665 "Addr: %u ## MULTIPLY (operand_1=%u, operand_2=%u)",
666 current_address
, operand_1
, operand_2
);
669 * execute the instruction
670 * MULTIPLY (m, n) := m * n (modulo 2^16)
672 if ( operand_2
== 0){
674 goto decompression_failure
;
676 result
= operand_1
* operand_2
;
679 buff
[result_dest
] = msb
;
680 buff
[(result_dest
+1) & 0xffff] = lsb
;
682 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1," Loading result %u at %u",
683 result
, result_dest
);
685 current_address
= next_operand_address
;
686 goto execute_next_instruction
;
689 case SIGCOMP_INSTR_DIVIDE
: /* 9 DIVIDE ($operand_1, %operand_2) */
690 if (show_instr_detail_level
== 2 ){
691 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,
692 "Addr: %u ## DIVIDE(9) (operand_1, operand_2)",
696 operand_address
= current_address
+ 1;
697 next_operand_address
= dissect_udvm_reference_operand(buff
, operand_address
, &operand_1
, &result_dest
);
698 if (show_instr_detail_level
== 2 ){
699 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,"Addr: %u operand_1 %u",
700 operand_address
, operand_1
);
702 operand_address
= next_operand_address
;
704 next_operand_address
= decode_udvm_multitype_operand(buff
, operand_address
, &operand_2
);
705 if (show_instr_detail_level
== 2 ){
706 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,"Addr: %u operand_2 %u",
707 operand_address
, operand_2
);
709 if (show_instr_detail_level
== 1)
711 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,
712 "Addr: %u ## DIVIDE (operand_1=%u, operand_2=%u)",
713 current_address
, operand_1
, operand_2
);
716 * execute the instruction
717 * DIVIDE (m, n) := floor(m / n)
718 * Decompression failure occurs if a DIVIDE or REMAINDER instruction
719 * encounters an operand_2 that is zero.
721 if ( operand_2
== 0){
723 goto decompression_failure
;
725 result
= operand_1
/ operand_2
;
728 buff
[result_dest
] = msb
;
729 buff
[(result_dest
+1) & 0xffff] = lsb
;
731 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1," Loading result %u at %u",
732 result
, result_dest
);
734 current_address
= next_operand_address
;
735 goto execute_next_instruction
;
738 case SIGCOMP_INSTR_REMAINDER
: /* 10 REMAINDER ($operand_1, %operand_2) */
739 if (show_instr_detail_level
== 2 ){
740 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,
741 "Addr: %u ## REMAINDER(10) (operand_1, operand_2)",
745 operand_address
= current_address
+ 1;
746 next_operand_address
= dissect_udvm_reference_operand(buff
, operand_address
, &operand_1
, &result_dest
);
747 if (show_instr_detail_level
== 2 ){
748 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,"Addr: %u operand_1 %u",
749 operand_address
, operand_1
);
751 operand_address
= next_operand_address
;
753 next_operand_address
= decode_udvm_multitype_operand(buff
, operand_address
, &operand_2
);
754 if (show_instr_detail_level
== 2 ){
755 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,"Addr: %u operand_2 %u",
756 operand_address
, operand_2
);
758 if (show_instr_detail_level
== 1)
760 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,
761 "Addr: %u ## REMAINDER (operand_1=%u, operand_2=%u)",
762 current_address
, operand_1
, operand_2
);
765 * execute the instruction
766 * REMAINDER (m, n) := m - n * floor(m / n)
767 * Decompression failure occurs if a DIVIDE or REMAINDER instruction
768 * encounters an operand_2 that is zero.
770 if ( operand_2
== 0){
772 goto decompression_failure
;
774 result
= operand_1
- operand_2
* (operand_1
/ operand_2
);
777 buff
[result_dest
] = msb
;
778 buff
[(result_dest
+1) & 0xffff] = lsb
;
780 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1," Loading result %u at %u",
781 result
, result_dest
);
783 current_address
= next_operand_address
;
784 goto execute_next_instruction
;
786 case SIGCOMP_INSTR_SORT_ASCENDING
: /* 11 SORT-ASCENDING (%start, %n, %k) */
788 * used_udvm_cycles = 1 + k * (ceiling(log2(k)) + n)
791 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,
792 "Addr: %u ## SORT-ASCENDING(11) (start, n, k))",
795 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,"Execution of this instruction is NOT implemented");
797 * used_udvm_cycles = 1 + k * (ceiling(log2(k)) + n)
801 case SIGCOMP_INSTR_SORT_DESCENDING
: /* 12 SORT-DESCENDING (%start, %n, %k) */
803 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,
804 "Addr: %u ## SORT-DESCENDING(12) (start, n, k))",
807 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,"Execution of this instruction is NOT implemented");
809 * used_udvm_cycles = 1 + k * (ceiling(log2(k)) + n)
812 case SIGCOMP_INSTR_SHA_1
: /* 13 SHA-1 (%position, %length, %destination) */
814 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,
815 "Addr: %u ## SHA-1(13) (position, length, destination)",
818 operand_address
= current_address
+ 1;
820 next_operand_address
= decode_udvm_multitype_operand(buff
, operand_address
, &position
);
822 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,"Addr: %u position %u",
823 operand_address
, position
);
825 operand_address
= next_operand_address
;
828 next_operand_address
= decode_udvm_multitype_operand(buff
, operand_address
, &length
);
830 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,"Addr: %u Length %u",
831 operand_address
, length
);
833 operand_address
= next_operand_address
;
836 next_operand_address
= dissect_udvm_reference_operand(buff
, operand_address
, &ref_destination
, &result_dest
);
838 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,"Addr: %u $destination %u",
839 operand_address
, ref_destination
);
841 used_udvm_cycles
= used_udvm_cycles
+ length
;
845 byte_copy_right
= buff
[66] << 8;
846 byte_copy_right
= byte_copy_right
| buff
[67];
847 byte_copy_left
= buff
[64] << 8;
848 byte_copy_left
= byte_copy_left
| buff
[65];
851 proto_tree_add_text(udvm_tree
, message_tvb
, 0, -1,
852 "byte_copy_right = %u", byte_copy_right
);
858 guint16 handle_now
= length
;
860 if ( k
< byte_copy_right
&& byte_copy_right
<= k
+ (length
-n
) ){
861 handle_now
= byte_copy_right
- position
;
864 if (k
+ handle_now
>= UDVM_MEMORY_SIZE
)
865 goto decompression_failure
;
866 sha1_update( &ctx
, &buff
[k
], handle_now
);
868 k
= ( k
+ handle_now
) & 0xffff;
869 n
= ( n
+ handle_now
) & 0xffff;
871 if ( k
>= byte_copy_right
) {
876 sha1_finish( &ctx
, sha1_digest_buf
);
880 for ( n
=0; n
< STATE_BUFFER_SIZE
; n
++ ) {
882 buff
[k
] = sha1_digest_buf
[n
];
884 k
= ( k
+ 1 ) & 0xffff;
887 if ( k
== byte_copy_right
){
893 proto_tree_add_text(udvm_tree
, message_tvb
, 0, -1,
894 "Calculated SHA-1: %s",
895 bytes_to_str(sha1_digest_buf
, STATE_BUFFER_SIZE
));
898 current_address
= next_operand_address
;
899 goto execute_next_instruction
;
902 case SIGCOMP_INSTR_LOAD
: /* 14 LOAD (%address, %value) */
903 if (show_instr_detail_level
== 2 ){
904 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,
905 "Addr: %u ## LOAD(14) (%%address, %%value)",
908 operand_address
= current_address
+ 1;
910 next_operand_address
= decode_udvm_multitype_operand(buff
, operand_address
, &addr
);
911 if (show_instr_detail_level
== 2 ){
912 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,"Addr: %u Address %u",
913 operand_address
, addr
);
915 operand_address
= next_operand_address
;
917 next_operand_address
= decode_udvm_multitype_operand(buff
, operand_address
, &value
);
918 if (show_instr_detail_level
== 1)
920 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,
921 "Addr: %u ## LOAD (%%address=%u, %%value=%u)",
922 current_address
, addr
, value
);
928 buff
[(addr
+ 1) & 0xffff] = lsb
;
931 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,"Addr: %u Value %u",
932 operand_address
, value
);
933 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1," Loading bytes at %u Value %u 0x%x",
936 current_address
= next_operand_address
;
937 goto execute_next_instruction
;
940 case SIGCOMP_INSTR_MULTILOAD
: /* 15 MULTILOAD (%address, #n, %value_0, ..., %value_n-1) */
942 * The MULTILOAD instruction sets a contiguous block of 2-byte words in
943 * the UDVM memory to specified values.
944 * Hmm what if the value to load only takes one byte ? Chose to always load two bytes.
946 if (show_instr_detail_level
== 2 ){
947 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,
948 "Addr: %u ## MULTILOAD(15) (%%address, #n, value_0, ..., value_n-1)",
951 operand_address
= current_address
+ 1;
953 next_operand_address
= decode_udvm_multitype_operand(buff
, operand_address
, &addr
);
954 if (show_instr_detail_level
== 2 ){
955 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,"Addr: %u Address %u",
956 operand_address
, addr
);
958 operand_address
= next_operand_address
;
961 next_operand_address
= decode_udvm_literal_operand(buff
,operand_address
, &n
);
962 if (show_instr_detail_level
== 2 ){
963 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,"Addr: %u n %u",
966 if (show_instr_detail_level
== 1)
968 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,
969 "Addr: %u ## MULTILOAD (%%address=%u, #n=%u, value_0, ..., value_%d)",
970 current_address
, addr
, n
, n
-1);
972 operand_address
= next_operand_address
;
973 used_udvm_cycles
= used_udvm_cycles
+ n
;
977 next_operand_address
= decode_udvm_multitype_operand(buff
, operand_address
, &value
);
981 if (addr
>= UDVM_MEMORY_SIZE
- 1)
982 goto decompression_failure
;
985 buff
[(addr
+ 1) & 0xffff] = lsb
;
988 length
= next_operand_address
- operand_address
;
991 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1, "Addr: %u Value %5u - Loading bytes at %5u Value %5u 0x%x",
992 operand_address
, value
, addr
, value
, value
);
995 operand_address
= next_operand_address
;
997 current_address
= next_operand_address
;
998 goto execute_next_instruction
;
1002 case SIGCOMP_INSTR_PUSH
: /* 16 PUSH (%value) */
1003 if (show_instr_detail_level
== 2){
1004 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,
1005 "Addr: %u ## PUSH(16) (value)",
1008 operand_address
= current_address
+ 1;
1010 next_operand_address
= decode_udvm_multitype_operand(buff
, operand_address
, &value
);
1011 if (show_instr_detail_level
== 2){
1012 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,"Addr: %u Value %u",
1013 operand_address
, value
);
1015 if (show_instr_detail_level
== 1)
1017 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,
1018 "Addr: %u ## PUSH (value=%u)",
1019 current_address
, value
);
1021 current_address
= next_operand_address
;
1023 /* Push the value address onto the stack */
1024 stack_location
= (buff
[70] << 8) | buff
[71];
1025 stack_fill
= (buff
[stack_location
] << 8)
1026 | buff
[(stack_location
+1) & 0xFFFF];
1027 addr
= (stack_location
+ stack_fill
* 2 + 2) & 0xFFFF;
1029 if (addr
>= UDVM_MEMORY_SIZE
- 1)
1030 goto decompression_failure
;
1032 buff
[addr
] = (value
>> 8) & 0x00FF;
1033 buff
[(addr
+1) & 0xFFFF] = value
& 0x00FF;
1035 if (stack_location
>= UDVM_MEMORY_SIZE
- 1)
1036 goto decompression_failure
;
1038 stack_fill
= (stack_fill
+ 1) & 0xFFFF;
1039 buff
[stack_location
] = (stack_fill
>> 8) & 0x00FF;
1040 buff
[(stack_location
+1) & 0xFFFF] = stack_fill
& 0x00FF;
1042 goto execute_next_instruction
;
1046 case SIGCOMP_INSTR_POP
: /* 17 POP (%address) */
1047 if (show_instr_detail_level
== 2){
1048 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,
1049 "Addr: %u ## POP(16) (value)",
1052 operand_address
= current_address
+ 1;
1054 next_operand_address
= decode_udvm_multitype_operand(buff
, operand_address
, &destination
);
1055 if (show_instr_detail_level
== 2){
1056 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,"Addr: %u Value %u",
1057 operand_address
, destination
);
1059 if (show_instr_detail_level
== 1)
1061 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,
1062 "Addr: %u ## POP (address=%u)",
1063 current_address
, destination
);
1065 current_address
= next_operand_address
;
1067 /* Pop value from the top of the stack */
1068 stack_location
= (buff
[70] << 8) | buff
[71];
1069 stack_fill
= (buff
[stack_location
] << 8)
1070 | buff
[(stack_location
+1) & 0xFFFF];
1071 if (stack_fill
== 0)
1074 goto decompression_failure
;
1077 if (stack_location
>= UDVM_MEMORY_SIZE
- 1)
1078 goto decompression_failure
;
1080 stack_fill
= (stack_fill
- 1) & 0xFFFF;
1081 buff
[stack_location
] = (stack_fill
>> 8) & 0x00FF;
1082 buff
[(stack_location
+1) & 0xFFFF] = stack_fill
& 0x00FF;
1084 addr
= (stack_location
+ stack_fill
* 2 + 2) & 0xFFFF;
1086 if (addr
>= UDVM_MEMORY_SIZE
- 1)
1087 goto decompression_failure
;
1089 value
= (buff
[addr
] << 8)
1090 | buff
[(addr
+1) & 0xFFFF];
1092 /* ... and store the popped value. */
1093 if (destination
>= UDVM_MEMORY_SIZE
- 1)
1094 goto decompression_failure
;
1095 buff
[destination
] = (value
>> 8) & 0x00FF;
1096 buff
[(destination
+1) & 0xFFFF] = value
& 0x00FF;
1098 goto execute_next_instruction
;
1102 case SIGCOMP_INSTR_COPY
: /* 18 COPY (%position, %length, %destination) */
1103 if (show_instr_detail_level
== 2 ){
1104 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,
1105 "Addr: %u ## COPY(18) (position, length, destination)",
1108 operand_address
= current_address
+ 1;
1110 next_operand_address
= decode_udvm_multitype_operand(buff
, operand_address
, &position
);
1111 if (show_instr_detail_level
== 2 ){
1112 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,"Addr: %u position %u",
1113 operand_address
, position
);
1115 operand_address
= next_operand_address
;
1118 next_operand_address
= decode_udvm_multitype_operand(buff
, operand_address
, &length
);
1119 if (show_instr_detail_level
== 2 ){
1120 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,"Addr: %u Length %u",
1121 operand_address
, length
);
1123 operand_address
= next_operand_address
;
1126 next_operand_address
= decode_udvm_multitype_operand(buff
, operand_address
, &destination
);
1127 if (show_instr_detail_level
== 2 ){
1128 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,"Addr: %u Destination %u",
1129 operand_address
, destination
);
1131 if (show_instr_detail_level
== 1)
1133 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,
1134 "Addr: %u ## COPY (position=%u, length=%u, destination=%u)",
1135 current_address
, position
, length
, destination
);
1137 current_address
= next_operand_address
;
1141 * The string of bytes is copied in ascending order of memory address,
1142 * respecting the bounds set by byte_copy_left and byte_copy_right.
1143 * More precisely, if a byte is copied from/to Address m then the next
1144 * byte is copied from/to Address n where n is calculated as follows:
1146 * Set k := m + 1 (modulo 2^16)
1147 * If k = byte_copy_right then set n := byte_copy_left, else set n := k
1153 byte_copy_right
= buff
[66] << 8;
1154 byte_copy_right
= byte_copy_right
| buff
[67];
1155 byte_copy_left
= buff
[64] << 8;
1156 byte_copy_left
= byte_copy_left
| buff
[65];
1157 if (print_level_2
){
1158 proto_tree_add_text(udvm_tree
, message_tvb
, input_address
, 1,
1159 " byte_copy_right = %u", byte_copy_right
);
1162 while ( n
< length
){
1163 buff
[k
] = buff
[position
];
1164 if (print_level_2
){
1165 proto_tree_add_text(udvm_tree
, message_tvb
, input_address
, 1,
1166 " Copying value: %u (0x%x) to Addr: %u",
1167 buff
[position
], buff
[position
], k
);
1169 position
= ( position
+ 1 ) & 0xffff;
1170 k
= ( k
+ 1 ) & 0xffff;
1174 * Check for circular buffer wrapping after the positions are
1175 * incremented. If either started at BCR then they should continue
1176 * to increment beyond BCR.
1178 if ( k
== byte_copy_right
){
1181 if ( position
== byte_copy_right
){
1182 position
= byte_copy_left
;
1185 used_udvm_cycles
= used_udvm_cycles
+ length
;
1186 goto execute_next_instruction
;
1189 case SIGCOMP_INSTR_COPY_LITERAL
: /* 19 COPY-LITERAL (%position, %length, $destination) */
1190 if (show_instr_detail_level
== 2 ){
1191 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,
1192 "Addr: %u ## COPY-LITERAL(19) (position, length, $destination)",
1195 operand_address
= current_address
+ 1;
1197 next_operand_address
= decode_udvm_multitype_operand(buff
, operand_address
, &position
);
1198 if (show_instr_detail_level
== 2 ){
1199 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,"Addr: %u position %u",
1200 operand_address
, position
);
1202 operand_address
= next_operand_address
;
1205 next_operand_address
= decode_udvm_multitype_operand(buff
, operand_address
, &length
);
1206 if (show_instr_detail_level
== 2 ){
1207 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,"Addr: %u Length %u",
1208 operand_address
, length
);
1210 operand_address
= next_operand_address
;
1214 next_operand_address
= dissect_udvm_reference_operand(buff
, operand_address
, &ref_destination
, &result_dest
);
1215 if (show_instr_detail_level
== 2 ){
1216 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,"Addr: %u destination %u",
1217 operand_address
, ref_destination
);
1219 if (show_instr_detail_level
== 1)
1221 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,
1222 "Addr: %u ## COPY-LITERAL (position=%u, length=%u, $destination=%u)",
1223 current_address
, position
, length
, ref_destination
);
1225 current_address
= next_operand_address
;
1231 * The string of bytes is copied in ascending order of memory address,
1232 * respecting the bounds set by byte_copy_left and byte_copy_right.
1233 * More precisely, if a byte is copied from/to Address m then the next
1234 * byte is copied from/to Address n where n is calculated as follows:
1236 * Set k := m + 1 (modulo 2^16)
1237 * If k = byte_copy_right then set n := byte_copy_left, else set n := k
1242 k
= ref_destination
;
1243 byte_copy_right
= buff
[66] << 8;
1244 byte_copy_right
= byte_copy_right
| buff
[67];
1245 byte_copy_left
= buff
[64] << 8;
1246 byte_copy_left
= byte_copy_left
| buff
[65];
1247 if (print_level_2
){
1248 proto_tree_add_text(udvm_tree
, message_tvb
, input_address
, 1,
1249 " byte_copy_right = %u", byte_copy_right
);
1251 while ( n
< length
){
1253 buff
[k
] = buff
[position
];
1254 if (print_level_2
){
1255 proto_tree_add_text(udvm_tree
, message_tvb
, input_address
, 1,
1256 " Copying value: %u (0x%x) to Addr: %u",
1257 buff
[position
], buff
[position
], k
);
1259 position
= ( position
+ 1 ) & 0xffff;
1260 k
= ( k
+ 1 ) & 0xffff;
1264 * Check for circular buffer wrapping after the positions are
1265 * incremented. It is important that k cannot be left set
1266 * to BCR. Also, if either started at BCR then they should continue
1267 * to increment beyond BCR.
1269 if ( k
== byte_copy_right
){
1272 if ( position
== byte_copy_right
){
1273 position
= byte_copy_left
;
1276 buff
[result_dest
] = k
>> 8;
1277 buff
[(result_dest
+ 1) & 0xffff] = k
& 0x00ff;
1279 used_udvm_cycles
= used_udvm_cycles
+ length
;
1280 goto execute_next_instruction
;
1283 case SIGCOMP_INSTR_COPY_OFFSET
: /* 20 COPY-OFFSET (%offset, %length, $destination) */
1284 if (show_instr_detail_level
== 2 ){
1285 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,
1286 "Addr: %u ## COPY-OFFSET(20) (offset, length, $destination)",
1289 operand_address
= current_address
+ 1;
1291 next_operand_address
= decode_udvm_multitype_operand(buff
, operand_address
, &multy_offset
);
1292 if (show_instr_detail_level
== 2 ){
1293 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,"Addr: %u offset %u",
1294 operand_address
, multy_offset
);
1296 operand_address
= next_operand_address
;
1299 next_operand_address
= decode_udvm_multitype_operand(buff
, operand_address
, &length
);
1300 if (show_instr_detail_level
== 2 ){
1301 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,"Addr: %u Length %u",
1302 operand_address
, length
);
1304 operand_address
= next_operand_address
;
1308 next_operand_address
= dissect_udvm_reference_operand(buff
, operand_address
, &ref_destination
, &result_dest
);
1309 if (show_instr_detail_level
== 2 ){
1310 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,"Addr: %u $destination %u",
1311 operand_address
, ref_destination
);
1314 if (show_instr_detail_level
== 1)
1316 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,
1317 "Addr: %u ## COPY-OFFSET (offset=%u, length=%u, $destination=%u)",
1318 current_address
, multy_offset
, length
, result_dest
);
1320 current_address
= next_operand_address
;
1322 /* Execute the instruction:
1323 * To derive the value of the position operand, starting at the memory
1324 * address specified by destination, the UDVM counts backwards a total
1325 * of offset memory addresses.
1327 * If the memory address specified in byte_copy_left is reached, the
1328 * next memory address is taken to be (byte_copy_right - 1) modulo 2^16.
1330 byte_copy_left
= buff
[64] << 8;
1331 byte_copy_left
= byte_copy_left
| buff
[65];
1332 byte_copy_right
= buff
[66] << 8;
1333 byte_copy_right
= byte_copy_right
| buff
[67];
1336 * In order to work out the position, simple arithmetic is tricky
1337 * to apply because there some nasty corner cases. A simple loop
1338 * is inefficient but the logic is simple.
1340 * FUTURE: This could be optimised.
1342 for (position
= ref_destination
, i
= 0; i
< multy_offset
; i
++)
1344 if ( position
== byte_copy_left
)
1346 position
= (byte_copy_right
- 1) & 0xffff;
1350 position
= (position
- 1) & 0xffff;
1354 if (print_level_2
){
1355 proto_tree_add_text(udvm_tree
, message_tvb
, input_address
, 1,
1356 " byte_copy_left = %u byte_copy_right = %u position= %u",
1357 byte_copy_left
, byte_copy_right
, position
);
1359 /* The COPY-OFFSET instruction then behaves as a COPY-LITERAL
1360 * instruction, taking the value of the position operand to be the last
1361 * memory address reached in the above step.
1367 * The string of bytes is copied in ascending order of memory address,
1368 * respecting the bounds set by byte_copy_left and byte_copy_right.
1369 * More precisely, if a byte is copied from/to Address m then the next
1370 * byte is copied from/to Address n where n is calculated as follows:
1372 * Set k := m + 1 (modulo 2^16)
1373 * If k = byte_copy_right then set n := byte_copy_left, else set n := k
1378 k
= ref_destination
;
1379 if (print_level_2
){
1380 proto_tree_add_text(udvm_tree
, message_tvb
, input_address
, 1,
1381 " byte_copy_left = %u byte_copy_right = %u", byte_copy_left
, byte_copy_right
);
1383 while ( n
< length
){
1384 buff
[k
] = buff
[position
];
1385 if (print_level_2
){
1386 proto_tree_add_text(udvm_tree
, message_tvb
, input_address
, 1,
1387 " Copying value: %5u (0x%x) from Addr: %u to Addr: %u",
1388 buff
[position
], buff
[position
],(position
), k
);
1391 k
= ( k
+ 1 ) & 0xffff;
1392 position
= ( position
+ 1 ) & 0xffff;
1395 * Check for circular buffer wrapping after the positions are
1396 * incremented. It is important that k cannot be left set
1397 * to BCR. Also, if either started at BCR then they should continue
1398 * to increment beyond BCR.
1400 if ( k
== byte_copy_right
){
1403 if ( position
== byte_copy_right
){
1404 position
= byte_copy_left
;
1407 buff
[result_dest
] = k
>> 8;
1408 buff
[result_dest
+ 1] = k
& 0x00ff;
1409 used_udvm_cycles
= used_udvm_cycles
+ length
;
1410 goto execute_next_instruction
;
1413 case SIGCOMP_INSTR_MEMSET
: /* 21 MEMSET (%address, %length, %start_value, %offset) */
1414 if (show_instr_detail_level
== 2 ){
1415 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,
1416 "Addr: %u ## MEMSET(21) (address, length, start_value, offset)",
1419 operand_address
= current_address
+ 1;
1422 next_operand_address
= decode_udvm_multitype_operand(buff
, operand_address
, &addr
);
1423 if (show_instr_detail_level
== 2 ){
1424 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,"Addr: %u Address %u",
1425 operand_address
, addr
);
1427 operand_address
= next_operand_address
;
1430 next_operand_address
= decode_udvm_multitype_operand(buff
, operand_address
, &length
);
1431 if (show_instr_detail_level
== 2 ){
1432 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,"Addr: %u Length %u",
1433 operand_address
, length
);
1435 operand_address
= next_operand_address
;
1437 next_operand_address
= decode_udvm_multitype_operand(buff
, operand_address
, &start_value
);
1438 if (show_instr_detail_level
== 2 ){
1439 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,"Addr: %u start_value %u",
1440 operand_address
, start_value
);
1442 operand_address
= next_operand_address
;
1445 next_operand_address
= decode_udvm_multitype_operand(buff
, operand_address
, &multy_offset
);
1446 if (show_instr_detail_level
== 2 ){
1447 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,"Addr: %u offset %u",
1448 operand_address
, multy_offset
);
1450 if (show_instr_detail_level
== 1)
1452 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,
1453 "Addr: %u ## MEMSET (address=%u, length=%u, start_value=%u, offset=%u)",
1454 current_address
, addr
, length
, start_value
, multy_offset
);
1456 current_address
= next_operand_address
;
1457 /* exetute the instruction
1458 * The sequence of values used by the MEMSET instruction is specified by
1459 * the following formula:
1461 * Seq[n] := (start_value + n * offset) modulo 256
1465 byte_copy_right
= buff
[66] << 8;
1466 byte_copy_right
= byte_copy_right
| buff
[67];
1467 byte_copy_left
= buff
[64] << 8;
1468 byte_copy_left
= byte_copy_left
| buff
[65];
1469 if (print_level_2
){
1470 proto_tree_add_text(udvm_tree
, message_tvb
, input_address
, 1,
1471 " byte_copy_left = %u byte_copy_right = %u", byte_copy_left
, byte_copy_right
);
1473 while ( n
< length
){
1474 if ( k
== byte_copy_right
){
1477 buff
[k
] = (start_value
+ ( n
* multy_offset
)) & 0xff;
1478 if (print_level_2
){
1479 proto_tree_add_text(udvm_tree
, message_tvb
, input_address
, 1,
1480 " Storing value: %u (0x%x) at Addr: %u",
1481 buff
[k
], buff
[k
], k
);
1483 k
= ( k
+ 1 ) & 0xffff;
1486 used_udvm_cycles
= used_udvm_cycles
+ length
;
1487 goto execute_next_instruction
;
1491 case SIGCOMP_INSTR_JUMP
: /* 22 JUMP (@address) */
1492 if (show_instr_detail_level
== 2 ){
1493 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,
1494 "Addr: %u ## JUMP(22) (@address)",
1497 operand_address
= current_address
+ 1;
1499 /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
1500 /*next_operand_address = */decode_udvm_address_operand(buff
,operand_address
, &at_address
, current_address
);
1501 if (show_instr_detail_level
== 2 ){
1502 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,"Addr: %u @Address %u",
1503 operand_address
, at_address
);
1505 if (show_instr_detail_level
== 1)
1507 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,
1508 "Addr: %u ## JUMP (@address=%u)",
1509 current_address
, at_address
);
1511 current_address
= at_address
;
1512 goto execute_next_instruction
;
1515 case SIGCOMP_INSTR_COMPARE
: /* 23 */
1516 /* COMPARE (%value_1, %value_2, @address_1, @address_2, @address_3)
1518 if (show_instr_detail_level
== 2 ){
1519 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,
1520 "Addr: %u ## COMPARE(23) (value_1, value_2, @address_1, @address_2, @address_3)",
1523 operand_address
= current_address
+ 1;
1526 next_operand_address
= decode_udvm_multitype_operand(buff
, operand_address
, &value_1
);
1527 if (show_instr_detail_level
== 2 ){
1528 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,"Addr: %u Value %u",
1529 operand_address
, value_1
);
1531 operand_address
= next_operand_address
;
1534 next_operand_address
= decode_udvm_multitype_operand(buff
, operand_address
, &value_2
);
1535 if (show_instr_detail_level
== 2 ){
1536 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,"Addr: %u Value %u",
1537 operand_address
, value_2
);
1539 operand_address
= next_operand_address
;
1542 /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
1543 next_operand_address
= decode_udvm_multitype_operand(buff
, operand_address
, &at_address_1
);
1544 at_address_1
= ( current_address
+ at_address_1
) & 0xffff;
1545 if (show_instr_detail_level
== 2 ){
1546 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,"Addr: %u @Address %u",
1547 operand_address
, at_address_1
);
1549 operand_address
= next_operand_address
;
1553 /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
1554 next_operand_address
= decode_udvm_multitype_operand(buff
, operand_address
, &at_address_2
);
1555 at_address_2
= ( current_address
+ at_address_2
) & 0xffff;
1556 if (show_instr_detail_level
== 2 ){
1557 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,"Addr: %u @Address %u",
1558 operand_address
, at_address_2
);
1560 operand_address
= next_operand_address
;
1563 /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
1564 /*next_operand_address = */decode_udvm_multitype_operand(buff
, operand_address
, &at_address_3
);
1565 at_address_3
= ( current_address
+ at_address_3
) & 0xffff;
1566 if (show_instr_detail_level
== 2 ){
1567 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,"Addr: %u @Address %u",
1568 operand_address
, at_address_3
);
1570 if (show_instr_detail_level
== 1)
1572 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,
1573 "Addr: %u ## COMPARE (value_1=%u, value_2=%u, @address_1=%u, @address_2=%u, @address_3=%u)",
1574 current_address
, value_1
, value_2
, at_address_1
, at_address_2
, at_address_3
);
1576 /* execute the instruction
1577 * If value_1 < value_2 then the UDVM continues instruction execution at
1578 * the memory address specified by address 1. If value_1 = value_2 then
1579 * it jumps to the address specified by address_2. If value_1 > value_2
1580 * then it jumps to the address specified by address_3.
1582 if ( value_1
< value_2
)
1583 current_address
= at_address_1
;
1584 if ( value_1
== value_2
)
1585 current_address
= at_address_2
;
1586 if ( value_1
> value_2
)
1587 current_address
= at_address_3
;
1588 goto execute_next_instruction
;
1591 case SIGCOMP_INSTR_CALL
: /* 24 CALL (@address) (PUSH addr )*/
1592 if (show_instr_detail_level
== 2){
1593 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,
1594 "Addr: %u ## CALL(24) (@address) (PUSH addr )",
1597 operand_address
= current_address
+ 1;
1599 next_operand_address
= decode_udvm_address_operand(buff
,operand_address
, &at_address
, current_address
);
1600 if (show_instr_detail_level
== 2 ){
1601 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,"Addr: %u @Address %u",
1602 operand_address
, at_address
);
1604 if (show_instr_detail_level
== 1)
1606 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,
1607 "Addr: %u ## CALL (@address=%u)",
1608 current_address
, at_address
);
1610 current_address
= next_operand_address
;
1612 /* Push the current address onto the stack */
1613 stack_location
= (buff
[70] << 8) | buff
[71];
1614 stack_fill
= (buff
[stack_location
] << 8)
1615 | buff
[(stack_location
+1) & 0xFFFF];
1616 addr
= (stack_location
+ stack_fill
* 2 + 2) & 0xFFFF;
1617 if (addr
>= UDVM_MEMORY_SIZE
- 1)
1618 goto decompression_failure
;
1619 buff
[addr
] = (current_address
>> 8) & 0x00FF;
1620 buff
[(addr
+1) & 0xFFFF] = current_address
& 0x00FF;
1622 stack_fill
= (stack_fill
+ 1) & 0xFFFF;
1623 if (stack_location
>= UDVM_MEMORY_SIZE
- 1)
1624 goto decompression_failure
;
1625 buff
[stack_location
] = (stack_fill
>> 8) & 0x00FF;
1626 buff
[(stack_location
+1) & 0xFFFF] = stack_fill
& 0x00FF;
1628 /* ... and jump to the destination address */
1629 current_address
= at_address
;
1631 goto execute_next_instruction
;
1635 case SIGCOMP_INSTR_RETURN
: /* 25 POP and return */
1636 if (print_level_1
|| show_instr_detail_level
== 1){
1637 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,
1638 "Addr: %u ## POP(25) and return",
1642 /* Pop value from the top of the stack */
1643 stack_location
= (buff
[70] << 8) | buff
[71];
1644 stack_fill
= (buff
[stack_location
] << 8)
1645 | buff
[(stack_location
+1) & 0xFFFF];
1646 if (stack_fill
== 0)
1649 goto decompression_failure
;
1652 stack_fill
= (stack_fill
- 1) & 0xFFFF;
1653 if (stack_location
>= UDVM_MEMORY_SIZE
- 1)
1654 goto decompression_failure
;
1655 buff
[stack_location
] = (stack_fill
>> 8) & 0x00FF;
1656 buff
[(stack_location
+1) & 0xFFFF] = stack_fill
& 0x00FF;
1658 addr
= (stack_location
+ stack_fill
* 2 + 2) & 0xFFFF;
1659 at_address
= (buff
[addr
] << 8)
1660 | buff
[(addr
+1) & 0xFFFF];
1662 /* ... and set the PC to the popped value */
1663 current_address
= at_address
;
1665 goto execute_next_instruction
;
1669 case SIGCOMP_INSTR_SWITCH
: /* 26 SWITCH (#n, %j, @address_0, @address_1, ... , @address_n-1) */
1671 * When a SWITCH instruction is encountered the UDVM reads the value of
1672 * j. It then continues instruction execution at the address specified
1675 * Decompression failure occurs if j specifies a value of n or more, or
1676 * if the address lies beyond the overall UDVM memory size.
1678 instruction_address
= current_address
;
1679 if (print_level_1
){
1680 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,
1681 "Addr: %u ## SWITCH (#n, j, @address_0, @address_1, ... , @address_n-1))",
1684 operand_address
= current_address
+ 1;
1686 * Number of addresses in the instruction
1688 next_operand_address
= decode_udvm_literal_operand(buff
,operand_address
, &n
);
1689 if (print_level_1
){
1690 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,"Addr: %u n %u",
1691 operand_address
, n
);
1693 operand_address
= next_operand_address
;
1695 next_operand_address
= decode_udvm_multitype_operand(buff
, operand_address
, &j
);
1696 if (print_level_1
){
1697 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,"Addr: %u j %u",
1698 operand_address
, j
);
1700 operand_address
= next_operand_address
;
1704 /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
1705 next_operand_address
= decode_udvm_multitype_operand(buff
, operand_address
, &at_address_1
);
1706 at_address_1
= ( instruction_address
+ at_address_1
) & 0xffff;
1707 if (print_level_1
){
1708 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,"Addr: %u @Address %u",
1709 operand_address
, at_address_1
);
1712 current_address
= at_address_1
;
1714 operand_address
= next_operand_address
;
1717 /* Check decompression failure */
1718 if ( ( j
== n
) || ( j
> n
)){
1720 goto decompression_failure
;
1722 if ( current_address
> UDVM_MEMORY_SIZE
){
1724 goto decompression_failure
;
1726 used_udvm_cycles
= used_udvm_cycles
+ n
;
1728 goto execute_next_instruction
;
1731 case SIGCOMP_INSTR_CRC
: /* 27 CRC (%value, %position, %length, @address) */
1732 if (print_level_1
){
1733 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,
1734 "Addr: %u ## CRC (value, position, length, @address)",
1738 operand_address
= current_address
+ 1;
1741 next_operand_address
= decode_udvm_multitype_operand(buff
, operand_address
, &value
);
1742 if (print_level_1
){
1743 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,"Addr: %u Value %u",
1744 operand_address
, value
);
1746 operand_address
= next_operand_address
;
1749 next_operand_address
= decode_udvm_multitype_operand(buff
, operand_address
, &position
);
1750 if (print_level_1
){
1751 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,"Addr: %u position %u",
1752 operand_address
, position
);
1754 operand_address
= next_operand_address
;
1757 next_operand_address
= decode_udvm_multitype_operand(buff
, operand_address
, &length
);
1758 if (print_level_1
){
1759 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,"Addr: %u Length %u",
1760 operand_address
, length
);
1762 operand_address
= next_operand_address
;
1765 next_operand_address
= decode_udvm_multitype_operand(buff
, operand_address
, &at_address
);
1766 at_address
= ( current_address
+ at_address
) & 0xffff;
1767 if (print_level_1
){
1768 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,"Addr: %u @Address %u",
1769 operand_address
, at_address
);
1771 /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
1772 used_udvm_cycles
= used_udvm_cycles
+ length
;
1776 byte_copy_right
= buff
[66] << 8;
1777 byte_copy_right
= byte_copy_right
| buff
[67];
1778 byte_copy_left
= buff
[64] << 8;
1779 byte_copy_left
= byte_copy_left
| buff
[65];
1782 if (print_level_2
){
1783 proto_tree_add_text(udvm_tree
, message_tvb
, 0, -1,
1784 "byte_copy_right = %u", byte_copy_right
);
1789 guint16 handle_now
= length
- n
;
1791 if ( k
< byte_copy_right
&& byte_copy_right
<= k
+ (length
-n
) ){
1792 handle_now
= byte_copy_right
- k
;
1795 if (k
+ handle_now
>= UDVM_MEMORY_SIZE
)
1796 goto decompression_failure
;
1797 result
= crc16_ccitt_seed(&buff
[k
], handle_now
, (guint16
) (result
^ 0xffff));
1799 k
= ( k
+ handle_now
) & 0xffff;
1800 n
= ( n
+ handle_now
) & 0xffff;
1802 if ( k
>= byte_copy_right
) {
1807 result
= result
^ 0xffff;
1809 if (print_level_1
){
1810 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1, "Calculated CRC %u", result
);
1812 if (result
!= value
){
1813 current_address
= at_address
;
1816 current_address
= next_operand_address
;
1818 goto execute_next_instruction
;
1822 case SIGCOMP_INSTR_INPUT_BYTES
: /* 28 INPUT-BYTES (%length, %destination, @address) */
1823 if (show_instr_detail_level
== 2 ){
1824 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,
1825 "Addr: %u ## INPUT-BYTES(28) length, destination, @address)",
1828 operand_address
= current_address
+ 1;
1830 next_operand_address
= decode_udvm_multitype_operand(buff
, operand_address
, &length
);
1831 if (show_instr_detail_level
== 2 ){
1832 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,"Addr: %u Length %u",
1833 operand_address
, length
);
1835 operand_address
= next_operand_address
;
1838 next_operand_address
= decode_udvm_multitype_operand(buff
, operand_address
, &destination
);
1839 if (show_instr_detail_level
== 2 ){
1840 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,"Addr: %u Destination %u",
1841 operand_address
, destination
);
1843 operand_address
= next_operand_address
;
1846 /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
1847 next_operand_address
= decode_udvm_multitype_operand(buff
, operand_address
, &at_address
);
1848 at_address
= ( current_address
+ at_address
) & 0xffff;
1849 if (show_instr_detail_level
== 2 ){
1850 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,"Addr: %u @Address %u",
1851 operand_address
, at_address
);
1853 if (show_instr_detail_level
== 1)
1855 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,
1856 "Addr: %u ## INPUT-BYTES length=%u, destination=%u, @address=%u)",
1857 current_address
, length
, destination
, at_address
);
1859 /* execute the instruction TODO insert checks
1863 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1864 * | byte_copy_left | 64 - 65
1865 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1866 * | byte_copy_right | 66 - 67
1867 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1868 * | input_bit_order | 68 - 69
1869 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1870 * | stack_location | 70 - 71
1871 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1873 * Figure 7: Memory addresses of the UDVM registers
1877 * The string of bytes is copied in ascending order of memory address,
1878 * respecting the bounds set by byte_copy_left and byte_copy_right.
1879 * More precisely, if a byte is copied from/to Address m then the next
1880 * byte is copied from/to Address n where n is calculated as follows:
1882 * Set k := m + 1 (modulo 2^16)
1883 * If k = byte_copy_right then set n := byte_copy_left, else set n := k
1889 byte_copy_right
= buff
[66] << 8;
1890 byte_copy_right
= byte_copy_right
| buff
[67];
1891 byte_copy_left
= buff
[64] << 8;
1892 byte_copy_left
= byte_copy_left
| buff
[65];
1893 if (print_level_1
){
1894 proto_tree_add_text(udvm_tree
, message_tvb
, input_address
, 1,
1895 " byte_copy_right = %u", byte_copy_right
);
1897 /* clear out remaining bits if any */
1900 /* operand_address used as dummy */
1901 while ( n
< length
){
1902 if (input_address
> ( msg_end
- 1)){
1903 current_address
= at_address
;
1905 goto execute_next_instruction
;
1908 if ( k
== byte_copy_right
){
1911 octet
= tvb_get_guint8(message_tvb
, input_address
);
1913 if (print_level_1
){
1914 proto_tree_add_text(udvm_tree
, message_tvb
, input_address
, 1,
1915 " Loading value: %u (0x%x) at Addr: %u", octet
, octet
, k
);
1919 * If the instruction requests data that lies beyond the end of the
1920 * SigComp message, no data is returned. Instead the UDVM moves program
1921 * execution to the address specified by the address operand.
1925 k
= ( k
+ 1 ) & 0xffff;
1928 used_udvm_cycles
= used_udvm_cycles
+ length
;
1929 current_address
= next_operand_address
;
1930 goto execute_next_instruction
;
1932 case SIGCOMP_INSTR_INPUT_BITS
:/* 29 INPUT-BITS (%length, %destination, @address) */
1934 * The length operand indicates the requested number of bits.
1935 * Decompression failure occurs if this operand does not lie between 0
1938 * The destination operand specifies the memory address to which the
1939 * compressed data should be copied. Note that the requested bits are
1940 * interpreted as a 2-byte integer ranging from 0 to 2^length - 1, as
1941 * explained in Section 8.2.
1943 * If the instruction requests data that lies beyond the end of the
1944 * SigComp message, no data is returned. Instead the UDVM moves program
1945 * execution to the address specified by the address operand.
1948 if (show_instr_detail_level
== 2 ){
1949 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,
1950 "Addr: %u ## INPUT-BITS(29) (length, destination, @address)",
1953 operand_address
= current_address
+ 1;
1956 next_operand_address
= decode_udvm_multitype_operand(buff
, operand_address
, &length
);
1957 if (show_instr_detail_level
== 2 ){
1958 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,"Addr: %u length %u",
1959 operand_address
, length
);
1961 operand_address
= next_operand_address
;
1963 next_operand_address
= decode_udvm_multitype_operand(buff
, operand_address
, &destination
);
1964 if (show_instr_detail_level
== 2 ){
1965 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,"Addr: %u Destination %u",
1966 operand_address
, destination
);
1968 operand_address
= next_operand_address
;
1971 /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
1972 next_operand_address
= decode_udvm_address_operand(buff
,operand_address
, &at_address
, current_address
);
1973 if (show_instr_detail_level
== 2 ){
1974 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,"Addr: %u @Address %u",
1975 operand_address
, at_address
);
1977 if (show_instr_detail_level
== 1)
1979 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,
1980 "Addr: %u ## INPUT-BITS length=%u, destination=%u, @address=%u)",
1981 current_address
, length
, destination
, at_address
);
1983 current_address
= next_operand_address
;
1986 * Execute actual instr.
1987 * The input_bit_order register contains the following three flags:
1990 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1991 * | reserved |F|H|P| 68 - 69
1992 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1994 input_bit_order
= buff
[68] << 8;
1995 input_bit_order
= input_bit_order
| buff
[69];
1997 * If the instruction requests data that lies beyond the end of the
1998 * SigComp message, no data is returned. Instead the UDVM moves program
1999 * execution to the address specified by the address operand.
2004 goto decompression_failure
;
2006 if ( input_bit_order
> 7 ){
2008 goto decompression_failure
;
2012 * Transfer F bit to bit_order to tell decomp dispatcher which bit order to use
2014 bit_order
= ( input_bit_order
& 0x0004 ) >> 2;
2015 value
= decomp_dispatch_get_bits( message_tvb
, udvm_tree
, bit_order
,
2016 buff
, &old_input_bit_order
, &remaining_bits
,
2017 &input_bits
, &input_address
, length
, &result_code
, msg_end
);
2018 if ( result_code
== 11 ){
2019 current_address
= at_address
;
2020 goto execute_next_instruction
;
2023 lsb
= value
& 0x00ff;
2024 if (destination
>= UDVM_MEMORY_SIZE
- 1)
2025 goto decompression_failure
;
2026 buff
[destination
] = msb
;
2027 buff
[(destination
+ 1) & 0xffff]=lsb
;
2028 if (print_level_1
){
2029 proto_tree_add_text(udvm_tree
, message_tvb
, input_address
, 1,
2030 " Loading value: %u (0x%x) at Addr: %u, remaining_bits: %u", value
, value
, destination
, remaining_bits
);
2033 goto execute_next_instruction
;
2035 case SIGCOMP_INSTR_INPUT_HUFFMAN
: /* 30 */
2037 * INPUT-HUFFMAN (%destination, @address, #n, %bits_1, %lower_bound_1,
2038 * %upper_bound_1, %uncompressed_1, ... , %bits_n, %lower_bound_n,
2039 * %upper_bound_n, %uncompressed_n)
2041 if (show_instr_detail_level
== 2 ){
2042 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,
2043 "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)",
2046 operand_address
= current_address
+ 1;
2049 next_operand_address
= decode_udvm_multitype_operand(buff
, operand_address
, &destination
);
2050 if (show_instr_detail_level
== 2 ){
2051 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,"Addr: %u Destination %u",
2052 operand_address
, destination
);
2054 operand_address
= next_operand_address
;
2057 /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
2058 next_operand_address
= decode_udvm_address_operand(buff
,operand_address
, &at_address
, current_address
);
2059 if (show_instr_detail_level
== 2 ){
2060 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,"Addr: %u @Address %u",
2061 operand_address
, at_address
);
2063 operand_address
= next_operand_address
;
2066 next_operand_address
= decode_udvm_literal_operand(buff
,operand_address
, &n
);
2067 if (show_instr_detail_level
== 2 ){
2068 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,"Addr: %u n %u",
2069 operand_address
, n
);
2071 operand_address
= next_operand_address
;
2072 if (show_instr_detail_level
== 1)
2074 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,
2075 "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)",
2076 current_address
, destination
, at_address
, n
, n
, n
, n
, n
);
2079 used_udvm_cycles
= used_udvm_cycles
+ n
;
2082 * Note that if n = 0 then the INPUT-HUFFMAN instruction is ignored and
2083 * program execution resumes at the following instruction.
2084 * Decompression failure occurs if (bits_1 + ... + bits_n) > 16.
2086 * In all other cases, the behavior of the INPUT-HUFFMAN instruction is
2089 * 1. Set j := 1 and set H := 0.
2091 * 2. Request bits_j compressed bits. Interpret the returned bits as an
2092 * integer k from 0 to 2^bits_j - 1, as explained in Section 8.2.
2094 * 3. Set H := H * 2^bits_j + k.
2096 * 4. If data is requested that lies beyond the end of the SigComp
2097 * message, terminate the INPUT-HUFFMAN instruction and move program
2098 * execution to the memory address specified by the address operand.
2100 * 5. If (H < lower_bound_j) or (H > upper_bound_j) then set j := j + 1.
2101 * Then go back to Step 2, unless j > n in which case decompression
2104 * 6. Copy (H + uncompressed_j - lower_bound_j) modulo 2^16 to the
2105 * memory address specified by the destination operand.
2109 * The input_bit_order register contains the following three flags:
2112 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2113 * | reserved |F|H|P| 68 - 69
2114 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2116 * Transfer H bit to bit_order to tell decomp dispatcher which bit order to use
2118 input_bit_order
= buff
[68] << 8;
2119 input_bit_order
= input_bit_order
| buff
[69];
2120 bit_order
= ( input_bit_order
& 0x0002 ) >> 1;
2125 outside_huffman_boundaries
= TRUE
;
2126 print_in_loop
= print_level_3
;
2129 next_operand_address
= decode_udvm_multitype_operand(buff
, operand_address
, &bits_n
);
2130 if (print_in_loop
){
2131 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,"Addr: %u bits_n %u",
2132 operand_address
, bits_n
);
2134 operand_address
= next_operand_address
;
2136 /* %lower_bound_n */
2137 next_operand_address
= decode_udvm_multitype_operand(buff
, operand_address
, &lower_bound_n
);
2138 if (print_in_loop
){
2139 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,"Addr: %u lower_bound_n %u",
2140 operand_address
, lower_bound_n
);
2142 operand_address
= next_operand_address
;
2143 /* %upper_bound_n */
2144 next_operand_address
= decode_udvm_multitype_operand(buff
, operand_address
, &upper_bound_n
);
2145 if (print_in_loop
){
2146 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,"Addr: %u upper_bound_n %u",
2147 operand_address
, upper_bound_n
);
2149 operand_address
= next_operand_address
;
2150 /* %uncompressed_n */
2151 next_operand_address
= decode_udvm_multitype_operand(buff
, operand_address
, &uncompressed_n
);
2152 if (print_in_loop
){
2153 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,"Addr: %u uncompressed_n %u",
2154 operand_address
, uncompressed_n
);
2156 operand_address
= next_operand_address
;
2157 /* execute instruction */
2158 if ( outside_huffman_boundaries
) {
2160 * 2. Request bits_j compressed bits. Interpret the returned bits as an
2161 * integer k from 0 to 2^bits_j - 1, as explained in Section 8.2.
2163 k
= decomp_dispatch_get_bits( message_tvb
, udvm_tree
, bit_order
,
2164 buff
, &old_input_bit_order
, &remaining_bits
,
2165 &input_bits
, &input_address
, bits_n
, &result_code
, msg_end
);
2166 if ( result_code
== 11 ){
2168 * 4. If data is requested that lies beyond the end of the SigComp
2169 * message, terminate the INPUT-HUFFMAN instruction and move program
2170 * execution to the memory address specified by the address operand.
2172 current_address
= at_address
;
2173 goto execute_next_instruction
;
2177 * 3. Set H := H * 2^bits_j + k.
2178 * [In practice is a shift+OR operation.]
2181 H
= (H
<< bits_n
) | k
;
2182 if (print_level_3
){
2183 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1," Set H(%u) := H(%u) * 2^bits_j(%u) + k(%u)",
2184 H
,oldH
, 1<<bits_n
,k
);
2188 * 5. If (H < lower_bound_j) or (H > upper_bound_j) then set j := j + 1.
2189 * Then go back to Step 2, unless j > n in which case decompression
2192 if ((H
< lower_bound_n
) || (H
> upper_bound_n
)){
2193 outside_huffman_boundaries
= TRUE
;
2195 outside_huffman_boundaries
= FALSE
;
2196 print_in_loop
= FALSE
;
2198 * 6. Copy (H + uncompressed_j - lower_bound_j) modulo 2^16 to the
2199 * memory address specified by the destination operand.
2201 if (print_level_2
){
2202 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,
2203 " H(%u) = H(%u) + uncompressed_n(%u) - lower_bound_n(%u)",
2204 (H
+ uncompressed_n
- lower_bound_n
),H
, uncompressed_n
, lower_bound_n
);
2206 H
= H
+ uncompressed_n
- lower_bound_n
;
2209 if (destination
>= UDVM_MEMORY_SIZE
- 1)
2210 goto decompression_failure
;
2211 buff
[destination
] = msb
;
2212 buff
[(destination
+ 1) & 0xffff]=lsb
;
2213 if (print_level_1
){
2214 proto_tree_add_text(udvm_tree
, message_tvb
, input_address
, 1,
2215 " Loading H: %u (0x%x) at Addr: %u,j = %u remaining_bits: %u",
2216 H
, H
, destination
,( n
- m
+ 1 ), remaining_bits
);
2225 if ( outside_huffman_boundaries
) {
2227 goto decompression_failure
;
2230 current_address
= next_operand_address
;
2231 goto execute_next_instruction
;
2234 case SIGCOMP_INSTR_STATE_ACCESS
: /* 31 */
2235 /* STATE-ACCESS (%partial_identifier_start, %partial_identifier_length,
2236 * %state_begin, %state_length, %state_address, %state_instruction)
2238 if (show_instr_detail_level
== 2 ){
2239 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,
2240 "Addr: %u ## STATE-ACCESS(31) (partial_identifier_start, partial_identifier_length,state_begin, state_length, state_address, state_instruction)",
2243 operand_address
= current_address
+ 1;
2246 * %partial_identifier_start
2248 next_operand_address
= decode_udvm_multitype_operand(buff
, operand_address
, &p_id_start
);
2249 if (show_instr_detail_level
== 2 ){
2250 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,"Addr: %u partial_identifier_start %u",
2251 operand_address
, p_id_start
);
2255 * %partial_identifier_length
2257 operand_address
= next_operand_address
;
2258 next_operand_address
= decode_udvm_multitype_operand(buff
, operand_address
, &p_id_length
);
2259 if (show_instr_detail_level
== 2 ){
2260 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,"Addr: %u partial_identifier_length %u",
2261 operand_address
, p_id_length
);
2266 operand_address
= next_operand_address
;
2267 next_operand_address
= decode_udvm_multitype_operand(buff
, operand_address
, &state_begin
);
2268 if (show_instr_detail_level
== 2 ){
2269 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,"Addr: %u state_begin %u",
2270 operand_address
, state_begin
);
2275 operand_address
= next_operand_address
;
2276 next_operand_address
= decode_udvm_multitype_operand(buff
, operand_address
, &state_length
);
2277 if (show_instr_detail_level
== 2 ){
2278 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,"Addr: %u state_length %u",
2279 operand_address
, state_length
);
2284 operand_address
= next_operand_address
;
2285 next_operand_address
= decode_udvm_multitype_operand(buff
, operand_address
, &state_address
);
2286 if (show_instr_detail_level
== 2 ){
2287 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,"Addr: %u state_address %u",
2288 operand_address
, state_address
);
2291 * %state_instruction
2293 operand_address
= next_operand_address
;
2294 next_operand_address
= decode_udvm_multitype_operand(buff
, operand_address
, &state_instruction
);
2295 if (show_instr_detail_level
== 2 ){
2296 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,"Addr: %u state_instruction %u",
2297 operand_address
, state_instruction
);
2299 if (show_instr_detail_level
== 1)
2301 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,
2302 "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)",
2303 current_address
, p_id_start
, p_id_length
, state_begin
, state_length
, state_address
, state_instruction
);
2305 current_address
= next_operand_address
;
2306 byte_copy_right
= buff
[66] << 8;
2307 byte_copy_right
= byte_copy_right
| buff
[67];
2308 byte_copy_left
= buff
[64] << 8;
2309 byte_copy_left
= byte_copy_left
| buff
[65];
2310 if (print_level_2
){
2311 proto_tree_add_text(udvm_tree
, message_tvb
, input_address
, 1,
2312 " byte_copy_right = %u, byte_copy_left = %u", byte_copy_right
,byte_copy_left
);
2315 result_code
= udvm_state_access(message_tvb
, udvm_tree
, buff
, p_id_start
, p_id_length
, state_begin
, &state_length
,
2316 &state_address
, &state_instruction
, hf_id
);
2317 if ( result_code
!= 0 ){
2318 goto decompression_failure
;
2320 used_udvm_cycles
= used_udvm_cycles
+ state_length
;
2321 goto execute_next_instruction
;
2323 case SIGCOMP_INSTR_STATE_CREATE
: /* 32 */
2325 * STATE-CREATE (%state_length, %state_address, %state_instruction,
2326 * %minimum_access_length, %state_retention_priority)
2328 if (show_instr_detail_level
== 2 ){
2329 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,
2330 "Addr: %u ## STATE-CREATE(32) (state_length, state_address, state_instruction,minimum_access_length, state_retention_priority)",
2333 operand_address
= current_address
+ 1;
2338 next_operand_address
= decode_udvm_multitype_operand(buff
, operand_address
, &state_length
);
2339 if (show_instr_detail_level
== 2 ){
2340 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,"Addr: %u state_length %u",
2341 operand_address
, state_length
);
2346 operand_address
= next_operand_address
;
2347 next_operand_address
= decode_udvm_multitype_operand(buff
, operand_address
, &state_address
);
2348 if (show_instr_detail_level
== 2 ){
2349 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,"Addr: %u state_address %u",
2350 operand_address
, state_address
);
2353 * %state_instruction
2355 operand_address
= next_operand_address
;
2356 next_operand_address
= decode_udvm_multitype_operand(buff
, operand_address
, &state_instruction
);
2357 if (show_instr_detail_level
== 2 ){
2358 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,"Addr: %u state_instruction %u",
2359 operand_address
, state_instruction
);
2362 * %minimum_access_length
2364 operand_address
= next_operand_address
;
2365 next_operand_address
= decode_udvm_multitype_operand(buff
, operand_address
, &minimum_access_length
);
2366 if (show_instr_detail_level
== 2 ){
2367 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,"Addr: %u minimum_access_length %u",
2368 operand_address
, minimum_access_length
);
2371 * %state_retention_priority
2373 operand_address
= next_operand_address
;
2374 next_operand_address
= decode_udvm_multitype_operand(buff
, operand_address
, &state_retention_priority
);
2375 if (show_instr_detail_level
== 2 ){
2376 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,"Addr: %u state_retention_priority %u",
2377 operand_address
, state_retention_priority
);
2379 if (show_instr_detail_level
== 1)
2381 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,
2382 "Addr: %u ## STATE-CREATE(32) (state_length=%u, state_address=%u, state_instruction=%u,minimum_access_length=%u, state_retention_priority=%u)",
2383 current_address
, state_length
, state_address
, state_instruction
,minimum_access_length
, state_retention_priority
);
2385 current_address
= next_operand_address
;
2386 /* Execute the instruction
2387 * TODO Implement the instruction
2389 * Note that the new state item cannot be created until a valid
2390 * compartment identifier has been returned by the application.
2391 * Consequently, when a STATE-CREATE instruction is encountered the UDVM
2392 * simply buffers the five supplied operands until the END-MESSAGE
2393 * instruction is reached. The steps taken at this point are described
2396 * Decompression failure MUST occur if more than four state creation
2397 * requests are made before the END-MESSAGE instruction is encountered.
2398 * Decompression failure also occurs if the minimum_access_length does
2399 * not lie between 6 and 20 inclusive, or if the
2400 * state_retention_priority is 65535.
2402 no_of_state_create
++;
2403 if ( no_of_state_create
> 4 ){
2405 goto decompression_failure
;
2407 if (( minimum_access_length
< 6 ) || ( minimum_access_length
> STATE_BUFFER_SIZE
)){
2409 goto decompression_failure
;
2411 if ( state_retention_priority
== 65535 ){
2413 goto decompression_failure
;
2415 state_length_buff
[no_of_state_create
] = state_length
;
2416 state_address_buff
[no_of_state_create
] = state_address
;
2417 state_instruction_buff
[no_of_state_create
] = state_instruction
;
2418 state_minimum_access_length_buff
[no_of_state_create
] = minimum_access_length
;
2419 /* state_state_retention_priority_buff[no_of_state_create] = state_retention_priority; */
2420 used_udvm_cycles
= used_udvm_cycles
+ state_length
;
2422 byte_copy_right
= buff
[66] << 8;
2423 byte_copy_right
= byte_copy_right
| buff
[67];
2424 byte_copy_left
= buff
[64] << 8;
2425 byte_copy_left
= byte_copy_left
| buff
[65];
2428 while ( n
< state_length
){
2429 if ( k
== byte_copy_right
){
2434 if (print_level_3
){
2435 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,
2436 " Addr: %5u State value: %u (0x%x) ASCII(%s)",
2437 k
,buff
[k
],buff
[k
],format_text(string
, 1));
2439 k
= ( k
+ 1 ) & 0xffff;
2444 goto execute_next_instruction
;
2446 case SIGCOMP_INSTR_STATE_FREE
: /* 33 */
2448 * STATE-FREE (%partial_identifier_start, %partial_identifier_length)
2450 if (show_instr_detail_level
== 2 ){
2451 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,
2452 "Addr: %u ## STATE-FREE (partial_identifier_start, partial_identifier_length)",
2455 operand_address
= current_address
+ 1;
2457 * %partial_identifier_start
2459 next_operand_address
= decode_udvm_multitype_operand(buff
, operand_address
, &p_id_start
);
2460 if (show_instr_detail_level
== 2 ){
2461 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,"Addr: %u partial_identifier_start %u",
2462 operand_address
, p_id_start
);
2464 operand_address
= next_operand_address
;
2467 * %partial_identifier_length
2469 next_operand_address
= decode_udvm_multitype_operand(buff
, operand_address
, &p_id_length
);
2470 if (show_instr_detail_level
== 2 ){
2471 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,"Addr: %u partial_identifier_length %u",
2472 operand_address
, p_id_length
);
2474 if (show_instr_detail_level
== 1)
2476 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,
2477 "Addr: %u ## STATE-FREE (partial_identifier_start=%u, partial_identifier_length=%u)",
2478 current_address
, p_id_start
, p_id_length
);
2480 current_address
= next_operand_address
;
2482 /* Execute the instruction:
2485 udvm_state_free(buff
,p_id_start
,p_id_length
);
2487 goto execute_next_instruction
;
2489 case SIGCOMP_INSTR_OUTPUT
: /* 34 OUTPUT (%output_start, %output_length) */
2490 if (show_instr_detail_level
== 2 ){
2491 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,
2492 "Addr: %u ## OUTPUT(34) (output_start, output_length)",
2495 operand_address
= current_address
+ 1;
2499 next_operand_address
= decode_udvm_multitype_operand(buff
, operand_address
, &output_start
);
2500 if (show_instr_detail_level
== 2 ){
2501 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,"Addr: %u output_start %u",
2502 operand_address
, output_start
);
2504 operand_address
= next_operand_address
;
2508 next_operand_address
= decode_udvm_multitype_operand(buff
, operand_address
, &output_length
);
2509 if (show_instr_detail_level
== 2 ){
2510 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,"Addr: %u output_length %u",
2511 operand_address
, output_length
);
2513 if (show_instr_detail_level
== 1)
2515 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,
2516 "Addr: %u ## OUTPUT (output_start=%u, output_length=%u)",
2517 current_address
, output_start
, output_length
);
2519 current_address
= next_operand_address
;
2522 * Execute instruction
2525 * The string of bytes is copied in ascending order of memory address,
2526 * respecting the bounds set by byte_copy_left and byte_copy_right.
2527 * More precisely, if a byte is copied from/to Address m then the next
2528 * byte is copied from/to Address n where n is calculated as follows:
2530 * Set k := m + 1 (modulo 2^16)
2531 * If k = byte_copy_right then set n := byte_copy_left, else set n := k
2537 byte_copy_right
= buff
[66] << 8;
2538 byte_copy_right
= byte_copy_right
| buff
[67];
2539 byte_copy_left
= buff
[64] << 8;
2540 byte_copy_left
= byte_copy_left
| buff
[65];
2541 if (print_level_3
){
2542 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,
2543 " byte_copy_right = %u", byte_copy_right
);
2545 while ( n
< output_length
){
2547 if ( k
== byte_copy_right
){
2550 out_buff
[output_address
] = buff
[k
];
2553 if (print_level_3
){
2554 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,
2555 " Output value: %u (0x%x) ASCII(%s) from Addr: %u ,output to dispatcher position %u",
2556 buff
[k
],buff
[k
],format_text(string
,1), k
,output_address
);
2558 k
= ( k
+ 1 ) & 0xffff;
2562 used_udvm_cycles
= used_udvm_cycles
+ output_length
;
2563 goto execute_next_instruction
;
2565 case SIGCOMP_INSTR_END_MESSAGE
: /* 35 */
2567 * END-MESSAGE (%requested_feedback_location,
2568 * %returned_parameters_location, %state_length, %state_address,
2569 * %state_instruction, %minimum_access_length,
2570 * %state_retention_priority)
2572 if (show_instr_detail_level
== 2 ){
2573 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,
2574 "Addr: %u ## END-MESSAGE (requested_feedback_location,state_instruction, minimum_access_length,state_retention_priority)",
2577 operand_address
= current_address
+ 1;
2579 /* %requested_feedback_location */
2580 next_operand_address
= decode_udvm_multitype_operand(buff
, operand_address
, &requested_feedback_location
);
2581 if (show_instr_detail_level
== 2 ){
2582 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,"Addr: %u requested_feedback_location %u",
2583 operand_address
, requested_feedback_location
);
2585 operand_address
= next_operand_address
;
2586 /* returned_parameters_location */
2587 next_operand_address
= decode_udvm_multitype_operand(buff
, operand_address
, &returned_parameters_location
);
2588 if (show_instr_detail_level
== 2 ){
2589 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,"Addr: %u returned_parameters_location %u",
2590 operand_address
, returned_parameters_location
);
2595 operand_address
= next_operand_address
;
2596 next_operand_address
= decode_udvm_multitype_operand(buff
, operand_address
, &state_length
);
2597 if (show_instr_detail_level
== 2 ){
2598 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,"Addr: %u state_length %u",
2599 operand_address
, state_length
);
2604 operand_address
= next_operand_address
;
2605 next_operand_address
= decode_udvm_multitype_operand(buff
, operand_address
, &state_address
);
2606 if (show_instr_detail_level
== 2 ){
2607 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,"Addr: %u state_address %u",
2608 operand_address
, state_address
);
2611 * %state_instruction
2613 operand_address
= next_operand_address
;
2614 next_operand_address
= decode_udvm_multitype_operand(buff
, operand_address
, &state_instruction
);
2615 if (show_instr_detail_level
== 2 ){
2616 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,"Addr: %u state_instruction %u",
2617 operand_address
, state_instruction
);
2621 * %minimum_access_length
2623 operand_address
= next_operand_address
;
2624 next_operand_address
= decode_udvm_multitype_operand(buff
, operand_address
, &minimum_access_length
);
2625 if (show_instr_detail_level
== 2 ){
2626 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,"Addr: %u minimum_access_length %u",
2627 operand_address
, minimum_access_length
);
2631 * %state_retention_priority
2633 operand_address
= next_operand_address
;
2634 /*next_operand_address =*/ decode_udvm_multitype_operand(buff
, operand_address
, &state_retention_priority
);
2635 if (show_instr_detail_level
== 2 ){
2636 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,"Addr: %u state_retention_priority %u",
2637 operand_address
, state_retention_priority
);
2639 if (show_instr_detail_level
== 1)
2641 proto_tree_add_text(udvm_tree
, bytecode_tvb
, 0, -1,
2642 "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)",
2643 current_address
, requested_feedback_location
, returned_parameters_location
, state_length
, state_address
, state_instruction
, minimum_access_length
,state_retention_priority
);
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
= (guint8
*)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
);