docs: def merge(self, *others, **kwargs):
          """
          Merges this state with the other states. Returns the merging result, merged state, and the merge flag.
  
          :param states: the states to merge
          :param merge_conditions: a tuple of the conditions under which each state holds
          :param common_ancestor:  a state that represents the common history between the states being merged. Usually it
                                   is only available when EFFICIENT_STATE_MERGING is enabled, otherwise weak-refed states
                                   might be dropped from state history instances.
          :param plugin_whitelist: a list of plugin names that will be merged. If this option is given and is not None,
                                   any plugin that is not inside this list will not be merged, and will be created as a
                                   fresh instance in the new state.
          :param common_ancestor_history:
                                   a SimStateHistory instance that represents the common history between the states being
                                   merged. This is to allow optimal state merging when EFFICIENT_STATE_MERGING is
                                   disabled.
          :return: (merged state, merge flag, a bool indicating if any merging occured)
          """
  
          merge_conditions = kwargs.pop('merge_conditions', None)
          common_ancestor = kwargs.pop('common_ancestor', None)
          plugin_whitelist = kwargs.pop('plugin_whitelist', None)
          common_ancestor_history = kwargs.pop('common_ancestor_history', None)
  
          if len(kwargs) != 0:
              raise ValueError("invalid arguments: %s" % kwargs.keys())
  
          if merge_conditions is None:
              # TODO: maybe make the length of this smaller? Maybe: math.ceil(math.log(len(others)+1, 2))
              merge_flag = self.solver.BVS("state_merge_%d" % next(merge_counter), 16)
              merge_values = range(len(others)+1)
              merge_conditions = [ merge_flag == b for b in merge_values ]
          else:
              merge_conditions = [
                  (self.solver.true if len(mc) == 0 else self.solver.And(*mc)) for mc in merge_conditions
              ]
  
          if len(set(o.arch.name for o in others)) != 1:
              raise SimMergeError("Unable to merge due to different architectures.")
  
          all_plugins = set(self.plugins.keys()) | set.union(*(set(o.plugins.keys()) for o in others))
  
          if plugin_whitelist is not None:
              all_plugins = all_plugins.intersection(set(plugin_whitelist))
  
          merged = self.copy()
          merging_occurred = False
  
          # fix parent
          merged.history.parent = self.history
  
          # plugins
          for p in all_plugins:
              our_plugin = merged.plugins[p] if p in merged.plugins else None
              their_plugins = [ (pl.plugins[p] if p in pl.plugins else None) for pl in others ]
  
              plugin_classes = (
                  set([our_plugin.__class__]) | set(pl.__class__ for pl in their_plugins)
              ) - set([None.__class__])
              if len(plugin_classes) != 1:
                  raise SimMergeError(
                      "There are differing plugin classes (%s) for plugin %s" % (plugin_classes, p)
                  )
              plugin_class = plugin_classes.pop()
  
              our_filled_plugin = our_plugin if our_plugin is not None else merged.register_plugin(
                  p, plugin_class()
              )
              their_filled_plugins = [
                  (tp if tp is not None else t.register_plugin(p, plugin_class()))
                  for t,tp in zip(others, their_plugins)
              ]
  
              plugin_common_ancestor = (
                  common_ancestor.plugins[p] if
                  (common_ancestor is not None and p in common_ancestor.plugins) else
                  None
              )
              if plugin_common_ancestor is None and \
                      plugin_class is SimStateHistory and \
                      common_ancestor_history is not None:
                  plugin_common_ancestor = common_ancestor_history
  
              plugin_state_merged = our_filled_plugin.merge(
                  their_filled_plugins, merge_conditions, common_ancestor=plugin_common_ancestor,
              )
              if plugin_state_merged:
                  l.debug('Merging occurred in %s', p)
                  merging_occurred = True
  
          merged.add_constraints(merged.solver.Or(*merge_conditions))
          return merged, merge_conditions, merging_occurred