/*
 * Copyright (c) 2015-2017 Advanced Micro Devices, Inc.
 * All rights reserved.
 *
 * Copyright (c) 2003-2005 The Regents of The University of Michigan
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Authors: Nathan Binkert
 *          Anthony Gutierrez
 */

#ifndef __BASE_AMO_HH__
#define __BASE_AMO_HH__

#include <array>
#include <cstdint>
#include <functional>

struct AtomicOpFunctor
{
    virtual void operator()(uint8_t *p) = 0;
    virtual AtomicOpFunctor* clone() = 0;
    virtual ~AtomicOpFunctor() {}
};

template <class T>
struct TypedAtomicOpFunctor : public AtomicOpFunctor
{
    void operator()(uint8_t *p) { execute((T *)p); }
    virtual AtomicOpFunctor* clone() = 0;
    virtual void execute(T * p) = 0;
};

template<typename T>
class AtomicGeneric2Op : public TypedAtomicOpFunctor<T>
{
  public:
    AtomicGeneric2Op(T _a, std::function<void(T*,T)> _op)
        : a(_a), op(_op)
    {}
    AtomicOpFunctor* clone() override
    {
        return new AtomicGeneric2Op<T>(*this);
    }
    void execute(T *b) override
    {
        op(b, a);
    }
  private:
    T a;
    std::function<void(T*,T)> op;
 };

template<typename T>
class AtomicGeneric3Op : public TypedAtomicOpFunctor<T>
{
  public:
    AtomicGeneric3Op(T _a, T _c, std::function<void(T*, T, T)> _op)
        : a(_a), c(_c), op(_op)
    {}
    AtomicOpFunctor* clone() override
    {
        return new AtomicGeneric3Op<T>(*this);
    }
    void execute(T *b) override
    {
        op(b, a, c);
    }
  private:
    T a;
    T c;
    std::function<void(T*, T, T)> op;
};

template<typename T>
class AtomicGenericPair3Op : public TypedAtomicOpFunctor<T>
{
  public:
    AtomicGenericPair3Op(std::array<T, 2>& _a, std::array<T, 2> _c,
           std::function<void(T*, std::array<T, 2>&, std::array<T, 2>)> _op)
        : a(_a), c(_c), op(_op)
    {}
    AtomicOpFunctor* clone() override
    {
        return new AtomicGenericPair3Op<T>(*this);
    }
    void execute(T* b) override
    {
        op(b, a, c);
    }
  private:
    std::array<T, 2> a;
    std::array<T, 2> c;
    std::function<void(T*, std::array<T, 2>&, std::array<T, 2>)> op;
};

template<typename T>
class AtomicOpAnd : public TypedAtomicOpFunctor<T>
{
  public:
    T a;
    AtomicOpAnd(T _a) : a(_a) { }
    void execute(T *b) { *b &= a; }
    AtomicOpFunctor* clone () { return new AtomicOpAnd(a); }
};

template<typename T>
class AtomicOpOr : public TypedAtomicOpFunctor<T>
{
  public:
    T a;
    AtomicOpOr(T _a) : a(_a) { }
    void execute(T *b) { *b |= a; }
    AtomicOpFunctor* clone () { return new AtomicOpOr(a); }
};

template<typename T>
class AtomicOpXor : public TypedAtomicOpFunctor<T>
{
  public:
    T a;
    AtomicOpXor(T _a) : a(_a) {}
    void execute(T *b) { *b ^= a; }
    AtomicOpFunctor* clone () { return new AtomicOpXor(a); }
};

template<typename T>
class AtomicOpExch : public TypedAtomicOpFunctor<T>
{
  public:
    T a;
    AtomicOpExch(T _a) : a(_a) { }
    void execute(T *b) { *b = a; }
    AtomicOpFunctor* clone () { return new AtomicOpExch(a); }
};

template<typename T>
class AtomicOpAdd : public TypedAtomicOpFunctor<T>
{
  public:
    T a;
    AtomicOpAdd(T _a) : a(_a) { }
    void execute(T *b) { *b += a; }
    AtomicOpFunctor* clone () { return new AtomicOpAdd(a); }
};

template<typename T>
class AtomicOpSub : public TypedAtomicOpFunctor<T>
{
  public:
    T a;
    AtomicOpSub(T _a) : a(_a) { }
    void execute(T *b) { *b -= a; }
    AtomicOpFunctor* clone () { return new AtomicOpSub(a); }
};

template<typename T>
class AtomicOpInc : public TypedAtomicOpFunctor<T>
{
  public:
    AtomicOpInc() { }
    void execute(T *b) { *b += 1; }
    AtomicOpFunctor* clone () { return new AtomicOpInc(); }
};

template<typename T>
class AtomicOpDec : public TypedAtomicOpFunctor<T>
{
  public:
    AtomicOpDec() {}
    void execute(T *b) { *b -= 1; }
    AtomicOpFunctor* clone () { return new AtomicOpDec(); }
};

template<typename T>
class AtomicOpMax : public TypedAtomicOpFunctor<T>
{
  public:
    T a;
    AtomicOpMax(T _a) : a(_a) { }

    void
    execute(T *b)
    {
        if (a > *b)
            *b = a;
    }
    AtomicOpFunctor* clone () { return new AtomicOpMax(a); }
};

template<typename T>
class AtomicOpMin : public TypedAtomicOpFunctor<T>
{
  public:
    T a;
    AtomicOpMin(T _a) : a(_a) {}

    void
    execute(T *b)
    {
        if (a < *b)
            *b = a;
    }
    AtomicOpFunctor* clone () { return new AtomicOpMin(a); }
};

typedef std::unique_ptr<AtomicOpFunctor> AtomicOpFunctorPtr;

#endif // __BASE_AMO_HH__
