/*
 * Copyright (c) 2003-2006, 2008 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
 */

/*
 * Copyright (c) 2007-2008 The Hewlett-Packard Development Company
 * All rights reserved.
 *
 * Redistribution and use of this software in source and binary forms,
 * with or without modification, are permitted provided that the
 * following conditions are met:
 *
 * The software must be used only for Non-Commercial Use which means any
 * use which is NOT directed to receiving any direct monetary
 * compensation for, or commercial advantage from such use.  Illustrative
 * examples of non-commercial use are academic research, personal study,
 * teaching, education and corporate research & development.
 * Illustrative examples of commercial use are distributing products for
 * commercial advantage and providing services using the software for
 * commercial advantage.
 *
 * If you wish to use this software or functionality therein that may be
 * covered by patents for commercial use, please contact:
 *     Director of Intellectual Property Licensing
 *     Office of Strategy and Technology
 *     Hewlett-Packard Company
 *     1501 Page Mill Road
 *     Palo Alto, California  94304
 *
 * 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 HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.  No right of
 * sublicense is granted herewith.  Derivatives of the software and
 * output created using the software may be prepared, but only for
 * Non-Commercial Uses.  Derivatives of the software may be shared with
 * others provided: (i) the others agree to abide by the list of
 * conditions herein which includes the Non-Commercial Use restrictions;
 * and (ii) such Derivatives of the software include the above copyright
 * notice to acknowledge the contribution from this software where
 * applicable, this list of conditions and the disclaimer below.
 *
 * 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
 */

#include "arch/x86/miscregfile.hh"
#include "arch/x86/tlb.hh"
#include "cpu/thread_context.hh"
#include "sim/serialize.hh"

using namespace X86ISA;
using namespace std;

class Checkpoint;

//These functions map register indices to names
string X86ISA::getMiscRegName(RegIndex index)
{
    panic("No misc registers in x86 yet!\n");
}

void MiscRegFile::clear()
{
    // Blank everything. 0 might not be an appropriate value for some things.
    memset(regVal, 0, NumMiscRegs * sizeof(MiscReg));
}

MiscReg MiscRegFile::readRegNoEffect(int miscReg)
{
    // Make sure we're not dealing with an illegal control register.
    // Instructions should filter out these indexes, and nothing else should
    // attempt to read them directly.
    assert( miscReg != MISCREG_CR1 &&
            !(miscReg > MISCREG_CR4 &&
              miscReg < MISCREG_CR8) &&
            !(miscReg > MISCREG_CR8 &&
              miscReg <= MISCREG_CR15));

    return regVal[miscReg];
}

MiscReg MiscRegFile::readReg(int miscReg, ThreadContext * tc)
{
    if (miscReg >= MISCREG_APIC_START && miscReg <= MISCREG_APIC_END) {
        if (miscReg >= MISCREG_APIC_IN_SERVICE(0) &&
                miscReg <= MISCREG_APIC_IN_SERVICE(15)) {
            panic("Local APIC In-Service registers are unimplemented.\n");
        }
        if (miscReg >= MISCREG_APIC_TRIGGER_MODE(0) &&
                miscReg <= MISCREG_APIC_TRIGGER_MODE(15)) {
            panic("Local APIC Trigger Mode registers are unimplemented.\n");
        }
        if (miscReg >= MISCREG_APIC_INTERRUPT_REQUEST(0) &&
                miscReg <= MISCREG_APIC_INTERRUPT_REQUEST(15)) {
            panic("Local APIC Interrupt Request registers "
                    "are unimplemented.\n");
        }
        switch (miscReg) {
          case MISCREG_APIC_TASK_PRIORITY:
            panic("Local APIC Task Priority register unimplemented.\n");
            break;
          case MISCREG_APIC_ARBITRATION_PRIORITY:
            panic("Local APIC Arbitration Priority register unimplemented.\n");
            break;
          case MISCREG_APIC_PROCESSOR_PRIORITY:
            panic("Local APIC Processor Priority register unimplemented.\n");
            break;
          case MISCREG_APIC_EOI:
            panic("Local APIC EOI register unimplemented.\n");
            break;
          case MISCREG_APIC_LOGICAL_DESTINATION:
            panic("Local APIC Logical Destination register unimplemented.\n");
            break;
          case MISCREG_APIC_DESTINATION_FORMAT:
            panic("Local APIC Destination Format register unimplemented.\n");
            break;
          case MISCREG_APIC_ERROR_STATUS:
            regVal[MISCREG_APIC_INTERNAL_STATE] &= ~ULL(0x1);
            break;
          case MISCREG_APIC_INTERRUPT_COMMAND_LOW:
            panic("Local APIC Interrupt Command low"
                    " register unimplemented.\n");
            break;
          case MISCREG_APIC_INTERRUPT_COMMAND_HIGH:
            panic("Local APIC Interrupt Command high"
                    " register unimplemented.\n");
            break;
          case MISCREG_APIC_INITIAL_COUNT:
            panic("Local APIC Initial Count register unimplemented.\n");
            break;
          case MISCREG_APIC_CURRENT_COUNT:
            panic("Local APIC Current Count register unimplemented.\n");
            break;
          case MISCREG_APIC_DIVIDE_COUNT:
            panic("Local APIC Divide Count register unimplemented.\n");
            break;
        }
    }
    return readRegNoEffect(miscReg);
}

void MiscRegFile::setRegNoEffect(int miscReg, const MiscReg &val)
{
    // Make sure we're not dealing with an illegal control register.
    // Instructions should filter out these indexes, and nothing else should
    // attempt to write to them directly.
    assert( miscReg != MISCREG_CR1 &&
            !(miscReg > MISCREG_CR4 &&
              miscReg < MISCREG_CR8) &&
            !(miscReg > MISCREG_CR8 &&
              miscReg <= MISCREG_CR15));
    regVal[miscReg] = val;
}

void MiscRegFile::setReg(int miscReg,
        const MiscReg &val, ThreadContext * tc)
{
    MiscReg newVal = val;
    if (miscReg >= MISCREG_APIC_START && miscReg <= MISCREG_APIC_END) {
        if (miscReg >= MISCREG_APIC_IN_SERVICE(0) &&
                miscReg <= MISCREG_APIC_IN_SERVICE(15)) {
            panic("Local APIC In-Service registers are unimplemented.\n");
        }
        if (miscReg >= MISCREG_APIC_TRIGGER_MODE(0) &&
                miscReg <= MISCREG_APIC_TRIGGER_MODE(15)) {
            panic("Local APIC Trigger Mode registers are unimplemented.\n");
        }
        if (miscReg >= MISCREG_APIC_INTERRUPT_REQUEST(0) &&
                miscReg <= MISCREG_APIC_INTERRUPT_REQUEST(15)) {
            panic("Local APIC Interrupt Request registers "
                    "are unimplemented.\n");
        }
        switch (miscReg) {
          case MISCREG_APIC_ID:
            panic("Local APIC ID register unimplemented.\n");
            break;
          case MISCREG_APIC_VERSION:
            panic("Local APIC Version register is read only.\n");
            break;
          case MISCREG_APIC_TASK_PRIORITY:
            panic("Local APIC Task Priority register unimplemented.\n");
            break;
          case MISCREG_APIC_ARBITRATION_PRIORITY:
            panic("Local APIC Arbitration Priority register unimplemented.\n");
            break;
          case MISCREG_APIC_PROCESSOR_PRIORITY:
            panic("Local APIC Processor Priority register unimplemented.\n");
            break;
          case MISCREG_APIC_EOI:
            panic("Local APIC EOI register unimplemented.\n");
            break;
          case MISCREG_APIC_LOGICAL_DESTINATION:
            panic("Local APIC Logical Destination register unimplemented.\n");
            break;
          case MISCREG_APIC_DESTINATION_FORMAT:
            panic("Local APIC Destination Format register unimplemented.\n");
            break;
          case MISCREG_APIC_SPURIOUS_INTERRUPT_VECTOR:
            regVal[MISCREG_APIC_INTERNAL_STATE] &= ~ULL(1 << 1);
            regVal[MISCREG_APIC_INTERNAL_STATE] |= val & (1 << 8);
            if (val & (1 << 9))
                warn("Focus processor checking not implemented.\n");
            break;
          case MISCREG_APIC_ERROR_STATUS:
            {
                if (regVal[MISCREG_APIC_INTERNAL_STATE] & 0x1) {
                    regVal[MISCREG_APIC_INTERNAL_STATE] &= ~ULL(0x1);
                    newVal = 0;
                } else {
                    regVal[MISCREG_APIC_INTERNAL_STATE] |= ULL(0x1);
                    return;
                }

            }
            break;
          case MISCREG_APIC_INTERRUPT_COMMAND_LOW:
            panic("Local APIC Interrupt Command low"
                    " register unimplemented.\n");
            break;
          case MISCREG_APIC_INTERRUPT_COMMAND_HIGH:
            panic("Local APIC Interrupt Command high"
                    " register unimplemented.\n");
            break;
          case MISCREG_APIC_LVT_TIMER:
          case MISCREG_APIC_LVT_THERMAL_SENSOR:
          case MISCREG_APIC_LVT_PERFORMANCE_MONITORING_COUNTERS:
          case MISCREG_APIC_LVT_LINT0:
          case MISCREG_APIC_LVT_LINT1:
          case MISCREG_APIC_LVT_ERROR:
            {
                uint64_t readOnlyMask = (1 << 12) | (1 << 14);
                newVal = (val & ~readOnlyMask) |
                         (regVal[miscReg] & readOnlyMask);
            }
            break;
          case MISCREG_APIC_INITIAL_COUNT:
            panic("Local APIC Initial Count register unimplemented.\n");
            break;
          case MISCREG_APIC_CURRENT_COUNT:
            panic("Local APIC Current Count register unimplemented.\n");
            break;
          case MISCREG_APIC_DIVIDE_COUNT:
            panic("Local APIC Divide Count register unimplemented.\n");
            break;
        }
        setRegNoEffect(miscReg, newVal);
        return;
    }
    switch(miscReg)
    {
      case MISCREG_CR0:
        {
            CR0 toggled = regVal[miscReg] ^ val;
            CR0 newCR0 = val;
            Efer efer = regVal[MISCREG_EFER];
            if (toggled.pg && efer.lme) {
                if (newCR0.pg) {
                    //Turning on long mode
                    efer.lma = 1;
                    regVal[MISCREG_EFER] = efer;
                } else {
                    //Turning off long mode
                    efer.lma = 0;
                    regVal[MISCREG_EFER] = efer;
                }
            }
            if (toggled.pg) {
                tc->getITBPtr()->invalidateAll();
                tc->getDTBPtr()->invalidateAll();
            }
            //This must always be 1.
            newCR0.et = 1;
            newVal = newCR0;
        }
        break;
      case MISCREG_CR2:
        break;
      case MISCREG_CR3:
        tc->getITBPtr()->invalidateNonGlobal();
        tc->getDTBPtr()->invalidateNonGlobal();
        break;
      case MISCREG_CR4:
        {
            CR4 toggled = regVal[miscReg] ^ val;
            if (toggled.pae || toggled.pse || toggled.pge) {
                tc->getITBPtr()->invalidateAll();
                tc->getDTBPtr()->invalidateAll();
            }
        }
        break;
      case MISCREG_CR8:
        break;
      case MISCREG_CS_ATTR:
        {
            SegAttr toggled = regVal[miscReg] ^ val;
            SegAttr newCSAttr = val;
            if (toggled.longMode) {
                SegAttr newCSAttr = val;
                if (newCSAttr.longMode) {
                    regVal[MISCREG_ES_EFF_BASE] = 0;
                    regVal[MISCREG_CS_EFF_BASE] = 0;
                    regVal[MISCREG_SS_EFF_BASE] = 0;
                    regVal[MISCREG_DS_EFF_BASE] = 0;
                } else {
                    regVal[MISCREG_ES_EFF_BASE] = regVal[MISCREG_ES_BASE];
                    regVal[MISCREG_CS_EFF_BASE] = regVal[MISCREG_CS_BASE];
                    regVal[MISCREG_SS_EFF_BASE] = regVal[MISCREG_SS_BASE];
                    regVal[MISCREG_DS_EFF_BASE] = regVal[MISCREG_DS_BASE];
                }
            }
        }
        break;
      // These segments always actually use their bases, or in other words
      // their effective bases must stay equal to their actual bases.
      case MISCREG_FS_BASE:
      case MISCREG_GS_BASE:
      case MISCREG_HS_BASE:
      case MISCREG_TSL_BASE:
      case MISCREG_TSG_BASE:
      case MISCREG_TR_BASE:
      case MISCREG_IDTR_BASE:
        regVal[MISCREG_SEG_EFF_BASE(miscReg - MISCREG_SEG_BASE_BASE)] = val;
        break;
      // These segments ignore their bases in 64 bit mode.
      // their effective bases must stay equal to their actual bases.
      case MISCREG_ES_BASE:
      case MISCREG_CS_BASE:
      case MISCREG_SS_BASE:
      case MISCREG_DS_BASE:
        {
            Efer efer = regVal[MISCREG_EFER];
            SegAttr csAttr = regVal[MISCREG_CS_ATTR];
            if (!efer.lma || !csAttr.longMode) // Check for non 64 bit mode.
                regVal[MISCREG_SEG_EFF_BASE(miscReg -
                        MISCREG_SEG_BASE_BASE)] = val;
        }
        break;
    }
    setRegNoEffect(miscReg, newVal);
}

void MiscRegFile::serialize(std::ostream & os)
{
    SERIALIZE_ARRAY(regVal, NumMiscRegs);
}

void MiscRegFile::unserialize(Checkpoint * cp, const std::string & section)
{
    UNSERIALIZE_ARRAY(regVal, NumMiscRegs);
}
