blob: a125f317cbe01d64eb8b70913e9a4e2ca0e10fa8 [file] [log] [blame]
/*
* Copyright (C) 2021 Igalia S.L.
*
* 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
#if ENABLE(ASSEMBLER) && CPU(RISCV64)
#include "AssemblerBuffer.h"
#include "RISCV64Registers.h"
namespace JSC {
namespace RISCV64Registers {
typedef enum : int8_t {
#define REGISTER_ID(id, name, r, cs) id,
FOR_EACH_GP_REGISTER(REGISTER_ID)
#undef REGISTER_ID
#define REGISTER_ALIAS(id, name, alias) id = alias,
FOR_EACH_REGISTER_ALIAS(REGISTER_ALIAS)
#undef REGISTER_ALIAS
InvalidGPRReg = -1,
} RegisterID;
typedef enum : int8_t {
#define REGISTER_ID(id, name) id,
FOR_EACH_SP_REGISTER(REGISTER_ID)
#undef REGISTER_ID
InvalidSPReg = -1,
} SPRegisterID;
typedef enum : int8_t {
#define REGISTER_ID(id, name, r, cs) id,
FOR_EACH_FP_REGISTER(REGISTER_ID)
#undef REGISTER_ID
InvalidFPRReg = -1,
} FPRegisterID;
} // namespace RISCV64Registers
class RISCV64Assembler {
public:
using RegisterID = RISCV64Registers::RegisterID;
using SPRegisterID = RISCV64Registers::SPRegisterID;
using FPRegisterID = RISCV64Registers::FPRegisterID;
static constexpr RegisterID firstRegister() { return RISCV64Registers::x0; }
static constexpr RegisterID lastRegister() { return RISCV64Registers::x31; }
static constexpr unsigned numberOfRegisters() { return lastRegister() - firstRegister() + 1; }
static constexpr SPRegisterID firstSPRegister() { return RISCV64Registers::pc; }
static constexpr SPRegisterID lastSPRegister() { return RISCV64Registers::pc; }
static constexpr unsigned numberOfSPRegisters() { return lastSPRegister() - firstSPRegister() + 1; }
static constexpr FPRegisterID firstFPRegister() { return RISCV64Registers::f0; }
static constexpr FPRegisterID lastFPRegister() { return RISCV64Registers::f31; }
static constexpr unsigned numberOfFPRegisters() { return lastFPRegister() - firstFPRegister() + 1; }
static const char* gprName(RegisterID id)
{
ASSERT(id >= firstRegister() && id <= lastRegister());
static const char* const nameForRegister[numberOfRegisters()] = {
#define REGISTER_NAME(id, name, r, cs) name,
FOR_EACH_GP_REGISTER(REGISTER_NAME)
#undef REGISTER_NAME
};
return nameForRegister[id];
}
static const char* sprName(SPRegisterID id)
{
ASSERT(id >= firstSPRegister() && id <= lastSPRegister());
static const char* const nameForRegister[numberOfSPRegisters()] = {
#define REGISTER_NAME(id, name) name,
FOR_EACH_SP_REGISTER(REGISTER_NAME)
#undef REGISTER_NAME
};
return nameForRegister[id];
}
static const char* fprName(FPRegisterID id)
{
ASSERT(id >= firstFPRegister() && id <= lastFPRegister());
static const char* const nameForRegister[numberOfFPRegisters()] = {
#define REGISTER_NAME(id, name, r, cs) name,
FOR_EACH_FP_REGISTER(REGISTER_NAME)
#undef REGISTER_NAME
};
return nameForRegister[id];
}
RISCV64Assembler() { }
AssemblerBuffer& buffer() { return m_buffer; }
typedef enum {
ConditionEQ,
ConditionNE,
ConditionHS, ConditionCS = ConditionHS,
ConditionLO, ConditionCC = ConditionLO,
ConditionMI,
ConditionPL,
ConditionVS,
ConditionVC,
ConditionHI,
ConditionLS,
ConditionGE,
ConditionLT,
ConditionGT,
ConditionLE,
ConditionAL,
ConditionInvalid
} Condition;
static Condition invert(Condition cond)
{
return static_cast<Condition>(cond ^ 1);
}
static void* getRelocatedAddress(void* code, AssemblerLabel label)
{
ASSERT(label.isSet());
return reinterpret_cast<void*>(reinterpret_cast<ptrdiff_t>(code) + label.offset());
}
size_t codeSize() const { return m_buffer.codeSize(); }
static unsigned getCallReturnOffset(AssemblerLabel) { return 0; }
AssemblerLabel labelIgnoringWatchpoints() { return { }; }
AssemblerLabel labelForWatchpoint() { return { }; }
AssemblerLabel label() { return { }; }
static void linkJump(void*, AssemblerLabel, void*) { }
static void linkJump(AssemblerLabel, AssemblerLabel) { }
static void linkCall(void*, AssemblerLabel, void*) { }
static void linkPointer(void*, AssemblerLabel, void*) { }
static ptrdiff_t maxJumpReplacementSize()
{
return 4;
}
static constexpr ptrdiff_t patchableJumpSize()
{
return 4;
}
static void repatchPointer(void*, void*) { }
static void relinkJump(void*, void*) { }
static void relinkJumpToNop(void*) { }
static void relinkCall(void*, void*) { }
unsigned debugOffset() { return m_buffer.debugOffset(); }
static void cacheFlush(void*, size_t) { }
using CopyFunction = void*(&)(void*, const void*, size_t);
template <CopyFunction copy>
static void fillNops(void*, size_t) { }
AssemblerBuffer m_buffer;
};
} // namespace JSC
#endif // ENABLE(ASSEMBLER) && CPU(RISCV64)