/*
 * 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: Gabe Black
 *          Kevin Lim
 */

#include "arch/alpha/ev5.hh"
#include "arch/alpha/faults.hh"
#include "arch/alpha/tlb.hh"
#include "base/trace.hh"
#include "cpu/base.hh"
#include "cpu/thread_context.hh"
#include "mem/page_table.hh"
#include "sim/process.hh"
#include "sim/full_system.hh"

namespace AlphaISA {

FaultName MachineCheckFault::_name = "mchk";
FaultVect MachineCheckFault::_vect = 0x0401;
FaultStat MachineCheckFault::_count;

FaultName AlignmentFault::_name = "unalign";
FaultVect AlignmentFault::_vect = 0x0301;
FaultStat AlignmentFault::_count;

FaultName ResetFault::_name = "reset";
FaultVect ResetFault::_vect = 0x0001;
FaultStat ResetFault::_count;

FaultName ArithmeticFault::_name = "arith";
FaultVect ArithmeticFault::_vect = 0x0501;
FaultStat ArithmeticFault::_count;

FaultName InterruptFault::_name = "interrupt";
FaultVect InterruptFault::_vect = 0x0101;
FaultStat InterruptFault::_count;

FaultName NDtbMissFault::_name = "dtb_miss_single";
FaultVect NDtbMissFault::_vect = 0x0201;
FaultStat NDtbMissFault::_count;

FaultName PDtbMissFault::_name = "dtb_miss_double";
FaultVect PDtbMissFault::_vect = 0x0281;
FaultStat PDtbMissFault::_count;

FaultName DtbPageFault::_name = "dtb_page_fault";
FaultVect DtbPageFault::_vect = 0x0381;
FaultStat DtbPageFault::_count;

FaultName DtbAcvFault::_name = "dtb_acv_fault";
FaultVect DtbAcvFault::_vect = 0x0381;
FaultStat DtbAcvFault::_count;

FaultName DtbAlignmentFault::_name = "unalign";
FaultVect DtbAlignmentFault::_vect = 0x0301;
FaultStat DtbAlignmentFault::_count;

FaultName ItbPageFault::_name = "itbmiss";
FaultVect ItbPageFault::_vect = 0x0181;
FaultStat ItbPageFault::_count;

FaultName ItbAcvFault::_name = "iaccvio";
FaultVect ItbAcvFault::_vect = 0x0081;
FaultStat ItbAcvFault::_count;

FaultName UnimplementedOpcodeFault::_name = "opdec";
FaultVect UnimplementedOpcodeFault::_vect = 0x0481;
FaultStat UnimplementedOpcodeFault::_count;

FaultName FloatEnableFault::_name = "fen";
FaultVect FloatEnableFault::_vect = 0x0581;
FaultStat FloatEnableFault::_count;

FaultName PalFault::_name = "pal";
FaultVect PalFault::_vect = 0x2001;
FaultStat PalFault::_count;

FaultName IntegerOverflowFault::_name = "intover";
FaultVect IntegerOverflowFault::_vect = 0x0501;
FaultStat IntegerOverflowFault::_count;

void
AlphaFault::invoke(ThreadContext *tc, StaticInstPtr inst)
{
    FaultBase::invoke(tc);
    if (!FullSystem)
        return;
    countStat()++;

    PCState pc = tc->pcState();

    // exception restart address
    if (setRestartAddress() || !(pc.pc() & 0x3))
        tc->setMiscRegNoEffect(IPR_EXC_ADDR, pc.pc());

    if (skipFaultingInstruction()) {
        // traps...  skip faulting instruction.
        tc->setMiscRegNoEffect(IPR_EXC_ADDR,
                   tc->readMiscRegNoEffect(IPR_EXC_ADDR) + 4);
    }

    pc.set(tc->readMiscRegNoEffect(IPR_PAL_BASE) + vect());
    tc->pcState(pc);
}

void
ArithmeticFault::invoke(ThreadContext *tc, StaticInstPtr inst)
{
    FaultBase::invoke(tc);
    if (!FullSystem)
        return;
    panic("Arithmetic traps are unimplemented!");
}

void
DtbFault::invoke(ThreadContext *tc, StaticInstPtr inst)
{
    if (FullSystem) {
        // Set fault address and flags.  Even though we're modeling an
        // EV5, we use the EV6 technique of not latching fault registers
        // on VPTE loads (instead of locking the registers until IPR_VA is
        // read, like the EV5).  The EV6 approach is cleaner and seems to
        // work with EV5 PAL code, but not the other way around.
        if (!tc->misspeculating() &&
            reqFlags.noneSet(Request::VPTE | Request::PREFETCH)) {
            // set VA register with faulting address
            tc->setMiscRegNoEffect(IPR_VA, vaddr);

            // set MM_STAT register flags
            MachInst machInst = inst->machInst;
            tc->setMiscRegNoEffect(IPR_MM_STAT,
                (((Opcode(machInst) & 0x3f) << 11) |
                 ((Ra(machInst) & 0x1f) << 6) |
                 (flags & 0x3f)));

            // set VA_FORM register with faulting formatted address
            tc->setMiscRegNoEffect(IPR_VA_FORM,
                tc->readMiscRegNoEffect(IPR_MVPTBR) | (vaddr.vpn() << 3));
        }
    }

    AlphaFault::invoke(tc);
}

void
ItbFault::invoke(ThreadContext *tc, StaticInstPtr inst)
{
    if (FullSystem) {
        if (!tc->misspeculating()) {
            tc->setMiscRegNoEffect(IPR_ITB_TAG, pc);
            tc->setMiscRegNoEffect(IPR_IFAULT_VA_FORM,
                tc->readMiscRegNoEffect(IPR_IVPTBR) | (VAddr(pc).vpn() << 3));
        }
    }

    AlphaFault::invoke(tc);
}

void
ItbPageFault::invoke(ThreadContext *tc, StaticInstPtr inst)
{
    if (FullSystem) {
        ItbFault::invoke(tc);
        return;
    }

    Process *p = tc->getProcessPtr();
    TlbEntry entry;
    bool success = p->pTable->lookup(pc, entry);
    if (!success) {
        panic("Tried to execute unmapped address %#x.\n", pc);
    } else {
        VAddr vaddr(pc);
        tc->getITBPtr()->insert(vaddr.page(), entry);
    }
}

void
NDtbMissFault::invoke(ThreadContext *tc, StaticInstPtr inst)
{
    if (FullSystem) {
        DtbFault::invoke(tc, inst);
        return;
    }

    Process *p = tc->getProcessPtr();
    TlbEntry entry;
    bool success = p->pTable->lookup(vaddr, entry);
    if (!success) {
        if (p->fixupStackFault(vaddr))
            success = p->pTable->lookup(vaddr, entry);
    }
    if (!success) {
        panic("Tried to access unmapped address %#x.\n", (Addr)vaddr);
    } else {
        tc->getDTBPtr()->insert(vaddr.page(), entry);
    }
}

} // namespace AlphaISA

