/*
 * Copyright (c) 2014,2016-2018 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.
 *
 * Copyright (c) 2007-2008 The Florida State University
 * 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.
 */

#include "arch/arm/insts/pseudo.hh"

#include "cpu/exec_context.hh"

namespace gem5
{

using namespace ArmISA;

DecoderFaultInst::DecoderFaultInst(ExtMachInst _machInst)
    : ArmStaticInst("gem5decoderFault", _machInst, No_OpClass),
      faultId(static_cast<DecoderFault>(
                  static_cast<uint8_t>(_machInst.decoderFault)))
{
    // Don't call execute() if we're on a speculative path and the
    // fault is an internal panic fault.
    flags[IsNonSpeculative] = (faultId == DecoderFault::PANIC);
}

Fault
DecoderFaultInst::execute(ExecContext *xc, Trace::InstRecord *traceData) const
{
    const Addr pc = xc->pcState().instAddr();

    switch (faultId) {
      case DecoderFault::UNALIGNED:
        if (machInst.aarch64) {
            return std::make_shared<PCAlignmentFault>(pc);
        } else {
            // TODO: We should check if we the receiving end is in
            // aarch64 mode and raise a PCAlignment fault instead.
            return std::make_shared<PrefetchAbort>(
                pc, ArmFault::AlignmentFault);
        }

      case DecoderFault::PANIC:
        panic("Internal error in instruction decoder\n");

      case DecoderFault::OK:
        panic("Decoder fault instruction without decoder fault.\n");
    }

    panic("Unhandled fault type");
}

const char *
DecoderFaultInst::faultName() const
{
    switch (faultId) {
      case DecoderFault::OK:
        return "OK";

      case DecoderFault::UNALIGNED:
        return "UnalignedInstruction";

      case DecoderFault::PANIC:
        return "DecoderPanic";
    }

    panic("Unhandled fault type");
}

std::string
DecoderFaultInst::generateDisassembly(
        Addr pc, const loader::SymbolTable *symtab) const
{
    return csprintf("gem5fault %s", faultName());
}



FailUnimplemented::FailUnimplemented(const char *_mnemonic,
                                     ExtMachInst _machInst)
    : ArmStaticInst(_mnemonic, _machInst, No_OpClass)
{
    // don't call execute() (which panics) if we're on a
    // speculative path
    flags[IsNonSpeculative] = true;
}

FailUnimplemented::FailUnimplemented(const char *_mnemonic,
                                     ExtMachInst _machInst,
                                     const std::string& _fullMnemonic)
    : ArmStaticInst(_mnemonic, _machInst, No_OpClass),
      fullMnemonic(_fullMnemonic)
{
    // don't call execute() (which panics) if we're on a
    // speculative path
    flags[IsNonSpeculative] = true;
}

Fault
FailUnimplemented::execute(ExecContext *xc, Trace::InstRecord *traceData) const
{
    return std::make_shared<UndefinedInstruction>(machInst, false, mnemonic);
}

std::string
FailUnimplemented::generateDisassembly(
        Addr pc, const loader::SymbolTable *symtab) const
{
    return csprintf("%-10s (unimplemented)",
                    fullMnemonic.size() ? fullMnemonic.c_str() : mnemonic);
}



WarnUnimplemented::WarnUnimplemented(const char *_mnemonic,
                                     ExtMachInst _machInst)
    : ArmStaticInst(_mnemonic, _machInst, No_OpClass), warned(false)
{
    // don't call execute() (which panics) if we're on a
    // speculative path
    flags[IsNonSpeculative] = true;
}

WarnUnimplemented::WarnUnimplemented(const char *_mnemonic,
                                     ExtMachInst _machInst,
                                     const std::string& _fullMnemonic)
    : ArmStaticInst(_mnemonic, _machInst, No_OpClass), warned(false),
      fullMnemonic(_fullMnemonic)
{
    // don't call execute() (which panics) if we're on a
    // speculative path
    flags[IsNonSpeculative] = true;
}

Fault
WarnUnimplemented::execute(ExecContext *xc, Trace::InstRecord *traceData) const
{
    if (!warned) {
        warn("\tinstruction '%s' unimplemented\n",
             fullMnemonic.size() ? fullMnemonic.c_str() : mnemonic);
        warned = true;
    }

    return NoFault;
}

std::string
WarnUnimplemented::generateDisassembly(
        Addr pc, const loader::SymbolTable *symtab) const
{
    return csprintf("%-10s (unimplemented)",
                    fullMnemonic.size() ? fullMnemonic.c_str() : mnemonic);
}

IllegalExecInst::IllegalExecInst(ExtMachInst _machInst)
    : ArmStaticInst("Illegal Execution", _machInst, No_OpClass)
{}

Fault
IllegalExecInst::execute(ExecContext *xc, Trace::InstRecord *traceData) const
{
    return std::make_shared<IllegalInstSetStateFault>();
}

DebugStep::DebugStep(ExtMachInst _machInst)
    : ArmStaticInst("DebugStep", _machInst, No_OpClass)
{ }

Fault
DebugStep::execute(ExecContext *xc, Trace::InstRecord *traceData) const
{
    PCState pc_state = xc->pcState().as<PCState>();
    pc_state.debugStep(false);
    xc->pcState(pc_state);

    SelfDebug *sd = ArmISA::ISA::getSelfDebug(xc->tcBase());

    bool ldx = sd->getSstep()->getLdx();

    return std::make_shared<SoftwareStepFault>(machInst, ldx,
                                               pc_state.stepped());
}

} // namespace gem5
