<commit_before>/*
 * Copyright (c) 2002-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.
 */

#include "arch/alpha/tlb.hh"
#include "arch/alpha/isa_traits.hh"
#include "arch/alpha/osfpal.hh"
#include "base/kgdb.h"
#include "base/remote_gdb.hh"
#include "base/stats/events.hh"
#include "config/full_system.hh"
#include "cpu/base.hh"
#include "cpu/exec_context.hh"
#include "cpu/fast/cpu.hh"
#include "kern/kernel_stats.hh"
#include "sim/debug.hh"
#include "sim/sim_events.hh"

#if FULL_SYSTEM

using namespace EV5;

////////////////////////////////////////////////////////////////////////
//
//  Machine dependent functions
//
void
AlphaISA::initCPU(RegFile *regs, int cpuId)
{
    initIPRs(&regs->miscRegs, cpuId);

    regs->intRegFile[16] = cpuId;
    regs->intRegFile[0] = cpuId;

    regs->pc = regs->miscRegs.readReg(IPR_PAL_BASE) + (new ResetFault)->vect();
    regs->npc = regs->pc + sizeof(MachInst);
}

////////////////////////////////////////////////////////////////////////
//
//
//
void
AlphaISA::initIPRs(MiscRegFile *miscRegs, int cpuId)
{
    miscRegs->clearIprs();

    miscRegs->setReg(IPR_PAL_BASE, PalBase);
    miscRegs->setReg(IPR_MCSR, 0x6);
    miscRegs->setReg(IPR_PALtemp16, cpuId);
}


template <class CPU>
void
AlphaISA::processInterrupts(CPU *cpu)
{
    //Check if there are any outstanding interrupts
    //Handle the interrupts
    int ipl = 0;
    int summary = 0;

    cpu->checkInterrupts = false;

    if (cpu->readMiscReg(IPR_ASTRR))
        panic("asynchronous traps not implemented\n");

    if (cpu->readMiscReg(IPR_SIRR)) {
        for (int i = INTLEVEL_SOFTWARE_MIN;
             i < INTLEVEL_SOFTWARE_MAX; i++) {
            if (cpu->readMiscReg(IPR_SIRR) & (ULL(1) << i)) {
                // See table 4-19 of the 21164 hardware reference
                ipl = (i - INTLEVEL_SOFTWARE_MIN) + 1;
                summary |= (ULL(1) << i);
            }
        }
    }

    uint64_t interrupts = cpu->intr_status();

    if (interrupts) {
        for (int i = INTLEVEL_EXTERNAL_MIN;
             i < INTLEVEL_EXTERNAL_MAX; i++) {
            if (interrupts & (ULL(1) << i)) {
                // See table 4-19 of the 21164 hardware reference
                ipl = i;
                summary |= (ULL(1) << i);
            }
        }
    }

    if (ipl && ipl > cpu->readMiscReg(IPR_IPLR)) {
        cpu->setMiscReg(IPR_ISR, summary);
        cpu->setMiscReg(IPR_INTID, ipl);
        cpu->trap(new InterruptFault);
        DPRINTF(Flow, "Interrupt! IPLR=%d ipl=%d summary=%x\n",
                cpu->readMiscReg(IPR_IPLR), ipl, summary);
    }

}

template <class CPU>
void
AlphaISA::zeroRegisters(CPU *cpu)
{
    // Insure ISA semantics
    // (no longer very clean due to the change in setIntReg() in the
    // cpu model.  Consider changing later.)
    cpu->xc->setIntReg(ZeroReg, 0);
    cpu->xc->setFloatRegDouble(ZeroReg, 0.0);
}

void
ExecContext::ev5_temp_trap(Fault fault)
{
    DPRINTF(Fault, "Fault %s at PC: %#x\n", fault->name(), regs.pc);
    cpu->recordEvent(csprintf("Fault %s", fault->name()));

    assert(!misspeculating());
    kernelStats->fault(fault);

    if (fault->isA<ArithmeticFault>())
        panic("Arithmetic traps are unimplemented!");

    // exception restart address
    if (!fault->isA<InterruptFault>() || !inPalMode())
        setMiscReg(AlphaISA::IPR_EXC_ADDR, regs.pc);

    if (fault->isA<PalFault>() || fault->isA<ArithmeticFault>() /* ||
        fault == InterruptFault && !inPalMode() */) {
        // traps...  skip faulting instruction.
        setMiscReg(AlphaISA::IPR_EXC_ADDR,
                   readMiscReg(AlphaISA::IPR_EXC_ADDR) + 4);
    }

    regs.pc = readMiscReg(AlphaISA::IPR_PAL_BASE) +
        (dynamic_cast<AlphaFault *>(fault.get()))->vect();
    regs.npc = regs.pc + sizeof(MachInst);
}


void
AlphaISA::intr_post(RegFile *regs, Fault fault, Addr pc)
{
    bool use_pc = (fault == NoFault);

    if (fault->isA<ArithmeticFault>())
        panic("arithmetic faults NYI...");

    // compute exception restart address
    if (use_pc || fault->isA<PalFault>() || fault->isA<ArithmeticFault>()) {
        // traps...  skip faulting instruction
        regs->miscRegs.setReg(IPR_EXC_ADDR, regs->pc + 4);
    } else {
        // fault, post fault at excepting instruction
        regs->miscRegs.setReg(IPR_EXC_ADDR, regs->pc);
    }

    // jump to expection address (PAL PC bit set here as well...)
    if (!use_pc)
        regs->npc = regs->miscRegs.readReg(IPR_PAL_BASE) +
            (dynamic_cast<AlphaFault *>(fault.get()))->vect();
    else
        regs->npc = regs->miscRegs.readReg(IPR_PAL_BASE) + pc;

    // that's it! (orders of magnitude less painful than x86)
}

Fault
ExecContext::hwrei()
{
    if (!inPalMode())
        return new UnimplementedOpcodeFault;

    setNextPC(readMiscReg(AlphaISA::IPR_EXC_ADDR));

    if (!misspeculating()) {
        kernelStats->hwrei();

        cpu->checkInterrupts = true;
    }

    // FIXME: XXX check for interrupts? XXX
    return NoFault;
}

void
AlphaISA::MiscRegFile::clearIprs()
{
    bzero((char *)ipr, NumInternalProcRegs * sizeof(InternalProcReg));
}<commit_msg>Remove intr_post function.  No longer being used.<commit_after>/*
 * Copyright (c) 2002-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.
 */

#include "arch/alpha/tlb.hh"
#include "arch/alpha/isa_traits.hh"
#include "arch/alpha/osfpal.hh"
#include "base/kgdb.h"
#include "base/remote_gdb.hh"
#include "base/stats/events.hh"
#include "config/full_system.hh"
#include "cpu/base.hh"
#include "cpu/exec_context.hh"
#include "cpu/fast/cpu.hh"
#include "kern/kernel_stats.hh"
#include "sim/debug.hh"
#include "sim/sim_events.hh"

#if FULL_SYSTEM

using namespace EV5;

////////////////////////////////////////////////////////////////////////
//
//  Machine dependent functions
//
void
AlphaISA::initCPU(RegFile *regs, int cpuId)
{
    initIPRs(&regs->miscRegs, cpuId);

    regs->intRegFile[16] = cpuId;
    regs->intRegFile[0] = cpuId;

    regs->pc = regs->miscRegs.readReg(IPR_PAL_BASE) + (new ResetFault)->vect();
    regs->npc = regs->pc + sizeof(MachInst);
}

////////////////////////////////////////////////////////////////////////
//
//
//
void
AlphaISA::initIPRs(MiscRegFile *miscRegs, int cpuId)
{
    miscRegs->clearIprs();

    miscRegs->setReg(IPR_PAL_BASE, PalBase);
    miscRegs->setReg(IPR_MCSR, 0x6);
    miscRegs->setReg(IPR_PALtemp16, cpuId);
}


template <class CPU>
void
AlphaISA::processInterrupts(CPU *cpu)
{
    //Check if there are any outstanding interrupts
    //Handle the interrupts
    int ipl = 0;
    int summary = 0;

    cpu->checkInterrupts = false;

    if (cpu->readMiscReg(IPR_ASTRR))
        panic("asynchronous traps not implemented\n");

    if (cpu->readMiscReg(IPR_SIRR)) {
        for (int i = INTLEVEL_SOFTWARE_MIN;
             i < INTLEVEL_SOFTWARE_MAX; i++) {
            if (cpu->readMiscReg(IPR_SIRR) & (ULL(1) << i)) {
                // See table 4-19 of the 21164 hardware reference
                ipl = (i - INTLEVEL_SOFTWARE_MIN) + 1;
                summary |= (ULL(1) << i);
            }
        }
    }

    uint64_t interrupts = cpu->intr_status();

    if (interrupts) {
        for (int i = INTLEVEL_EXTERNAL_MIN;
             i < INTLEVEL_EXTERNAL_MAX; i++) {
            if (interrupts & (ULL(1) << i)) {
                // See table 4-19 of the 21164 hardware reference
                ipl = i;
                summary |= (ULL(1) << i);
            }
        }
    }

    if (ipl && ipl > cpu->readMiscReg(IPR_IPLR)) {
        cpu->setMiscReg(IPR_ISR, summary);
        cpu->setMiscReg(IPR_INTID, ipl);
        cpu->trap(new InterruptFault);
        DPRINTF(Flow, "Interrupt! IPLR=%d ipl=%d summary=%x\n",
                cpu->readMiscReg(IPR_IPLR), ipl, summary);
    }

}

template <class CPU>
void
AlphaISA::zeroRegisters(CPU *cpu)
{
    // Insure ISA semantics
    // (no longer very clean due to the change in setIntReg() in the
    // cpu model.  Consider changing later.)
    cpu->xc->setIntReg(ZeroReg, 0);
    cpu->xc->setFloatRegDouble(ZeroReg, 0.0);
}

void
ExecContext::ev5_temp_trap(Fault fault)
{
    DPRINTF(Fault, "Fault %s at PC: %#x\n", fault->name(), regs.pc);
    cpu->recordEvent(csprintf("Fault %s", fault->name()));

    assert(!misspeculating());
    kernelStats->fault(fault);

    if (fault->isA<ArithmeticFault>())
        panic("Arithmetic traps are unimplemented!");

    // exception restart address
    if (!fault->isA<InterruptFault>() || !inPalMode())
        setMiscReg(AlphaISA::IPR_EXC_ADDR, regs.pc);

    if (fault->isA<PalFault>() || fault->isA<ArithmeticFault>() /* ||
        fault == InterruptFault && !inPalMode() */) {
        // traps...  skip faulting instruction.
        setMiscReg(AlphaISA::IPR_EXC_ADDR,
                   readMiscReg(AlphaISA::IPR_EXC_ADDR) + 4);
    }

    regs.pc = readMiscReg(AlphaISA::IPR_PAL_BASE) +
        (dynamic_cast<AlphaFault *>(fault.get()))->vect();
    regs.npc = regs.pc + sizeof(MachInst);
}


Fault
ExecContext::hwrei()
{
    if (!inPalMode())
        return new UnimplementedOpcodeFault;

    setNextPC(readMiscReg(AlphaISA::IPR_EXC_ADDR));

    if (!misspeculating()) {
        kernelStats->hwrei();

        cpu->checkInterrupts = true;
    }

    // FIXME: XXX check for interrupts? XXX
    return NoFault;
}

void
AlphaISA::MiscRegFile::clearIprs()
{
    bzero((char *)ipr, NumInternalProcRegs * sizeof(InternalProcReg));
}
{'fraction_non_alphanumeric': 0.14297227595099934, 'fraction_numerical': 0.007656350741457124, 'mean_word_length': 2.8633250311332503, 'pattern_counts': {'":': 0, '<': 41, '<?xml version=': 0, '>': 109, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1728681', 'n_tokens_mistral': 4208, 'n_tokens_neox': 3891, 'n_words': 1082}