let data_binop kr binop ka ga kb gb =
    match binop with

      (* pointer arithmetics *)

      | (IndexPI | PlusPI-> data_shift ka ga kb gb ~is_pos:true
      | MinusPI -> data_shift ka ga kb gb ~is_pos:false
      | MinusPP ->
          begin
            match ka with
              | Kptr te ->
                  let obj = object_of te in
                 data_of_integer
                   (D.minus_pointer
                      (M.pointer_of_loc (loc_of_data obj ga))
                      (M.pointer_of_loc (loc_of_data obj gb)))
              | _ -> WpLog.fatal "wrong parameters for pointer arithmetics"
          end

      (* scalar arithmetics *)

      | PlusA | MinusA | Mult | Div | Mod
      | BAnd | BXor | BOr | Shiftlt | Shiftrt ->
          begin
            match kr with
             | (Kint  | Kcint _)  -> data_of_integer
                   (int_op binop
                      (integer_of_data ka ga) (integer_of_data kb gb))
              | Kreal -> data_of_real
                  (real_op binop (real_of_data ka ga) (real_of_data kb gb))
              | (Kset Kint |Kset (Kcint _)) when binop = PlusA ->
                  add_integer ka ga kb gb
              | _ -> WpLog.fatal "wrong parameters for scalar arithmetics"
          end

      (* comparisons *)
      | Eq | Ne | Gt | Ge | Lt | Le ->
          data_of_boolean (data_cmp binop ka ga kb gb)

      (*logic or *)
      | LOr ->
          data_of_boolean (F.e_or (boolean_of_data ga) (boolean_of_data gb))

      (* logic and *)
      | LAnd ->
          data_of_boolean (F.e_and (boolean_of_data ga) (boolean_of_data gb))