/*
 * Copyright (c) 2010, 2012-2021 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) 2009 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.
 */

#ifndef __ARCH_ARM_ISA_HH__
#define __ARCH_ARM_ISA_HH__

#include "arch/arm/isa_device.hh"
#include "arch/arm/mmu.hh"
#include "arch/arm/pcstate.hh"
#include "arch/arm/regs/int.hh"
#include "arch/arm/regs/misc.hh"
#include "arch/arm/regs/vec.hh"
#include "arch/arm/self_debug.hh"
#include "arch/arm/system.hh"
#include "arch/arm/types.hh"
#include "arch/arm/utility.hh"
#include "arch/generic/isa.hh"
#include "debug/Checkpoint.hh"
#include "enums/DecoderFlavor.hh"
#include "sim/sim_object.hh"

namespace gem5
{

struct ArmISAParams;
struct DummyArmISADeviceParams;
class Checkpoint;
class EventManager;

namespace ArmISA
{
    class ISA : public BaseISA
    {
      protected:
        // Parent system
        ArmSystem *system;

        // Micro Architecture
        const enums::DecoderFlavor _decoderFlavor;

        /** Dummy device for to handle non-existing ISA devices */
        DummyISADevice dummyDevice;

        // PMU belonging to this ISA
        BaseISADevice *pmu;

        // Generic timer interface belonging to this ISA
        std::unique_ptr<BaseISADevice> timer;

        // GICv3 CPU interface belonging to this ISA
        std::unique_ptr<BaseISADevice> gicv3CpuInterface;

        // Cached copies of system-level properties
        bool highestELIs64;
        bool haveLargeAsid64;
        uint8_t physAddrRange;

        /** SVE vector length in quadwords */
        unsigned sveVL;

        /** This could be either a FS or a SE release */
        const ArmRelease *release;

        /**
         * If true, accesses to IMPLEMENTATION DEFINED registers are treated
         * as NOP hence not causing UNDEFINED INSTRUCTION.
         */
        bool impdefAsNop;

        SelfDebug * selfDebug;

        const MiscRegLUTEntryInitializer
        InitReg(uint32_t reg)
        {
            return MiscRegLUTEntryInitializer(lookUpMiscReg[reg]);
        }

        void initializeMiscRegMetadata();

        BaseISADevice &getGenericTimer();
        BaseISADevice &getGICv3CPUInterface();
        BaseISADevice *getGICv3CPUInterface(ThreadContext *tc);

        RegVal miscRegs[NUM_MISCREGS];
        const RegId *intRegMap;

        void
        updateRegMap(CPSR cpsr)
        {
            if (cpsr.width == 0) {
                intRegMap = int_reg::Reg64Map;
            } else {
                switch (cpsr.mode) {
                  case MODE_USER:
                  case MODE_SYSTEM:
                    intRegMap = int_reg::RegUsrMap;
                    break;
                  case MODE_FIQ:
                    intRegMap = int_reg::RegFiqMap;
                    break;
                  case MODE_IRQ:
                    intRegMap = int_reg::RegIrqMap;
                    break;
                  case MODE_SVC:
                    intRegMap = int_reg::RegSvcMap;
                    break;
                  case MODE_MON:
                    intRegMap = int_reg::RegMonMap;
                    break;
                  case MODE_ABORT:
                    intRegMap = int_reg::RegAbtMap;
                    break;
                  case MODE_HYP:
                    intRegMap = int_reg::RegHypMap;
                    break;
                  case MODE_UNDEFINED:
                    intRegMap = int_reg::RegUndMap;
                    break;
                  default:
                    panic("Unrecognized mode setting in CPSR.\n");
                }
            }
        }

      public:
        const RegId &mapIntRegId(RegIndex idx) const { return intRegMap[idx]; }

      public:
        void clear() override;

      protected:
        void clear32(const ArmISAParams &p, const SCTLR &sctlr_rst);
        void clear64(const ArmISAParams &p);
        void initID32(const ArmISAParams &p);
        void initID64(const ArmISAParams &p);

        void addressTranslation(MMU::ArmTranslationType tran_type,
            BaseMMU::Mode mode, Request::Flags flags, RegVal val);
        void addressTranslation64(MMU::ArmTranslationType tran_type,
            BaseMMU::Mode mode, Request::Flags flags, RegVal val);

      public:
        SelfDebug*
        getSelfDebug() const
        {
            return selfDebug;
        }

        static SelfDebug*
        getSelfDebug(ThreadContext *tc)
        {
            auto *arm_isa = static_cast<ArmISA::ISA *>(tc->getIsaPtr());
            return arm_isa->getSelfDebug();
        }

        const ArmRelease* getRelease() const { return release; }

        RegVal readMiscRegNoEffect(RegIndex idx) const override;
        RegVal readMiscReg(RegIndex idx) override;
        void setMiscRegNoEffect(RegIndex idx, RegVal val) override;
        void setMiscReg(RegIndex, RegVal val) override;

        int
        flattenMiscIndex(int reg) const
        {
            assert(reg >= 0);
            int flat_idx = reg;

            if (reg == MISCREG_SPSR) {
                CPSR cpsr = miscRegs[MISCREG_CPSR];
                switch (cpsr.mode) {
                  case MODE_EL0T:
                    warn("User mode does not have SPSR\n");
                    flat_idx = MISCREG_SPSR;
                    break;
                  case MODE_EL1T:
                  case MODE_EL1H:
                    flat_idx = MISCREG_SPSR_EL1;
                    break;
                  case MODE_EL2T:
                  case MODE_EL2H:
                    flat_idx = MISCREG_SPSR_EL2;
                    break;
                  case MODE_EL3T:
                  case MODE_EL3H:
                    flat_idx = MISCREG_SPSR_EL3;
                    break;
                  case MODE_USER:
                    warn("User mode does not have SPSR\n");
                    flat_idx = MISCREG_SPSR;
                    break;
                  case MODE_FIQ:
                    flat_idx = MISCREG_SPSR_FIQ;
                    break;
                  case MODE_IRQ:
                    flat_idx = MISCREG_SPSR_IRQ;
                    break;
                  case MODE_SVC:
                    flat_idx = MISCREG_SPSR_SVC;
                    break;
                  case MODE_MON:
                    flat_idx = MISCREG_SPSR_MON;
                    break;
                  case MODE_ABORT:
                    flat_idx = MISCREG_SPSR_ABT;
                    break;
                  case MODE_HYP:
                    flat_idx = MISCREG_SPSR_HYP;
                    break;
                  case MODE_UNDEFINED:
                    flat_idx = MISCREG_SPSR_UND;
                    break;
                  default:
                    warn("Trying to access SPSR in an invalid mode: %d\n",
                         cpsr.mode);
                    flat_idx = MISCREG_SPSR;
                    break;
                }
            } else if (lookUpMiscReg[reg].info[MISCREG_MUTEX]) {
                // Mutually exclusive CP15 register
                switch (reg) {
                  case MISCREG_PRRR_MAIR0:
                  case MISCREG_PRRR_MAIR0_NS:
                  case MISCREG_PRRR_MAIR0_S:
                    {
                        TTBCR ttbcr = readMiscRegNoEffect(MISCREG_TTBCR);
                        // If the muxed reg has been flattened, work out the
                        // offset and apply it to the unmuxed reg
                        int idxOffset = reg - MISCREG_PRRR_MAIR0;
                        if (ttbcr.eae)
                            flat_idx = flattenMiscIndex(MISCREG_MAIR0 +
                                                        idxOffset);
                        else
                            flat_idx = flattenMiscIndex(MISCREG_PRRR +
                                                        idxOffset);
                    }
                    break;
                  case MISCREG_NMRR_MAIR1:
                  case MISCREG_NMRR_MAIR1_NS:
                  case MISCREG_NMRR_MAIR1_S:
                    {
                        TTBCR ttbcr = readMiscRegNoEffect(MISCREG_TTBCR);
                        // If the muxed reg has been flattened, work out the
                        // offset and apply it to the unmuxed reg
                        int idxOffset = reg - MISCREG_NMRR_MAIR1;
                        if (ttbcr.eae)
                            flat_idx = flattenMiscIndex(MISCREG_MAIR1 +
                                                        idxOffset);
                        else
                            flat_idx = flattenMiscIndex(MISCREG_NMRR +
                                                        idxOffset);
                    }
                    break;
                  case MISCREG_PMXEVTYPER_PMCCFILTR:
                    {
                        PMSELR pmselr = miscRegs[MISCREG_PMSELR];
                        if (pmselr.sel == 31)
                            flat_idx = flattenMiscIndex(MISCREG_PMCCFILTR);
                        else
                            flat_idx = flattenMiscIndex(MISCREG_PMXEVTYPER);
                    }
                    break;
                  default:
                    panic("Unrecognized misc. register.\n");
                    break;
                }
            } else {
                if (lookUpMiscReg[reg].info[MISCREG_BANKED]) {
                    bool secure_reg = !highestELIs64 && inSecureState();
                    flat_idx += secure_reg ? 2 : 1;
                } else {
                    flat_idx = snsBankedIndex64((MiscRegIndex)reg,
                        !inSecureState());
                }
            }
            return flat_idx;
        }

        /**
         * Returns the enconcing equivalent when VHE is implemented and
         * HCR_EL2.E2H is enabled and executing at EL2
         */
        int redirectRegVHE(int misc_reg);

        int
        snsBankedIndex64(MiscRegIndex reg, bool ns) const
        {
            int reg_as_int = static_cast<int>(reg);
            if (lookUpMiscReg[reg].info[MISCREG_BANKED64]) {
                reg_as_int += (release->has(ArmExtension::SECURITY) && !ns) ?
                    2 : 1;
            }
            return reg_as_int;
        }

        std::pair<int,int>
        getMiscIndices(int misc_reg) const
        {
            // Note: indexes of AArch64 registers are left unchanged
            int flat_idx = flattenMiscIndex(misc_reg);

            if (lookUpMiscReg[flat_idx].lower == 0) {
                return std::make_pair(flat_idx, 0);
            }

            // do additional S/NS flattenings if mapped to NS while in S
            bool S = !highestELIs64 && inSecureState();

            int lower = lookUpMiscReg[flat_idx].lower;
            int upper = lookUpMiscReg[flat_idx].upper;
            // upper == 0, which is CPSR, is not MISCREG_BANKED_CHILD (no-op)
            lower += S && lookUpMiscReg[lower].info[MISCREG_BANKED_CHILD];
            upper += S && lookUpMiscReg[upper].info[MISCREG_BANKED_CHILD];
            return std::make_pair(lower, upper);
        }

        /** Return true if the PE is in Secure state */
        bool inSecureState() const;

        /**
         * Returns the current Exception Level (EL) of the ISA object
         */
        ExceptionLevel currEL() const;

        unsigned getCurSveVecLenInBits() const;

        unsigned getCurSveVecLenInBitsAtReset() const { return sveVL * 128; }

        template <typename Elem>
        static void
        zeroSveVecRegUpperPart(Elem *v, unsigned eCount)
        {
            static_assert(sizeof(Elem) <= sizeof(uint64_t),
                    "Elem type is too large.");
            eCount *= (sizeof(uint64_t) / sizeof(Elem));
            for (int i = 16 / sizeof(Elem); i < eCount; ++i) {
                v[i] = 0;
            }
        }

        void serialize(CheckpointOut &cp) const override;
        void unserialize(CheckpointIn &cp) override;

        void startup() override;

        void setupThreadContext();

        PCStateBase *
        newPCState(Addr new_inst_addr=0) const override
        {
            return new PCState(new_inst_addr);
        }

        void takeOverFrom(ThreadContext *new_tc,
                          ThreadContext *old_tc) override;

        enums::DecoderFlavor decoderFlavor() const { return _decoderFlavor; }

        PARAMS(ArmISA);

        ISA(const Params &p);

        uint64_t
        getExecutingAsid() const override
        {
            return readMiscRegNoEffect(MISCREG_CONTEXTIDR);
        }

        bool
        inUserMode() const override
        {
            CPSR cpsr = miscRegs[MISCREG_CPSR];
            return ArmISA::inUserMode(cpsr);
        }

        void copyRegsFrom(ThreadContext *src) override;

        void handleLockedRead(const RequestPtr &req) override;
        void handleLockedRead(ExecContext *xc, const RequestPtr &req) override;

        bool handleLockedWrite(const RequestPtr &req,
                Addr cacheBlockMask) override;
        bool handleLockedWrite(ExecContext *xc, const RequestPtr &req,
                Addr cacheBlockMask) override;

        void handleLockedSnoop(PacketPtr pkt, Addr cacheBlockMask) override;
        void handleLockedSnoop(ExecContext *xc, PacketPtr pkt,
                Addr cacheBlockMask) override;
        void handleLockedSnoopHit() override;
        void handleLockedSnoopHit(ExecContext *xc) override;

        void globalClearExclusive() override;
        void globalClearExclusive(ExecContext *xc) override;
    };

} // namespace ArmISA
} // namespace gem5

#endif
