/*
 * Copyright 2020 Google Inc.
 *
 * 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.
 */

#ifndef __ARCH_SPARC_SE_WORKLOAD_HH__
#define __ARCH_SPARC_SE_WORKLOAD_HH__

#include <vector>

#include "arch/sparc/regs/int.hh"
#include "arch/sparc/regs/misc.hh"
#include "arch/sparc/remote_gdb.hh"
#include "base/loader/object_file.hh"
#include "cpu/thread_context.hh"
#include "sim/se_workload.hh"
#include "sim/syscall_abi.hh"

namespace gem5
{

namespace SparcISA
{

class SEWorkload : public gem5::SEWorkload
{
  public:
    using gem5::SEWorkload::SEWorkload;

    void
    setSystem(System *sys) override
    {
        gem5::SEWorkload::setSystem(sys);
        gdb = BaseRemoteGDB::build<RemoteGDB>(system);
    }

    virtual void handleTrap(ThreadContext *tc, int trapNum);
    virtual void flushWindows(ThreadContext *tc);

    bool is64(ThreadContext *tc);

    struct BaseSyscallABI
    {
        static const std::vector<int> ArgumentRegs;
    };

    struct SyscallABI32 : public GenericSyscallABI32,
                          public BaseSyscallABI
    {};

    struct SyscallABI64 : public GenericSyscallABI64,
                          public BaseSyscallABI
    {};
};

} // namespace SparcISA

GEM5_DEPRECATED_NAMESPACE(GuestABI, guest_abi);
namespace guest_abi
{

template <typename ABI>
struct Result<ABI, SyscallReturn,
    typename std::enable_if_t<std::is_base_of_v<
        SparcISA::SEWorkload::BaseSyscallABI, ABI>>>
{
    static void
    store(ThreadContext *tc, const SyscallReturn &ret)
    {
        if (ret.suppressed() || ret.needsRetry())
            return;

        // check for error condition.  SPARC syscall convention is to
        // indicate success/failure in reg the carry bit of the ccr
        // and put the return value itself in the standard return value reg.
        SparcISA::PSTATE pstate =
            tc->readMiscRegNoEffect(SparcISA::MISCREG_PSTATE);
        SparcISA::CCR ccr = tc->readIntReg(SparcISA::INTREG_CCR);
        RegVal val;
        if (ret.successful()) {
            ccr.xcc.c = ccr.icc.c = 0;
            val = ret.returnValue();
        } else {
            ccr.xcc.c = ccr.icc.c = 1;
            val = ret.errnoValue();
        }
        tc->setIntReg(SparcISA::INTREG_CCR, ccr);
        if (pstate.am)
            val = bits(val, 31, 0);
        tc->setIntReg(SparcISA::ReturnValueReg, val);
        if (ret.count() == 2)
            tc->setIntReg(SparcISA::SyscallPseudoReturnReg, ret.value2());
    }
};

template <typename Arg>
struct Argument<SparcISA::SEWorkload::SyscallABI32, Arg,
    typename std::enable_if_t<
        std::is_integral_v<Arg> &&
        SparcISA::SEWorkload::SyscallABI32::IsWideV<Arg>>>
{
    using ABI = SparcISA::SEWorkload::SyscallABI32;

    static Arg
    get(ThreadContext *tc, typename ABI::State &state)
    {
        panic_if(state + 1 >= ABI::ArgumentRegs.size(),
                "Ran out of syscall argument registers.");
        auto high = ABI::ArgumentRegs[state++];
        auto low = ABI::ArgumentRegs[state++];
        return (Arg)ABI::mergeRegs(tc, low, high);
    }
};

} // namespace guest_abi
} // namespace gem5

#endif // __ARCH_SPARC_SE_WORKLOAD_HH__
