/*
 * Copyright (C) 2017 Apple Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. 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.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``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 APPLE INC. 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.
 */

#pragma once

#include "MacroAssembler.h"
#include "ProbeStack.h"

#if ENABLE(MASM_PROBE)

namespace JSC {
namespace Probe {

struct CPUState {
    using RegisterID = MacroAssembler::RegisterID;
    using SPRegisterID = MacroAssembler::SPRegisterID;
    using FPRegisterID = MacroAssembler::FPRegisterID;

    static inline const char* gprName(RegisterID id) { return MacroAssembler::gprName(id); }
    static inline const char* sprName(SPRegisterID id) { return MacroAssembler::sprName(id); }
    static inline const char* fprName(FPRegisterID id) { return MacroAssembler::fprName(id); }
    inline uintptr_t& gpr(RegisterID);
    inline uintptr_t& spr(SPRegisterID);
    inline double& fpr(FPRegisterID);

    template<typename T> T gpr(RegisterID) const;
    template<typename T> T spr(SPRegisterID) const;
    template<typename T> T fpr(FPRegisterID) const;

    void*& pc();
    void*& fp();
    void*& sp();
    template<typename T> T pc() const;
    template<typename T> T fp() const;
    template<typename T> T sp() const;

    uintptr_t gprs[MacroAssembler::numberOfRegisters()];
    uintptr_t sprs[MacroAssembler::numberOfSPRegisters()];
    double fprs[MacroAssembler::numberOfFPRegisters()];
};

inline uintptr_t& CPUState::gpr(RegisterID id)
{
    ASSERT(id >= MacroAssembler::firstRegister() && id <= MacroAssembler::lastRegister());
    return gprs[id];
}

inline uintptr_t& CPUState::spr(SPRegisterID id)
{
    ASSERT(id >= MacroAssembler::firstSPRegister() && id <= MacroAssembler::lastSPRegister());
    return sprs[id];
}

inline double& CPUState::fpr(FPRegisterID id)
{
    ASSERT(id >= MacroAssembler::firstFPRegister() && id <= MacroAssembler::lastFPRegister());
    return fprs[id];
}

template<typename T>
T CPUState::gpr(RegisterID id) const
{
    CPUState* cpu = const_cast<CPUState*>(this);
    auto& from = cpu->gpr(id);
    typename std::remove_const<T>::type to { };
    std::memcpy(&to, &from, sizeof(to)); // Use std::memcpy to avoid strict aliasing issues.
    return to;
}

template<typename T>
T CPUState::spr(SPRegisterID id) const
{
    CPUState* cpu = const_cast<CPUState*>(this);
    auto& from = cpu->spr(id);
    typename std::remove_const<T>::type to { };
    std::memcpy(&to, &from, sizeof(to)); // Use std::memcpy to avoid strict aliasing issues.
    return to;
}

template<typename T>
T CPUState::fpr(FPRegisterID id) const
{
    CPUState* cpu = const_cast<CPUState*>(this);
    return bitwise_cast<T>(cpu->fpr(id));
}

inline void*& CPUState::pc()
{
#if CPU(X86) || CPU(X86_64)
    return *reinterpret_cast<void**>(&spr(X86Registers::eip));
#elif CPU(ARM64)
    return *reinterpret_cast<void**>(&spr(ARM64Registers::pc));
#elif CPU(ARM_THUMB2) || CPU(ARM_TRADITIONAL)
    return *reinterpret_cast<void**>(&gpr(ARMRegisters::pc));
#elif CPU(MIPS)
    return *reinterpret_cast<void**>(&spr(MIPSRegisters::pc));
#else
#error "Unsupported CPU"
#endif
}

inline void*& CPUState::fp()
{
#if CPU(X86) || CPU(X86_64)
    return *reinterpret_cast<void**>(&gpr(X86Registers::ebp));
#elif CPU(ARM64)
    return *reinterpret_cast<void**>(&gpr(ARM64Registers::fp));
#elif CPU(ARM_THUMB2) || CPU(ARM_TRADITIONAL)
    return *reinterpret_cast<void**>(&gpr(ARMRegisters::fp));
#elif CPU(MIPS)
    return *reinterpret_cast<void**>(&gpr(MIPSRegisters::fp));
#else
#error "Unsupported CPU"
#endif
}

inline void*& CPUState::sp()
{
#if CPU(X86) || CPU(X86_64)
    return *reinterpret_cast<void**>(&gpr(X86Registers::esp));
#elif CPU(ARM64)
    return *reinterpret_cast<void**>(&gpr(ARM64Registers::sp));
#elif CPU(ARM_THUMB2) || CPU(ARM_TRADITIONAL)
    return *reinterpret_cast<void**>(&gpr(ARMRegisters::sp));
#elif CPU(MIPS)
    return *reinterpret_cast<void**>(&gpr(MIPSRegisters::sp));
#else
#error "Unsupported CPU"
#endif
}

template<typename T>
T CPUState::pc() const
{
    CPUState* cpu = const_cast<CPUState*>(this);
    return reinterpret_cast<T>(cpu->pc());
}

template<typename T>
T CPUState::fp() const
{
    CPUState* cpu = const_cast<CPUState*>(this);
    return reinterpret_cast<T>(cpu->fp());
}

template<typename T>
T CPUState::sp() const
{
    CPUState* cpu = const_cast<CPUState*>(this);
    return reinterpret_cast<T>(cpu->sp());
}

struct State;
typedef void (*StackInitializationFunction)(State*);

struct State {
    Probe::Function probeFunction;
    void* arg;
    StackInitializationFunction initializeStackFunction;
    void* initializeStackArg;
    CPUState cpu;
};

class Context {
    WTF_MAKE_FAST_ALLOCATED;
public:
    using RegisterID = MacroAssembler::RegisterID;
    using SPRegisterID = MacroAssembler::SPRegisterID;
    using FPRegisterID = MacroAssembler::FPRegisterID;

    Context(State* state)
        : cpu(state->cpu)
        , m_state(state)
    { }

    template<typename T>
    T arg() { return reinterpret_cast<T>(m_state->arg); }

    uintptr_t& gpr(RegisterID id) { return cpu.gpr(id); }
    uintptr_t& spr(SPRegisterID id) { return cpu.spr(id); }
    double& fpr(FPRegisterID id) { return cpu.fpr(id); }
    const char* gprName(RegisterID id) { return cpu.gprName(id); }
    const char* sprName(SPRegisterID id) { return cpu.sprName(id); }
    const char* fprName(FPRegisterID id) { return cpu.fprName(id); }

    template<typename T> T gpr(RegisterID id) const { return cpu.gpr<T>(id); }
    template<typename T> T spr(SPRegisterID id) const { return cpu.spr<T>(id); }
    template<typename T> T fpr(FPRegisterID id) const { return cpu.fpr<T>(id); }

    void*& pc() { return cpu.pc(); }
    void*& fp() { return cpu.fp(); }
    void*& sp() { return cpu.sp(); }

    template<typename T> T pc() { return cpu.pc<T>(); }
    template<typename T> T fp() { return cpu.fp<T>(); }
    template<typename T> T sp() { return cpu.sp<T>(); }

    Stack& stack()
    {
        ASSERT(m_stack.isValid());
        return m_stack;
    };

    bool hasWritesToFlush() { return m_stack.hasWritesToFlush(); }
    Stack* releaseStack() { return new Stack(WTFMove(m_stack)); }

    CPUState& cpu;

private:
    State* m_state;
    Stack m_stack;

    friend JS_EXPORT_PRIVATE void* probeStateForContext(Context&); // Not for general use. This should only be for writing tests.
};

void executeProbe(State*);

} // namespace Probe
} // namespace JSC

#endif // ENABLE(MASM_PROBE)
