/*
 * Copyright (c) 2016-2017 ARM Limited
 * All rights reserved
 *
 * The license below extends only to copyright in the software and shall
 * not be construed as granting a license to any other intellectual
 * property including but not limited to intellectual property relating
 * to a hardware implementation of the functionality of the software
 * licensed hereunder.  You may use the software subject to the license
 * terms below provided that you ensure that this notice is replicated
 * unmodified and in its entirety in all distributions of the software,
 * modified or unmodified, in source code or in binary form.
 *
 * 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: Nathanael Premillieu
 */

#ifndef __CPU_INST_RES_HH__
#define __CPU_INST_RES_HH__

#include <type_traits>

#include "arch/generic/types.hh"
#include "arch/generic/vec_reg.hh"

class InstResult {
    using VecRegContainer = TheISA::VecRegContainer;
    using VecElem = TheISA::VecElem;
    using VecPredRegContainer = TheISA::VecPredRegContainer;
  public:
    union MultiResult {
        uint64_t integer;
        double dbl;
        VecRegContainer vector;
        VecElem vecElem;
        VecPredRegContainer pred;
        MultiResult() {}
    };

    enum class ResultType {
        Scalar,
        VecElem,
        VecReg,
        VecPredReg,
        NumResultTypes,
        Invalid
    };

  private:
    MultiResult result;
    ResultType type;

  public:
    /** Default constructor creates an invalid result. */
    InstResult() : type(ResultType::Invalid) { }
    /** Scalar result from scalar. */
    template<typename T>
    explicit InstResult(T i, const ResultType& t) : type(t) {
        static_assert(std::is_integral<T>::value ^
                        std::is_floating_point<T>::value,
                "Parameter type is neither integral nor fp, or it is both");
        if (std::is_integral<T>::value) {
            result.integer = i;
        } else if (std::is_floating_point<T>::value) {
            result.dbl = i;
        }
    }
    /** Vector result. */
    explicit InstResult(const VecRegContainer& v, const ResultType& t)
        : type(t) { result.vector = v; }
    /** Predicate result. */
    explicit InstResult(const VecPredRegContainer& v, const ResultType& t)
        : type(t) { result.pred = v; }

    InstResult& operator=(const InstResult& that) {
        type = that.type;
        switch (type) {
        /* Given that misc regs are not written to, there may be invalids in
         * the result stack. */
        case ResultType::Invalid:
            break;
        case ResultType::Scalar:
            result.integer = that.result.integer;
            break;
        case ResultType::VecElem:
            result.vecElem = that.result.vecElem;
            break;
        case ResultType::VecReg:
            result.vector = that.result.vector;
            break;
        case ResultType::VecPredReg:
            result.pred = that.result.pred;
            break;

        default:
            panic("Assigning result from unknown result type");
            break;
        }
        return *this;
    }
    /**
     * Result comparison
     * Two invalid results always differ.
     */
    bool operator==(const InstResult& that) const {
        if (this->type != that.type)
            return false;
        switch (type) {
        case ResultType::Scalar:
            return result.integer == that.result.integer;
        case ResultType::VecElem:
            return result.vecElem == that.result.vecElem;
        case ResultType::VecReg:
            return result.vector == that.result.vector;
        case ResultType::VecPredReg:
            return result.pred == that.result.pred;
        case ResultType::Invalid:
            return false;
        default:
            panic("Unknown type of result: %d\n", (int)type);
        }
    }

    bool operator!=(const InstResult& that) const {
        return !operator==(that);
    }

    /** Checks */
    /** @{ */
    /** Is this a scalar result?. */
    bool isScalar() const { return type == ResultType::Scalar; }
    /** Is this a vector result?. */
    bool isVector() const { return type == ResultType::VecReg; }
    /** Is this a vector element result?. */
    bool isVecElem() const { return type == ResultType::VecElem; }
    /** Is this a predicate result?. */
    bool isPred() const { return type == ResultType::VecPredReg; }
    /** Is this a valid result?. */
    bool isValid() const { return type != ResultType::Invalid; }
    /** @} */

    /** Explicit cast-like operations. */
    /** @{ */
    const uint64_t&
    asInteger() const
    {
        assert(isScalar());
        return result.integer;
    }

    /** Cast to integer without checking type.
     * This is required to have the o3 cpu checker happy, as it
     * compares results as integers without being fully aware of
     * their nature. */
    const uint64_t&
    asIntegerNoAssert() const
    {
        return result.integer;
    }
    const VecRegContainer&
    asVector() const
    {
        panic_if(!isVector(), "Converting scalar (or invalid) to vector!!");
        return result.vector;
    }
    const VecElem&
    asVectorElem() const
    {
        panic_if(!isVecElem(), "Converting scalar (or invalid) to vector!!");
        return result.vecElem;
    }

    const VecPredRegContainer&
    asPred() const
    {
        panic_if(!isPred(), "Converting scalar (or invalid) to predicate!!");
        return result.pred;
    }

    /** @} */
};

#endif // __CPU_INST_RES_HH__
