aboutsummaryrefslogtreecommitdiffstats
path: root/epan/sigcomp-udvm.c
diff options
context:
space:
mode:
authoretxrab <etxrab@f5534014-38df-0310-8fa8-9805f1628bb7>2004-10-08 15:54:06 +0000
committeretxrab <etxrab@f5534014-38df-0310-8fa8-9805f1628bb7>2004-10-08 15:54:06 +0000
commit69e3b16aef3545f5825b6c676126f1e0747adc3e (patch)
tree4b8c536778016d558eeb31733111987f8c877563 /epan/sigcomp-udvm.c
parentacfcb66e6045c9456b0d03ee793440116a28d23c (diff)
Add sigcomp Universal Decompressor Virtual Machine (UDVM) and state handler, for decompression of
sigcomp messages. Currently states are or not saved so only messages with bytecode can be decompressed. git-svn-id: http://anonsvn.wireshark.org/wireshark/trunk@12236 f5534014-38df-0310-8fa8-9805f1628bb7
Diffstat (limited to 'epan/sigcomp-udvm.c')
-rw-r--r--epan/sigcomp-udvm.c2946
1 files changed, 2946 insertions, 0 deletions
diff --git a/epan/sigcomp-udvm.c b/epan/sigcomp-udvm.c
new file mode 100644
index 0000000000..caa0a84c9c
--- /dev/null
+++ b/epan/sigcomp-udvm.c
@@ -0,0 +1,2946 @@
+/* sigcomp-udvm.c
+ * Routines making up the Universal Decompressor Virtual Machine (UDVM) used for
+ * Signaling Compression (SigComp) dissection.
+ * Copyright 2004, Anders Broman <anders.broman@ericsson.com>
+ *
+ * $Id: udvm.c 11445 2004-07-20 19:04:48Z etxrab $
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * References:
+ * http://www.ietf.org/rfc/rfc3320.txt?number=3320
+ * http://www.ietf.org/rfc/rfc3321.txt?number=3321
+ * Useful links :
+ * http://www.ietf.org/internet-drafts/draft-ietf-rohc-sigcomp-impl-guide-03.txt
+ * http://www.ietf.org/internet-drafts/draft-ietf-rohc-sigcomp-sip-01.txt
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#include <glib.h>
+
+#ifdef NEED_SNPRINTF_H
+# include "snprintf.h"
+#endif
+
+#include "packet.h"
+#include "sigcomp-udvm.h"
+#include "sigcomp_state_hdlr.h"
+#include "sha1.h"
+
+#define SIGCOMP_INSTR_DECOMPRESSION_FAILURE 0
+#define SIGCOMP_INSTR_AND 1
+#define SIGCOMP_INSTR_OR 2
+#define SIGCOMP_INSTR_NOT 3
+#define SIGCOMP_INSTR_LSHIFT 4
+#define SIGCOMP_INSTR_RSHIFT 5
+#define SIGCOMP_INSTR_ADD 6
+#define SIGCOMP_INSTR_SUBTRACT 7
+#define SIGCOMP_INSTR_MULTIPLY 8
+#define SIGCOMP_INSTR_DIVIDE 9
+#define SIGCOMP_INSTR_REMAINDER 10
+#define SIGCOMP_INSTR_SORT_ASCENDING 11
+#define SIGCOMP_INSTR_SORT_DESCENDING 12
+#define SIGCOMP_INSTR_SHA_1 13
+#define SIGCOMP_INSTR_LOAD 14
+#define SIGCOMP_INSTR_MULTILOAD 15
+#define SIGCOMP_INSTR_PUSH 16
+#define SIGCOMP_INSTR_POP 17
+#define SIGCOMP_INSTR_COPY 18
+#define SIGCOMP_INSTR_COPY_LITERAL 19
+#define SIGCOMP_INSTR_COPY_OFFSET 20
+#define SIGCOMP_INSTR_MEMSET 21
+#define SIGCOMP_INSTR_JUMP 22
+#define SIGCOMP_INSTR_COMPARE 23
+#define SIGCOMP_INSTR_CALL 24
+#define SIGCOMP_INSTR_RETURN 25
+#define SIGCOMP_INSTR_SWITCH 26
+#define SIGCOMP_INSTR_CRC 27
+#define SIGCOMP_INSTR_INPUT_BYTES 28
+#define SIGCOMP_INSTR_INPUT_BITS 29
+#define SIGCOMP_INSTR_INPUT_HUFFMAN 30
+#define SIGCOMP_INSTR_STATE_ACCESS 31
+#define SIGCOMP_INSTR_STATE_CREATE 32
+#define SIGCOMP_INSTR_STATE_FREE 33
+#define SIGCOMP_INSTR_OUTPUT 34
+#define SIGCOMP_INSTR_END_MESSAGE 35
+
+#define UDVM_MEMORY_SIZE 65536
+
+static gboolean print_level_1;
+static gboolean print_level_2;
+static gboolean print_level_3;
+
+/* Internal result code values of decompression failures */
+static const value_string result_code_vals[] = {
+ { 0, "No decomprssion failure" },
+ { 1, "Partial state length less than 6 or greater than 20 bytes long" },
+ { 2, "No state match" },
+ { 3, "state_begin + state_length > size of state" },
+ { 4, "Operand_2 is Zero" },
+ { 5, "Switch statement failed j >= n" },
+ { 6, "Atempt to jump outside of UDVM memory" },
+ { 7, "L in input-bits > 16" },
+ { 8, "input_bit_order > 7" },
+ { 9, "Instruction Decompression failure encounterd" },
+ {10, "Input huffman failed j > n" },
+ {11, "Input bits requested beond end of message" },
+ {12, "more than four state creation requests are made before the END-MESSAGE instruction" },
+ {13, "state_retention_priority is 65535" },
+ {14, "Input bytes requested beond end of message" },
+ {15, "Maximum number of UDVM cycles reached" },
+ { 255, "This branch isn't coded yet" },
+ { 0, NULL }
+};
+
+static int decode_udvm_literal_operand(guint8 buff[],guint operand_address, guint16 *value);
+static int dissect_udvm_reference_operand(guint8 buff[],guint operand_address, guint16 *value, guint *result_dest);
+static int decode_udvm_multitype_operand(guint8 buff[],guint operand_address,guint16 *value);
+static int decode_udvm_address_operand(guint8 buff[],guint operand_address, guint16 *value,guint current_address);
+static int decomp_dispatch_get_bits(tvbuff_t *message_tvb,proto_tree *udvm_tree,guint8 bit_order,
+ guint8 buff[],guint16 *old_input_bit_order, guint16 *remaining_bits,
+ guint16 *input_bits, guint *input_address, guint16 length, guint16 *result_code,guint msg_end);
+
+
+tvbuff_t*
+decompress_sigcomp_message(tvbuff_t *bytecode_tvb, tvbuff_t *message_tvb, packet_info *pinfo,
+ proto_tree *udvm_tree, gint udvm_mem_dest, gint print_flags)
+{
+ tvbuff_t *decomp_tvb;
+ guint8 buff[UDVM_MEMORY_SIZE];
+ char string[2];
+ guint8 out_buff[65536]; /* Largest allowed size for a message is 65535 */
+ guint32 i = 0;
+ guint16 n = 0;
+ guint16 m = 0;
+ guint16 x;
+ guint k = 0;
+ guint16 H;
+ guint16 oldH;
+ guint offset = 0;
+ guint result_dest;
+ guint code_length =0;
+ guint8 current_instruction;
+ guint current_address;
+ guint operand_address;
+ guint input_address;
+ guint16 output_address = 0;
+ guint next_operand_address;
+ guint8 octet;
+ guint8 msb;
+ guint8 lsb;
+ guint16 byte_copy_right;
+ guint16 byte_copy_left;
+ guint16 input_bit_order;
+ guint16 result;
+ guint msg_end = tvb_reported_length_remaining(message_tvb, 0);
+ guint16 result_code;
+ guint16 old_input_bit_order = 0;
+ guint16 remaining_bits = 0;
+ guint16 input_bits = 0;
+ guint8 bit_order = 0;
+ gboolean outside_huffman_boundaries = TRUE;
+ gboolean print_in_loop = FALSE;
+ guint16 instruction_address;
+ guint8 no_of_state_create = 0;
+ guint16 state_length_buff[5];
+ guint16 state_address_buff[5];
+ guint16 state_instruction_buff[5];
+ guint16 state_minimum_access_length_buff[5];
+ guint16 state_state_retention_priority_buff[5];
+ guint32 used_udvm_cycles = 0;
+ guint16 cycles_per_bit;
+ guint16 maximum_UDVM_cycles;
+ guint8 *sha1buff;
+ unsigned char sha1_digest_buf[20];
+ sha1_context ctx;
+
+
+ /* UDVM operand variables */
+ guint16 length;
+ guint16 at_address;
+ guint16 destination;
+ guint16 address;
+ guint16 value;
+ guint16 p_id_start;
+ guint16 p_id_length;
+ guint16 state_begin;
+ guint16 state_length;
+ guint16 state_address;
+ guint16 state_instruction;
+ guint16 operand_1;
+ guint16 operand_2;
+ guint16 value_1;
+ guint16 value_2;
+ guint16 at_address_1;
+ guint16 at_address_2;
+ guint16 at_address_3;
+ guint16 j;
+ guint16 bits_n;
+ guint16 lower_bound_n;
+ guint16 upper_bound_n;
+ guint16 uncompressed_n;
+ guint16 position;
+ guint16 ref_destination; /* could I have used $destination ? */
+ guint16 multy_offset;
+ guint16 output_start;
+ guint16 output_length;
+ guint16 minimum_access_length;
+ guint16 state_retention_priority;
+ guint16 requested_feedback_location;
+ guint16 returned_parameters_location;
+ guint16 start_value;
+
+ /* Set print parameters */
+ print_level_1 = FALSE;
+ print_level_2 = FALSE;
+ print_level_3 = FALSE;
+ switch( print_flags ) {
+ case 0:
+ break;
+
+ case 1:
+ print_level_1 = TRUE;
+ break;
+ case 2:
+ print_level_1 = TRUE;
+ print_level_2 = TRUE;
+ break;
+ case 3:
+ print_level_1 = TRUE;
+ print_level_2 = TRUE;
+ print_level_3 = TRUE;
+ break;
+ default:
+ print_level_1 = TRUE;
+ break;
+ }
+
+
+
+
+
+
+ /* UDVM memory must be initialised to zero */
+ while ( i < UDVM_MEMORY_SIZE ) {
+ buff[i] = 0;
+ i++;
+ }
+ /* Set initial UDVM data
+ * The first 32 bytes of UDVM memory are then initialized to special
+ * values as illustrated in Figure 5.
+ *
+ * 0 7 8 15
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | UDVM_memory_size | 0 - 1
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | cycles_per_bit | 2 - 3
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | SigComp_version | 4 - 5
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | partial_state_ID_length | 6 - 7
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | state_length | 8 - 9
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | |
+ * : reserved : 10 - 31
+ * | |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *
+ * Figure 5: Initializing Useful Values in UDVM memory
+ */
+ /* UDVM_memory_size */
+ buff[0] = 0;
+ buff[1] = 0;
+ /* cycles_per_bit */
+ buff[2] = 0;
+ buff[3] = 16;
+ /* SigComp_version */
+ buff[4] = 0;
+ buff[5] = 1;
+ /* partial_state_ID_length */
+ buff[6] = 0;
+ buff[7] = 0;
+ /* state_length */
+ buff[8] = 0;
+ buff[9] = 0;
+ code_length = tvb_reported_length_remaining(bytecode_tvb, 0);
+
+ /* Load bytecode into UDVM starting at "udvm_mem_dest" */
+ i = udvm_mem_dest;
+ while ( code_length > offset ) {
+ buff[i] = tvb_get_guint8(bytecode_tvb, offset);
+ i++;
+ offset++;
+
+ }
+ cycles_per_bit = buff[2] << 8;
+ cycles_per_bit = cycles_per_bit | buff[3];
+ /*
+ * maximum_UDVM_cycles = (8 * n + 1000) * cycles_per_bit
+ */
+ maximum_UDVM_cycles = (( 8 * msg_end ) + 1000) * cycles_per_bit;
+ /* Start executing code */
+ current_address = udvm_mem_dest;
+ input_address = 0;
+ operand_address = 0;
+
+ proto_tree_add_text(udvm_tree, bytecode_tvb, offset, 1,"UDVM EXECUTION STARTED at Address: %u Message size %u",
+ udvm_mem_dest,msg_end);
+
+execute_next_instruction:
+
+ if ( used_udvm_cycles > maximum_UDVM_cycles ){
+ result_code = 15;
+ goto decompression_failure;
+ }
+ current_instruction = buff[current_address];
+ switch ( current_instruction ) {
+ case SIGCOMP_INSTR_DECOMPRESSION_FAILURE:
+ used_udvm_cycles++;
+ if ( result_code == 0 )
+ result_code = 9;
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
+ "Addr: %u ## DECOMPRESSION-FAILURE(0)",
+ current_address);
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Ethereal UDVM diagnostic: %s.",
+ val_to_str(result_code, result_code_vals,"Unknown (%u)"));
+ }
+ if ( output_address > 0 ){
+ /* At least something got decompressed, show it */
+ decomp_tvb = tvb_new_real_data(out_buff,output_address,output_address);
+ tvb_set_child_real_data_tvbuff(message_tvb,decomp_tvb);
+ add_new_data_source(pinfo, decomp_tvb, "Decompressed SigComp message(Incomplete)");
+ proto_tree_add_text(udvm_tree, decomp_tvb, 0, -1,"SigComp message Decompression failure");
+ return decomp_tvb;
+ }
+
+ return NULL;
+ break;
+
+ case SIGCOMP_INSTR_AND: /* 1 AND ($operand_1, %operand_2) */
+ used_udvm_cycles++;
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
+ "Addr: %u ## AND(1) (operand_1, operand_2)",
+ current_address);
+ }
+ /* $operand_1*/
+ operand_address = current_address + 1;
+ next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &operand_1, &result_dest);
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_1 %u",
+ operand_address, operand_1);
+ }
+ operand_address = next_operand_address;
+ /* %operand_2*/
+ next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &operand_2);
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_2 %u",
+ operand_address, operand_2);
+ }
+ /* execute the instruction */
+ result = operand_1 & operand_2;
+ lsb = result & 0xff;
+ msb = result >> 8;
+ buff[result_dest] = msb;
+ buff[result_dest+1] = lsb;
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," Loading result %u at %u",
+ result, result_dest);
+ }
+ current_address = next_operand_address;
+ goto execute_next_instruction;
+
+ break;
+
+ case SIGCOMP_INSTR_OR: /* 2 OR ($operand_1, %operand_2) */
+ used_udvm_cycles++;
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
+ "Addr: %u ## OR(2) (operand_1, operand_2)",
+ current_address);
+ }
+ /* $operand_1*/
+ operand_address = current_address + 1;
+ next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &operand_1, &result_dest);
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_1 %u",
+ operand_address, operand_1);
+ }
+ operand_address = next_operand_address;
+ /* %operand_2*/
+ next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &operand_2);
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_2 %u",
+ operand_address, operand_2);
+ }
+ /* execute the instruction */
+ result = operand_1 | operand_2;
+ lsb = result & 0xff;
+ msb = result >> 8;
+ buff[result_dest] = msb;
+ buff[result_dest+1] = lsb;
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," Loading result %u at %u",
+ result, result_dest);
+ }
+ current_address = next_operand_address;
+ goto execute_next_instruction;
+
+ break;
+
+ case SIGCOMP_INSTR_NOT: /* 3 NOT ($operand_1) */
+ used_udvm_cycles++;
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
+ "Addr: %u ## NOT(3) ($operand_1)",
+ current_address);
+ }
+ /* $operand_1*/
+ operand_address = current_address + 1;
+ next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &operand_1, &result_dest);
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_1 %u",
+ operand_address, operand_1);
+ }
+ /* execute the instruction */
+ result = operand_1 ^ 0xffff;
+ lsb = result & 0xff;
+ msb = result >> 8;
+ buff[result_dest] = msb;
+ buff[result_dest+1] = lsb;
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," Loading result %u at %u",
+ result, result_dest);
+ }
+ current_address = next_operand_address;
+ goto execute_next_instruction;
+ break;
+
+ case SIGCOMP_INSTR_LSHIFT: /* 4 LSHIFT ($operand_1, %operand_2) */
+ used_udvm_cycles++;
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
+ "Addr: %u ## LSHIFT(4) ($operand_1, operand_2)",
+ current_address);
+ }
+ /* $operand_1*/
+ operand_address = current_address + 1;
+ next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &operand_1, &result_dest);
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_1 %u",
+ operand_address, operand_1);
+ }
+ operand_address = next_operand_address;
+ /* %operand_2*/
+ next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &operand_2);
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_2 %u",
+ operand_address, operand_2);
+ }
+ /* execute the instruction */
+ result = operand_1 << operand_2;
+ lsb = result & 0xff;
+ msb = result >> 8;
+ buff[result_dest] = msb;
+ buff[result_dest+1] = lsb;
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," Loading result %u at %u",
+ result, result_dest);
+ }
+ current_address = next_operand_address;
+ goto execute_next_instruction;
+
+ break;
+ case SIGCOMP_INSTR_RSHIFT: /* 5 RSHIFT ($operand_1, %operand_2) */
+ used_udvm_cycles++;
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
+ "Addr: %u ## RSHIFT(5) (operand_1, operand_2)",
+ current_address);
+ }
+ /* $operand_1*/
+ operand_address = current_address + 1;
+ next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &operand_1, &result_dest);
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_1 %u",
+ operand_address, operand_1);
+ }
+ operand_address = next_operand_address;
+ /* %operand_2*/
+ next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &operand_2);
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_2 %u",
+ operand_address, operand_2);
+ }
+ /* execute the instruction */
+ result = operand_1 >> operand_2;
+ lsb = result & 0xff;
+ msb = result >> 8;
+ buff[result_dest] = msb;
+ buff[result_dest+1] = lsb;
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," Loading result %u at %u",
+ result, result_dest);
+ }
+ current_address = next_operand_address;
+ goto execute_next_instruction;
+ break;
+ case SIGCOMP_INSTR_ADD: /* 6 ADD ($operand_1, %operand_2) */
+ used_udvm_cycles++;
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
+ "Addr: %u ## ADD(6) (operand_1, operand_2)",
+ current_address);
+ }
+ /* $operand_1*/
+ operand_address = current_address + 1;
+ next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &operand_1, &result_dest);
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_1 %u",
+ operand_address, operand_1);
+ }
+ operand_address = next_operand_address;
+ /* %operand_2*/
+ next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &operand_2);
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_2 %u",
+ operand_address, operand_2);
+ }
+ /* execute the instruction */
+ result = operand_1 + operand_2;
+ lsb = result & 0xff;
+ msb = result >> 8;
+ buff[result_dest] = msb;
+ buff[result_dest+1] = lsb;
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," Loading result %u at %u",
+ result, result_dest);
+ }
+ current_address = next_operand_address;
+ goto execute_next_instruction;
+
+ case SIGCOMP_INSTR_SUBTRACT: /* 7 SUBTRACT ($operand_1, %operand_2) */
+ used_udvm_cycles++;
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
+ "Addr: %u ## SUBTRACT(7) (operand_1, operand_2)",
+ current_address);
+ }
+ /* $operand_1*/
+ operand_address = current_address + 1;
+ next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &operand_1, &result_dest);
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_1 %u",
+ operand_address, operand_1);
+ }
+ operand_address = next_operand_address;
+ /* %operand_2*/
+ next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &operand_2);
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_2 %u",
+ operand_address, operand_2);
+ }
+ /* execute the instruction */
+ result = operand_1 - operand_2;
+ lsb = result & 0xff;
+ msb = result >> 8;
+ buff[result_dest] = msb;
+ buff[result_dest+1] = lsb;
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," Loading result %u at %u",
+ result, result_dest);
+ }
+ current_address = next_operand_address;
+ goto execute_next_instruction;
+ break;
+
+ case SIGCOMP_INSTR_MULTIPLY: /* 8 MULTIPLY ($operand_1, %operand_2) */
+ used_udvm_cycles++;
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
+ "Addr: %u ##MULTIPLY(8) (operand_1, operand_2)",
+ current_address);
+ }
+ /* $operand_1*/
+ operand_address = current_address + 1;
+ next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &operand_1, &result_dest);
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_1 %u",
+ operand_address, operand_1);
+ }
+ operand_address = next_operand_address;
+ /* %operand_2*/
+ next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &operand_2);
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_2 %u",
+ operand_address, operand_2);
+ }
+ /*
+ * execute the instruction
+ * MULTIPLY (m, n) := m * n (modulo 2^16)
+ */
+ if ( operand_2 == 0){
+ result_code = 4;
+ goto decompression_failure;
+ }
+ result = operand_1 * operand_2;
+ lsb = result & 0xff;
+ msb = result >> 8;
+ buff[result_dest] = msb;
+ buff[result_dest+1] = lsb;
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," Loading result %u at %u",
+ result, result_dest);
+ }
+ current_address = next_operand_address;
+ goto execute_next_instruction;
+ break;
+
+ case SIGCOMP_INSTR_DIVIDE: /* 9 DIVIDE ($operand_1, %operand_2) */
+ used_udvm_cycles++;
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
+ "Addr: %u ## DIVIDE(9) (operand_1, operand_2)",
+ current_address);
+ }
+ /* $operand_1*/
+ operand_address = current_address + 1;
+ next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &operand_1, &result_dest);
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_1 %u",
+ operand_address, operand_1);
+ }
+ operand_address = next_operand_address;
+ /* %operand_2*/
+ next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &operand_2);
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_2 %u",
+ operand_address, operand_2);
+ }
+ /*
+ * execute the instruction
+ * DIVIDE (m, n) := floor(m / n)
+ * Decompression failure occurs if a DIVIDE or REMAINDER instruction
+ * encounters an operand_2 that is zero.
+ */
+ if ( operand_2 == 0){
+ result_code = 4;
+ goto decompression_failure;
+ }
+ result = (guint16)floor(operand_1/operand_2);
+ lsb = result & 0xff;
+ msb = result >> 8;
+ buff[result_dest] = msb;
+ buff[result_dest+1] = lsb;
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," Loading result %u at %u",
+ result, result_dest);
+ }
+ current_address = next_operand_address;
+ goto execute_next_instruction;
+ break;
+
+ case SIGCOMP_INSTR_REMAINDER: /* 10 REMAINDER ($operand_1, %operand_2) */
+ used_udvm_cycles++;
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
+ "Addr: %u ## REMAINDER(10) (operand_1, operand_2)",
+ current_address);
+ }
+ /* $operand_1*/
+ operand_address = current_address + 1;
+ next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &operand_1, &result_dest);
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_1 %u",
+ operand_address, operand_1);
+ }
+ operand_address = next_operand_address;
+ /* %operand_2*/
+ next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &operand_2);
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u operand_2 %u",
+ operand_address, operand_2);
+ }
+ /*
+ * execute the instruction
+ * REMAINDER (m, n) := m - n * floor(m / n)
+ * Decompression failure occurs if a DIVIDE or REMAINDER instruction
+ * encounters an operand_2 that is zero.
+ */
+ if ( operand_2 == 0){
+ result_code = 4;
+ goto decompression_failure;
+ }
+ result = operand_1 - operand_2 * (guint16)floor(operand_1/operand_2);
+ lsb = result & 0xff;
+ msb = result >> 8;
+ buff[result_dest] = msb;
+ buff[result_dest+1] = lsb;
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," Loading result %u at %u",
+ result, result_dest);
+ }
+ current_address = next_operand_address;
+ goto execute_next_instruction;
+ break;
+ case SIGCOMP_INSTR_SORT_ASCENDING: /* 11 SORT-ASCENDING (%start, %n, %k) */
+ /*
+ * used_udvm_cycles = 1 + k * (ceiling(log2(k)) + n)
+ */
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
+ "Addr: %u ## SORT-ASCENDING(11) (start, n, k))",
+ current_address);
+ }
+ operand_address = current_address + 1;
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Execution of this instruction is NOT implemented");
+ /*
+ * used_udvm_cycles = 1 + k * (ceiling(log2(k)) + n)
+ */
+ break;
+
+ case SIGCOMP_INSTR_SORT_DESCENDING: /* 12 SORT-DESCENDING (%start, %n, %k) */
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
+ "Addr: %u ## SORT-DESCENDING(12) (start, n, k))",
+ current_address);
+ }
+ operand_address = current_address + 1;
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Execution of this instruction is NOT implemented");
+ /*
+ * used_udvm_cycles = 1 + k * (ceiling(log2(k)) + n)
+ */
+ break;
+ case SIGCOMP_INSTR_SHA_1: /* 13 SHA-1 (%position, %length, %destination) */
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
+ "Addr: %u ## SHA-1(13) (position, length, destination)",
+ current_address);
+ }
+ operand_address = current_address + 1;
+ /* %position */
+ next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &position);
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u position %u",
+ operand_address, position);
+ }
+ operand_address = next_operand_address;
+
+ /* %length */
+ next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &length);
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Length %u",
+ operand_address, length);
+ }
+ operand_address = next_operand_address;
+
+ /* $destination */
+ next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &ref_destination, &result_dest);
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u $destination %u",
+ operand_address, ref_destination);
+ }
+ current_address = next_operand_address;
+ used_udvm_cycles = used_udvm_cycles + 1 + length;
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Execution of this instruction is NOT implemented");
+ break;
+
+ case SIGCOMP_INSTR_LOAD: /* 14 LOAD (%address, %value) */
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
+ "Addr: %u ## LOAD(14) (%address, %value)",
+ current_address);
+ }
+ operand_address = current_address + 1;
+ /* %address */
+ next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &address);
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Address %u",
+ operand_address, address);
+ }
+ operand_address = next_operand_address;
+ /* %value */
+ next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &value);
+ lsb = value & 0xff;
+ msb = value >> 8;
+
+ buff[address] = msb;
+ buff[address + 1] = lsb;
+
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Value %u",
+ operand_address, value);
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," Loading bytes at %u Value %u 0x%x",
+ address, value, value);
+ }
+ used_udvm_cycles++;
+ current_address = next_operand_address;
+ goto execute_next_instruction;
+ break;
+
+ case SIGCOMP_INSTR_MULTILOAD: /* 15 MULTILOAD (%address, #n, %value_0, ..., %value_n-1) */
+ /* RFC 3320:
+ * The MULTILOAD instruction sets a contiguous block of 2-byte words in
+ * the UDVM memory to specified values.
+ * Hmm what if the value to load only takes one byte ? Chose to always load two bytes.
+ */
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
+ "Addr: %u ## MULTILOAD(15) (%address, #n, value_0, ..., value_n-1)",
+ current_address);
+ }
+ operand_address = current_address + 1;
+ /* %address */
+ next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &address);
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Address %u",
+ operand_address, address);
+ }
+ operand_address = next_operand_address;
+
+ /* #n */
+ next_operand_address = decode_udvm_literal_operand(buff,operand_address, &n);
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u n %u",
+ operand_address, n);
+ }
+ operand_address = next_operand_address;
+ used_udvm_cycles = used_udvm_cycles + n;
+ while ( n > 0) {
+ n = n - 1;
+ /* %value */
+ next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &value);
+ lsb = value & 0xff;
+ msb = value >> 8;
+
+ buff[address] = msb;
+ buff[address + 1] = lsb;
+ /* debug
+ */
+ length = next_operand_address - operand_address;
+
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, operand_address - 128, length,"Addr: %u Value %5u - Loading bytes at %5u Value %5u 0x%x",
+ operand_address, value, address, value, value);
+ }
+ address = address + 2;
+ operand_address = next_operand_address;
+ }
+ current_address = next_operand_address;
+ goto execute_next_instruction;
+
+ break;
+
+ case SIGCOMP_INSTR_PUSH: /* 16 PUSH (%value) */
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
+ "Addr: %u ## PUSH(16) (value)",
+ current_address);
+ }
+ operand_address = current_address + 1;
+ /* %value */
+ next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &value);
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Value %u",
+ operand_address, value);
+ }
+ used_udvm_cycles++;
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Execution of this instruction is NOT implemented");
+ break;
+
+ case SIGCOMP_INSTR_POP: /* 17 POP (%address) */
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
+ "Addr: %u ## POP(17) (address)",
+ current_address);
+ }
+ operand_address = current_address + 1;
+ /* %address */
+ next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &address);
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Address %u",
+ operand_address, address);
+ }
+ operand_address = next_operand_address;
+ used_udvm_cycles++;
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Execution of this instruction is NOT implemented");
+ break;
+
+ case SIGCOMP_INSTR_COPY: /* 18 COPY (%position, %length, %destination) */
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
+ "Addr: %u ## COPY(18) (position, length, destination)",
+ current_address);
+ }
+ operand_address = current_address + 1;
+ /* %position */
+ next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &position);
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u position %u",
+ operand_address, position);
+ }
+ operand_address = next_operand_address;
+
+ /* %length */
+ next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &length);
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Length %u",
+ operand_address, length);
+ }
+ operand_address = next_operand_address;
+
+ /* %destination */
+ next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &destination);
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Destination %u",
+ operand_address, destination);
+ }
+ current_address = next_operand_address;
+ /*
+ * 8.4. Byte copying
+ * :
+ * The string of bytes is copied in ascending order of memory address,
+ * respecting the bounds set by byte_copy_left and byte_copy_right.
+ * More precisely, if a byte is copied from/to Address m then the next
+ * byte is copied from/to Address n where n is calculated as follows:
+ *
+ * Set k := m + 1 (modulo 2^16)
+ * If k = byte_copy_right then set n := byte_copy_left, else set n := k
+ *
+ */
+
+ n = 0;
+ k = destination;
+ byte_copy_right = buff[66] << 8;
+ byte_copy_right = byte_copy_right | buff[67];
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
+ " byte_copy_right = %u", byte_copy_right);
+ }
+
+ while ( n < length ){
+
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
+ " byte_copy_right = %u", byte_copy_right);
+ }
+ if ( k == byte_copy_right ){
+ byte_copy_left = buff[64] << 8;
+ byte_copy_left = byte_copy_left | buff[65];
+ k = byte_copy_left;
+ }
+ buff[k] = buff[position + n];
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
+ " Copying value: %u (0x%x) to Addr: %u", buff[position + n], buff[position + n], k);
+ }
+ k = ( k + 1 ) & 0xffff;
+ n++;
+ }
+ used_udvm_cycles = used_udvm_cycles + 1 + length;
+ goto execute_next_instruction;
+ break;
+
+ case SIGCOMP_INSTR_COPY_LITERAL: /* 19 COPY-LITERAL (%position, %length, $destination) */
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
+ "Addr: %u ## COPY-LITERAL(19) (position, length, $destination)",
+ current_address);
+ }
+ operand_address = current_address + 1;
+ /* %position */
+ next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &position);
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u position %u",
+ operand_address, address);
+ }
+ operand_address = next_operand_address;
+
+ /* %length */
+ next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &length);
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Length %u",
+ operand_address, length);
+ }
+ operand_address = next_operand_address;
+
+
+ /* $destination */
+ next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &ref_destination, &result_dest);
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u destination %u",
+ operand_address, ref_destination);
+ }
+ current_address = next_operand_address;
+
+
+ /*
+ * 8.4. Byte copying
+ * :
+ * The string of bytes is copied in ascending order of memory address,
+ * respecting the bounds set by byte_copy_left and byte_copy_right.
+ * More precisely, if a byte is copied from/to Address m then the next
+ * byte is copied from/to Address n where n is calculated as follows:
+ *
+ * Set k := m + 1 (modulo 2^16)
+ * If k = byte_copy_right then set n := byte_copy_left, else set n := k
+ *
+ */
+
+ n = 0;
+ k = ref_destination;
+ byte_copy_right = buff[66] << 8;
+ byte_copy_right = byte_copy_right | buff[67];
+ while ( n < length ){
+
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
+ " byte_copy_right = %u", byte_copy_right);
+ }
+ if ( k == byte_copy_right ){
+ byte_copy_left = buff[64] << 8;
+ byte_copy_left = byte_copy_left | buff[65];
+ k = byte_copy_left;
+ }
+ buff[k] = buff[position + n];
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
+ " Copying value: %u (0x%x) to Addr: %u", buff[position + n], buff[position + n], k);
+ }
+ k = ( k + 1 ) & 0xffff;
+ n++;
+ }
+ buff[result_dest] = k >> 8;
+ buff[result_dest + 1] = k & 0x00ff;
+
+ used_udvm_cycles = used_udvm_cycles + 1 + length;
+ goto execute_next_instruction;
+ break;
+
+ case SIGCOMP_INSTR_COPY_OFFSET: /* 20 COPY-OFFSET (%offset, %length, $destination) */
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
+ "Addr: %u ## COPY-OFFSET(20) (offset, length, $destination)",
+ current_address);
+ }
+ operand_address = current_address + 1;
+ /* %offset */
+ next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &multy_offset);
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u offset %u",
+ operand_address, multy_offset);
+ }
+ operand_address = next_operand_address;
+
+ /* %length */
+ next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &length);
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Length %u",
+ operand_address, length);
+ }
+ operand_address = next_operand_address;
+
+
+ /* $destination */
+ next_operand_address = dissect_udvm_reference_operand(buff, operand_address, &ref_destination, &result_dest);
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u $destination %u",
+ operand_address, ref_destination);
+ }
+ current_address = next_operand_address;
+
+ /* Execute the instruction:
+ * To derive the value of the position operand, starting at the memory
+ * address specified by destination, the UDVM counts backwards a total
+ * of offset memory addresses.
+ *
+ * If the memory address specified in byte_copy_left is reached, the
+ * next memory address is taken to be (byte_copy_right - 1) modulo 2^16.
+ */
+ byte_copy_left = buff[64] << 8;
+ byte_copy_left = byte_copy_left | buff[65];
+ byte_copy_right = buff[66] << 8;
+ byte_copy_right = byte_copy_right | buff[67];
+
+ if ( (byte_copy_left + multy_offset) > ( ref_destination )){
+ /* wrap around */
+ position = byte_copy_right - ( multy_offset - ( ref_destination - byte_copy_left ));
+ }else{
+ position = ref_destination - multy_offset;
+ }
+
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
+ " byte_copy_left = %u byte_copy_right = %u position= %u",
+ byte_copy_left, byte_copy_right, position);
+ }
+ /* The COPY-OFFSET instruction then behaves as a COPY-LITERAL
+ * instruction, taking the value of the position operand to be the last
+ * memory address reached in the above step.
+ */
+
+ /*
+ * 8.4. Byte copying
+ * :
+ * The string of bytes is copied in ascending order of memory address,
+ * respecting the bounds set by byte_copy_left and byte_copy_right.
+ * More precisely, if a byte is copied from/to Address m then the next
+ * byte is copied from/to Address n where n is calculated as follows:
+ *
+ * Set k := m + 1 (modulo 2^16)
+ * If k = byte_copy_right then set n := byte_copy_left, else set n := k
+ *
+ */
+
+ n = 0;
+ k = ref_destination;
+ byte_copy_right = buff[66] << 8;
+ byte_copy_right = byte_copy_right | buff[67];
+ while ( n < length ){
+ if ( k == byte_copy_right ){
+ byte_copy_left = buff[64] << 8;
+ byte_copy_left = byte_copy_left | buff[65];
+ k = byte_copy_left;
+ if (print_level_2 ){
+ proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
+ " byte_copy_left = %u byte_copy_right = %u", byte_copy_left, byte_copy_right);
+ }
+ }
+ if ( position == byte_copy_right ){
+ byte_copy_left = buff[64] << 8;
+ byte_copy_left = byte_copy_left | buff[65];
+ position = byte_copy_left;
+ if (print_level_2 ){
+ proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
+ " byte_copy_left = %u byte_copy_right = %u", byte_copy_left, byte_copy_right);
+ }
+ }
+ buff[k] = buff[position];
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
+ " Copying value: %5u (0x%x) from Addr: %u to Addr: %u",
+ buff[position + n], buff[position + n],(position + n), k);
+ }
+ k = ( k + 1 ) & 0xffff;
+ n++;
+ position++;
+ }
+ buff[result_dest] = k >> 8;
+ buff[result_dest + 1] = k & 0x00ff;
+ used_udvm_cycles = used_udvm_cycles + 1 + length;
+ goto execute_next_instruction;
+
+ break;
+ case SIGCOMP_INSTR_MEMSET: /* 21 MEMSET (%address, %length, %start_value, %offset) */
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
+ "Addr: %u ## MEMSET(21) (address, length, start_value, offset)",
+ current_address);
+ }
+ operand_address = current_address + 1;
+
+ /* %address */
+ next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &address);
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Address %u",
+ operand_address, address);
+ }
+ operand_address = next_operand_address;
+
+ /* %length, */
+ next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &length);
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Length %u",
+ operand_address, length);
+ }
+ operand_address = next_operand_address;
+ /* %start_value */
+ next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &start_value);
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u start_value %u",
+ operand_address, start_value);
+ }
+ operand_address = next_operand_address;
+
+ /* %offset */
+ next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &multy_offset);
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u offset %u",
+ operand_address, multy_offset);
+ }
+ current_address = next_operand_address;
+ /* exetute the instruction
+ * The sequence of values used by the MEMSET instruction is specified by
+ * the following formula:
+ *
+ * Seq[n] := (start_value + n * offset) modulo 256
+ */
+ n = 0;
+ k = address;
+ byte_copy_right = buff[66] << 8;
+ byte_copy_right = byte_copy_right | buff[67];
+ while ( n < length ){
+ if ( k == byte_copy_right ){
+ byte_copy_left = buff[64] << 8;
+ byte_copy_left = byte_copy_left | buff[65];
+ k = byte_copy_left;
+ if (print_level_2 ){
+ proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
+ " byte_copy_left = %u byte_copy_right = %u", byte_copy_left, byte_copy_right);
+ }
+ }
+ buff[k] = (start_value + ( n * multy_offset)) & 0xff;
+ if (print_level_2 ){
+ proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
+ " Storing value: %u (0x%x) at Addr: %u",
+ buff[k], buff[k], k);
+ }
+ k = ( k + 1 ) & 0xffff;
+ n++;
+ }/* end while */
+ used_udvm_cycles = used_udvm_cycles + 1 + length;
+ goto execute_next_instruction;
+ break;
+
+
+ case SIGCOMP_INSTR_JUMP: /* 22 JUMP (@address) */
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
+ "Addr: %u ## JUMP(22) (@address)",
+ current_address);
+ }
+ operand_address = current_address + 1;
+ /* @address */
+ /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
+ next_operand_address = decode_udvm_address_operand(buff,operand_address, &at_address, current_address);
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u @Address %u",
+ operand_address, at_address);
+ }
+ current_address = at_address;
+ used_udvm_cycles++;
+ goto execute_next_instruction;
+ break;
+
+ case SIGCOMP_INSTR_COMPARE: /* 23 */
+ /* COMPARE (%value_1, %value_2, @address_1, @address_2, @address_3)
+ */
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
+ "Addr: %u ## COMPARE(23) (value_1, value_2, @address_1, @address_2, @address_3)",
+ current_address);
+ }
+ operand_address = current_address + 1;
+
+ /* %value_1 */
+ next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &value_1);
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Value %u",
+ operand_address, value_1);
+ }
+ operand_address = next_operand_address;
+
+ /* %value_2 */
+ next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &value_2);
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Value %u",
+ operand_address, value_2);
+ }
+ operand_address = next_operand_address;
+
+ /* @address_1 */
+ /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
+ next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &at_address_1);
+ at_address_1 = ( current_address + at_address_1) & 0xffff;
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u @Address %u",
+ operand_address, at_address_1);
+ }
+ operand_address = next_operand_address;
+
+
+ /* @address_2 */
+ /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
+ next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &at_address_2);
+ at_address_2 = ( current_address + at_address_2) & 0xffff;
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u @Address %u",
+ operand_address, at_address_2);
+ }
+ operand_address = next_operand_address;
+
+ /* @address_3 */
+ /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
+ next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &at_address_3);
+ at_address_3 = ( current_address + at_address_3) & 0xffff;
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u @Address %u",
+ operand_address, at_address_3);
+ }
+ /* execute the instruction
+ * If value_1 < value_2 then the UDVM continues instruction execution at
+ * the memory address specified by address 1. If value_1 = value_2 then
+ * it jumps to the address specified by address_2. If value_1 > value_2
+ * then it jumps to the address specified by address_3.
+ */
+ if ( value_1 < value_2 )
+ current_address = at_address_1;
+ if ( value_1 == value_2 )
+ current_address = at_address_2;
+ if ( value_1 > value_2 )
+ current_address = at_address_3;
+ used_udvm_cycles++;
+ goto execute_next_instruction;
+ break;
+
+ case SIGCOMP_INSTR_CALL: /* 24 CALL (@address) (PUSH addr )*/
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
+ "Addr: %u ## CALL(24) (@address) (PUSH addr )",
+ current_address);
+ }
+ operand_address = current_address + 1;
+ /* @address */
+ next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &at_address);
+ at_address = ( current_address + at_address) & 0xffff;
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u @Address %u",
+ operand_address, at_address);
+ /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
+ }
+ used_udvm_cycles++;
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Execution of this instruction is NOT implemented");
+ break;
+
+ case SIGCOMP_INSTR_RETURN: /* 25 POP and return */
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
+ "Addr: %u ## POP(25) and return",
+ current_address);
+ }
+ operand_address = current_address + 1;
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Execution of this instruction is NOT implemented");
+ used_udvm_cycles++;
+ break;
+
+ case SIGCOMP_INSTR_SWITCH: /* 26 SWITCH (#n, %j, @address_0, @address_1, ... , @address_n-1) */
+ /*
+ * When a SWITCH instruction is encountered the UDVM reads the value of
+ * j. It then continues instruction execution at the address specified
+ * by address j.
+ *
+ * Decompression failure occurs if j specifies a value of n or more, or
+ * if the address lies beyond the overall UDVM memory size.
+ */
+ instruction_address = current_address;
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
+ "Addr: %u ## SWITCH (#n, j, @address_0, @address_1, ... , @address_n-1))",
+ current_address);
+ }
+ operand_address = current_address + 1;
+ /* #n
+ * Number of addresses in the instruction
+ */
+ next_operand_address = decode_udvm_literal_operand(buff,operand_address, &n);
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u n %u",
+ operand_address, n);
+ }
+ operand_address = next_operand_address;
+ /* %j */
+ next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &j);
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u j %u",
+ operand_address, j);
+ }
+ operand_address = next_operand_address;
+ m = 0;
+ while ( m < n ){
+ /* @address_n-1 */
+ /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
+ next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &at_address_1);
+ at_address_1 = ( instruction_address + at_address_1) & 0xffff;
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u @Address %u",
+ operand_address, at_address_1);
+ }
+ if ( j == m ){
+ current_address = at_address_1;
+ }
+ operand_address = next_operand_address;
+ m++;
+ }
+ /* Check decompression failure */
+ if ( ( j == n ) || ( j > n )){
+ result_code = 5;
+ goto decompression_failure;
+ }
+ if ( current_address > UDVM_MEMORY_SIZE ){
+ result_code = 6;
+ goto decompression_failure;
+ }
+ used_udvm_cycles = used_udvm_cycles + 1 + n;
+;
+ goto execute_next_instruction;
+
+ break;
+ case SIGCOMP_INSTR_CRC: /* 27 CRC (%value, %position, %length, @address) */
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
+ "Addr: %u ## CRC (value, position, length, @address)",
+ current_address);
+ }
+ /* %value */
+ next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &value);
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Value %u",
+ operand_address, value);
+ }
+ /* %position */
+ next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &position);
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u position %u",
+ operand_address, position);
+ }
+ operand_address = next_operand_address;
+
+ /* %length */
+ next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &length);
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Length %u",
+ operand_address, length);
+ }
+ operand_address = next_operand_address;
+
+ /* @address */
+ next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &at_address);
+ at_address = ( current_address + at_address) & 0xffff;
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u @Address %u",
+ operand_address, at_address);
+ }
+ /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
+ used_udvm_cycles = used_udvm_cycles + 1 + length;
+
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Execution of this instruction is NOT implemented");
+ break;
+
+
+ case SIGCOMP_INSTR_INPUT_BYTES: /* 28 INPUT-BYTES (%length, %destination, @address) */
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u ## INPUT-BYTES(28) length, destination, @address)",
+ current_address);
+ }
+ operand_address = current_address + 1;
+ /* %length */
+ next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &length);
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Length %u",
+ operand_address, length);
+ }
+ operand_address = next_operand_address;
+
+ /* %destination */
+ next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &destination);
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Destination %u",
+ operand_address, destination);
+ }
+ operand_address = next_operand_address;
+
+ /* @address */
+ /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
+ next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &at_address);
+ at_address = ( current_address + at_address) & 0xffff;
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u @Address %u",
+ operand_address, at_address);
+ }
+ /* execute the instruction TODO insert checks
+ * RFC 3320 :
+ *
+ * 0 7 8 15
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | byte_copy_left | 64 - 65
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | byte_copy_right | 66 - 67
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | input_bit_order | 68 - 69
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | stack_location | 70 - 71
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *
+ * Figure 7: Memory addresses of the UDVM registers
+ * :
+ * 8.4. Byte copying
+ * :
+ * The string of bytes is copied in ascending order of memory address,
+ * respecting the bounds set by byte_copy_left and byte_copy_right.
+ * More precisely, if a byte is copied from/to Address m then the next
+ * byte is copied from/to Address n where n is calculated as follows:
+ *
+ * Set k := m + 1 (modulo 2^16)
+ * If k = byte_copy_right then set n := byte_copy_left, else set n := k
+ *
+ */
+
+ n = 0;
+ k = destination;
+ byte_copy_right = buff[66] << 8;
+ byte_copy_right = byte_copy_right | buff[67];
+ /* clear out remaining bits if any */
+ remaining_bits = 0;
+ input_bits=0;
+ /* operand_address used as dummy */
+ while ( n < length ){
+ if (input_address > ( msg_end - 1)){
+ current_address = at_address;
+ result_code = 14;
+ goto execute_next_instruction;
+ }
+
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
+ " byte_copy_right = %u", byte_copy_right);
+ }
+ if ( k == byte_copy_right ){
+ byte_copy_left = buff[64] << 8;
+ byte_copy_left = byte_copy_left | buff[65];
+ k = byte_copy_left;
+ }
+ octet = tvb_get_guint8(message_tvb, input_address);
+ buff[k] = octet;
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
+ " Loading value: %u (0x%x) at Addr: %u", octet, octet, k);
+ }
+ input_address++;
+ /*
+ * If the instruction requests data that lies beyond the end of the
+ * SigComp message, no data is returned. Instead the UDVM moves program
+ * execution to the address specified by the address operand.
+ */
+
+
+ k = ( k + 1 ) & 0xffff;
+ n++;
+ }
+ used_udvm_cycles = used_udvm_cycles + 1 + length;
+ current_address = next_operand_address;
+ goto execute_next_instruction;
+ break;
+ case SIGCOMP_INSTR_INPUT_BITS:/* 29 INPUT-BITS (%length, %destination, @address) */
+ /*
+ * The length operand indicates the requested number of bits.
+ * Decompression failure occurs if this operand does not lie between 0
+ * and 16 inclusive.
+ *
+ * The destination operand specifies the memory address to which the
+ * compressed data should be copied. Note that the requested bits are
+ * interpreted as a 2-byte integer ranging from 0 to 2^length - 1, as
+ * explained in Section 8.2.
+ *
+ * If the instruction requests data that lies beyond the end of the
+ * SigComp message, no data is returned. Instead the UDVM moves program
+ * execution to the address specified by the address operand.
+ */
+
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
+ "Addr: %u ## INPUT-BITS(29) (length, destination, @address)",
+ current_address);
+ }
+ operand_address = current_address + 1;
+
+ /* %length */
+ next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &length);
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u length %u",
+ operand_address, length);
+ }
+ operand_address = next_operand_address;
+ /* %destination */
+ next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &destination);
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Destination %u",
+ operand_address, destination);
+ }
+ operand_address = next_operand_address;
+
+ /* @address */
+ /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
+ next_operand_address = decode_udvm_address_operand(buff,operand_address, &at_address, current_address);
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u @Address %u",
+ operand_address, at_address);
+ }
+ current_address = next_operand_address;
+
+ /*
+ * Execute actual instr.
+ * The input_bit_order register contains the following three flags:
+ *
+ * 0 7 8 15
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | reserved |F|H|P| 68 - 69
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ */
+ input_bit_order = buff[68] << 8;
+ input_bit_order = input_bit_order | buff[69];
+ /*
+ * If the instruction requests data that lies beyond the end of the
+ * SigComp message, no data is returned. Instead the UDVM moves program
+ * execution to the address specified by the address operand.
+ */
+
+ if ((input_address > ( msg_end -1)) && (remaining_bits == 0 )){
+ result_code = 11;
+ current_address = at_address;
+ goto execute_next_instruction;
+ }
+
+ if ( length > 16 ){
+ result_code = 7;
+ goto decompression_failure;
+ }
+ if ( input_bit_order > 7 ){
+ result_code = 8;
+ goto decompression_failure;
+ }
+ /* Transfer F bit to bit_order to tell decomp dispatcher which bit order to use */
+ bit_order = ( input_bit_order & 0x0004 ) >> 2;
+ value = decomp_dispatch_get_bits( message_tvb, udvm_tree, bit_order,
+ buff, &old_input_bit_order, &remaining_bits,
+ &input_bits, &input_address, length, &result_code, msg_end);
+ if ( result_code == 11 ){
+ current_address = at_address;
+ goto execute_next_instruction;
+ }
+ msb = value >> 8;
+ lsb = value & 0x00ff;
+ buff[destination] = msb;
+ buff[destination + 1]=lsb;
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
+ " Loading value: %u (0x%x) at Addr: %u, remaining_bits: %u", value, value, destination, remaining_bits);
+ }
+
+ used_udvm_cycles = used_udvm_cycles + 1 + length;
+ goto execute_next_instruction;
+ break;
+ case SIGCOMP_INSTR_INPUT_HUFFMAN: /* 30 */
+ /*
+ * 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)
+ */
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
+ "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)",
+ current_address);
+ }
+ operand_address = current_address + 1;
+
+ /* %destination */
+ next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &destination);
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u Destination %u",
+ operand_address, destination);
+ }
+ operand_address = next_operand_address;
+
+ /* @address */
+ /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
+ next_operand_address = decode_udvm_address_operand(buff,operand_address, &at_address, current_address);
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u @Address %u",
+ operand_address, at_address);
+ }
+ operand_address = next_operand_address;
+
+ /* #n */
+ next_operand_address = decode_udvm_literal_operand(buff,operand_address, &n);
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u n %u",
+ operand_address, n);
+ }
+ operand_address = next_operand_address;
+ /*
+ * Note that if n = 0 then the INPUT-HUFFMAN instruction is ignored and
+ * program execution resumes at the following instruction.
+ * Decompression failure occurs if (bits_1 + ... + bits_n) > 16.
+ *
+ * In all other cases, the behavior of the INPUT-HUFFMAN instruction is
+ * defined below:
+ *
+ * 1. Set j := 1 and set H := 0.
+ *
+ * 2. Request bits_j compressed bits. Interpret the returned bits as an
+ * integer k from 0 to 2^bits_j - 1, as explained in Section 8.2.
+ *
+ * 3. Set H := H * 2^bits_j + k.
+ *
+ * 4. If data is requested that lies beyond the end of the SigComp
+ * message, terminate the INPUT-HUFFMAN instruction and move program
+ * execution to the memory address specified by the address operand.
+ *
+ * 5. If (H < lower_bound_j) or (H > upper_bound_j) then set j := j + 1.
+ * Then go back to Step 2, unless j > n in which case decompression
+ * failure occurs.
+ *
+ * 6. Copy (H + uncompressed_j - lower_bound_j) modulo 2^16 to the
+ * memory address specified by the destination operand.
+ *
+ */
+ /*
+ * The input_bit_order register contains the following three flags:
+ *
+ * 0 7 8 15
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | reserved |F|H|P| 68 - 69
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *
+ * Transfer H bit to bit_order to tell decomp dispatcher which bit order to use
+ */
+ bit_order = ( input_bit_order & 0x0002 ) >> 1;
+
+ j = 1;
+ H = 0;
+ m = n;
+ outside_huffman_boundaries = TRUE;
+ print_in_loop = print_level_1;
+ while ( m > 0 ){
+ /* %bits_n */
+ next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &bits_n);
+ if (print_in_loop ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u bits_n %u",
+ operand_address, bits_n);
+ }
+ operand_address = next_operand_address;
+
+ /* %lower_bound_n */
+ next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &lower_bound_n);
+ if (print_in_loop ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u lower_bound_n %u",
+ operand_address, lower_bound_n);
+ }
+ operand_address = next_operand_address;
+ /* %upper_bound_n */
+ next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &upper_bound_n);
+ if (print_in_loop ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u upper_bound_n %u",
+ operand_address, upper_bound_n);
+ }
+ operand_address = next_operand_address;
+ /* %uncompressed_n */
+ next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &uncompressed_n);
+ if (print_in_loop ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u uncompressed_n %u",
+ operand_address, uncompressed_n);
+ }
+ operand_address = next_operand_address;
+ /* execute instruction */
+ if ( outside_huffman_boundaries ) {
+ /*
+ * 3. Set H := H * 2^bits_j + k.
+ */
+ k = decomp_dispatch_get_bits( message_tvb, udvm_tree, bit_order,
+ buff, &old_input_bit_order, &remaining_bits,
+ &input_bits, &input_address, bits_n, &result_code, msg_end);
+ if ( result_code == 11 ){
+ current_address = at_address;
+ goto execute_next_instruction;
+ }
+ /* ldexp Returns x multiplied by 2 raised to the power of exponent.
+ * x*2^exponent
+ */
+ oldH = H;
+ H = ( (guint16)ldexp( H, bits_n) + k );
+ if (print_level_3 ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1," Set H(%u) := H(%u) * 2^bits_j(%u) + k(%u)",
+ H ,oldH,((guint16)pow(2,bits_n)),k);
+ }
+
+ /*
+ * 4. If data is requested that lies beyond the end of the SigComp
+ * message, terminate the INPUT-HUFFMAN instruction and move program
+ * execution to the memory address specified by the address operand.
+ */
+ if ( input_address > msg_end ){
+ current_address = at_address;
+ goto execute_next_instruction;
+ }
+ /*
+ * 5. If (H < lower_bound_j) or (H > upper_bound_j) then set j := j + 1.
+ * Then go back to Step 2, unless j > n in which case decompression
+ * failure occurs.
+ */
+ if ((H < lower_bound_n) || (H > upper_bound_n)){
+ outside_huffman_boundaries = TRUE;
+ }else{
+ outside_huffman_boundaries = FALSE;
+ print_in_loop = FALSE;
+ /*
+ * 6. Copy (H + uncompressed_j - lower_bound_j) modulo 2^16 to the
+ * memory address specified by the destination operand.
+ */
+ if (print_level_2 ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
+ " H(%u) = H(%u) + uncompressed_n(%u) - lower_bound_n(%u)",
+ (H + uncompressed_n - lower_bound_n ),H, uncompressed_n, lower_bound_n);
+ }
+ H = H + uncompressed_n - lower_bound_n;
+ msb = H >> 8;
+ lsb = H & 0x00ff;
+ buff[destination] = msb;
+ buff[destination + 1]=lsb;
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
+ " Loading H: %u (0x%x) at Addr: %u,j = %u remaining_bits: %u",
+ H, H, destination,( n - m + 1 ), remaining_bits);
+ }
+
+ }
+
+
+ }
+ m = m - 1;
+ }
+ if ( outside_huffman_boundaries ) {
+ result_code = 10;
+ goto decompression_failure;
+ }
+
+ current_address = next_operand_address;
+ used_udvm_cycles = used_udvm_cycles + 1 + n;
+ goto execute_next_instruction;
+ break;
+
+ case SIGCOMP_INSTR_STATE_ACCESS: /* 31 */
+ /* STATE-ACCESS (%partial_identifier_start, %partial_identifier_length,
+ * %state_begin, %state_length, %state_address, %state_instruction)
+ */
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
+ "Addr: %u ## STATE-ACCESS(31) (partial_identifier_start, partial_identifier_length,state_begin, state_length, state_address, state_instruction)",
+ current_address);
+ }
+ operand_address = current_address + 1;
+
+ /*
+ * %partial_identifier_start
+ */
+ next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &p_id_start);
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u partial_identifier_start %u",
+ operand_address, p_id_start);
+ }
+ operand_address = next_operand_address;
+
+ /*
+ * %partial_identifier_length
+ */
+ operand_address = next_operand_address;
+ next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &p_id_length);
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u partial_identifier_length %u",
+ operand_address, p_id_length);
+ }
+ /*
+ * %state_begin
+ */
+ operand_address = next_operand_address;
+ next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_begin);
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_begin %u",
+ operand_address, state_begin);
+ }
+ /*
+ * %state_length
+ */
+ operand_address = next_operand_address;
+ next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_length); if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_length %u",
+ operand_address, state_length);
+ }
+ /*
+ * %state_address
+ */
+ operand_address = next_operand_address;
+ next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_address);
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_address %u",
+ operand_address, state_address);
+ }
+ /*
+ * %state_instruction
+ */
+ operand_address = next_operand_address;
+ next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_instruction);
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_instruction %u",
+ operand_address, state_instruction);
+ }
+ current_address = next_operand_address;
+ byte_copy_right = buff[66] << 8;
+ byte_copy_right = byte_copy_right | buff[67];
+ byte_copy_left = buff[64] << 8;
+ byte_copy_left = byte_copy_left | buff[65];
+ if (print_level_2 ){
+ proto_tree_add_text(udvm_tree, message_tvb, input_address, 1,
+ " byte_copy_right = %u, byte_copy_left = %u", byte_copy_right,byte_copy_left);
+ }
+
+ result_code = udvm_state_access(buff, p_id_start, p_id_length, state_begin, state_length,
+ state_address, state_instruction);
+ if ( result_code != 0 ){
+ goto decompression_failure;
+ }
+ used_udvm_cycles = used_udvm_cycles + 1 + state_length;
+ goto execute_next_instruction;
+ break;
+ case SIGCOMP_INSTR_STATE_CREATE: /* 32 */
+ /*
+ * STATE-CREATE (%state_length, %state_address, %state_instruction,
+ * %minimum_access_length, %state_retention_priority)
+ */
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
+ "Addr: %u ## STATE-CREATE(32) (state_length, state_address, state_instruction,minimum_access_length, state_retention_priority)",
+ current_address);
+ }
+ operand_address = current_address + 1;
+
+ /*
+ * %state_length
+ */
+ next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_length);
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_length %u",
+ operand_address, state_length);
+ }
+ /*
+ * %state_address
+ */
+ operand_address = next_operand_address;
+ next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_address);
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_address %u",
+ operand_address, state_address);
+ }
+ /*
+ * %state_instruction
+ */
+ operand_address = next_operand_address;
+ next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_instruction);
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_instruction %u",
+ operand_address, state_instruction);
+ }
+ operand_address = next_operand_address;
+ /*
+ * %minimum_access_length
+ */
+ operand_address = next_operand_address;
+ next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &minimum_access_length);
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u minimum_access_length %u",
+ operand_address, minimum_access_length);
+ }
+ operand_address = next_operand_address;
+ /*
+ * %state_retention_priority
+ */
+ operand_address = next_operand_address;
+ next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_retention_priority);
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_retention_priority %u",
+ operand_address, state_retention_priority);
+ }
+ current_address = next_operand_address;
+ /* Execute the instruction
+ * TODO Implement the instruction
+ * RFC3320:
+ * Note that the new state item cannot be created until a valid
+ * compartment identifier has been returned by the application.
+ * Consequently, when a STATE-CREATE instruction is encountered the UDVM
+ * simply buffers the five supplied operands until the END-MESSAGE
+ * instruction is reached. The steps taken at this point are described
+ * in Section 9.4.9.
+ *
+ * Decompression failure MUST occur if more than four state creation
+ * requests are made before the END-MESSAGE instruction is encountered.
+ * Decompression failure also occurs if the minimum_access_length does
+ * not lie between 6 and 20 inclusive, or if the
+ * state_retention_priority is 65535.
+ */
+ no_of_state_create++;
+ if ( no_of_state_create > 4 ){
+ result_code = 12;
+ goto decompression_failure;
+ }
+ if (( minimum_access_length < 6 ) || ( minimum_access_length > 20 )){
+ result_code = 1;
+ goto decompression_failure;
+ }
+ if ( state_retention_priority == 65535 ){
+ result_code = 13;
+ goto decompression_failure;
+ }
+ state_length_buff[no_of_state_create] = state_length;
+ state_address_buff[no_of_state_create] = state_address;
+ state_instruction_buff[no_of_state_create] = state_instruction;
+ state_minimum_access_length_buff[no_of_state_create] = minimum_access_length;
+ state_state_retention_priority_buff[no_of_state_create] = state_retention_priority;
+ used_udvm_cycles = used_udvm_cycles + 1 + state_length;
+ /* Debug */
+ byte_copy_right = buff[66] << 8;
+ byte_copy_right = byte_copy_right | buff[67];
+ n = 0;
+ k = state_address;
+ while ( n < state_length ){
+ if ( k == byte_copy_right ){
+ byte_copy_left = buff[64] << 8;
+ byte_copy_left = byte_copy_left | buff[65];
+ k = byte_copy_left;
+ }
+ string[0]= buff[k];
+ string[1]= '\0';
+ if (print_level_3 ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
+ " Addr: %5u State value: %u (0x%x) ASCII(%s)",
+ k,buff[k],buff[k],string);
+ }
+ k = ( k + 1 ) & 0xffff;
+ n++;
+ }
+ /* End debug */
+
+ goto execute_next_instruction;
+ break;
+ case SIGCOMP_INSTR_STATE_FREE: /* 33 */
+ /*
+ * STATE-FREE (%partial_identifier_start, %partial_identifier_length)
+ */
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
+ "Addr: %u ## STATE-FREE (partial_identifier_start, partial_identifier_length)",
+ current_address);
+ }
+ operand_address = current_address + 1;
+ /*
+ * %partial_identifier_start
+ */
+ next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &p_id_start);
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u partial_identifier_start %u",
+ operand_address, p_id_start);
+ }
+ operand_address = next_operand_address;
+
+ /*
+ * %partial_identifier_length
+ */
+ operand_address = next_operand_address;
+ next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &p_id_length);
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u partial_identifier_length %u",
+ operand_address, p_id_length);
+ }
+ /* Execute the instruction:
+ * TODO implement it
+ */
+ used_udvm_cycles++;
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Execution of this instruction is NOT implemented");
+ break;
+ case SIGCOMP_INSTR_OUTPUT: /* 34 OUTPUT (%output_start, %output_length) */
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
+ "Addr: %u ## OUTPUT(34) (output_start, output_length)",
+ current_address);
+ }
+ operand_address = current_address + 1;
+ /*
+ * %output_start
+ */
+ next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &output_start);
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u output_start %u",
+ operand_address, output_start);
+ }
+ operand_address = next_operand_address;
+ /*
+ * %output_length
+ */
+ next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &output_length);
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u output_length %u",
+ operand_address, output_length);
+ }
+ current_address = next_operand_address;
+
+ /*
+ * Execute instruction
+ * 8.4. Byte copying
+ * :
+ * The string of bytes is copied in ascending order of memory address,
+ * respecting the bounds set by byte_copy_left and byte_copy_right.
+ * More precisely, if a byte is copied from/to Address m then the next
+ * byte is copied from/to Address n where n is calculated as follows:
+ *
+ * Set k := m + 1 (modulo 2^16)
+ * If k = byte_copy_right then set n := byte_copy_left, else set n := k
+ *
+ */
+
+ n = 0;
+ k = output_start;
+ byte_copy_right = buff[66] << 8;
+ byte_copy_right = byte_copy_right | buff[67];
+ if (print_level_3 ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
+ " byte_copy_right = %u", byte_copy_right);
+ }
+ while ( n < output_length ){
+
+ if ( k == byte_copy_right ){
+ byte_copy_left = buff[64] << 8;
+ byte_copy_left = byte_copy_left | buff[65];
+ k = byte_copy_left;
+ if (print_level_3 ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
+ " byte_copy_right = %u", byte_copy_right);
+ }
+ }
+ out_buff[output_address] = buff[k];
+ string[0]= buff[k];
+ string[1]= '\0';
+ if (print_level_3 ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
+ " Output value: %u (0x%x) ASCII(%s) from Addr: %u ,output to dispatcher position %u",
+ buff[k],buff[k],string, k,output_address);
+ }
+ k = ( k + 1 ) & 0xffff;
+ output_address ++;
+ n++;
+ }
+ used_udvm_cycles = used_udvm_cycles + 1 + output_length;
+ goto execute_next_instruction;
+ break;
+ case SIGCOMP_INSTR_END_MESSAGE: /* 35 */
+ /*
+ * END-MESSAGE (%requested_feedback_location,
+ * %returned_parameters_location, %state_length, %state_address,
+ * %state_instruction, %minimum_access_length,
+ * %state_retention_priority)
+ */
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,
+ "Addr: %u ## END-MESSAGE (requested_feedback_location,state_instruction, minimum_access_length,state_retention_priority)",
+ current_address);
+ }
+ operand_address = current_address + 1;
+
+ /* %requested_feedback_location */
+ next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &requested_feedback_location);
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u requested_feedback_location %u",
+ operand_address, requested_feedback_location);
+ }
+ operand_address = next_operand_address;
+ /* returned_parameters_location */
+ next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &returned_parameters_location);
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u returned_parameters_location %u",
+ operand_address, returned_parameters_location);
+ }
+ operand_address = next_operand_address;
+ /*
+ * %state_length
+ */
+ operand_address = next_operand_address;
+ next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_length);
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_length %u",
+ operand_address, state_length);
+ }
+ /*
+ * %state_address
+ */
+ operand_address = next_operand_address;
+ next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_address);
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_address %u",
+ operand_address, state_address);
+ }
+ /*
+ * %state_instruction
+ */
+ operand_address = next_operand_address;
+ next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_instruction);
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_instruction %u",
+ operand_address, state_instruction);
+ }
+ operand_address = next_operand_address;
+ /*
+ * %minimum_access_length
+ */
+ operand_address = next_operand_address;
+ next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &minimum_access_length);
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u minimum_access_length %u",
+ operand_address, minimum_access_length);
+ }
+ operand_address = next_operand_address;
+
+ /*
+ * %state_retention_priority
+ */
+ operand_address = next_operand_address;
+ next_operand_address = decode_udvm_multitype_operand(buff, operand_address, &state_retention_priority);
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Addr: %u state_retention_priority %u",
+ operand_address, state_retention_priority);
+ }
+ current_address = next_operand_address;
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"Execution of this instruction is NOT FULLY implemented( STATES NOT SAVED)");
+ /* TODO: This isn't currently totaly correct as END_INSTRUCTION might not create state */
+ no_of_state_create++;
+ if ( no_of_state_create > 4 ){
+ result_code = 12;
+ goto decompression_failure;
+ }
+ state_length_buff[no_of_state_create] = state_length;
+ state_address_buff[no_of_state_create] = state_address;
+ state_instruction_buff[no_of_state_create] = state_instruction;
+ /* Not used ? */
+ state_minimum_access_length_buff[no_of_state_create] = minimum_access_length;
+ state_state_retention_priority_buff[no_of_state_create] = state_retention_priority;
+
+ /* Execute the instruction
+ * TODO Implement the instruction
+ */
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"no_of_state_create %u",no_of_state_create);
+ if ( no_of_state_create != 0 ){
+ for( x=0; x < 20; x++){
+ sha1_digest_buf[x]=0;
+ }
+ n = 1;
+ byte_copy_right = buff[66] << 8;
+ byte_copy_right = byte_copy_right | buff[67];
+ while ( n < no_of_state_create + 1 ){
+ sha1buff = g_malloc(state_length_buff[n]+8);
+ sha1buff[0] = state_length_buff[n] >> 8;
+ sha1buff[1] = state_length_buff[n] & 0xff;
+ sha1buff[2] = state_address_buff[n] >> 8;
+ sha1buff[3] = state_address_buff[n] & 0xff;
+ sha1buff[4] = state_instruction_buff[n] >> 8;
+ sha1buff[5] = state_instruction_buff[n] & 0xff;
+ sha1buff[6] = state_minimum_access_length_buff[n] >> 8;
+ sha1buff[7] = state_minimum_access_length_buff[n] & 0xff;
+ if (print_level_3 ){
+ for( x=0; x < 8; x++){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"sha1buff %u 0x%x",
+ x,sha1buff[x]);
+ }
+ }
+ k = state_address_buff[n];
+ for( x=0; x < state_length_buff[n]; x++)
+ {
+ if ( k == byte_copy_right ){
+ byte_copy_left = buff[64] << 8;
+ byte_copy_left = byte_copy_left | buff[65];
+ k = byte_copy_left;
+ }
+ sha1buff[8+x] = buff[k];
+ k = ( k + 1 ) & 0xffff;
+ }
+
+ sha1_starts( &ctx );
+ sha1_update( &ctx, (guint8 *) sha1buff, state_length_buff[n] + 8);
+ sha1_finish( &ctx, sha1_digest_buf );
+ if (print_level_3 ){
+ for( x=0; x < 20; x++){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"SHA1 digest byte %u 0x%x",
+ x,sha1_digest_buf[x]);
+ }
+ }
+ udvm_state_create(sha1buff, sha1_digest_buf);
+ n++;
+
+ }
+ }
+
+
+
+ /* At least something got decompressed, show it */
+ decomp_tvb = tvb_new_real_data(out_buff,output_address,output_address);
+ tvb_set_child_real_data_tvbuff(message_tvb,decomp_tvb);
+ add_new_data_source(pinfo, decomp_tvb, "Decompressed SigComp message");
+ /*
+ proto_tree_add_text(udvm_tree, decomp_tvb, 0, -1,"SigComp message Decompressed");
+ */
+ used_udvm_cycles = used_udvm_cycles + 1 + state_length;
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"maximum_UDVM_cycles %u used_udvm_cycles %u",
+ maximum_UDVM_cycles, used_udvm_cycles);
+ return decomp_tvb;
+ break;
+
+ default:
+ break;
+ }
+ return NULL;
+decompression_failure:
+
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, bytecode_tvb, 0, -1,"DECOMPRESSION FAILURE: %s",
+ val_to_str(result_code, result_code_vals,"Unknown (%u)"));
+ }
+ return NULL;
+
+
+
+}
+
+ /* The simplest operand type is the literal (#), which encodes a
+ * constant integer from 0 to 65535 inclusive. A literal operand may
+ * require between 1 and 3 bytes depending on its value.
+ * Bytecode: Operand value: Range:
+ * 0nnnnnnn N 0 - 127
+ * 10nnnnnn nnnnnnnn N 0 - 16383
+ * 11000000 nnnnnnnn nnnnnnnn N 0 - 65535
+ *
+ * Figure 8: Bytecode for a literal (#) operand
+ *
+ */
+static int
+decode_udvm_literal_operand(guint8 buff[],guint operand_address, guint16 *value)
+{
+ guint bytecode;
+ guint16 operand;
+ guint test_bits;
+ guint offset = operand_address;
+ guint8 temp_data;
+
+ bytecode = buff[operand_address];
+ test_bits = bytecode >> 7;
+ if (test_bits == 1){
+ test_bits = bytecode >> 6;
+ if (test_bits == 2){
+ /*
+ * 10nnnnnn nnnnnnnn N 0 - 16383
+ */
+ temp_data = buff[operand_address] & 0x1f;
+ operand = temp_data << 8;
+ temp_data = buff[operand_address + 1];
+ operand = operand | temp_data;
+ *value = operand;
+ offset = offset + 2;
+
+ }else{
+ /*
+ * 111000000 nnnnnnnn nnnnnnnn N 0 - 65535
+ */
+ offset ++;
+ temp_data = buff[operand_address] & 0x1f;
+ operand = temp_data << 8;
+ temp_data = buff[operand_address + 1];
+ operand = operand | temp_data;
+ *value = operand;
+ offset = offset + 2;
+
+ }
+ }else{
+ /*
+ * 0nnnnnnn N 0 - 127
+ */
+ operand = ( bytecode & 0x7f);
+ *value = operand;
+ offset ++;
+ }
+
+ return offset;
+
+}
+
+/*
+ * The second operand type is the reference ($), which is always used to
+ * access a 2-byte value located elsewhere in the UDVM memory. The
+ * bytecode for a reference operand is decoded to be a constant integer
+ * from 0 to 65535 inclusive, which is interpreted as the memory address
+ * containing the actual value of the operand.
+ * Bytecode: Operand value: Range:
+ *
+ * 0nnnnnnn memory[2 * N] 0 - 65535
+ * 10nnnnnn nnnnnnnn memory[2 * N] 0 - 65535
+ * 11000000 nnnnnnnn nnnnnnnn memory[N] 0 - 65535
+ *
+ * Figure 9: Bytecode for a reference ($) operand
+ */
+static int
+dissect_udvm_reference_operand(guint8 buff[],guint operand_address, guint16 *value,guint *result_dest)
+{
+ guint bytecode;
+ guint16 operand;
+ guint offset = operand_address;
+ guint test_bits;
+ guint8 temp_data;
+ guint16 temp_data16;
+
+ bytecode = buff[operand_address];
+ test_bits = bytecode >> 7;
+ if (test_bits == 1){
+ test_bits = bytecode >> 6;
+ if (test_bits == 2){
+ /*
+ * 10nnnnnn nnnnnnnn memory[2 * N] 0 - 65535
+ */
+ temp_data = buff[operand_address] & 0x3f;
+ operand = temp_data << 8;
+ temp_data = buff[operand_address + 1];
+ operand = operand | temp_data;
+ operand = (operand * 2);
+ *result_dest = operand;
+ temp_data16 = buff[operand] << 8;
+ temp_data16 = temp_data16 | buff[operand+1];
+ *value = temp_data16;
+ offset = offset + 2;
+
+ }else{
+ /*
+ * 11000000 nnnnnnnn nnnnnnnn memory[N] 0 - 65535
+ */
+ operand_address++;
+ operand = buff[operand_address] << 8;
+ operand = operand | buff[operand_address + 1];
+ *result_dest = operand;
+ temp_data16 = buff[operand] << 8;
+ temp_data16 = temp_data16 | buff[operand+1];
+ *value = temp_data16;
+ offset = offset + 3;
+
+ }
+ }else{
+ /*
+ * 0nnnnnnn memory[2 * N] 0 - 65535
+ */
+ operand = ( bytecode & 0x7f);
+ operand = (operand * 2);
+ *result_dest = operand;
+ temp_data16 = buff[operand] << 8;
+ temp_data16 = temp_data16 | buff[operand+1];
+ *value = temp_data16;
+ offset ++;
+ }
+
+ return offset;
+}
+
+ /* RFC3320
+ * Figure 10: Bytecode for a multitype (%) operand
+ * Bytecode: Operand value: Range: HEX val
+ * 00nnnnnn N 0 - 63 0x00
+ * 01nnnnnn memory[2 * N] 0 - 65535 0x40
+ * 1000011n 2 ^ (N + 6) 64 , 128 0x86
+ * 10001nnn 2 ^ (N + 8) 256 , ... , 32768 0x88
+ * 111nnnnn N + 65504 65504 - 65535 0xe0
+ * 1001nnnn nnnnnnnn N + 61440 61440 - 65535 0x90
+ * 101nnnnn nnnnnnnn N 0 - 8191 0xa0
+ * 110nnnnn nnnnnnnn memory[N] 0 - 65535 0xc0
+ * 10000000 nnnnnnnn nnnnnnnn N 0 - 65535 0x80
+ * 10000001 nnnnnnnn nnnnnnnn memory[N] 0 - 65535 0x81
+ */
+static int
+decode_udvm_multitype_operand(guint8 buff[],guint operand_address, guint16 *value)
+{
+ guint test_bits;
+ guint bytecode;
+ guint offset = operand_address;
+ guint16 operand;
+ guint32 result;
+ guint8 temp_data;
+ guint16 temp_data16;
+ guint16 memmory_addr = 0;
+
+ bytecode = buff[operand_address];
+ test_bits = ( bytecode & 0xc0 ) >> 6;
+ switch (test_bits ){
+ case 0:
+ /*
+ * 00nnnnnn N 0 - 63
+ */
+ operand = buff[operand_address];
+ /* debug
+ *g_warning("Reading 0x%x From address %u",operand,offset);
+ */
+ *value = operand;
+ offset ++;
+ break;
+ case 1:
+ /*
+ * 01nnnnnn memory[2 * N] 0 - 65535
+ */
+ memmory_addr = ( bytecode & 0x3f) * 2;
+ temp_data16 = buff[memmory_addr] << 8;
+ temp_data16 = temp_data16 | buff[memmory_addr+1];
+ *value = temp_data16;
+ offset ++;
+ break;
+ case 2:
+ /* Check tree most significant bits */
+ test_bits = ( bytecode & 0xe0 ) >> 5;
+ if ( test_bits == 5 ){
+ /*
+ * 101nnnnn nnnnnnnn N 0 - 8191
+ */
+ temp_data = buff[operand_address] & 0x1f;
+ operand = temp_data << 8;
+ temp_data = buff[operand_address + 1];
+ operand = operand | temp_data;
+ *value = operand;
+ offset = offset + 2;
+ }else{
+ test_bits = ( bytecode & 0xf0 ) >> 4;
+ if ( test_bits == 9 ){
+ /*
+ * 1001nnnn nnnnnnnn N + 61440 61440 - 65535
+ */
+ temp_data = buff[operand_address] & 0x0f;
+ operand = temp_data << 8;
+ temp_data = buff[operand_address + 1];
+ operand = operand | temp_data;
+ operand = operand + 61440;
+ *value = operand;
+ offset = offset + 2;
+ }else{
+ test_bits = ( bytecode & 0x08 ) >> 3;
+ if ( test_bits == 1){
+ /*
+ * 10001nnn 2 ^ (N + 8) 256 , ... , 32768
+ */
+
+ result = (guint32)pow(2,( buff[operand_address] & 0x07) + 8);
+ operand = result & 0xffff;
+ *value = operand;
+ offset ++;
+ }else{
+ test_bits = ( bytecode & 0x0e ) >> 1;
+ if ( test_bits == 3 ){
+ /*
+ * 1000 011n 2 ^ (N + 6) 64 , 128
+ */
+ result = (guint32)pow(2,( buff[operand_address] & 0x01) + 6);
+ operand = result & 0xffff;
+ *value = operand;
+ offset ++;
+ }else{
+ /*
+ * 1000 0000 nnnnnnnn nnnnnnnn N 0 - 65535
+ * 1000 0001 nnnnnnnn nnnnnnnn memory[N] 0 - 65535
+ */
+ offset ++;
+ temp_data16 = buff[operand_address + 1] << 8;
+ temp_data16 = temp_data16 | buff[operand_address + 2];
+ /* debug
+ * g_warning("Reading 0x%x From address %u",temp_data16,operand_address);
+ */
+ if ( (bytecode & 0x01) == 1 ){
+ memmory_addr = temp_data16;
+ temp_data16 = buff[memmory_addr] << 8;
+ temp_data16 = temp_data16 | buff[memmory_addr+1];
+ }
+ *value = temp_data16;
+ offset = offset +2;
+ }
+
+
+ }
+ }
+ }
+ break;
+
+ case 3:
+ test_bits = ( bytecode & 0x20 ) >> 5;
+ if ( test_bits == 1 ){
+ /*
+ * 111nnnnn N + 65504 65504 - 65535
+ */
+ operand = ( buff[operand_address] & 0x1f) + 65504;
+ *value = operand;
+ offset ++;
+ }else{
+ /*
+ * 110nnnnn nnnnnnnn memory[N] 0 - 65535
+ */
+ memmory_addr = buff[operand_address] & 0x1f;
+ memmory_addr = memmory_addr << 8;
+ memmory_addr = memmory_addr | buff[operand_address + 1];
+ temp_data16 = buff[memmory_addr] << 8;
+ temp_data16 = temp_data16 | buff[memmory_addr+1];
+ *value = temp_data16;
+ /* debug
+ * g_warning("Reading 0x%x From address %u",temp_data16,memmory_addr);
+ */
+ offset = offset +2;
+ }
+
+ default :
+ break;
+ }
+ return offset;
+}
+ /*
+ *
+ * The fourth operand type is the address (@). This operand is decoded
+ * as a multitype operand followed by a further step: the memory address
+ * of the UDVM instruction containing the address operand is added to
+ * obtain the correct operand value. So if the operand value from
+ * Figure 10 is D then the actual operand value of an address is
+ * calculated as follows:
+ *
+ * operand_value = (memory_address_of_instruction + D) modulo 2^16
+ *
+ * Address operands are always used in instructions that control program
+ * flow, because they ensure that the UDVM bytecode is position-
+ * independent code (i.e., it will run independently of where it is
+ * placed in the UDVM memory).
+ */
+static int
+decode_udvm_address_operand(guint8 buff[],guint operand_address, guint16 *value,guint current_address)
+{
+ guint32 result;
+ guint16 value1;
+ guint next_opreand_address;
+
+ next_opreand_address = decode_udvm_multitype_operand(buff, operand_address, &value1);
+ result = value1 & 0xffff;
+ result = result + current_address;
+ *value = result & 0xffff;
+ return next_opreand_address;
+}
+
+static int
+decomp_dispatch_get_bits(tvbuff_t *message_tvb,proto_tree *udvm_tree,guint8 bit_order,
+ guint8 buff[],guint16 *old_input_bit_order, guint16 *remaining_bits,
+ guint16 *input_bits, guint *input_address, guint16 length,
+ guint16 *result_code,guint msg_end){
+
+guint16 input_bit_order;
+guint16 value;
+guint16 mask;
+guint8 octet;
+guint8 n;
+guint8 i;
+
+
+
+ input_bit_order = buff[68] << 8;
+ input_bit_order = input_bit_order | buff[69];
+ *result_code = 0;
+
+ /*
+ * Note that after one or more INPUT instructions the dispatcher may
+ * hold a fraction of a byte (what used to be the LSBs if P = 0, or, the
+ * MSBs, if P = 1). If an INPUT instruction is encountered and the P-
+ * bit has changed since the last INPUT instruction, any fraction of a
+ * byte still held by the dispatcher MUST be discarded (even if the
+ * INPUT instruction requests zero bits). The first bit passed to the
+ * INPUT instruction is taken from the subsequent byte.
+ */
+ if (print_level_1 ){
+ if ( *input_address > ( msg_end - 1)){
+ proto_tree_add_text(udvm_tree, message_tvb, (msg_end - 1), 1,
+ " input_bit_order = 0x%x, old_input_bit_order = 0x%x MSG BUFFER END", input_bit_order, *old_input_bit_order);
+ }else{
+ proto_tree_add_text(udvm_tree, message_tvb, *input_address, 1,
+ " input_bit_order = 0x%x, old_input_bit_order = 0x%x", input_bit_order,*old_input_bit_order);
+ }
+ }
+
+ if ( (*old_input_bit_order & 0x0001 ) != ( input_bit_order & 0x0001 )){
+ /* clear out remaining bits TODO check this further */
+ *remaining_bits = 0;
+ *old_input_bit_order = input_bit_order;
+ }
+
+ /*
+ * Do we hold a fraction of a byte ?
+ */
+ if ( *remaining_bits != 0 ){
+ if ( *remaining_bits < length ){
+ if (*remaining_bits > 8 ){
+ proto_tree_add_text(udvm_tree, message_tvb, *input_address, 1,
+ " Yikes!! haven't coded this case yet!!remaining_bits %u > 8 ", *remaining_bits, length);
+ return 0xfbad;
+ }
+ if ( *input_address > ( msg_end -1 ) ){
+ *result_code = 11;
+ return 0xfbad;
+ }
+
+ octet = tvb_get_guint8(message_tvb, *input_address);
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, message_tvb, *input_address , 1,
+ " Geting value: %u (0x%x) From Addr: %u", octet, octet, *input_address);
+ }
+ *input_address = *input_address + 1;
+
+ if ( ( bit_order ) == 0 ){
+ /*
+ * F/H bit = 0
+ */
+ /* borrow value */
+ value = octet & 0x00ff;
+ value = value << ( 8 - (*remaining_bits));
+ *remaining_bits = *remaining_bits + 8;
+ }else{
+ /*
+ * F/H bit = 1
+ */
+ /* borrow value */
+ value = ( octet << 7) & 0x80;
+ value = value | (( octet << 5) & 0x40 );
+ value = value | (( octet << 3) & 0x20 );
+ value = value | (( octet << 1) & 0x10 );
+
+ value = value | (( octet >> 1) & 0x08 );
+ value = value | (( octet >> 3) & 0x04 );
+ value = value | (( octet >> 5) & 0x02 );
+ value = value | (( octet >> 7) & 0x01 );
+
+ value = value << ( 8 - (*remaining_bits));
+ *remaining_bits = *remaining_bits + 8;
+ }
+
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, message_tvb, *input_address - 1 , 1,
+ " Or value 0x%x with 0x%x remaining bits %u, Result 0x%x",
+ value, *input_bits, *remaining_bits, (*input_bits | value));
+ }
+ *input_bits = *input_bits | value;
+ }/* Bits remain */
+ if ( ( bit_order ) == 0 ){
+ /*
+ * F/H bit = 0
+ */
+ mask = (0xffff >> length)^0xffff;
+ value = *input_bits & mask;
+ value = value >> ( 16 - length);
+ *input_bits = *input_bits << length;
+ *remaining_bits = *remaining_bits - length;
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, message_tvb, *input_address, 1,
+ " Remaining input_bits 0x%x remaining_bits %u", *input_bits, *remaining_bits);
+ }
+ return value;
+ }
+ else{
+ /*
+ * F/H bit = 1
+ */
+ n = 15;
+ i = 0;
+ value = 0;
+ while ( i < length ){
+ value = value | (( *input_bits & 0x8000 ) >> n) ;
+ *input_bits = *input_bits << 1;
+ n--;
+ i++;
+ }
+ *remaining_bits = *remaining_bits - length;
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, message_tvb, *input_address, 1,
+ " Remaining input_bits 0x%x", *input_bits);
+ }
+ return value;
+ }
+
+ }
+ else
+ {
+ /*
+ * Do we need one or two bytes ?
+ */
+ if ( *input_address > ( msg_end -1 ) ){
+ *result_code = 11;
+ return 0xfbad;
+ }
+
+ if ( length < 9 ){
+ octet = tvb_get_guint8(message_tvb, *input_address);
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, message_tvb, *input_address , 1,
+ " Geting value: %u (0x%x) From Addr: %u", octet, octet, *input_address);
+ }
+ *input_address = *input_address + 1;
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, message_tvb, *input_address , 1,
+ " Next input from Addr: %u", *input_address);
+ }
+
+ if ( ( input_bit_order & 0x0001 ) == 0 ){
+ /*
+ * P bit = Zero
+ */
+ *input_bits = octet & 0xff;
+ *input_bits = *input_bits << 8;
+ *remaining_bits = 8;
+ }else{
+ /*
+ * P bit = One
+ */
+ *input_bits = ( octet << 7) & 0x80;
+ *input_bits = *input_bits | (( octet << 5) & 0x40 );
+ *input_bits = *input_bits | (( octet << 3) & 0x20 );
+ *input_bits = *input_bits | (( octet << 1) & 0x10 );
+
+ *input_bits = *input_bits | (( octet >> 1) & 0x08 );
+ *input_bits = *input_bits | (( octet >> 3) & 0x04 );
+ *input_bits = *input_bits | (( octet >> 5) & 0x02 );
+ *input_bits = *input_bits | (( octet >> 7) & 0x01 );
+
+ *input_bits = *input_bits << 8;
+ *remaining_bits = 8;
+ proto_tree_add_text(udvm_tree, message_tvb, *input_address -1, 1,
+ " P bit = 1, input_bits = 0x%x",*input_bits);
+
+ }
+
+ }
+ else{
+ /* Length > 9, we need two bytes */
+ octet = tvb_get_guint8(message_tvb, *input_address);
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, message_tvb, *input_address, 1,
+ " Geting first value: %u (0x%x) From Addr: %u", octet, octet, *input_address);
+ }
+ if ( ( input_bit_order & 0x0001 ) == 0 ){
+ *input_bits = octet & 0xff;
+ *input_bits = *input_bits << 8;
+ *input_address = *input_address + 1;
+ }else{
+ /*
+ * P bit = One
+ */
+ *input_bits = ( octet << 7) & 0x80;
+ *input_bits = *input_bits | (( octet << 5) & 0x40 );
+ *input_bits = *input_bits | (( octet << 3) & 0x20 );
+ *input_bits = *input_bits | (( octet << 1) & 0x10 );
+
+ *input_bits = *input_bits | (( octet >> 1) & 0x08 );
+ *input_bits = *input_bits | (( octet >> 3) & 0x04 );
+ *input_bits = *input_bits | (( octet >> 5) & 0x02 );
+ *input_bits = *input_bits | (( octet >> 7) & 0x01 );
+
+ *input_bits = *input_bits << 8;
+ *input_address = *input_address + 1;
+ proto_tree_add_text(udvm_tree, message_tvb, *input_address -1, 1,
+ " P bit = 1, input_bits = 0x%x",*input_bits);
+
+ }
+
+ if ( *input_address > ( msg_end - 1)){
+ *result_code = 11;
+ return 0xfbad;
+ }
+
+ octet = tvb_get_guint8(message_tvb, *input_address);
+ *input_address = *input_address + 1;
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, message_tvb, *input_address - 2, 2,
+ " Geting second value: %u (0x%x) From Addr: %u", octet, octet, *input_address);
+ }
+ if ( ( input_bit_order & 0x0001 ) == 0 ){
+ /*
+ * P bit = zero
+ */
+ *input_bits = *input_bits | octet;
+ *remaining_bits = 16;
+ }else{
+ /*
+ * P bit = One
+ */
+ *input_bits = ( octet << 7) & 0x80;
+ *input_bits = *input_bits | (( octet << 5) & 0x40 );
+ *input_bits = *input_bits | (( octet << 3) & 0x20 );
+ *input_bits = *input_bits | (( octet << 1) & 0x10 );
+
+ *input_bits = *input_bits | (( octet >> 1) & 0x08 );
+ *input_bits = *input_bits | (( octet >> 3) & 0x04 );
+ *input_bits = *input_bits | (( octet >> 5) & 0x02 );
+ *input_bits = *input_bits | (( octet >> 7) & 0x01 );
+
+ *input_bits = *input_bits << 8;
+ *input_address = *input_address + 1;
+ proto_tree_add_text(udvm_tree, message_tvb, *input_address -1, 1,
+ " P bit = 1, input_bits = 0x%x",*input_bits);
+
+ *remaining_bits = 16;
+ }
+
+ }
+ if ( ( bit_order ) == 0 ){
+ /*
+ * F/H bit = 0
+ */
+ mask = (0xffff >> length)^0xffff;
+ value = *input_bits & mask;
+ value = value >> ( 16 - length);
+ *input_bits = *input_bits << length;
+ *remaining_bits = *remaining_bits - length;
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, message_tvb, *input_address, 1,
+ " Remaining input_bits 0x%x", *input_bits);
+ }
+ return value;
+ }
+ else{
+ /*
+ * F/H bit = 1
+ */
+ n = 15;
+ i = 0;
+ value = 0;
+ while ( i < length ){
+ value = value | ( *input_bits & 0x8000 ) >> n ;
+ *input_bits = *input_bits << 1;
+ n--;
+ i++;
+ }
+ *remaining_bits = *remaining_bits - length;
+ if (print_level_1 ){
+ proto_tree_add_text(udvm_tree, message_tvb, *input_address, 1,
+ " Remaining input_bits 0x%x", *input_bits);
+ }
+ return value;
+ }
+
+ }
+}
+/* end udvm */ \ No newline at end of file