/*
 * Copyright (c) 2007 The Hewlett-Packard Development Company
 * Copyright (c) 2011 Advanced Micro Devices, Inc.
 * 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.
 *
 * 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
 */

#include "arch/x86/utility.hh"

#include "arch/x86/interrupts.hh"
#include "arch/x86/registers.hh"
#include "arch/x86/x86_traits.hh"
#include "cpu/base.hh"
#include "fputils/fp80.h"
#include "sim/full_system.hh"

namespace X86ISA {

uint64_t
getArgument(ThreadContext *tc, int &number, uint16_t size, bool fp)
{
    if (fp) {
        panic("getArgument(): Floating point arguments not implemented\n");
    } else if (size != 8) {
        panic("getArgument(): Can only handle 64-bit arguments.\n");
    }

    // The first 6 integer arguments are passed in registers, the rest
    // are passed on the stack.
    const int int_reg_map[] = {
        INTREG_RDI, INTREG_RSI, INTREG_RDX,
        INTREG_RCX, INTREG_R8, INTREG_R9
    };
    if (number < sizeof(int_reg_map) / sizeof(*int_reg_map)) {
        return tc->readIntReg(int_reg_map[number]);
    } else {
        panic("getArgument(): Don't know how to handle stack arguments.\n");
    }
}

void
copyMiscRegs(ThreadContext *src, ThreadContext *dest)
{
    // This function assumes no side effects other than TLB invalidation
    // need to be considered while copying state. That will likely not be
    // true in the future.
    for (int i = 0; i < NUM_MISCREGS; ++i) {
        if (!isValidMiscReg(i))
             continue;

        dest->setMiscRegNoEffect(i, src->readMiscRegNoEffect(i));
    }

    // The TSC has to be updated with side-effects if the CPUs in a
    // CPU switch have different frequencies.
    dest->setMiscReg(MISCREG_TSC, src->readMiscReg(MISCREG_TSC));

    dest->getITBPtr()->flushAll();
    dest->getDTBPtr()->flushAll();
}

void
copyRegs(ThreadContext *src, ThreadContext *dest)
{
    //copy int regs
    for (int i = 0; i < NumIntRegs; ++i)
         dest->setIntRegFlat(i, src->readIntRegFlat(i));
    //copy float regs
    for (int i = 0; i < NumFloatRegs; ++i)
         dest->setFloatRegFlat(i, src->readFloatRegFlat(i));
    //copy condition-code regs
    for (int i = 0; i < NumCCRegs; ++i)
         dest->setCCRegFlat(i, src->readCCRegFlat(i));
    copyMiscRegs(src, dest);
    dest->pcState(src->pcState());
}

void
skipFunction(ThreadContext *tc)
{
    panic("Not implemented for x86\n");
}

uint64_t
getRFlags(ThreadContext *tc)
{
    const uint64_t ncc_flags(tc->readMiscRegNoEffect(MISCREG_RFLAGS));
    const uint64_t cc_flags(tc->readCCReg(X86ISA::CCREG_ZAPS));
    const uint64_t cfof_bits(tc->readCCReg(X86ISA::CCREG_CFOF));
    const uint64_t df_bit(tc->readCCReg(X86ISA::CCREG_DF));
    // ecf (PSEUDO(3)) & ezf (PSEUDO(4)) are only visible to
    // microcode, so we can safely ignore them.

    // Reconstruct the real rflags state, mask out internal flags, and
    // make sure reserved bits have the expected values.
    return ((ncc_flags | cc_flags | cfof_bits | df_bit) & 0x3F7FD5)
        | 0x2;
}

void
setRFlags(ThreadContext *tc, uint64_t val)
{
    tc->setCCReg(X86ISA::CCREG_ZAPS, val & ccFlagMask);
    tc->setCCReg(X86ISA::CCREG_CFOF, val & cfofMask);
    tc->setCCReg(X86ISA::CCREG_DF, val & DFBit);

    // Internal microcode registers (ECF & EZF)
    tc->setCCReg(X86ISA::CCREG_ECF, 0);
    tc->setCCReg(X86ISA::CCREG_EZF, 0);

    // Update the RFLAGS misc reg with whatever didn't go into the
    // magic registers.
    tc->setMiscReg(MISCREG_RFLAGS, val & ~(ccFlagMask | cfofMask | DFBit));
}

uint8_t
convX87TagsToXTags(uint16_t ftw)
{
    uint8_t ftwx(0);
    for (int i = 0; i < 8; ++i) {
        // Extract the tag for the current element on the FP stack
        const unsigned tag((ftw >> (2 * i)) & 0x3);

        /*
         * Check the type of the current FP element. Valid values are:
         * 0 == Valid
         * 1 == Zero
         * 2 == Special (Nan, unsupported, infinity, denormal)
         * 3 == Empty
         */
        // The xsave version of the tag word only keeps track of
        // whether the element is empty or not. Set the corresponding
        // bit in the ftwx if it's not empty,
        if (tag != 0x3)
            ftwx |= 1 << i;
    }

    return ftwx;
}

uint16_t
convX87XTagsToTags(uint8_t ftwx)
{
    uint16_t ftw(0);
    for (int i = 0; i < 8; ++i) {
        const unsigned xtag(((ftwx >> i) & 0x1));

        // The xtag for an x87 stack position is 0 for empty stack positions.
        if (!xtag) {
            // Set the tag word to 3 (empty) for the current element.
            ftw |= 0x3 << (2 * i);
        } else {
            // TODO: We currently assume that non-empty elements are
            // valid (0x0), but we should ideally reconstruct the full
            // state (valid/zero/special).
        }
    }

    return ftw;
}

uint16_t
genX87Tags(uint16_t ftw, uint8_t top, int8_t spm)
{
    const uint8_t new_top((top + spm + 8) % 8);

    if (spm > 0) {
        // Removing elements from the stack. Flag the elements as empty.
        for (int i = top; i != new_top; i = (i + 1 + 8) % 8)
            ftw |= 0x3 << (2 * i);
    } else if (spm < 0) {
        // Adding elements to the stack. Flag the new elements as
        // valid. We should ideally decode them and "do the right
        // thing".
        for (int i = new_top; i != top; i = (i + 1 + 8) % 8)
            ftw &= ~(0x3 << (2 * i));
    }

    return ftw;
}

double
loadFloat80(const void *_mem)
{
    fp80_t fp80;
    memcpy(fp80.bits, _mem, 10);

    return fp80_cvtd(fp80);
}

void
storeFloat80(void *_mem, double value)
{
    fp80_t fp80 = fp80_cvfd(value);
    memcpy(_mem, fp80.bits, 10);
}

} // namespace X86_ISA
