HACK: pinfo->private_data points to smb_info again
[wireshark-wip.git] / epan / sigcomp-udvm.c
blobcf0a96787f0dd48135982461fbfc533f7c995ba9
1 /* sigcomp-udvm.c
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>
6 * $Id$
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.
25 * References:
26 * http://www.ietf.org/rfc/rfc3320.txt?number=3320
27 * http://www.ietf.org/rfc/rfc3321.txt?number=3321
28 * Useful links :
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
33 #include "config.h"
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <string.h>
38 #include <glib.h>
40 #include <epan/emem.h>
42 #include <wsutil/sha1.h>
43 #include <wsutil/crc16.h>
45 #include "packet.h"
46 #include "exceptions.h"
47 #include "strutil.h"
48 #include "to_str.h"
49 #include "sigcomp-udvm.h"
50 #include "sigcomp_state_hdlr.h"
51 #include "except.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" },
116 { 0, NULL }
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);
128 tvbuff_t*
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,
132 gint header_len,
133 gint byte_code_state_len, gint byte_code_id_len,
134 gint udvm_start_ip)
136 tvbuff_t *decomp_tvb;
137 /* UDVM memory must be initialised to zero */
138 guint8 *buff = (guint8 *)ep_alloc0(UDVM_MEMORY_SIZE);
139 char string[2];
140 guint8 *out_buff; /* Largest allowed size for a message is UDVM_MEMORY_SIZE = 65536 */
141 guint32 i = 0;
142 guint16 n = 0;
143 guint16 m = 0;
144 guint16 x;
145 guint k = 0;
146 guint16 H;
147 guint16 oldH;
148 guint offset = 0;
149 guint result_dest;
150 guint code_length =0;
151 guint8 current_instruction;
152 guint current_address;
153 guint operand_address;
154 guint input_address;
155 guint16 output_address = 0;
156 guint next_operand_address;
157 guint8 octet;
158 guint8 msb;
159 guint8 lsb;
160 guint16 byte_copy_right;
161 guint16 byte_copy_left;
162 guint16 input_bit_order;
163 guint16 stack_location;
164 guint16 stack_fill;
165 guint16 result;
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;
184 guint8 *sha1buff;
185 unsigned char sha1_digest_buf[STATE_BUFFER_SIZE];
186 sha1_context ctx;
189 /* UDVM operand variables */
190 guint16 length;
191 guint16 at_address;
192 guint16 destination;
193 guint16 addr;
194 guint16 value;
195 guint16 p_id_start;
196 guint16 p_id_length;
197 guint16 state_begin;
198 guint16 state_length;
199 guint16 state_address;
200 guint16 state_instruction;
201 guint16 operand_1;
202 guint16 operand_2;
203 guint16 value_1;
204 guint16 value_2;
205 guint16 at_address_1;
206 guint16 at_address_2;
207 guint16 at_address_3;
208 guint16 j;
209 guint16 bits_n;
210 guint16 lower_bound_n;
211 guint16 upper_bound_n;
212 guint16 uncompressed_n;
213 guint16 position;
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;
222 guint16 start_value;
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 ) {
234 case 0:
235 break;
237 case 1:
238 print_level_1 = TRUE;
239 show_instr_detail_level = 1;
240 break;
241 case 2:
242 print_level_1 = TRUE;
243 print_level_2 = TRUE;
244 show_instr_detail_level = 1;
245 break;
246 case 3:
247 print_level_1 = TRUE;
248 print_level_2 = TRUE;
249 print_level_3 = TRUE;
250 show_instr_detail_level = 2;
251 break;
252 default:
253 print_level_1 = TRUE;
254 show_instr_detail_level = 1;
255 break;
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.
262 * 0 7 8 15
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 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
274 * | |
275 * : reserved : 10 - 31
276 * | |
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;
284 /* cycles_per_bit */
285 buff[2] = 0;
286 buff[3] = 16;
287 /* SigComp_version */
288 buff[4] = 0;
289 buff[5] = 1;
290 /* partial_state_ID_length */
291 buff[6] = (byte_code_id_len >> 8) & 0x00FF;
292 buff[7] = byte_code_id_len & 0x00FF;
293 /* state_length */
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" */
310 i = udvm_mem_dest;
311 if ( print_level_3 )
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);
315 if ( print_level_3 )
316 proto_tree_add_text(udvm_tree, bytecode_tvb, offset, 1,
317 " Addr: %u Instruction code(0x%0x) ", i, buff[i]);
319 i++;
320 offset++;
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;
327 input_address = 0;
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 ){
335 result_code = 15;
336 goto decompression_failure;
338 used_udvm_cycles++;
339 current_instruction = buff[current_address & 0xffff];
341 switch ( current_instruction ) {
342 case SIGCOMP_INSTR_DECOMPRESSION_FAILURE:
343 if ( result_code == 0 )
344 result_code = 9;
345 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
346 "Addr: %u ## DECOMPRESSION-FAILURE(0)",
347 current_address);
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
354 * tvbuff is freed.
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
359 * is cleaned up.
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");
363 return decomp_tvb;
365 g_free(out_buff);
366 return NULL;
367 break;
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)",
373 current_address);
375 /* $operand_1*/
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;
383 /* %operand_2*/
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;
397 lsb = result & 0xff;
398 msb = result >> 8;
399 buff[result_dest] = msb;
400 buff[(result_dest+1) & 0xffff] = lsb;
401 if (print_level_1 ){
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;
408 break;
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)",
414 current_address);
416 /* $operand_1*/
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;
424 /* %operand_2*/
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;
438 lsb = result & 0xff;
439 msb = result >> 8;
440 buff[result_dest] = msb;
441 buff[(result_dest+1) & 0xffff] = lsb;
442 if (print_level_1 ){
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;
449 break;
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)",
455 current_address);
457 /* $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;
472 lsb = result & 0xff;
473 msb = result >> 8;
474 buff[result_dest] = msb;
475 buff[(result_dest+1) & 0xffff] = lsb;
476 if (print_level_1 ){
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;
482 break;
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)",
488 current_address);
490 /* $operand_1*/
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;
498 /* %operand_2*/
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;
512 lsb = result & 0xff;
513 msb = result >> 8;
514 buff[result_dest] = msb;
515 buff[(result_dest+1) & 0xffff] = lsb;
516 if (print_level_1 ){
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;
523 break;
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)",
528 current_address);
530 /* $operand_1*/
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;
538 /* %operand_2*/
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;
552 lsb = result & 0xff;
553 msb = result >> 8;
554 buff[result_dest] = msb;
555 buff[(result_dest+1) & 0xffff] = lsb;
556 if (print_level_1 ){
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;
562 break;
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)",
567 current_address);
569 /* $operand_1*/
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;
577 /* %operand_2*/
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;
591 lsb = result & 0xff;
592 msb = result >> 8;
593 buff[result_dest] = msb;
594 buff[(result_dest+1) & 0xffff] = lsb;
595 if (print_level_1 ){
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)",
606 current_address);
608 /* $operand_1*/
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;
616 /* %operand_2*/
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;
630 lsb = result & 0xff;
631 msb = result >> 8;
632 buff[result_dest] = msb;
633 buff[(result_dest+1) & 0xffff] = lsb;
634 if (print_level_1 ){
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;
640 break;
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)",
646 current_address);
648 /* $operand_1*/
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;
656 /* %operand_2*/
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){
673 result_code = 4;
674 goto decompression_failure;
676 result = operand_1 * operand_2;
677 lsb = result & 0xff;
678 msb = result >> 8;
679 buff[result_dest] = msb;
680 buff[(result_dest+1) & 0xffff] = lsb;
681 if (print_level_1 ){
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;
687 break;
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)",
693 current_address);
695 /* $operand_1*/
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;
703 /* %operand_2*/
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){
722 result_code = 4;
723 goto decompression_failure;
725 result = operand_1 / operand_2;
726 lsb = result & 0xff;
727 msb = result >> 8;
728 buff[result_dest] = msb;
729 buff[(result_dest+1) & 0xffff] = lsb;
730 if (print_level_1 ){
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;
736 break;
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)",
742 current_address);
744 /* $operand_1*/
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;
752 /* %operand_2*/
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){
771 result_code = 4;
772 goto decompression_failure;
774 result = operand_1 - operand_2 * (operand_1 / operand_2);
775 lsb = result & 0xff;
776 msb = result >> 8;
777 buff[result_dest] = msb;
778 buff[(result_dest+1) & 0xffff] = lsb;
779 if (print_level_1 ){
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;
785 break;
786 case SIGCOMP_INSTR_SORT_ASCENDING: /* 11 SORT-ASCENDING (%start, %n, %k) */
788 * used_udvm_cycles = 1 + k * (ceiling(log2(k)) + n)
790 if (print_level_1 ){
791 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
792 "Addr: %u ## SORT-ASCENDING(11) (start, n, k))",
793 current_address);
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)
799 break;
801 case SIGCOMP_INSTR_SORT_DESCENDING: /* 12 SORT-DESCENDING (%start, %n, %k) */
802 if (print_level_1 ){
803 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
804 "Addr: %u ## SORT-DESCENDING(12) (start, n, k))",
805 current_address);
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)
811 break;
812 case SIGCOMP_INSTR_SHA_1: /* 13 SHA-1 (%position, %length, %destination) */
813 if (print_level_1 ){
814 proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
815 "Addr: %u ## SHA-1(13) (position, length, destination)",
816 current_address);
818 operand_address = current_address + 1;
819 /* %position */
820 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &position);
821 if (print_level_1 ){
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;
827 /* %length */
828 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &length);
829 if (print_level_1 ){
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;
835 /* $destination */
836 next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &ref_destination, &result_dest);
837 if (print_level_1 ){
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;
843 n = 0;
844 k = position;
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];
850 if (print_level_2 ){
851 proto_tree_add_text(udvm_tree, message_tvb, 0, -1,
852 "byte_copy_right = %u", byte_copy_right);
855 sha1_starts( &ctx );
857 while (n<length) {
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 ) {
872 k = byte_copy_left;
876 sha1_finish( &ctx, sha1_digest_buf );
878 k = ref_destination;
880 for ( n=0; n< STATE_BUFFER_SIZE; n++ ) {
882 buff[k] = sha1_digest_buf[n];
884 k = ( k + 1 ) & 0xffff;
885 n++;
887 if ( k == byte_copy_right ){
888 k = byte_copy_left;
892 if (print_level_2 ){
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;
900 break;
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)",
906 current_address);
908 operand_address = current_address + 1;
909 /* %address */
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;
916 /* %value */
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);
924 lsb = value & 0xff;
925 msb = value >> 8;
927 buff[addr] = msb;
928 buff[(addr + 1) & 0xffff] = lsb;
930 if (print_level_1 ){
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",
934 addr, value, value);
936 current_address = next_operand_address;
937 goto execute_next_instruction;
938 break;
940 case SIGCOMP_INSTR_MULTILOAD: /* 15 MULTILOAD (%address, #n, %value_0, ..., %value_n-1) */
941 /* RFC 3320:
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)",
949 current_address);
951 operand_address = current_address + 1;
952 /* %address */
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;
960 /* #n */
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",
964 operand_address, n);
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;
974 while ( n > 0) {
975 n = n - 1;
976 /* %value */
977 next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &value);
978 lsb = value & 0xff;
979 msb = value >> 8;
981 if (addr >= UDVM_MEMORY_SIZE - 1)
982 goto decompression_failure;
984 buff[addr] = msb;
985 buff[(addr + 1) & 0xffff] = lsb;
986 /* debug
988 length = next_operand_address - operand_address;
990 if (print_level_1 ){
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);
994 addr = addr + 2;
995 operand_address = next_operand_address;
997 current_address = next_operand_address;
998 goto execute_next_instruction;
1000 break;
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)",
1006 current_address);
1008 operand_address = current_address + 1;
1009 /* %value */
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;
1044 break;
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)",
1050 current_address);
1052 operand_address = current_address + 1;
1053 /* %value */
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)
1073 result_code = 16;
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;
1100 break;
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)",
1106 current_address);
1108 operand_address = current_address + 1;
1109 /* %position */
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;
1117 /* %length */
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;
1125 /* %destination */
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;
1139 * 8.4. Byte copying
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
1151 n = 0;
1152 k = destination;
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;
1171 n++;
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 ){
1179 k = byte_copy_left;
1181 if ( position == byte_copy_right ){
1182 position = byte_copy_left;
1185 used_udvm_cycles = used_udvm_cycles + length;
1186 goto execute_next_instruction;
1187 break;
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)",
1193 current_address);
1195 operand_address = current_address + 1;
1196 /* %position */
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;
1204 /* %length */
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;
1213 /* $destination */
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;
1229 * 8.4. Byte copying
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
1241 n = 0;
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;
1261 n++;
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 ){
1270 k = byte_copy_left;
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;
1281 break;
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)",
1287 current_address);
1289 operand_address = current_address + 1;
1290 /* %offset */
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;
1298 /* %length */
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;
1307 /* $destination */
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;
1348 else
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.
1365 * 8.4. Byte copying
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
1377 n = 0;
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);
1390 n++;
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 ){
1401 k = byte_copy_left;
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;
1412 break;
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)",
1417 current_address);
1419 operand_address = current_address + 1;
1421 /* %address */
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;
1429 /* %length, */
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;
1436 /* %start_value */
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;
1444 /* %offset */
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
1463 n = 0;
1464 k = addr;
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 ){
1475 k = byte_copy_left;
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;
1484 n++;
1485 }/* end while */
1486 used_udvm_cycles = used_udvm_cycles + length;
1487 goto execute_next_instruction;
1488 break;
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)",
1495 current_address);
1497 operand_address = current_address + 1;
1498 /* @address */
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;
1513 break;
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)",
1521 current_address);
1523 operand_address = current_address + 1;
1525 /* %value_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;
1533 /* %value_2 */
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;
1541 /* @address_1 */
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;
1552 /* @address_2 */
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;
1562 /* @address_3 */
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;
1589 break;
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 )",
1595 current_address);
1597 operand_address = current_address + 1;
1598 /* @address */
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;
1633 break;
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",
1639 current_address);
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)
1648 result_code = 16;
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;
1667 break;
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
1673 * by address j.
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))",
1682 current_address);
1684 operand_address = current_address + 1;
1685 /* #n
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;
1694 /* %j */
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;
1701 m = 0;
1702 while ( m < n ){
1703 /* @address_n-1 */
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);
1711 if ( j == m ){
1712 current_address = at_address_1;
1714 operand_address = next_operand_address;
1715 m++;
1717 /* Check decompression failure */
1718 if ( ( j == n ) || ( j > n )){
1719 result_code = 5;
1720 goto decompression_failure;
1722 if ( current_address > UDVM_MEMORY_SIZE ){
1723 result_code = 6;
1724 goto decompression_failure;
1726 used_udvm_cycles = used_udvm_cycles + n;
1728 goto execute_next_instruction;
1730 break;
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)",
1735 current_address);
1738 operand_address = current_address + 1;
1740 /* %value */
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;
1748 /* %position */
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;
1756 /* %length */
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;
1764 /* @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;
1774 n = 0;
1775 k = position;
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];
1780 result = 0;
1782 if (print_level_2 ){
1783 proto_tree_add_text(udvm_tree, message_tvb, 0, -1,
1784 "byte_copy_right = %u", byte_copy_right);
1787 while (n<length) {
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 ) {
1803 k = byte_copy_left;
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;
1815 else {
1816 current_address = next_operand_address;
1818 goto execute_next_instruction;
1819 break;
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)",
1826 current_address);
1828 operand_address = current_address + 1;
1829 /* %length */
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;
1837 /* %destination */
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;
1845 /* @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
1860 * RFC 3320 :
1862 * 0 7 8 15
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
1875 * 8.4. Byte copying
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
1887 n = 0;
1888 k = destination;
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 */
1898 remaining_bits = 0;
1899 input_bits=0;
1900 /* operand_address used as dummy */
1901 while ( n < length ){
1902 if (input_address > ( msg_end - 1)){
1903 current_address = at_address;
1904 result_code = 14;
1905 goto execute_next_instruction;
1908 if ( k == byte_copy_right ){
1909 k = byte_copy_left;
1911 octet = tvb_get_guint8(message_tvb, input_address);
1912 buff[k] = octet;
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);
1917 input_address++;
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;
1926 n++;
1928 used_udvm_cycles = used_udvm_cycles + length;
1929 current_address = next_operand_address;
1930 goto execute_next_instruction;
1931 break;
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
1936 * and 16 inclusive.
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)",
1951 current_address);
1953 operand_address = current_address + 1;
1955 /* %length */
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;
1962 /* %destination */
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;
1970 /* @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:
1989 * 0 7 8 15
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.
2002 if ( length > 16 ){
2003 result_code = 7;
2004 goto decompression_failure;
2006 if ( input_bit_order > 7 ){
2007 result_code = 8;
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;
2022 msb = value >> 8;
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;
2034 break;
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)",
2044 current_address);
2046 operand_address = current_address + 1;
2048 /* %destination */
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;
2056 /* @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;
2065 /* #n */
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
2087 * defined below:
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
2102 * failure occurs.
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:
2111 * 0 7 8 15
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;
2122 j = 1;
2123 H = 0;
2124 m = n;
2125 outside_huffman_boundaries = TRUE;
2126 print_in_loop = print_level_3;
2127 while ( m > 0 ){
2128 /* %bits_n */
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.]
2180 oldH = H;
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
2190 * failure occurs.
2192 if ((H < lower_bound_n) || (H > upper_bound_n)){
2193 outside_huffman_boundaries = TRUE;
2194 }else{
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;
2207 msb = H >> 8;
2208 lsb = H & 0x00ff;
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);
2223 m = m - 1;
2225 if ( outside_huffman_boundaries ) {
2226 result_code = 10;
2227 goto decompression_failure;
2230 current_address = next_operand_address;
2231 goto execute_next_instruction;
2232 break;
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)",
2241 current_address);
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);
2264 * %state_begin
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);
2273 * %state_length
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);
2282 * %state_address
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;
2322 break;
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)",
2331 current_address);
2333 operand_address = current_address + 1;
2336 * %state_length
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);
2344 * %state_address
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
2388 * RFC3320:
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
2394 * in Section 9.4.9.
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 ){
2404 result_code = 12;
2405 goto decompression_failure;
2407 if (( minimum_access_length < 6 ) || ( minimum_access_length > STATE_BUFFER_SIZE )){
2408 result_code = 1;
2409 goto decompression_failure;
2411 if ( state_retention_priority == 65535 ){
2412 result_code = 13;
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;
2421 /* Debug */
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];
2426 n = 0;
2427 k = state_address;
2428 while ( n < state_length ){
2429 if ( k == byte_copy_right ){
2430 k = byte_copy_left;
2432 string[0]= buff[k];
2433 string[1]= '\0';
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;
2440 n++;
2442 /* End debug */
2444 goto execute_next_instruction;
2445 break;
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)",
2453 current_address);
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:
2483 * TODO implement it
2485 udvm_state_free(buff,p_id_start,p_id_length);
2487 goto execute_next_instruction;
2488 break;
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)",
2493 current_address);
2495 operand_address = current_address + 1;
2497 * %output_start
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;
2506 * %output_length
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
2523 * 8.4. Byte copying
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
2535 n = 0;
2536 k = output_start;
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 ){
2548 k = byte_copy_left;
2550 out_buff[output_address] = buff[k];
2551 string[0]= buff[k];
2552 string[1]= '\0';
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;
2559 output_address ++;
2560 n++;
2562 used_udvm_cycles = used_udvm_cycles + output_length;
2563 goto execute_next_instruction;
2564 break;
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)",
2575 current_address);
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);
2593 * %state_length
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);
2602 * %state_address
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 ){
2648 result_code = 12;
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;
2654 /* Not used ? */
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);
2663 n = 1;
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",
2681 x,sha1buff[x]);
2684 k = state_address_buff[n];
2685 for( x=0; x < state_length_buff[n]; x++)
2687 if ( k == byte_copy_right ){
2688 k = byte_copy_left;
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 */
2702 #if 0
2703 udvm_state_create(sha1buff, sha1_digest_buf, state_minimum_access_length_buff[n]);
2704 #endif
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]));
2710 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
2720 * tvbuff is freed.
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);
2731 return decomp_tvb;
2732 break;
2734 default:
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);
2737 break;
2739 g_free(out_buff);
2740 return NULL;
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);
2746 g_free(out_buff);
2747 return NULL;
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
2762 static int
2763 decode_udvm_literal_operand(guint8 *buff,guint operand_address, guint16 *value)
2765 guint bytecode;
2766 guint16 operand;
2767 guint test_bits;
2768 guint offset = operand_address;
2769 guint8 temp_data;
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;
2783 *value = operand;
2784 offset = offset + 2;
2786 }else{
2788 * 111000000 nnnnnnnn nnnnnnnn N 0 - 65535
2790 offset ++;
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;
2795 *value = operand;
2796 offset = offset + 2;
2799 }else{
2801 * 0nnnnnnn N 0 - 127
2803 operand = ( bytecode & 0x7f);
2804 *value = operand;
2805 offset ++;
2808 return offset;
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
2826 static int
2827 dissect_udvm_reference_operand(guint8 *buff,guint operand_address, guint16 *value,guint *result_dest)
2829 guint bytecode;
2830 guint16 operand;
2831 guint offset = operand_address;
2832 guint test_bits;
2833 guint8 temp_data;
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;
2855 }else{
2857 * 11000000 nnnnnnnn nnnnnnnn memory[N] 0 - 65535
2859 operand_address++;
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;
2869 }else{
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;
2879 offset ++;
2882 if (offset >= UDVM_MEMORY_SIZE || *result_dest >= UDVM_MEMORY_SIZE - 1 )
2883 THROW(ReportedBoundsError);
2885 return offset;
2888 /* RFC3320
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
2902 static int
2903 decode_udvm_multitype_operand(guint8 *buff,guint operand_address, guint16 *value)
2905 guint test_bits;
2906 guint bytecode;
2907 guint offset = operand_address;
2908 guint16 operand;
2909 guint32 result;
2910 guint8 temp_data;
2911 guint16 temp_data16;
2912 guint16 memmory_addr = 0;
2914 *value = 0;
2916 bytecode = buff[operand_address];
2917 test_bits = ( bytecode & 0xc0 ) >> 6;
2918 switch (test_bits ){
2919 case 0:
2921 * 00nnnnnn N 0 - 63
2923 operand = buff[operand_address];
2924 /* debug
2925 *g_warning("Reading 0x%x From address %u",operand,offset);
2927 *value = operand;
2928 offset ++;
2929 break;
2930 case 1:
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;
2938 offset ++;
2939 break;
2940 case 2:
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;
2951 *value = operand;
2952 offset = offset + 2;
2953 }else{
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;
2964 *value = operand;
2965 offset = offset + 2;
2966 }else{
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;
2975 *value = operand;
2976 offset ++;
2977 }else{
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;
2985 *value = operand;
2986 offset ++;
2987 }else{
2989 * 1000 0000 nnnnnnnn nnnnnnnn N 0 - 65535
2990 * 1000 0001 nnnnnnnn nnnnnnnn memory[N] 0 - 65535
2992 offset ++;
2993 temp_data16 = buff[(operand_address + 1) & 0xffff] << 8;
2994 temp_data16 = temp_data16 | buff[(operand_address + 2) & 0xffff];
2995 /* debug
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;
3004 offset = offset +2;
3011 break;
3013 case 3:
3014 test_bits = ( bytecode & 0x20 ) >> 5;
3015 if ( test_bits == 1 ){
3017 * 111nnnnn N + 65504 65504 - 65535
3019 operand = ( buff[operand_address] & 0x1f) + 65504;
3020 *value = operand;
3021 offset ++;
3022 }else{
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;
3032 /* debug
3033 * g_warning("Reading 0x%x From address %u",temp_data16,memmory_addr);
3035 offset = offset +2;
3038 default :
3039 break;
3041 return offset;
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).
3059 static int
3060 decode_udvm_address_operand(guint8 *buff,guint operand_address, guint16 *value,guint current_address)
3062 guint32 result;
3063 guint16 value1;
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
3113 static int
3114 decomp_dispatch_get_bits(
3115 tvbuff_t *message_tvb,
3116 proto_tree *udvm_tree,
3117 guint8 bit_order,
3118 guint8 *buff,
3119 guint16 *old_input_bit_order,
3120 guint16 *remaining_bits,
3121 guint16 *input_bits,
3122 guint *input_address,
3123 guint16 length,
3124 guint16 *result_code,
3125 guint msg_end)
3127 guint16 input_bit_order;
3128 guint16 bits_still_required = length;
3129 guint16 value = 0;
3130 guint8 octet;
3131 gint extra_bytes_available = msg_end - *input_address;
3132 gint p_bit;
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];
3139 *result_code = 0;
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)
3158 *result_code = 11;
3159 return 0xfbad;
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;
3180 if (p_bit != 0)
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 */
3199 if (bit_order != 0)
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);
3208 return value;
3212 /* end udvm */