/* -*- mode: C; c-basic-offset: 3; -*- */
/*
  This file is part of drd, a thread error detector.

  Copyright (C) 2006-2009 Bart Van Assche <bart.vanassche@gmail.com>.

  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.

  The GNU General Public License is contained in the file COPYING.
*/


#ifndef __DRD_THREAD_BITMAP_H
#define __DRD_THREAD_BITMAP_H


#include "drd_bitmap.h"
#include "drd_thread.h" /* running_thread_get_segment() */
#include "pub_drd_bitmap.h"


static __inline__
Bool bm_access_load_1_triggers_conflict(const Addr a1)
{
   DRD_(bm_access_load_1)(DRD_(running_thread_get_segment)()->bm, a1);
   return DRD_(bm_load_1_has_conflict_with)(DRD_(thread_get_conflict_set)(),
                                            a1);
}

static __inline__
Bool bm_access_load_2_triggers_conflict(const Addr a1)
{
   if ((a1 & 1) == 0)
   {
      bm_access_aligned_load(DRD_(running_thread_get_segment)()->bm, a1, 2);
      return bm_aligned_load_has_conflict_with(DRD_(thread_get_conflict_set)(),
                                               a1, 2);
   }
   else
   {
      DRD_(bm_access_range)(DRD_(running_thread_get_segment)()->bm,
                            a1, a1 + 2, eLoad);
      return DRD_(bm_has_conflict_with)(DRD_(thread_get_conflict_set)(),
                                        a1, a1 + 2, eLoad);
   }
}

static __inline__
Bool bm_access_load_4_triggers_conflict(const Addr a1)
{
   if ((a1 & 3) == 0)
   {
      bm_access_aligned_load(DRD_(running_thread_get_segment)()->bm, a1, 4);
      return bm_aligned_load_has_conflict_with(DRD_(thread_get_conflict_set)(),
                                               a1, 4);
   }
   else
   {
      DRD_(bm_access_range)(DRD_(running_thread_get_segment)()->bm,
                            a1, a1 + 4, eLoad);
      return DRD_(bm_has_conflict_with)(DRD_(thread_get_conflict_set)(),
                                        a1, a1 + 4, eLoad);
   }
}

static __inline__
Bool bm_access_load_8_triggers_conflict(const Addr a1)
{
   if ((a1 & 7) == 0)
   {
      bm_access_aligned_load(DRD_(running_thread_get_segment)()->bm, a1, 8);
      return bm_aligned_load_has_conflict_with(DRD_(thread_get_conflict_set)(),
                                               a1, 8);
   }
   else if ((a1 & 3) == 0)
   {
      bm_access_aligned_load(DRD_(running_thread_get_segment)()->bm, a1 + 0, 4);
      bm_access_aligned_load(DRD_(running_thread_get_segment)()->bm, a1 + 4, 4);
      return DRD_(bm_has_conflict_with)(DRD_(thread_get_conflict_set)(),
                                        a1, a1 + 8, eLoad);
   }
   else
   {
      DRD_(bm_access_range)(DRD_(running_thread_get_segment)()->bm,
                            a1, a1 + 8, eLoad);
      return DRD_(bm_has_conflict_with)(DRD_(thread_get_conflict_set)(),
                                        a1, a1 + 8, eLoad);
   }
}

static __inline__
Bool bm_access_load_triggers_conflict(const Addr a1, const Addr a2)
{
   DRD_(bm_access_range_load)(DRD_(running_thread_get_segment)()->bm, a1, a2);
   return DRD_(bm_load_has_conflict_with)(DRD_(thread_get_conflict_set)(),
                                          a1, a2);
}

static __inline__
Bool bm_access_store_1_triggers_conflict(const Addr a1)
{
   DRD_(bm_access_store_1)(DRD_(running_thread_get_segment)()->bm, a1);
   return DRD_(bm_store_1_has_conflict_with)(DRD_(thread_get_conflict_set)(),
                                             a1);
}

static __inline__
Bool bm_access_store_2_triggers_conflict(const Addr a1)
{
   if ((a1 & 1) == 0)
   {
      bm_access_aligned_store(DRD_(running_thread_get_segment)()->bm, a1, 2);
      return bm_aligned_store_has_conflict_with(DRD_(thread_get_conflict_set)(),
                                                a1, 2);
   }
   else
   {
      DRD_(bm_access_range)(DRD_(running_thread_get_segment)()->bm,
                            a1, a1 + 2, eStore);
      return DRD_(bm_has_conflict_with)(DRD_(thread_get_conflict_set)(),
                                        a1, a1 + 2, eStore);
   }
}

static __inline__
Bool bm_access_store_4_triggers_conflict(const Addr a1)
{
   if ((a1 & 3) == 0)
   {
      bm_access_aligned_store(DRD_(running_thread_get_segment)()->bm, a1, 4);
      return bm_aligned_store_has_conflict_with(DRD_(thread_get_conflict_set)(),
                                                a1, 4);
   }
   else
   {
      DRD_(bm_access_range)(DRD_(running_thread_get_segment)()->bm,
                            a1, a1 + 4, eStore);
      return DRD_(bm_has_conflict_with)(DRD_(thread_get_conflict_set)(),
                                        a1, a1 + 4, eStore);
   }
}

static __inline__
Bool bm_access_store_8_triggers_conflict(const Addr a1)
{
   if ((a1 & 7) == 0)
   {
      bm_access_aligned_store(DRD_(running_thread_get_segment)()->bm, a1, 8);
      return bm_aligned_store_has_conflict_with(DRD_(thread_get_conflict_set)(),
                                                a1, 8);
   }
   else if ((a1 & 3) == 0)
   {
      bm_access_aligned_store(DRD_(running_thread_get_segment)()->bm,
                              a1 + 0, 4);
      bm_access_aligned_store(DRD_(running_thread_get_segment)()->bm,
                              a1 + 4, 4);
      return DRD_(bm_has_conflict_with)(DRD_(thread_get_conflict_set)(),
                                        a1, a1 + 8, eStore);
   }
   else
   {
      DRD_(bm_access_range)(DRD_(running_thread_get_segment)()->bm,
                            a1, a1 + 8, eStore);
      return DRD_(bm_has_conflict_with)(DRD_(thread_get_conflict_set)(),
                                        a1, a1 + 8, eStore);
   }
}

static __inline__
Bool bm_access_store_triggers_conflict(const Addr a1, const Addr a2)
{
   DRD_(bm_access_range_store)(DRD_(running_thread_get_segment)()->bm, a1, a2);
   return DRD_(bm_store_has_conflict_with)(DRD_(thread_get_conflict_set)(),
                                           a1, a2);
}

#endif // __DRD_THREAD_BITMAP_H
